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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
use crate::bus::{StringIndex, UsbBus};
use crate::control;
use crate::control_pipe::ControlPipe;
use crate::descriptor::{BosWriter, DescriptorWriter};
use crate::endpoint::EndpointAddress;
use crate::{Result, UsbError};
/// A trait for implementing USB classes.
///
/// All methods are optional callbacks that will be called by
/// [UsbBus::poll](crate::bus::UsbBus::poll)
pub trait UsbClass<B: UsbBus> {
/// Called when a GET_DESCRIPTOR request is received for a configuration descriptor. When
/// called, the implementation should write its interface, endpoint and any extra class
/// descriptors into `writer`. The configuration descriptor itself will be written by
/// [UsbDevice](crate::device::UsbDevice) and shouldn't be written by classes.
///
/// # Errors
///
/// Generally errors returned by `DescriptorWriter`. Implementors should propagate any errors
/// using `?`.
fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
let _ = writer;
Ok(())
}
/// Called when a GET_DESCRIPTOR request is received for a BOS descriptor.
/// When called, the implementation should write its blobs such as capability
/// descriptors into `writer`. The BOS descriptor itself will be written by
/// [UsbDevice](crate::device::UsbDevice) and shouldn't be written by classes.
fn get_bos_descriptors(&self, writer: &mut BosWriter) -> Result<()> {
let _ = writer;
Ok(())
}
/// Gets a class-specific string descriptor.
///
/// Note: All string descriptor requests are passed to all classes in turn, so implementations
/// should return [`None`] if an unknown index is requested.
///
/// # Arguments
///
/// * `index` - A string index allocated earlier with
/// [`UsbAllocator`](crate::bus::UsbBusAllocator).
/// * `lang_id` - The language ID for the string to retrieve.
fn get_string(&self, index: StringIndex, lang_id: u16) -> Option<&str> {
let _ = (index, lang_id);
None
}
/// Called after a USB reset after the bus reset sequence is complete.
fn reset(&mut self) {}
/// Called whenever the `UsbDevice` is polled.
fn poll(&mut self) {}
/// Called when a control request is received with direction HostToDevice.
///
/// All requests are passed to classes in turn, which can choose to accept, ignore or report an
/// error. Classes can even choose to override standard requests, but doing that is rarely
/// necessary.
///
/// See [`ControlOut`] for how to respond to the transfer.
///
/// When implementing your own class, you should ignore any requests that are not meant for your
/// class so that any other classes in the composite device can process them.
///
/// # Arguments
///
/// * `req` - The request from the SETUP packet.
/// * `xfer` - A handle to the transfer.
fn control_out(&mut self, xfer: ControlOut<B>) {
let _ = xfer;
}
/// Called when a control request is received with direction DeviceToHost.
///
/// All requests are passed to classes in turn, which can choose to accept, ignore or report an
/// error. Classes can even choose to override standard requests, but doing that is rarely
/// necessary.
///
/// See [`ControlIn`] for how to respond to the transfer.
///
/// When implementing your own class, you should ignore any requests that are not meant for your
/// class so that any other classes in the composite device can process them.
///
/// # Arguments
///
/// * `req` - The request from the SETUP packet.
/// * `data` - Data to send in the DATA stage of the control transfer.
fn control_in(&mut self, xfer: ControlIn<B>) {
let _ = xfer;
}
/// Called when endpoint with address `addr` has received a SETUP packet. Implementing this
/// shouldn't be necessary in most cases, but is provided for completeness' sake.
///
/// Note: This method may be called for an endpoint address you didn't allocate, and in that
/// case you should ignore the event.
fn endpoint_setup(&mut self, addr: EndpointAddress) {
let _ = addr;
}
/// Called when endpoint with address `addr` has received data (OUT packet).
///
/// Note: This method may be called for an endpoint address you didn't allocate, and in that
/// case you should ignore the event.
fn endpoint_out(&mut self, addr: EndpointAddress) {
let _ = addr;
}
/// Called when endpoint with address `addr` has completed transmitting data (IN packet).
///
/// Note: This method may be called for an endpoint address you didn't allocate, and in that
/// case you should ignore the event.
fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
let _ = addr;
}
}
/// Handle for a control IN transfer. When implementing a class, use the methods of this object to
/// response to the transfer with either data or an error (STALL condition). To ignore the request
/// and pass it on to the next class, simply don't call any method.
pub struct ControlIn<'a, 'p, 'r, B: UsbBus> {
pipe: &'p mut ControlPipe<'a, B>,
req: &'r control::Request,
}
impl<'a, 'p, 'r, B: UsbBus> ControlIn<'a, 'p, 'r, B> {
pub(crate) fn new(pipe: &'p mut ControlPipe<'a, B>, req: &'r control::Request) -> Self {
ControlIn { pipe, req }
}
/// Gets the request from the SETUP packet.
pub fn request(&self) -> &control::Request {
self.req
}
/// Accepts the transfer with the supplied buffer.
pub fn accept_with(self, data: &[u8]) -> Result<()> {
self.pipe.accept_in(|buf| {
if data.len() > buf.len() {
return Err(UsbError::BufferOverflow);
}
buf[..data.len()].copy_from_slice(data);
Ok(data.len())
})
}
/// Accepts the transfer with the supplied static buffer.
/// This method is useful when you have a large static descriptor to send as one packet.
pub fn accept_with_static(self, data: &'static [u8]) -> Result<()> {
self.pipe.accept_in_static(data)
}
/// Accepts the transfer with a callback that can write to the internal buffer of the control
/// pipe. Can be used to avoid an extra copy.
pub fn accept(self, f: impl FnOnce(&mut [u8]) -> Result<usize>) -> Result<()> {
self.pipe.accept_in(f)
}
/// Rejects the transfer by stalling the pipe.
pub fn reject(self) -> Result<()> {
self.pipe.reject()
}
}
/// Handle for a control OUT transfer. When implementing a class, use the methods of this object to
/// response to the transfer with an ACT or an error (STALL condition). To ignore the request and
/// pass it on to the next class, simply don't call any method.
pub struct ControlOut<'a, 'p, 'r, B: UsbBus> {
pipe: &'p mut ControlPipe<'a, B>,
req: &'r control::Request,
}
impl<'a, 'p, 'r, B: UsbBus> ControlOut<'a, 'p, 'r, B> {
pub(crate) fn new(pipe: &'p mut ControlPipe<'a, B>, req: &'r control::Request) -> Self {
ControlOut { pipe, req }
}
/// Gets the request from the SETUP packet.
pub fn request(&self) -> &control::Request {
self.req
}
/// Gets the data from the data stage of the request. May be empty if there was no data stage.
pub fn data(&self) -> &[u8] {
self.pipe.data()
}
/// Accepts the transfer by succesfully responding to the status stage.
pub fn accept(self) -> Result<()> {
self.pipe.accept_out()
}
/// Rejects the transfer by stalling the pipe.
pub fn reject(self) -> Result<()> {
self.pipe.reject()
}
}