// 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 assertions::const_assert; use data_model::DataInit; use std::mem::size_of; use crate::bindings; /// 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 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 } fn _assert() { const_assert!(size_of::() == 8); } 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 { 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 { 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 { 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, } } }