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}