usb_device/class.rs
1use crate::bus::{InterfaceNumber, StringIndex, UsbBus};
2use crate::control;
3use crate::control_pipe::ControlPipe;
4use crate::descriptor::lang_id::LangID;
5use crate::descriptor::{BosWriter, DescriptorWriter};
6use crate::endpoint::EndpointAddress;
7use crate::{Result, UsbError};
8
9/// A trait for implementing USB classes.
10///
11/// All methods are optional callbacks that will be called by
12/// [UsbBus::poll](crate::bus::UsbBus::poll)
13pub trait UsbClass<B: UsbBus> {
14 /// Called when a GET_DESCRIPTOR request is received for a configuration descriptor. When
15 /// called, the implementation should write its interface, endpoint and any extra class
16 /// descriptors into `writer`. The configuration descriptor itself will be written by
17 /// [UsbDevice](crate::device::UsbDevice) and shouldn't be written by classes.
18 ///
19 /// # Errors
20 ///
21 /// Generally errors returned by `DescriptorWriter`. Implementors should propagate any errors
22 /// using `?`.
23 fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
24 let _ = writer;
25 Ok(())
26 }
27
28 /// Called when a GET_DESCRIPTOR request is received for a BOS descriptor.
29 /// When called, the implementation should write its blobs such as capability
30 /// descriptors into `writer`. The BOS descriptor itself will be written by
31 /// [UsbDevice](crate::device::UsbDevice) and shouldn't be written by classes.
32 fn get_bos_descriptors(&self, writer: &mut BosWriter) -> Result<()> {
33 let _ = writer;
34 Ok(())
35 }
36
37 /// Gets a class-specific string descriptor.
38 ///
39 /// Note: All string descriptor requests are passed to all classes in turn, so implementations
40 /// should return [`None`] if an unknown index is requested.
41 ///
42 /// # Arguments
43 ///
44 /// * `index` - A string index allocated earlier with
45 /// [`UsbAllocator`](crate::bus::UsbBusAllocator).
46 /// * `lang_id` - The language ID for the string to retrieve. If the requested lang_id is not
47 /// valid it will default to EN_US.
48 fn get_string(&self, index: StringIndex, lang_id: LangID) -> Option<&str> {
49 let _ = (index, lang_id);
50 None
51 }
52
53 /// Called after a USB reset after the bus reset sequence is complete.
54 fn reset(&mut self) {}
55
56 /// Called whenever the `UsbDevice` is polled.
57 fn poll(&mut self) {}
58
59 /// Called when a control request is received with direction HostToDevice.
60 ///
61 /// All requests are passed to classes in turn, which can choose to accept, ignore or report an
62 /// error. Classes can even choose to override standard requests, but doing that is rarely
63 /// necessary.
64 ///
65 /// See [`ControlOut`] for how to respond to the transfer.
66 ///
67 /// When implementing your own class, you should ignore any requests that are not meant for your
68 /// class so that any other classes in the composite device can process them.
69 ///
70 /// # Arguments
71 ///
72 /// * `req` - The request from the SETUP packet.
73 /// * `xfer` - A handle to the transfer.
74 fn control_out(&mut self, xfer: ControlOut<B>) {
75 let _ = xfer;
76 }
77
78 /// Called when a control request is received with direction DeviceToHost.
79 ///
80 /// All requests are passed to classes in turn, which can choose to accept, ignore or report an
81 /// error. Classes can even choose to override standard requests, but doing that is rarely
82 /// necessary.
83 ///
84 /// See [`ControlIn`] for how to respond to the transfer.
85 ///
86 /// When implementing your own class, you should ignore any requests that are not meant for your
87 /// class so that any other classes in the composite device can process them.
88 ///
89 /// # Arguments
90 ///
91 /// * `req` - The request from the SETUP packet.
92 /// * `data` - Data to send in the DATA stage of the control transfer.
93 fn control_in(&mut self, xfer: ControlIn<B>) {
94 let _ = xfer;
95 }
96
97 /// Called when endpoint with address `addr` has received a SETUP packet. Implementing this
98 /// shouldn't be necessary in most cases, but is provided for completeness' sake.
99 ///
100 /// Note: This method may be called for an endpoint address you didn't allocate, and in that
101 /// case you should ignore the event.
102 fn endpoint_setup(&mut self, addr: EndpointAddress) {
103 let _ = addr;
104 }
105
106 /// Called when endpoint with address `addr` has received data (OUT packet).
107 ///
108 /// Note: This method may be called for an endpoint address you didn't allocate, and in that
109 /// case you should ignore the event.
110 fn endpoint_out(&mut self, addr: EndpointAddress) {
111 let _ = addr;
112 }
113
114 /// Called when endpoint with address `addr` has completed transmitting data (IN packet).
115 ///
116 /// Note: This method may be called for an endpoint address you didn't allocate, and in that
117 /// case you should ignore the event.
118 fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
119 let _ = addr;
120 }
121
122 /// Called when the interfaces alternate setting state is requested.
123 ///
124 /// Note: This method may be called on interfaces, that are not relevant to this class.
125 /// You should return `None, if `interface` belongs to an interface you don't know.
126 fn get_alt_setting(&mut self, interface: InterfaceNumber) -> Option<u8> {
127 let _ = interface;
128 None
129 }
130
131 /// Called when the interfaces alternate setting state is altered.
132 ///
133 /// Note: This method may be called on interfaces, that are not relevant to this class.
134 /// You should return `false`, if `interface` belongs to an interface you don't know.
135 fn set_alt_setting(&mut self, interface: InterfaceNumber, alternative: u8) -> bool {
136 let _ = (interface, alternative);
137 false
138 }
139}
140
141/// Handle for a control IN transfer. When implementing a class, use the methods of this object to
142/// response to the transfer with either data or an error (STALL condition). To ignore the request
143/// and pass it on to the next class, simply don't call any method.
144pub struct ControlIn<'a, 'p, 'r, B: UsbBus> {
145 pipe: &'p mut ControlPipe<'a, B>,
146 req: &'r control::Request,
147}
148
149impl<'a, 'p, 'r, B: UsbBus> ControlIn<'a, 'p, 'r, B> {
150 pub(crate) fn new(pipe: &'p mut ControlPipe<'a, B>, req: &'r control::Request) -> Self {
151 ControlIn { pipe, req }
152 }
153
154 /// Gets the request from the SETUP packet.
155 pub fn request(&self) -> &control::Request {
156 self.req
157 }
158
159 /// Accepts the transfer with the supplied buffer.
160 pub fn accept_with(self, data: &[u8]) -> Result<()> {
161 self.pipe.accept_in(|buf| {
162 if data.len() > buf.len() {
163 return Err(UsbError::BufferOverflow);
164 }
165
166 buf[..data.len()].copy_from_slice(data);
167
168 Ok(data.len())
169 })
170 }
171
172 /// Accepts the transfer with the supplied static buffer.
173 /// This method is useful when you have a large static descriptor to send as one packet.
174 pub fn accept_with_static(self, data: &'static [u8]) -> Result<()> {
175 self.pipe.accept_in_static(data)
176 }
177
178 /// Accepts the transfer with a callback that can write to the internal buffer of the control
179 /// pipe. Can be used to avoid an extra copy.
180 pub fn accept(self, f: impl FnOnce(&mut [u8]) -> Result<usize>) -> Result<()> {
181 self.pipe.accept_in(f)
182 }
183
184 /// Rejects the transfer by stalling the pipe.
185 pub fn reject(self) -> Result<()> {
186 self.pipe.reject()
187 }
188}
189
190/// Handle for a control OUT transfer. When implementing a class, use the methods of this object to
191/// response to the transfer with an ACT or an error (STALL condition). To ignore the request and
192/// pass it on to the next class, simply don't call any method.
193pub struct ControlOut<'a, 'p, 'r, B: UsbBus> {
194 pipe: &'p mut ControlPipe<'a, B>,
195 req: &'r control::Request,
196}
197
198impl<'a, 'p, 'r, B: UsbBus> ControlOut<'a, 'p, 'r, B> {
199 pub(crate) fn new(pipe: &'p mut ControlPipe<'a, B>, req: &'r control::Request) -> Self {
200 ControlOut { pipe, req }
201 }
202
203 /// Gets the request from the SETUP packet.
204 pub fn request(&self) -> &control::Request {
205 self.req
206 }
207
208 /// Gets the data from the data stage of the request. May be empty if there was no data stage.
209 pub fn data(&self) -> &[u8] {
210 self.pipe.data()
211 }
212
213 /// Accepts the transfer by succesfully responding to the status stage.
214 pub fn accept(self) -> Result<()> {
215 self.pipe.accept_out()
216 }
217
218 /// Rejects the transfer by stalling the pipe.
219 pub fn reject(self) -> Result<()> {
220 self.pipe.reject()
221 }
222}