blob: 59bb5ed91f1f80c4f536b9061536f24094275442 [file] [log] [blame]
// 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);
}
}