summary refs log tree commit diff
path: root/usb_util/src/types.rs
diff options
context:
space:
mode:
authorJingkui Wang <jkwang@google.com>2018-11-02 00:27:48 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-12-01 01:08:35 -0800
commit33e08312f272c863f062fffe53ea4a4ce94e6e26 (patch)
treec58171884a5b0e4d16dd9a4ee8633d75a461a281 /usb_util/src/types.rs
parent9ae286d008fd1c2a5b7f25f4184529fe6b5f169d (diff)
downloadcrosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.tar
crosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.tar.gz
crosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.tar.bz2
crosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.tar.lz
crosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.tar.xz
crosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.tar.zst
crosvm-33e08312f272c863f062fffe53ea4a4ce94e6e26.zip
usb_util: Create libusb wrapper
This wrapper will be part of usb emulation backend.

BUG=chromium:831850
TEST=local build

Change-Id: I084b15201941e4c16c4e3ff9b967e55db09db567
Reviewed-on: https://chromium-review.googlesource.com/1124870
Commit-Ready: Jingkui Wang <jkwang@google.com>
Tested-by: Jingkui Wang <jkwang@google.com>
Reviewed-by: Jingkui Wang <jkwang@google.com>
Diffstat (limited to 'usb_util/src/types.rs')
-rw-r--r--usb_util/src/types.rs198
1 files changed, 198 insertions, 0 deletions
diff --git a/usb_util/src/types.rs b/usb_util/src/types.rs
new file mode 100644
index 0000000..59bb5ed
--- /dev/null
+++ b/usb_util/src/types.rs
@@ -0,0 +1,198 @@
+// 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 bindings;
+use data_model::DataInit;
+
+/// Speed of usb device. See usb spec for more details.
+#[derive(Debug)]
+pub enum Speed {
+    /// The OS doesn't report or know the device speed.
+    Unknown,
+    /// The device is operating at low speed (1.5MBit/s).
+    Low,
+    /// The device is operating at full speed (12MBit/s).
+    Full,
+    /// The device is operating at high speed (480MBit/s).
+    High,
+    /// The device is operating at super speed (5000MBit/s).
+    Super,
+}
+
+impl From<bindings::libusb_speed> for Speed {
+    fn from(speed: bindings::libusb_speed) -> Speed {
+        match speed {
+            bindings::LIBUSB_SPEED_LOW => Speed::Low,
+            bindings::LIBUSB_SPEED_FULL => Speed::Full,
+            bindings::LIBUSB_SPEED_HIGH => Speed::High,
+            bindings::LIBUSB_SPEED_SUPER => Speed::Super,
+            _ => Speed::Unknown,
+        }
+    }
+}
+
+/// Endpoint types.
+#[derive(PartialEq)]
+pub enum EndpointType {
+    Control,
+    Isochronous,
+    Bulk,
+    Interrupt,
+}
+
+/// Endpoint Directions.
+#[derive(PartialEq, Clone, Copy)]
+pub enum EndpointDirection {
+    HostToDevice = 0,
+    DeviceToHost = 1,
+}
+/// Endpoint direction offset.
+pub const ENDPOINT_DIRECTION_OFFSET: u8 = 7;
+
+/// Offset of data phase transfer direction.
+pub const DATA_PHASE_DIRECTION_OFFSET: u8 = 7;
+/// Bit mask of data phase transfer direction.
+pub const DATA_PHASE_DIRECTION: u8 = 1u8 << DATA_PHASE_DIRECTION_OFFSET;
+// Types of data phase transfer directions.
+#[derive(PartialEq)]
+pub enum ControlRequestDataPhaseTransferDirection {
+    HostToDevice = 0,
+    DeviceToHost = 1,
+}
+
+/// Offset of control request type.
+pub const CONTROL_REQUEST_TYPE_OFFSET: u8 = 5;
+/// Bit mask of control request type.
+pub const CONTROL_REQUEST_TYPE: u8 = 0b11 << CONTROL_REQUEST_TYPE_OFFSET;
+/// Request types.
+#[derive(PartialEq)]
+pub enum ControlRequestType {
+    Standard = 0,
+    Class = 1,
+    Vendor = 2,
+    Reserved = 3,
+}
+
+/// Recipient type bits.
+pub const REQUEST_RECIPIENT_TYPE: u8 = 0b1111;
+/// Recipient type of control request.
+#[derive(PartialEq)]
+pub enum ControlRequestRecipient {
+    Device = 0,
+    Interface = 1,
+    Endpoint = 2,
+    Other = 3,
+    Reserved,
+}
+
+/// Standard request defined in usb spec.
+#[derive(PartialEq)]
+pub enum StandardControlRequest {
+    GetStatus = 0x00,
+    ClearFeature = 0x01,
+    SetFeature = 0x03,
+    SetAddress = 0x05,
+    GetDescriptor = 0x06,
+    SetDescriptor = 0x07,
+    GetConfiguration = 0x08,
+    SetConfiguration = 0x09,
+    GetInterface = 0x0a,
+    SetInterface = 0x11,
+    SynchFrame = 0x12,
+}
+
+/// RequestSetup is first part of control transfer buffer.
+#[repr(C, packed)]
+#[derive(Copy, Clone, Debug)]
+pub struct UsbRequestSetup {
+    // USB Device Request. USB spec. rev. 2.0 9.3
+    pub request_type: u8, // bmRequestType
+    pub request: u8,      // bRequest
+    pub value: u16,       // wValue
+    pub index: u16,       // wIndex
+    pub length: u16,      // wLength
+}
+
+unsafe impl DataInit for UsbRequestSetup {}
+
+impl UsbRequestSetup {
+    pub fn new(
+        request_type: u8,
+        request: u8,
+        value: u16,
+        index: u16,
+        length: u16,
+    ) -> UsbRequestSetup {
+        UsbRequestSetup {
+            request_type,
+            request,
+            value,
+            index,
+            length,
+        }
+    }
+
+    /// Get type of request.
+    pub fn get_type(&self) -> Option<ControlRequestType> {
+        let ty = (self.request_type & CONTROL_REQUEST_TYPE) >> CONTROL_REQUEST_TYPE_OFFSET;
+        match ty {
+            0 => Some(ControlRequestType::Standard),
+            1 => Some(ControlRequestType::Class),
+            2 => Some(ControlRequestType::Vendor),
+            3 => Some(ControlRequestType::Reserved),
+            _ => None,
+        }
+    }
+
+    /// Get request direction.
+    pub fn get_direction(&self) -> Option<ControlRequestDataPhaseTransferDirection> {
+        let dir = (self.request_type & DATA_PHASE_DIRECTION) >> DATA_PHASE_DIRECTION_OFFSET;
+        match dir {
+            0 => Some(ControlRequestDataPhaseTransferDirection::HostToDevice),
+            1 => Some(ControlRequestDataPhaseTransferDirection::DeviceToHost),
+            _ => None,
+        }
+    }
+
+    /// Get recipient of this control transfer.
+    pub fn get_recipient(&self) -> ControlRequestRecipient {
+        let recipienet = self.request_type & REQUEST_RECIPIENT_TYPE;
+        match recipienet {
+            0 => ControlRequestRecipient::Device,
+            1 => ControlRequestRecipient::Interface,
+            2 => ControlRequestRecipient::Endpoint,
+            3 => ControlRequestRecipient::Other,
+            _ => ControlRequestRecipient::Reserved,
+        }
+    }
+
+    /// Return the type of standard control request.
+    pub fn get_standard_request(&self) -> Option<StandardControlRequest> {
+        match self.request {
+            0x00 => Some(StandardControlRequest::GetStatus),
+            0x01 => Some(StandardControlRequest::ClearFeature),
+            0x03 => Some(StandardControlRequest::SetFeature),
+            0x05 => Some(StandardControlRequest::SetAddress),
+            0x06 => Some(StandardControlRequest::GetDescriptor),
+            0x07 => Some(StandardControlRequest::SetDescriptor),
+            0x08 => Some(StandardControlRequest::GetConfiguration),
+            0x09 => Some(StandardControlRequest::SetConfiguration),
+            0x0a => Some(StandardControlRequest::GetInterface),
+            0x11 => Some(StandardControlRequest::SetInterface),
+            0x12 => Some(StandardControlRequest::SynchFrame),
+            _ => None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::mem::size_of;
+
+    #[test]
+    fn check_request_setup_size() {
+        assert_eq!(size_of::<UsbRequestSetup>(), 8);
+    }
+}