1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
//! USB control data types.
use core::mem;
use crate::driver::Direction;
/// Control request type.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum RequestType {
/// Request is a USB standard request. Usually handled by
/// [`UsbDevice`](crate::UsbDevice).
Standard = 0,
/// Request is intended for a USB class.
Class = 1,
/// Request is vendor-specific.
Vendor = 2,
/// Reserved.
Reserved = 3,
}
/// Control request recipient.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Recipient {
/// Request is intended for the entire device.
Device = 0,
/// Request is intended for an interface. Generally, the `index` field of the request specifies
/// the interface number.
Interface = 1,
/// Request is intended for an endpoint. Generally, the `index` field of the request specifies
/// the endpoint address.
Endpoint = 2,
/// None of the above.
Other = 3,
/// Reserved.
Reserved = 4,
}
/// A control request read from a SETUP packet.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Request {
/// Direction of the request.
pub direction: Direction,
/// Type of the request.
pub request_type: RequestType,
/// Recipient of the request.
pub recipient: Recipient,
/// Request code. The meaning of the value depends on the previous fields.
pub request: u8,
/// Request value. The meaning of the value depends on the previous fields.
pub value: u16,
/// Request index. The meaning of the value depends on the previous fields.
pub index: u16,
/// Length of the DATA stage. For control OUT transfers this is the exact length of the data the
/// host sent. For control IN transfers this is the maximum length of data the device should
/// return.
pub length: u16,
}
impl Request {
/// Standard USB control request Get Status
pub const GET_STATUS: u8 = 0;
/// Standard USB control request Clear Feature
pub const CLEAR_FEATURE: u8 = 1;
/// Standard USB control request Set Feature
pub const SET_FEATURE: u8 = 3;
/// Standard USB control request Set Address
pub const SET_ADDRESS: u8 = 5;
/// Standard USB control request Get Descriptor
pub const GET_DESCRIPTOR: u8 = 6;
/// Standard USB control request Set Descriptor
pub const SET_DESCRIPTOR: u8 = 7;
/// Standard USB control request Get Configuration
pub const GET_CONFIGURATION: u8 = 8;
/// Standard USB control request Set Configuration
pub const SET_CONFIGURATION: u8 = 9;
/// Standard USB control request Get Interface
pub const GET_INTERFACE: u8 = 10;
/// Standard USB control request Set Interface
pub const SET_INTERFACE: u8 = 11;
/// Standard USB control request Synch Frame
pub const SYNCH_FRAME: u8 = 12;
/// Standard USB feature Endpoint Halt for Set/Clear Feature
pub const FEATURE_ENDPOINT_HALT: u16 = 0;
/// Standard USB feature Device Remote Wakeup for Set/Clear Feature
pub const FEATURE_DEVICE_REMOTE_WAKEUP: u16 = 1;
/// Parses a USB control request from a byte array.
pub fn parse(buf: &[u8; 8]) -> Request {
let rt = buf[0];
let recipient = rt & 0b11111;
Request {
direction: if rt & 0x80 == 0 { Direction::Out } else { Direction::In },
request_type: unsafe { mem::transmute((rt >> 5) & 0b11) },
recipient: if recipient <= 3 {
unsafe { mem::transmute(recipient) }
} else {
Recipient::Reserved
},
request: buf[1],
value: (buf[2] as u16) | ((buf[3] as u16) << 8),
index: (buf[4] as u16) | ((buf[5] as u16) << 8),
length: (buf[6] as u16) | ((buf[7] as u16) << 8),
}
}
/// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request.
pub const fn descriptor_type_index(&self) -> (u8, u8) {
((self.value >> 8) as u8, self.value as u8)
}
}
/// Response for a CONTROL OUT request.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OutResponse {
/// The request was accepted.
Accepted,
/// The request was rejected.
Rejected,
}
/// Response for a CONTROL IN request.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InResponse<'a> {
/// The request was accepted. The buffer contains the response data.
Accepted(&'a [u8]),
/// The request was rejected.
Rejected,
}