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