mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-10-26 13:45:33 +00:00
110 lines
3.9 KiB
Rust
110 lines
3.9 KiB
Rust
|
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
use std;
|
||
|
|
||
|
use bindings;
|
||
|
use config_descriptor::ConfigDescriptor;
|
||
|
use device_handle::DeviceHandle;
|
||
|
use error::{Error, Result};
|
||
|
use libusb_context::LibUsbContextInner;
|
||
|
use std::sync::Arc;
|
||
|
use types::Speed;
|
||
|
|
||
|
pub type DeviceDescriptor = bindings::libusb_device_descriptor;
|
||
|
|
||
|
/// LibUsbDevice wraps libusb_device.
|
||
|
pub struct LibUsbDevice {
|
||
|
_context: Arc<LibUsbContextInner>,
|
||
|
device: *mut bindings::libusb_device,
|
||
|
}
|
||
|
|
||
|
unsafe impl Send for LibUsbDevice {}
|
||
|
|
||
|
impl Drop for LibUsbDevice {
|
||
|
fn drop(&mut self) {
|
||
|
// Safe because 'self.device' is a valid pointer and libusb_ref_device is invoked when
|
||
|
// 'self' is built.
|
||
|
unsafe {
|
||
|
bindings::libusb_unref_device(self.device);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl LibUsbDevice {
|
||
|
/// Create a new LibUsbDevice. 'device' should be a valid pointer to libusb_device.
|
||
|
pub unsafe fn new(
|
||
|
ctx: Arc<LibUsbContextInner>,
|
||
|
device: *mut bindings::libusb_device,
|
||
|
) -> LibUsbDevice {
|
||
|
bindings::libusb_ref_device(device);
|
||
|
LibUsbDevice {
|
||
|
_context: ctx,
|
||
|
device,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Get device descriptor of this device.
|
||
|
pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
|
||
|
// Safe because memory is initialized later.
|
||
|
let mut descriptor: bindings::libusb_device_descriptor =
|
||
|
unsafe { std::mem::uninitialized() };
|
||
|
// Safe because 'self.device' is valid and '&mut descriptor' is valid.
|
||
|
try_libusb!(unsafe {
|
||
|
bindings::libusb_get_device_descriptor(self.device, &mut descriptor)
|
||
|
});
|
||
|
Ok(descriptor)
|
||
|
}
|
||
|
|
||
|
/// Get config descriptor at index of idx.
|
||
|
pub fn get_config_descriptor(&self, idx: u8) -> Result<ConfigDescriptor> {
|
||
|
let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut();
|
||
|
// Safe because 'self.device' is valid and '&mut descriptor' is valid.
|
||
|
try_libusb!(unsafe {
|
||
|
bindings::libusb_get_config_descriptor(self.device, idx, &mut descriptor)
|
||
|
});
|
||
|
// Safe because descriptor is inited with valid pointer.
|
||
|
Ok(unsafe { ConfigDescriptor::new(descriptor) })
|
||
|
}
|
||
|
|
||
|
/// Get active config descriptor of this device.
|
||
|
pub fn get_active_config_descriptor(&self) -> Result<ConfigDescriptor> {
|
||
|
let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut();
|
||
|
// Safe because 'self.device' is valid and '&mut descriptor' is valid.
|
||
|
try_libusb!(unsafe {
|
||
|
bindings::libusb_get_active_config_descriptor(self.device, &mut descriptor)
|
||
|
});
|
||
|
// Safe becuase descriptor points to valid memory.
|
||
|
Ok(unsafe { ConfigDescriptor::new(descriptor) })
|
||
|
}
|
||
|
|
||
|
/// Get bus number of this device.
|
||
|
pub fn get_bus_number(&self) -> u8 {
|
||
|
// Safe because 'self.device' is valid.
|
||
|
unsafe { bindings::libusb_get_bus_number(self.device) }
|
||
|
}
|
||
|
|
||
|
/// Get address of this device.
|
||
|
pub fn get_address(&self) -> u8 {
|
||
|
// Safe because 'self.device' is valid.
|
||
|
unsafe { bindings::libusb_get_device_address(self.device) }
|
||
|
}
|
||
|
|
||
|
/// Get speed of this device.
|
||
|
pub fn get_speed(&self) -> Speed {
|
||
|
// Safe because 'self.device' is valid.
|
||
|
let speed = unsafe { bindings::libusb_get_device_speed(self.device) };
|
||
|
Speed::from(speed as u32)
|
||
|
}
|
||
|
|
||
|
/// Get device handle of this device.
|
||
|
pub fn open(&self) -> Result<DeviceHandle> {
|
||
|
let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut();
|
||
|
// Safe because 'self.device' is valid and handle is on stack.
|
||
|
try_libusb!(unsafe { bindings::libusb_open(self.device, &mut handle) });
|
||
|
// Safe because handle points to valid memory.
|
||
|
Ok(unsafe { DeviceHandle::new(self._context.clone(), handle) })
|
||
|
}
|
||
|
}
|