usb: unify ControlHandler+DeviceStateHandler, route all control requests to all handlers.
- Allows classes to handle vendor requests. - Allows classes to use a single handler for multiple interfaces. - Allows classes to access the other events (previously only `reset` was available).
This commit is contained in:
		@@ -74,7 +74,6 @@ impl<const N: usize> UsbLogger<N> {
 | 
				
			|||||||
            &mut state.config_descriptor,
 | 
					            &mut state.config_descriptor,
 | 
				
			||||||
            &mut state.bos_descriptor,
 | 
					            &mut state.bos_descriptor,
 | 
				
			||||||
            &mut state.control_buf,
 | 
					            &mut state.control_buf,
 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Create classes on the builder.
 | 
					        // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,15 @@ max-interface-count-6 = []
 | 
				
			|||||||
max-interface-count-7 = []
 | 
					max-interface-count-7 = []
 | 
				
			||||||
max-interface-count-8 = []
 | 
					max-interface-count-8 = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					max-handler-count-1 = []
 | 
				
			||||||
 | 
					max-handler-count-2 = []
 | 
				
			||||||
 | 
					max-handler-count-3 = []
 | 
				
			||||||
 | 
					max-handler-count-4 = [] # Default
 | 
				
			||||||
 | 
					max-handler-count-5 = []
 | 
				
			||||||
 | 
					max-handler-count-6 = []
 | 
				
			||||||
 | 
					max-handler-count-7 = []
 | 
				
			||||||
 | 
					max-handler-count-8 = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# END AUTOGENERATED CONFIG FEATURES
 | 
					# END AUTOGENERATED CONFIG FEATURES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ static CONFIGS: &[(&str, usize)] = &[
 | 
				
			|||||||
    // BEGIN AUTOGENERATED CONFIG FEATURES
 | 
					    // BEGIN AUTOGENERATED CONFIG FEATURES
 | 
				
			||||||
    // Generated by gen_config.py. DO NOT EDIT.
 | 
					    // Generated by gen_config.py. DO NOT EDIT.
 | 
				
			||||||
    ("MAX_INTERFACE_COUNT", 4),
 | 
					    ("MAX_INTERFACE_COUNT", 4),
 | 
				
			||||||
 | 
					    ("MAX_HANDLER_COUNT", 4),
 | 
				
			||||||
    // END AUTOGENERATED CONFIG FEATURES
 | 
					    // END AUTOGENERATED CONFIG FEATURES
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@ def feature(name, default, min, max, pow2=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
feature("max_interface_count", default=4, min=1, max=8)
 | 
					feature("max_interface_count", default=4, min=1, max=8)
 | 
				
			||||||
 | 
					feature("max_handler_count", default=4, min=1, max=8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ========= Update Cargo.toml
 | 
					# ========= Update Cargo.toml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
use heapless::Vec;
 | 
					use heapless::Vec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::control::ControlHandler;
 | 
					use crate::config::*;
 | 
				
			||||||
use crate::descriptor::{BosWriter, DescriptorWriter};
 | 
					use crate::descriptor::{BosWriter, DescriptorWriter};
 | 
				
			||||||
use crate::driver::{Driver, Endpoint, EndpointType};
 | 
					use crate::driver::{Driver, Endpoint, EndpointType};
 | 
				
			||||||
#[cfg(feature = "msos-descriptor")]
 | 
					#[cfg(feature = "msos-descriptor")]
 | 
				
			||||||
use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
 | 
					use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
 | 
				
			||||||
use crate::types::*;
 | 
					use crate::types::*;
 | 
				
			||||||
use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
 | 
					use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Copy, Clone)]
 | 
					#[derive(Debug, Copy, Clone)]
 | 
				
			||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
@@ -122,8 +122,8 @@ impl<'a> Config<'a> {
 | 
				
			|||||||
/// [`UsbDevice`] builder.
 | 
					/// [`UsbDevice`] builder.
 | 
				
			||||||
pub struct Builder<'d, D: Driver<'d>> {
 | 
					pub struct Builder<'d, D: Driver<'d>> {
 | 
				
			||||||
    config: Config<'d>,
 | 
					    config: Config<'d>,
 | 
				
			||||||
    handler: Option<&'d dyn DeviceStateHandler>,
 | 
					    handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
 | 
				
			||||||
    interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
 | 
					    interfaces: Vec<Interface, MAX_INTERFACE_COUNT>,
 | 
				
			||||||
    control_buf: &'d mut [u8],
 | 
					    control_buf: &'d mut [u8],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    driver: D,
 | 
					    driver: D,
 | 
				
			||||||
@@ -151,7 +151,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
 | 
				
			|||||||
        bos_descriptor_buf: &'d mut [u8],
 | 
					        bos_descriptor_buf: &'d mut [u8],
 | 
				
			||||||
        #[cfg(feature = "msos-descriptor")] msos_descriptor_buf: &'d mut [u8],
 | 
					        #[cfg(feature = "msos-descriptor")] msos_descriptor_buf: &'d mut [u8],
 | 
				
			||||||
        control_buf: &'d mut [u8],
 | 
					        control_buf: &'d mut [u8],
 | 
				
			||||||
        handler: Option<&'d dyn DeviceStateHandler>,
 | 
					 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        // Magic values specified in USB-IF ECN on IADs.
 | 
					        // Magic values specified in USB-IF ECN on IADs.
 | 
				
			||||||
        if config.composite_with_iads
 | 
					        if config.composite_with_iads
 | 
				
			||||||
@@ -179,9 +178,9 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Builder {
 | 
					        Builder {
 | 
				
			||||||
            driver,
 | 
					            driver,
 | 
				
			||||||
            handler,
 | 
					 | 
				
			||||||
            config,
 | 
					            config,
 | 
				
			||||||
            interfaces: Vec::new(),
 | 
					            interfaces: Vec::new(),
 | 
				
			||||||
 | 
					            handlers: Vec::new(),
 | 
				
			||||||
            control_buf,
 | 
					            control_buf,
 | 
				
			||||||
            next_string_index: STRING_INDEX_CUSTOM_START,
 | 
					            next_string_index: STRING_INDEX_CUSTOM_START,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -205,7 +204,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
 | 
				
			|||||||
        UsbDevice::build(
 | 
					        UsbDevice::build(
 | 
				
			||||||
            self.driver,
 | 
					            self.driver,
 | 
				
			||||||
            self.config,
 | 
					            self.config,
 | 
				
			||||||
            self.handler,
 | 
					            self.handlers,
 | 
				
			||||||
            self.device_descriptor.into_buf(),
 | 
					            self.device_descriptor.into_buf(),
 | 
				
			||||||
            self.config_descriptor.into_buf(),
 | 
					            self.config_descriptor.into_buf(),
 | 
				
			||||||
            self.bos_descriptor.writer.into_buf(),
 | 
					            self.bos_descriptor.writer.into_buf(),
 | 
				
			||||||
@@ -248,6 +247,26 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Add a Handler.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The Handler is called on some USB bus events, and to handle all control requests not already
 | 
				
			||||||
 | 
					    /// handled by the USB stack.
 | 
				
			||||||
 | 
					    pub fn handler(&mut self, handler: &'d mut dyn Handler) {
 | 
				
			||||||
 | 
					        if self.handlers.push(handler).is_err() {
 | 
				
			||||||
 | 
					            panic!(
 | 
				
			||||||
 | 
					                "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}",
 | 
				
			||||||
 | 
					                MAX_HANDLER_COUNT
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Allocates a new string index.
 | 
				
			||||||
 | 
					    pub fn string(&mut self) -> StringIndex {
 | 
				
			||||||
 | 
					        let index = self.next_string_index;
 | 
				
			||||||
 | 
					        self.next_string_index += 1;
 | 
				
			||||||
 | 
					        StringIndex::new(index)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(feature = "msos-descriptor")]
 | 
					    #[cfg(feature = "msos-descriptor")]
 | 
				
			||||||
    /// Add an MS OS 2.0 Descriptor Set.
 | 
					    /// Add an MS OS 2.0 Descriptor Set.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
@@ -301,10 +320,8 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let number = self.builder.interfaces.len() as _;
 | 
					        let number = self.builder.interfaces.len() as _;
 | 
				
			||||||
        let iface = Interface {
 | 
					        let iface = Interface {
 | 
				
			||||||
            handler: None,
 | 
					 | 
				
			||||||
            current_alt_setting: 0,
 | 
					            current_alt_setting: 0,
 | 
				
			||||||
            num_alt_settings: 0,
 | 
					            num_alt_settings: 0,
 | 
				
			||||||
            num_strings: 0,
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.builder.interfaces.push(iface).is_err() {
 | 
					        if self.builder.interfaces.push(iface).is_err() {
 | 
				
			||||||
@@ -350,17 +367,9 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
 | 
				
			|||||||
        self.interface_number
 | 
					        self.interface_number
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn handler(&mut self, handler: &'d mut dyn ControlHandler) {
 | 
					 | 
				
			||||||
        self.builder.interfaces[self.interface_number.0 as usize].handler = Some(handler);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Allocates a new string index.
 | 
					    /// Allocates a new string index.
 | 
				
			||||||
    pub fn string(&mut self) -> StringIndex {
 | 
					    pub fn string(&mut self) -> StringIndex {
 | 
				
			||||||
        let index = self.builder.next_string_index;
 | 
					        self.builder.string()
 | 
				
			||||||
        self.builder.next_string_index += 1;
 | 
					 | 
				
			||||||
        self.builder.interfaces[self.interface_number.0 as usize].num_strings += 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        StringIndex::new(index)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Add an alternate setting to the interface and write its descriptor.
 | 
					    /// Add an alternate setting to the interface and write its descriptor.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,10 +6,10 @@ use core::sync::atomic::{AtomicBool, Ordering};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use embassy_sync::blocking_mutex::CriticalSectionMutex;
 | 
					use embassy_sync::blocking_mutex::CriticalSectionMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::control::{self, ControlHandler, InResponse, OutResponse, Request};
 | 
					use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
 | 
				
			||||||
use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
 | 
					use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
 | 
				
			||||||
use crate::types::*;
 | 
					use crate::types::*;
 | 
				
			||||||
use crate::Builder;
 | 
					use crate::{Builder, Handler};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// This should be used as `device_class` when building the `UsbDevice`.
 | 
					/// This should be used as `device_class` when building the `UsbDevice`.
 | 
				
			||||||
pub const USB_CLASS_CDC: u8 = 0x02;
 | 
					pub const USB_CLASS_CDC: u8 = 0x02;
 | 
				
			||||||
@@ -67,6 +67,7 @@ pub struct CdcAcmClass<'d, D: Driver<'d>> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Control<'a> {
 | 
					struct Control<'a> {
 | 
				
			||||||
 | 
					    comm_if: InterfaceNumber,
 | 
				
			||||||
    shared: &'a ControlShared,
 | 
					    shared: &'a ControlShared,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,7 +99,7 @@ impl<'a> Control<'a> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d> ControlHandler for Control<'d> {
 | 
					impl<'d> Handler for Control<'d> {
 | 
				
			||||||
    fn reset(&mut self) {
 | 
					    fn reset(&mut self) {
 | 
				
			||||||
        let shared = self.shared();
 | 
					        let shared = self.shared();
 | 
				
			||||||
        shared.line_coding.lock(|x| x.set(LineCoding::default()));
 | 
					        shared.line_coding.lock(|x| x.set(LineCoding::default()));
 | 
				
			||||||
@@ -106,12 +107,18 @@ impl<'d> ControlHandler for Control<'d> {
 | 
				
			|||||||
        shared.rts.store(false, Ordering::Relaxed);
 | 
					        shared.rts.store(false, Ordering::Relaxed);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn control_out(&mut self, req: control::Request, data: &[u8]) -> OutResponse {
 | 
					    fn control_out(&mut self, req: control::Request, data: &[u8]) -> Option<OutResponse> {
 | 
				
			||||||
 | 
					        if (req.request_type, req.recipient, req.index)
 | 
				
			||||||
 | 
					            != (RequestType::Class, Recipient::Interface, self.comm_if.0 as u16)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match req.request {
 | 
					        match req.request {
 | 
				
			||||||
            REQ_SEND_ENCAPSULATED_COMMAND => {
 | 
					            REQ_SEND_ENCAPSULATED_COMMAND => {
 | 
				
			||||||
                // We don't actually support encapsulated commands but pretend we do for standards
 | 
					                // We don't actually support encapsulated commands but pretend we do for standards
 | 
				
			||||||
                // compatibility.
 | 
					                // compatibility.
 | 
				
			||||||
                OutResponse::Accepted
 | 
					                Some(OutResponse::Accepted)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            REQ_SET_LINE_CODING if data.len() >= 7 => {
 | 
					            REQ_SET_LINE_CODING if data.len() >= 7 => {
 | 
				
			||||||
                let coding = LineCoding {
 | 
					                let coding = LineCoding {
 | 
				
			||||||
@@ -123,7 +130,7 @@ impl<'d> ControlHandler for Control<'d> {
 | 
				
			|||||||
                self.shared().line_coding.lock(|x| x.set(coding));
 | 
					                self.shared().line_coding.lock(|x| x.set(coding));
 | 
				
			||||||
                debug!("Set line coding to: {:?}", coding);
 | 
					                debug!("Set line coding to: {:?}", coding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                OutResponse::Accepted
 | 
					                Some(OutResponse::Accepted)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            REQ_SET_CONTROL_LINE_STATE => {
 | 
					            REQ_SET_CONTROL_LINE_STATE => {
 | 
				
			||||||
                let dtr = (req.value & 0x0001) != 0;
 | 
					                let dtr = (req.value & 0x0001) != 0;
 | 
				
			||||||
@@ -134,13 +141,19 @@ impl<'d> ControlHandler for Control<'d> {
 | 
				
			|||||||
                shared.rts.store(rts, Ordering::Relaxed);
 | 
					                shared.rts.store(rts, Ordering::Relaxed);
 | 
				
			||||||
                debug!("Set dtr {}, rts {}", dtr, rts);
 | 
					                debug!("Set dtr {}, rts {}", dtr, rts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                OutResponse::Accepted
 | 
					                Some(OutResponse::Accepted)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => OutResponse::Rejected,
 | 
					            _ => Some(OutResponse::Rejected),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
 | 
				
			||||||
 | 
					        if (req.request_type, req.recipient, req.index)
 | 
				
			||||||
 | 
					            != (RequestType::Class, Recipient::Interface, self.comm_if.0 as u16)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match req.request {
 | 
					        match req.request {
 | 
				
			||||||
            // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below.
 | 
					            // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below.
 | 
				
			||||||
            REQ_GET_LINE_CODING if req.length == 7 => {
 | 
					            REQ_GET_LINE_CODING if req.length == 7 => {
 | 
				
			||||||
@@ -151,9 +164,9 @@ impl<'d> ControlHandler for Control<'d> {
 | 
				
			|||||||
                buf[4] = coding.stop_bits as u8;
 | 
					                buf[4] = coding.stop_bits as u8;
 | 
				
			||||||
                buf[5] = coding.parity_type as u8;
 | 
					                buf[5] = coding.parity_type as u8;
 | 
				
			||||||
                buf[6] = coding.data_bits;
 | 
					                buf[6] = coding.data_bits;
 | 
				
			||||||
                InResponse::Accepted(&buf[0..7])
 | 
					                Some(InResponse::Accepted(&buf[0..7]))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => InResponse::Rejected,
 | 
					            _ => Some(InResponse::Rejected),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -162,17 +175,12 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
 | 
				
			|||||||
    /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For
 | 
					    /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For
 | 
				
			||||||
    /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64.
 | 
					    /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64.
 | 
				
			||||||
    pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self {
 | 
					    pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self {
 | 
				
			||||||
        let control = state.control.write(Control { shared: &state.shared });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let control_shared = &state.shared;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert!(builder.control_buf_len() >= 7);
 | 
					        assert!(builder.control_buf_len() >= 7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut func = builder.function(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE);
 | 
					        let mut func = builder.function(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Control interface
 | 
					        // Control interface
 | 
				
			||||||
        let mut iface = func.interface();
 | 
					        let mut iface = func.interface();
 | 
				
			||||||
        iface.handler(control);
 | 
					 | 
				
			||||||
        let comm_if = iface.interface_number();
 | 
					        let comm_if = iface.interface_number();
 | 
				
			||||||
        let data_if = u8::from(comm_if) + 1;
 | 
					        let data_if = u8::from(comm_if) + 1;
 | 
				
			||||||
        let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE, None);
 | 
					        let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE, None);
 | 
				
			||||||
@@ -213,6 +221,16 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
 | 
				
			|||||||
        let read_ep = alt.endpoint_bulk_out(max_packet_size);
 | 
					        let read_ep = alt.endpoint_bulk_out(max_packet_size);
 | 
				
			||||||
        let write_ep = alt.endpoint_bulk_in(max_packet_size);
 | 
					        let write_ep = alt.endpoint_bulk_in(max_packet_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        drop(func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let control = state.control.write(Control {
 | 
				
			||||||
 | 
					            shared: &state.shared,
 | 
				
			||||||
 | 
					            comm_if,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        builder.handler(control);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let control_shared = &state.shared;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CdcAcmClass {
 | 
					        CdcAcmClass {
 | 
				
			||||||
            _comm_ep: comm_ep,
 | 
					            _comm_ep: comm_ep,
 | 
				
			||||||
            _data_if: data_if,
 | 
					            _data_if: data_if,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,10 @@
 | 
				
			|||||||
use core::intrinsics::copy_nonoverlapping;
 | 
					use core::intrinsics::copy_nonoverlapping;
 | 
				
			||||||
use core::mem::{size_of, MaybeUninit};
 | 
					use core::mem::{size_of, MaybeUninit};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::control::{self, ControlHandler, InResponse, OutResponse, Request};
 | 
					use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
 | 
				
			||||||
use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
 | 
					use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
 | 
				
			||||||
use crate::types::*;
 | 
					use crate::types::*;
 | 
				
			||||||
use crate::Builder;
 | 
					use crate::{Builder, Handler};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod embassy_net;
 | 
					pub mod embassy_net;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,8 +117,7 @@ fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Internal state for the CDC-NCM class.
 | 
					/// Internal state for the CDC-NCM class.
 | 
				
			||||||
pub struct State<'a> {
 | 
					pub struct State<'a> {
 | 
				
			||||||
    comm_control: MaybeUninit<CommControl<'a>>,
 | 
					    control: MaybeUninit<Control<'a>>,
 | 
				
			||||||
    data_control: MaybeUninit<DataControl>,
 | 
					 | 
				
			||||||
    shared: ControlShared,
 | 
					    shared: ControlShared,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,8 +125,7 @@ impl<'a> State<'a> {
 | 
				
			|||||||
    /// Create a new `State`.
 | 
					    /// Create a new `State`.
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            comm_control: MaybeUninit::uninit(),
 | 
					            control: MaybeUninit::uninit(),
 | 
				
			||||||
            data_control: MaybeUninit::uninit(),
 | 
					 | 
				
			||||||
            shared: Default::default(),
 | 
					            shared: Default::default(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -144,29 +142,55 @@ impl Default for ControlShared {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CommControl<'a> {
 | 
					struct Control<'a> {
 | 
				
			||||||
    mac_addr_string: StringIndex,
 | 
					    mac_addr_string: StringIndex,
 | 
				
			||||||
    shared: &'a ControlShared,
 | 
					    shared: &'a ControlShared,
 | 
				
			||||||
    mac_addr_str: [u8; 12],
 | 
					    mac_addr_str: [u8; 12],
 | 
				
			||||||
 | 
					    comm_if: InterfaceNumber,
 | 
				
			||||||
 | 
					    data_if: InterfaceNumber,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d> ControlHandler for CommControl<'d> {
 | 
					impl<'d> Handler for Control<'d> {
 | 
				
			||||||
    fn control_out(&mut self, req: control::Request, _data: &[u8]) -> OutResponse {
 | 
					    fn set_alternate_setting(&mut self, iface: InterfaceNumber, alternate_setting: u8) {
 | 
				
			||||||
 | 
					        if iface != self.data_if {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match alternate_setting {
 | 
				
			||||||
 | 
					            ALTERNATE_SETTING_ENABLED => info!("ncm: interface enabled"),
 | 
				
			||||||
 | 
					            ALTERNATE_SETTING_DISABLED => info!("ncm: interface disabled"),
 | 
				
			||||||
 | 
					            _ => unreachable!(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn control_out(&mut self, req: control::Request, _data: &[u8]) -> Option<OutResponse> {
 | 
				
			||||||
 | 
					        if (req.request_type, req.recipient, req.index)
 | 
				
			||||||
 | 
					            != (RequestType::Class, Recipient::Interface, self.comm_if.0 as u16)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match req.request {
 | 
					        match req.request {
 | 
				
			||||||
            REQ_SEND_ENCAPSULATED_COMMAND => {
 | 
					            REQ_SEND_ENCAPSULATED_COMMAND => {
 | 
				
			||||||
                // We don't actually support encapsulated commands but pretend we do for standards
 | 
					                // We don't actually support encapsulated commands but pretend we do for standards
 | 
				
			||||||
                // compatibility.
 | 
					                // compatibility.
 | 
				
			||||||
                OutResponse::Accepted
 | 
					                Some(OutResponse::Accepted)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            REQ_SET_NTB_INPUT_SIZE => {
 | 
					            REQ_SET_NTB_INPUT_SIZE => {
 | 
				
			||||||
                // TODO
 | 
					                // TODO
 | 
				
			||||||
                OutResponse::Accepted
 | 
					                Some(OutResponse::Accepted)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => OutResponse::Rejected,
 | 
					            _ => Some(OutResponse::Rejected),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
 | 
				
			||||||
 | 
					        if (req.request_type, req.recipient, req.index)
 | 
				
			||||||
 | 
					            != (RequestType::Class, Recipient::Interface, self.comm_if.0 as u16)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match req.request {
 | 
					        match req.request {
 | 
				
			||||||
            REQ_GET_NTB_PARAMETERS => {
 | 
					            REQ_GET_NTB_PARAMETERS => {
 | 
				
			||||||
                let res = NtbParameters {
 | 
					                let res = NtbParameters {
 | 
				
			||||||
@@ -187,9 +211,9 @@ impl<'d> ControlHandler for CommControl<'d> {
 | 
				
			|||||||
                        max_datagram_count: 1, // We only decode 1 packet per NTB
 | 
					                        max_datagram_count: 1, // We only decode 1 packet per NTB
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                InResponse::Accepted(byteify(buf, res))
 | 
					                Some(InResponse::Accepted(byteify(buf, res)))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => InResponse::Rejected,
 | 
					            _ => Some(InResponse::Rejected),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -214,18 +238,6 @@ impl<'d> ControlHandler for CommControl<'d> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct DataControl {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ControlHandler for DataControl {
 | 
					 | 
				
			||||||
    fn set_alternate_setting(&mut self, alternate_setting: u8) {
 | 
					 | 
				
			||||||
        match alternate_setting {
 | 
					 | 
				
			||||||
            ALTERNATE_SETTING_ENABLED => info!("ncm: interface enabled"),
 | 
					 | 
				
			||||||
            ALTERNATE_SETTING_DISABLED => info!("ncm: interface disabled"),
 | 
					 | 
				
			||||||
            _ => unreachable!(),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// CDC-NCM class
 | 
					/// CDC-NCM class
 | 
				
			||||||
pub struct CdcNcmClass<'d, D: Driver<'d>> {
 | 
					pub struct CdcNcmClass<'d, D: Driver<'d>> {
 | 
				
			||||||
    _comm_if: InterfaceNumber,
 | 
					    _comm_if: InterfaceNumber,
 | 
				
			||||||
@@ -253,11 +265,6 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
 | 
				
			|||||||
        // Control interface
 | 
					        // Control interface
 | 
				
			||||||
        let mut iface = func.interface();
 | 
					        let mut iface = func.interface();
 | 
				
			||||||
        let mac_addr_string = iface.string();
 | 
					        let mac_addr_string = iface.string();
 | 
				
			||||||
        iface.handler(state.comm_control.write(CommControl {
 | 
					 | 
				
			||||||
            mac_addr_string,
 | 
					 | 
				
			||||||
            shared: &state.shared,
 | 
					 | 
				
			||||||
            mac_addr_str: [0; 12],
 | 
					 | 
				
			||||||
        }));
 | 
					 | 
				
			||||||
        let comm_if = iface.interface_number();
 | 
					        let comm_if = iface.interface_number();
 | 
				
			||||||
        let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_NCM, CDC_PROTOCOL_NONE, None);
 | 
					        let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_NCM, CDC_PROTOCOL_NONE, None);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -307,13 +314,23 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Data interface
 | 
					        // Data interface
 | 
				
			||||||
        let mut iface = func.interface();
 | 
					        let mut iface = func.interface();
 | 
				
			||||||
        iface.handler(state.data_control.write(DataControl {}));
 | 
					 | 
				
			||||||
        let data_if = iface.interface_number();
 | 
					        let data_if = iface.interface_number();
 | 
				
			||||||
        let _alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None);
 | 
					        let _alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None);
 | 
				
			||||||
        let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None);
 | 
					        let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None);
 | 
				
			||||||
        let read_ep = alt.endpoint_bulk_out(max_packet_size);
 | 
					        let read_ep = alt.endpoint_bulk_out(max_packet_size);
 | 
				
			||||||
        let write_ep = alt.endpoint_bulk_in(max_packet_size);
 | 
					        let write_ep = alt.endpoint_bulk_in(max_packet_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        drop(func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let control = state.control.write(Control {
 | 
				
			||||||
 | 
					            mac_addr_string,
 | 
				
			||||||
 | 
					            shared: &state.shared,
 | 
				
			||||||
 | 
					            mac_addr_str: [0; 12],
 | 
				
			||||||
 | 
					            comm_if,
 | 
				
			||||||
 | 
					            data_if,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        builder.handler(control);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CdcNcmClass {
 | 
					        CdcNcmClass {
 | 
				
			||||||
            _comm_if: comm_if,
 | 
					            _comm_if: comm_if,
 | 
				
			||||||
            comm_ep,
 | 
					            comm_ep,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,9 +9,10 @@ use ssmarshal::serialize;
 | 
				
			|||||||
#[cfg(feature = "usbd-hid")]
 | 
					#[cfg(feature = "usbd-hid")]
 | 
				
			||||||
use usbd_hid::descriptor::AsInputReport;
 | 
					use usbd_hid::descriptor::AsInputReport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::control::{ControlHandler, InResponse, OutResponse, Request, RequestType};
 | 
					use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType};
 | 
				
			||||||
use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
 | 
					use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
 | 
				
			||||||
use crate::Builder;
 | 
					use crate::types::InterfaceNumber;
 | 
				
			||||||
 | 
					use crate::{Builder, Handler};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const USB_CLASS_HID: u8 = 0x03;
 | 
					const USB_CLASS_HID: u8 = 0x03;
 | 
				
			||||||
const USB_SUBCLASS_NONE: u8 = 0x00;
 | 
					const USB_SUBCLASS_NONE: u8 = 0x00;
 | 
				
			||||||
@@ -100,17 +101,11 @@ fn build<'d, D: Driver<'d>>(
 | 
				
			|||||||
    config: Config<'d>,
 | 
					    config: Config<'d>,
 | 
				
			||||||
    with_out_endpoint: bool,
 | 
					    with_out_endpoint: bool,
 | 
				
			||||||
) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) {
 | 
					) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) {
 | 
				
			||||||
    let control = state.control.write(Control::new(
 | 
					 | 
				
			||||||
        config.report_descriptor,
 | 
					 | 
				
			||||||
        config.request_handler,
 | 
					 | 
				
			||||||
        &state.out_report_offset,
 | 
					 | 
				
			||||||
    ));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let len = config.report_descriptor.len();
 | 
					    let len = config.report_descriptor.len();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE);
 | 
					    let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE);
 | 
				
			||||||
    let mut iface = func.interface();
 | 
					    let mut iface = func.interface();
 | 
				
			||||||
    iface.handler(control);
 | 
					    let if_num = iface.interface_number();
 | 
				
			||||||
    let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE, None);
 | 
					    let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE, None);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // HID descriptor
 | 
					    // HID descriptor
 | 
				
			||||||
@@ -139,6 +134,16 @@ fn build<'d, D: Driver<'d>>(
 | 
				
			|||||||
        None
 | 
					        None
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    drop(func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let control = state.control.write(Control::new(
 | 
				
			||||||
 | 
					        if_num,
 | 
				
			||||||
 | 
					        config.report_descriptor,
 | 
				
			||||||
 | 
					        config.request_handler,
 | 
				
			||||||
 | 
					        &state.out_report_offset,
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					    builder.handler(control);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (ep_out, ep_in, &state.out_report_offset)
 | 
					    (ep_out, ep_in, &state.out_report_offset)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -400,6 +405,7 @@ pub trait RequestHandler {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Control<'d> {
 | 
					struct Control<'d> {
 | 
				
			||||||
 | 
					    if_num: InterfaceNumber,
 | 
				
			||||||
    report_descriptor: &'d [u8],
 | 
					    report_descriptor: &'d [u8],
 | 
				
			||||||
    request_handler: Option<&'d dyn RequestHandler>,
 | 
					    request_handler: Option<&'d dyn RequestHandler>,
 | 
				
			||||||
    out_report_offset: &'d AtomicUsize,
 | 
					    out_report_offset: &'d AtomicUsize,
 | 
				
			||||||
@@ -408,11 +414,13 @@ struct Control<'d> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<'d> Control<'d> {
 | 
					impl<'d> Control<'d> {
 | 
				
			||||||
    fn new(
 | 
					    fn new(
 | 
				
			||||||
 | 
					        if_num: InterfaceNumber,
 | 
				
			||||||
        report_descriptor: &'d [u8],
 | 
					        report_descriptor: &'d [u8],
 | 
				
			||||||
        request_handler: Option<&'d dyn RequestHandler>,
 | 
					        request_handler: Option<&'d dyn RequestHandler>,
 | 
				
			||||||
        out_report_offset: &'d AtomicUsize,
 | 
					        out_report_offset: &'d AtomicUsize,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        Control {
 | 
					        Control {
 | 
				
			||||||
 | 
					            if_num,
 | 
				
			||||||
            report_descriptor,
 | 
					            report_descriptor,
 | 
				
			||||||
            request_handler,
 | 
					            request_handler,
 | 
				
			||||||
            out_report_offset,
 | 
					            out_report_offset,
 | 
				
			||||||
@@ -438,88 +446,100 @@ impl<'d> Control<'d> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d> ControlHandler for Control<'d> {
 | 
					impl<'d> Handler for Control<'d> {
 | 
				
			||||||
    fn reset(&mut self) {
 | 
					    fn reset(&mut self) {
 | 
				
			||||||
        self.out_report_offset.store(0, Ordering::Release);
 | 
					        self.out_report_offset.store(0, Ordering::Release);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn get_descriptor<'a>(&'a mut self, req: Request, _buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					    fn control_out(&mut self, req: Request, data: &[u8]) -> Option<OutResponse> {
 | 
				
			||||||
        match (req.value >> 8) as u8 {
 | 
					        if (req.request_type, req.recipient, req.index)
 | 
				
			||||||
            HID_DESC_DESCTYPE_HID_REPORT => InResponse::Accepted(self.report_descriptor),
 | 
					            != (RequestType::Class, Recipient::Interface, self.if_num.0 as u16)
 | 
				
			||||||
            HID_DESC_DESCTYPE_HID => InResponse::Accepted(&self.hid_descriptor),
 | 
					        {
 | 
				
			||||||
            _ => InResponse::Rejected,
 | 
					            return None;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
 | 
					 | 
				
			||||||
        trace!("HID control_out {:?} {=[u8]:x}", req, data);
 | 
					        trace!("HID control_out {:?} {=[u8]:x}", req, data);
 | 
				
			||||||
        if let RequestType::Class = req.request_type {
 | 
					 | 
				
			||||||
            match req.request {
 | 
					 | 
				
			||||||
                HID_REQ_SET_IDLE => {
 | 
					 | 
				
			||||||
                    if let Some(handler) = self.request_handler {
 | 
					 | 
				
			||||||
                        let id = req.value as u8;
 | 
					 | 
				
			||||||
                        let id = (id != 0).then(|| ReportId::In(id));
 | 
					 | 
				
			||||||
                        let dur = u32::from(req.value >> 8);
 | 
					 | 
				
			||||||
                        let dur = if dur == 0 { u32::MAX } else { 4 * dur };
 | 
					 | 
				
			||||||
                        handler.set_idle_ms(id, dur);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    OutResponse::Accepted
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                HID_REQ_SET_REPORT => match (ReportId::try_from(req.value), self.request_handler) {
 | 
					 | 
				
			||||||
                    (Ok(id), Some(handler)) => handler.set_report(id, data),
 | 
					 | 
				
			||||||
                    _ => OutResponse::Rejected,
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                HID_REQ_SET_PROTOCOL => {
 | 
					 | 
				
			||||||
                    if req.value == 1 {
 | 
					 | 
				
			||||||
                        OutResponse::Accepted
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        warn!("HID Boot Protocol is unsupported.");
 | 
					 | 
				
			||||||
                        OutResponse::Rejected // UNSUPPORTED: Boot Protocol
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                _ => OutResponse::Rejected,
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            OutResponse::Rejected // UNSUPPORTED: SET_DESCRIPTOR
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					 | 
				
			||||||
        trace!("HID control_in {:?}", req);
 | 
					 | 
				
			||||||
        match req.request {
 | 
					        match req.request {
 | 
				
			||||||
            HID_REQ_GET_REPORT => {
 | 
					            HID_REQ_SET_IDLE => {
 | 
				
			||||||
                let size = match ReportId::try_from(req.value) {
 | 
					 | 
				
			||||||
                    Ok(id) => self.request_handler.and_then(|x| x.get_report(id, buf)),
 | 
					 | 
				
			||||||
                    Err(_) => None,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if let Some(size) = size {
 | 
					 | 
				
			||||||
                    InResponse::Accepted(&buf[0..size])
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    InResponse::Rejected
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            HID_REQ_GET_IDLE => {
 | 
					 | 
				
			||||||
                if let Some(handler) = self.request_handler {
 | 
					                if let Some(handler) = self.request_handler {
 | 
				
			||||||
                    let id = req.value as u8;
 | 
					                    let id = req.value as u8;
 | 
				
			||||||
                    let id = (id != 0).then(|| ReportId::In(id));
 | 
					                    let id = (id != 0).then(|| ReportId::In(id));
 | 
				
			||||||
                    if let Some(dur) = handler.get_idle_ms(id) {
 | 
					                    let dur = u32::from(req.value >> 8);
 | 
				
			||||||
                        let dur = u8::try_from(dur / 4).unwrap_or(0);
 | 
					                    let dur = if dur == 0 { u32::MAX } else { 4 * dur };
 | 
				
			||||||
                        buf[0] = dur;
 | 
					                    handler.set_idle_ms(id, dur);
 | 
				
			||||||
                        InResponse::Accepted(&buf[0..1])
 | 
					                }
 | 
				
			||||||
                    } else {
 | 
					                Some(OutResponse::Accepted)
 | 
				
			||||||
                        InResponse::Rejected
 | 
					            }
 | 
				
			||||||
                    }
 | 
					            HID_REQ_SET_REPORT => match (ReportId::try_from(req.value), self.request_handler) {
 | 
				
			||||||
 | 
					                (Ok(id), Some(handler)) => Some(handler.set_report(id, data)),
 | 
				
			||||||
 | 
					                _ => Some(OutResponse::Rejected),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            HID_REQ_SET_PROTOCOL => {
 | 
				
			||||||
 | 
					                if req.value == 1 {
 | 
				
			||||||
 | 
					                    Some(OutResponse::Accepted)
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    InResponse::Rejected
 | 
					                    warn!("HID Boot Protocol is unsupported.");
 | 
				
			||||||
 | 
					                    Some(OutResponse::Rejected) // UNSUPPORTED: Boot Protocol
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            HID_REQ_GET_PROTOCOL => {
 | 
					            _ => Some(OutResponse::Rejected),
 | 
				
			||||||
                // UNSUPPORTED: Boot Protocol
 | 
					        }
 | 
				
			||||||
                buf[0] = 1;
 | 
					    }
 | 
				
			||||||
                InResponse::Accepted(&buf[0..1])
 | 
					
 | 
				
			||||||
 | 
					    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
 | 
				
			||||||
 | 
					        if req.index != self.if_num.0 as u16 {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match (req.request_type, req.recipient) {
 | 
				
			||||||
 | 
					            (RequestType::Standard, Recipient::Interface) => match req.request {
 | 
				
			||||||
 | 
					                Request::GET_DESCRIPTOR => match (req.value >> 8) as u8 {
 | 
				
			||||||
 | 
					                    HID_DESC_DESCTYPE_HID_REPORT => Some(InResponse::Accepted(self.report_descriptor)),
 | 
				
			||||||
 | 
					                    HID_DESC_DESCTYPE_HID => Some(InResponse::Accepted(&self.hid_descriptor)),
 | 
				
			||||||
 | 
					                    _ => Some(InResponse::Rejected),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _ => Some(InResponse::Rejected),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            (RequestType::Class, Recipient::Interface) => {
 | 
				
			||||||
 | 
					                trace!("HID control_in {:?}", req);
 | 
				
			||||||
 | 
					                match req.request {
 | 
				
			||||||
 | 
					                    HID_REQ_GET_REPORT => {
 | 
				
			||||||
 | 
					                        let size = match ReportId::try_from(req.value) {
 | 
				
			||||||
 | 
					                            Ok(id) => self.request_handler.and_then(|x| x.get_report(id, buf)),
 | 
				
			||||||
 | 
					                            Err(_) => None,
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if let Some(size) = size {
 | 
				
			||||||
 | 
					                            Some(InResponse::Accepted(&buf[0..size]))
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            Some(InResponse::Rejected)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    HID_REQ_GET_IDLE => {
 | 
				
			||||||
 | 
					                        if let Some(handler) = self.request_handler {
 | 
				
			||||||
 | 
					                            let id = req.value as u8;
 | 
				
			||||||
 | 
					                            let id = (id != 0).then(|| ReportId::In(id));
 | 
				
			||||||
 | 
					                            if let Some(dur) = handler.get_idle_ms(id) {
 | 
				
			||||||
 | 
					                                let dur = u8::try_from(dur / 4).unwrap_or(0);
 | 
				
			||||||
 | 
					                                buf[0] = dur;
 | 
				
			||||||
 | 
					                                Some(InResponse::Accepted(&buf[0..1]))
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                Some(InResponse::Rejected)
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            Some(InResponse::Rejected)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    HID_REQ_GET_PROTOCOL => {
 | 
				
			||||||
 | 
					                        // UNSUPPORTED: Boot Protocol
 | 
				
			||||||
 | 
					                        buf[0] = 1;
 | 
				
			||||||
 | 
					                        Some(InResponse::Accepted(&buf[0..1]))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    _ => Some(InResponse::Rejected),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => InResponse::Rejected,
 | 
					            _ => None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@
 | 
				
			|||||||
use core::mem;
 | 
					use core::mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::driver::Direction;
 | 
					use crate::driver::Direction;
 | 
				
			||||||
use crate::types::StringIndex;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Control request type.
 | 
					/// Control request type.
 | 
				
			||||||
#[repr(u8)]
 | 
					#[repr(u8)]
 | 
				
			||||||
@@ -145,60 +144,3 @@ pub enum InResponse<'a> {
 | 
				
			|||||||
    /// The request was rejected.
 | 
					    /// The request was rejected.
 | 
				
			||||||
    Rejected,
 | 
					    Rejected,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Handler for control requests.
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// All methods are optional callbacks that will be called by
 | 
					 | 
				
			||||||
/// [`UsbDevice::run()`](crate::UsbDevice::run)
 | 
					 | 
				
			||||||
pub trait ControlHandler {
 | 
					 | 
				
			||||||
    /// Called after a USB reset after the bus reset sequence is complete.
 | 
					 | 
				
			||||||
    fn reset(&mut self) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Called when a "set alternate setting" control request is done on the interface.
 | 
					 | 
				
			||||||
    fn set_alternate_setting(&mut self, alternate_setting: u8) {
 | 
					 | 
				
			||||||
        let _ = alternate_setting;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Called when a control request is received with direction HostToDevice.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Arguments
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// * `req` - The request from the SETUP packet.
 | 
					 | 
				
			||||||
    /// * `data` - The data from the request.
 | 
					 | 
				
			||||||
    fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
 | 
					 | 
				
			||||||
        let _ = (req, data);
 | 
					 | 
				
			||||||
        OutResponse::Rejected
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Called when a control request is received with direction DeviceToHost.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// You should write the response somewhere (usually to `buf`, but you may use another buffer
 | 
					 | 
				
			||||||
    /// owned by yourself, or a static buffer), then return `InResponse::Accepted(data)`.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Arguments
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// * `req` - The request from the SETUP packet.
 | 
					 | 
				
			||||||
    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					 | 
				
			||||||
        let _ = (req, buf);
 | 
					 | 
				
			||||||
        InResponse::Rejected
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Called when a GET DESCRIPTOR control request is received on the interface.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// You should write the response somewhere (usually to `buf`, but you may use another buffer
 | 
					 | 
				
			||||||
    /// owned by yourself, or a static buffer), then return `InResponse::Accepted(data)`.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Arguments
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// * `req` - The request from the SETUP packet.
 | 
					 | 
				
			||||||
    fn get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					 | 
				
			||||||
        let _ = (req, buf);
 | 
					 | 
				
			||||||
        InResponse::Rejected
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Called when a GET_DESCRIPTOR STRING control request is received.
 | 
					 | 
				
			||||||
    fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&str> {
 | 
					 | 
				
			||||||
        let _ = (index, lang_id);
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
use crate::descriptor::descriptor_type;
 | 
					use crate::descriptor::descriptor_type;
 | 
				
			||||||
use crate::driver::EndpointAddress;
 | 
					use crate::driver::EndpointAddress;
 | 
				
			||||||
 | 
					use crate::types::InterfaceNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 | 
					#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 | 
				
			||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
@@ -75,7 +76,7 @@ impl<'a, 'b> Iterator for DescriptorIter<'a, 'b> {
 | 
				
			|||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
pub struct EndpointInfo {
 | 
					pub struct EndpointInfo {
 | 
				
			||||||
    pub configuration: u8,
 | 
					    pub configuration: u8,
 | 
				
			||||||
    pub interface: u8,
 | 
					    pub interface: InterfaceNumber,
 | 
				
			||||||
    pub interface_alt: u8,
 | 
					    pub interface_alt: u8,
 | 
				
			||||||
    pub ep_address: EndpointAddress,
 | 
					    pub ep_address: EndpointAddress,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -83,7 +84,7 @@ pub struct EndpointInfo {
 | 
				
			|||||||
pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result<(), ReadError> {
 | 
					pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result<(), ReadError> {
 | 
				
			||||||
    let mut ep = EndpointInfo {
 | 
					    let mut ep = EndpointInfo {
 | 
				
			||||||
        configuration: 0,
 | 
					        configuration: 0,
 | 
				
			||||||
        interface: 0,
 | 
					        interface: InterfaceNumber(0),
 | 
				
			||||||
        interface_alt: 0,
 | 
					        interface_alt: 0,
 | 
				
			||||||
        ep_address: EndpointAddress::from(0),
 | 
					        ep_address: EndpointAddress::from(0),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -96,7 +97,7 @@ pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result<
 | 
				
			|||||||
                ep.configuration = r.read_u8()?;
 | 
					                ep.configuration = r.read_u8()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            descriptor_type::INTERFACE => {
 | 
					            descriptor_type::INTERFACE => {
 | 
				
			||||||
                ep.interface = r.read_u8()?;
 | 
					                ep.interface = InterfaceNumber(r.read_u8()?);
 | 
				
			||||||
                ep.interface_alt = r.read_u8()?;
 | 
					                ep.interface_alt = r.read_u8()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            descriptor_type::ENDPOINT => {
 | 
					            descriptor_type::ENDPOINT => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,32 +82,87 @@ const STRING_INDEX_PRODUCT: u8 = 2;
 | 
				
			|||||||
const STRING_INDEX_SERIAL_NUMBER: u8 = 3;
 | 
					const STRING_INDEX_SERIAL_NUMBER: u8 = 3;
 | 
				
			||||||
const STRING_INDEX_CUSTOM_START: u8 = 4;
 | 
					const STRING_INDEX_CUSTOM_START: u8 = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A handler trait for changes in the device state of the [UsbDevice].
 | 
					/// Handler for device events and control requests.
 | 
				
			||||||
pub trait DeviceStateHandler {
 | 
					///
 | 
				
			||||||
 | 
					/// All methods are optional callbacks that will be called by
 | 
				
			||||||
 | 
					/// [`UsbDevice::run()`](crate::UsbDevice::run)
 | 
				
			||||||
 | 
					pub trait Handler {
 | 
				
			||||||
    /// Called when the USB device has been enabled or disabled.
 | 
					    /// Called when the USB device has been enabled or disabled.
 | 
				
			||||||
    fn enabled(&self, _enabled: bool) {}
 | 
					    fn enabled(&mut self, _enabled: bool) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when the host resets the device.
 | 
					    /// Called after a USB reset after the bus reset sequence is complete.
 | 
				
			||||||
    fn reset(&self) {}
 | 
					    fn reset(&mut self) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when the host has set the address of the device to `addr`.
 | 
					    /// Called when the host has set the address of the device to `addr`.
 | 
				
			||||||
    fn addressed(&self, _addr: u8) {}
 | 
					    fn addressed(&mut self, _addr: u8) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when the host has enabled or disabled the configuration of the device.
 | 
					    /// Called when the host has enabled or disabled the configuration of the device.
 | 
				
			||||||
    fn configured(&self, _configured: bool) {}
 | 
					    fn configured(&mut self, _configured: bool) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when the bus has entered or exited the suspend state.
 | 
					    /// Called when the bus has entered or exited the suspend state.
 | 
				
			||||||
    fn suspended(&self, _suspended: bool) {}
 | 
					    fn suspended(&mut self, _suspended: bool) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when remote wakeup feature is enabled or disabled.
 | 
					    /// Called when remote wakeup feature is enabled or disabled.
 | 
				
			||||||
    fn remote_wakeup_enabled(&self, _enabled: bool) {}
 | 
					    fn remote_wakeup_enabled(&mut self, _enabled: bool) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when a "set alternate setting" control request is done on the interface.
 | 
				
			||||||
 | 
					    fn set_alternate_setting(&mut self, iface: InterfaceNumber, alternate_setting: u8) {
 | 
				
			||||||
 | 
					        let _ = iface;
 | 
				
			||||||
 | 
					        let _ = alternate_setting;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when a control request is received with direction HostToDevice.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Arguments
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// * `req` - The request from the SETUP packet.
 | 
				
			||||||
 | 
					    /// * `data` - The data from the request.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Returns
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// If you didn't handle this request (for example if it's for the wrong interface), return
 | 
				
			||||||
 | 
					    /// `None`. In this case, the the USB stack will continue calling the other handlers, to see
 | 
				
			||||||
 | 
					    /// if another handles it.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// If you did, return `Some` with either `Accepted` or `Rejected`. This will make the USB stack
 | 
				
			||||||
 | 
					    /// respond to the control request, and stop calling other handlers.
 | 
				
			||||||
 | 
					    fn control_out(&mut self, req: Request, data: &[u8]) -> Option<OutResponse> {
 | 
				
			||||||
 | 
					        let _ = (req, data);
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when a control request is received with direction DeviceToHost.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// You should write the response somewhere (usually to `buf`, but you may use another buffer
 | 
				
			||||||
 | 
					    /// owned by yourself, or a static buffer), then return `InResponse::Accepted(data)`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Arguments
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// * `req` - The request from the SETUP packet.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Returns
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// If you didn't handle this request (for example if it's for the wrong interface), return
 | 
				
			||||||
 | 
					    /// `None`. In this case, the the USB stack will continue calling the other handlers, to see
 | 
				
			||||||
 | 
					    /// if another handles it.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// If you did, return `Some` with either `Accepted` or `Rejected`. This will make the USB stack
 | 
				
			||||||
 | 
					    /// respond to the control request, and stop calling other handlers.
 | 
				
			||||||
 | 
					    fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
 | 
				
			||||||
 | 
					        let _ = (req, buf);
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when a GET_DESCRIPTOR STRING control request is received.
 | 
				
			||||||
 | 
					    fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&str> {
 | 
				
			||||||
 | 
					        let _ = (index, lang_id);
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Interface<'d> {
 | 
					struct Interface {
 | 
				
			||||||
    handler: Option<&'d mut dyn ControlHandler>,
 | 
					 | 
				
			||||||
    current_alt_setting: u8,
 | 
					    current_alt_setting: u8,
 | 
				
			||||||
    num_alt_settings: u8,
 | 
					    num_alt_settings: u8,
 | 
				
			||||||
    num_strings: u8,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Main struct for the USB device stack.
 | 
					/// Main struct for the USB device stack.
 | 
				
			||||||
@@ -119,7 +174,6 @@ pub struct UsbDevice<'d, D: Driver<'d>> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct Inner<'d, D: Driver<'d>> {
 | 
					struct Inner<'d, D: Driver<'d>> {
 | 
				
			||||||
    bus: D::Bus,
 | 
					    bus: D::Bus,
 | 
				
			||||||
    handler: Option<&'d dyn DeviceStateHandler>,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config: Config<'d>,
 | 
					    config: Config<'d>,
 | 
				
			||||||
    device_descriptor: &'d [u8],
 | 
					    device_descriptor: &'d [u8],
 | 
				
			||||||
@@ -138,7 +192,9 @@ struct Inner<'d, D: Driver<'d>> {
 | 
				
			|||||||
    /// instead of regular `accept()`.
 | 
					    /// instead of regular `accept()`.
 | 
				
			||||||
    set_address_pending: bool,
 | 
					    set_address_pending: bool,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
 | 
					    interfaces: Vec<Interface, MAX_INTERFACE_COUNT>,
 | 
				
			||||||
 | 
					    handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(feature = "msos-descriptor")]
 | 
					    #[cfg(feature = "msos-descriptor")]
 | 
				
			||||||
    msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
 | 
					    msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -147,11 +203,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
    pub(crate) fn build(
 | 
					    pub(crate) fn build(
 | 
				
			||||||
        driver: D,
 | 
					        driver: D,
 | 
				
			||||||
        config: Config<'d>,
 | 
					        config: Config<'d>,
 | 
				
			||||||
        handler: Option<&'d dyn DeviceStateHandler>,
 | 
					        handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
 | 
				
			||||||
        device_descriptor: &'d [u8],
 | 
					        device_descriptor: &'d [u8],
 | 
				
			||||||
        config_descriptor: &'d [u8],
 | 
					        config_descriptor: &'d [u8],
 | 
				
			||||||
        bos_descriptor: &'d [u8],
 | 
					        bos_descriptor: &'d [u8],
 | 
				
			||||||
        interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
 | 
					        interfaces: Vec<Interface, MAX_INTERFACE_COUNT>,
 | 
				
			||||||
        control_buf: &'d mut [u8],
 | 
					        control_buf: &'d mut [u8],
 | 
				
			||||||
        #[cfg(feature = "msos-descriptor")] msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
 | 
					        #[cfg(feature = "msos-descriptor")] msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
 | 
				
			||||||
    ) -> UsbDevice<'d, D> {
 | 
					    ) -> UsbDevice<'d, D> {
 | 
				
			||||||
@@ -165,7 +221,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
            inner: Inner {
 | 
					            inner: Inner {
 | 
				
			||||||
                bus,
 | 
					                bus,
 | 
				
			||||||
                config,
 | 
					                config,
 | 
				
			||||||
                handler,
 | 
					 | 
				
			||||||
                device_descriptor,
 | 
					                device_descriptor,
 | 
				
			||||||
                config_descriptor,
 | 
					                config_descriptor,
 | 
				
			||||||
                bos_descriptor,
 | 
					                bos_descriptor,
 | 
				
			||||||
@@ -177,6 +232,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
                address: 0,
 | 
					                address: 0,
 | 
				
			||||||
                set_address_pending: false,
 | 
					                set_address_pending: false,
 | 
				
			||||||
                interfaces,
 | 
					                interfaces,
 | 
				
			||||||
 | 
					                handlers,
 | 
				
			||||||
                #[cfg(feature = "msos-descriptor")]
 | 
					                #[cfg(feature = "msos-descriptor")]
 | 
				
			||||||
                msos_descriptor,
 | 
					                msos_descriptor,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
@@ -221,7 +277,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
            self.inner.suspended = false;
 | 
					            self.inner.suspended = false;
 | 
				
			||||||
            self.inner.remote_wakeup_enabled = false;
 | 
					            self.inner.remote_wakeup_enabled = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if let Some(h) = &self.inner.handler {
 | 
					            for h in &mut self.inner.handlers {
 | 
				
			||||||
                h.enabled(false);
 | 
					                h.enabled(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -250,7 +306,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
            self.inner.bus.remote_wakeup().await?;
 | 
					            self.inner.bus.remote_wakeup().await?;
 | 
				
			||||||
            self.inner.suspended = false;
 | 
					            self.inner.suspended = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if let Some(h) = &self.inner.handler {
 | 
					            for h in &mut self.inner.handlers {
 | 
				
			||||||
                h.suspended(false);
 | 
					                h.suspended(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -361,29 +417,29 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                self.remote_wakeup_enabled = false;
 | 
					                self.remote_wakeup_enabled = false;
 | 
				
			||||||
                self.address = 0;
 | 
					                self.address = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for iface in self.interfaces.iter_mut() {
 | 
					                for h in &mut self.handlers {
 | 
				
			||||||
                    iface.current_alt_setting = 0;
 | 
					                    h.reset();
 | 
				
			||||||
                    if let Some(h) = &mut iface.handler {
 | 
					 | 
				
			||||||
                        h.reset();
 | 
					 | 
				
			||||||
                        h.set_alternate_setting(0);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Some(h) = &self.handler {
 | 
					                for (i, iface) in self.interfaces.iter_mut().enumerate() {
 | 
				
			||||||
                    h.reset();
 | 
					                    iface.current_alt_setting = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for h in &mut self.handlers {
 | 
				
			||||||
 | 
					                        h.set_alternate_setting(InterfaceNumber::new(i as _), 0);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Event::Resume => {
 | 
					            Event::Resume => {
 | 
				
			||||||
                trace!("usb: resume");
 | 
					                trace!("usb: resume");
 | 
				
			||||||
                self.suspended = false;
 | 
					                self.suspended = false;
 | 
				
			||||||
                if let Some(h) = &self.handler {
 | 
					                for h in &mut self.handlers {
 | 
				
			||||||
                    h.suspended(false);
 | 
					                    h.suspended(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Event::Suspend => {
 | 
					            Event::Suspend => {
 | 
				
			||||||
                trace!("usb: suspend");
 | 
					                trace!("usb: suspend");
 | 
				
			||||||
                self.suspended = true;
 | 
					                self.suspended = true;
 | 
				
			||||||
                if let Some(h) = &self.handler {
 | 
					                for h in &mut self.handlers {
 | 
				
			||||||
                    h.suspended(true);
 | 
					                    h.suspended(true);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -392,7 +448,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                self.bus.enable().await;
 | 
					                self.bus.enable().await;
 | 
				
			||||||
                self.device_state = UsbDeviceState::Default;
 | 
					                self.device_state = UsbDeviceState::Default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Some(h) = &self.handler {
 | 
					                for h in &mut self.handlers {
 | 
				
			||||||
                    h.enabled(true);
 | 
					                    h.enabled(true);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -401,7 +457,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                self.bus.disable().await;
 | 
					                self.bus.disable().await;
 | 
				
			||||||
                self.device_state = UsbDeviceState::Unpowered;
 | 
					                self.device_state = UsbDeviceState::Unpowered;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Some(h) = &self.handler {
 | 
					                for h in &mut self.handlers {
 | 
				
			||||||
                    h.enabled(false);
 | 
					                    h.enabled(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -416,14 +472,14 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
            (RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
 | 
					            (RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
 | 
				
			||||||
                (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
 | 
					                (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
 | 
				
			||||||
                    self.remote_wakeup_enabled = false;
 | 
					                    self.remote_wakeup_enabled = false;
 | 
				
			||||||
                    if let Some(h) = &self.handler {
 | 
					                    for h in &mut self.handlers {
 | 
				
			||||||
                        h.remote_wakeup_enabled(false);
 | 
					                        h.remote_wakeup_enabled(false);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    OutResponse::Accepted
 | 
					                    OutResponse::Accepted
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
 | 
					                (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
 | 
				
			||||||
                    self.remote_wakeup_enabled = true;
 | 
					                    self.remote_wakeup_enabled = true;
 | 
				
			||||||
                    if let Some(h) = &self.handler {
 | 
					                    for h in &mut self.handlers {
 | 
				
			||||||
                        h.remote_wakeup_enabled(true);
 | 
					                        h.remote_wakeup_enabled(true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    OutResponse::Accepted
 | 
					                    OutResponse::Accepted
 | 
				
			||||||
@@ -432,7 +488,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                    self.address = addr as u8;
 | 
					                    self.address = addr as u8;
 | 
				
			||||||
                    self.set_address_pending = true;
 | 
					                    self.set_address_pending = true;
 | 
				
			||||||
                    self.device_state = UsbDeviceState::Addressed;
 | 
					                    self.device_state = UsbDeviceState::Addressed;
 | 
				
			||||||
                    if let Some(h) = &self.handler {
 | 
					                    for h in &mut self.handlers {
 | 
				
			||||||
                        h.addressed(self.address);
 | 
					                        h.addressed(self.address);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    OutResponse::Accepted
 | 
					                    OutResponse::Accepted
 | 
				
			||||||
@@ -443,14 +499,14 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    // Enable all endpoints of selected alt settings.
 | 
					                    // Enable all endpoints of selected alt settings.
 | 
				
			||||||
                    foreach_endpoint(self.config_descriptor, |ep| {
 | 
					                    foreach_endpoint(self.config_descriptor, |ep| {
 | 
				
			||||||
                        let iface = &self.interfaces[ep.interface as usize];
 | 
					                        let iface = &self.interfaces[ep.interface.0 as usize];
 | 
				
			||||||
                        self.bus
 | 
					                        self.bus
 | 
				
			||||||
                            .endpoint_set_enabled(ep.ep_address, iface.current_alt_setting == ep.interface_alt);
 | 
					                            .endpoint_set_enabled(ep.ep_address, iface.current_alt_setting == ep.interface_alt);
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .unwrap();
 | 
					                    .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Notify handler.
 | 
					                    // Notify handlers.
 | 
				
			||||||
                    if let Some(h) = &self.handler {
 | 
					                    for h in &mut self.handlers {
 | 
				
			||||||
                        h.configured(true);
 | 
					                        h.configured(true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -468,8 +524,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                        })
 | 
					                        })
 | 
				
			||||||
                        .unwrap();
 | 
					                        .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // Notify handler.
 | 
					                        // Notify handlers.
 | 
				
			||||||
                        if let Some(h) = &self.handler {
 | 
					                        for h in &mut self.handlers {
 | 
				
			||||||
                            h.configured(false);
 | 
					                            h.configured(false);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -479,7 +535,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                _ => OutResponse::Rejected,
 | 
					                _ => OutResponse::Rejected,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            (RequestType::Standard, Recipient::Interface) => {
 | 
					            (RequestType::Standard, Recipient::Interface) => {
 | 
				
			||||||
                let iface = match self.interfaces.get_mut(req.index as usize) {
 | 
					                let iface_num = InterfaceNumber::new(req.index as _);
 | 
				
			||||||
 | 
					                let iface = match self.interfaces.get_mut(iface_num.0 as usize) {
 | 
				
			||||||
                    Some(iface) => iface,
 | 
					                    Some(iface) => iface,
 | 
				
			||||||
                    None => return OutResponse::Rejected,
 | 
					                    None => return OutResponse::Rejected,
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
@@ -497,7 +554,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                        // Enable/disable EPs of this interface as needed.
 | 
					                        // Enable/disable EPs of this interface as needed.
 | 
				
			||||||
                        foreach_endpoint(self.config_descriptor, |ep| {
 | 
					                        foreach_endpoint(self.config_descriptor, |ep| {
 | 
				
			||||||
                            if ep.interface == req.index as u8 {
 | 
					                            if ep.interface == iface_num {
 | 
				
			||||||
                                self.bus
 | 
					                                self.bus
 | 
				
			||||||
                                    .endpoint_set_enabled(ep.ep_address, iface.current_alt_setting == ep.interface_alt);
 | 
					                                    .endpoint_set_enabled(ep.ep_address, iface.current_alt_setting == ep.interface_alt);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
@@ -506,8 +563,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                        // TODO check it is valid (not out of range)
 | 
					                        // TODO check it is valid (not out of range)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if let Some(handler) = &mut iface.handler {
 | 
					                        for h in &mut self.handlers {
 | 
				
			||||||
                            handler.set_alternate_setting(new_altsetting);
 | 
					                            h.set_alternate_setting(iface_num, new_altsetting);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        OutResponse::Accepted
 | 
					                        OutResponse::Accepted
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -527,17 +584,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => OutResponse::Rejected,
 | 
					                _ => OutResponse::Rejected,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            (RequestType::Class, Recipient::Interface) => {
 | 
					            _ => self.handle_control_out_delegated(req, data),
 | 
				
			||||||
                let iface = match self.interfaces.get_mut(req.index as usize) {
 | 
					 | 
				
			||||||
                    Some(iface) => iface,
 | 
					 | 
				
			||||||
                    None => return OutResponse::Rejected,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                match &mut iface.handler {
 | 
					 | 
				
			||||||
                    Some(handler) => handler.control_out(req, data),
 | 
					 | 
				
			||||||
                    None => OutResponse::Rejected,
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            _ => OutResponse::Rejected,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -582,11 +629,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                        buf[0] = iface.current_alt_setting;
 | 
					                        buf[0] = iface.current_alt_setting;
 | 
				
			||||||
                        InResponse::Accepted(&buf[..1])
 | 
					                        InResponse::Accepted(&buf[..1])
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Request::GET_DESCRIPTOR => match &mut iface.handler {
 | 
					                    _ => self.handle_control_in_delegated(req, buf),
 | 
				
			||||||
                        Some(handler) => handler.get_descriptor(req, buf),
 | 
					 | 
				
			||||||
                        None => InResponse::Rejected,
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    _ => InResponse::Rejected,
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            (RequestType::Standard, Recipient::Endpoint) => match req.request {
 | 
					            (RequestType::Standard, Recipient::Endpoint) => match req.request {
 | 
				
			||||||
@@ -601,34 +644,48 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => InResponse::Rejected,
 | 
					                _ => InResponse::Rejected,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            (RequestType::Class, Recipient::Interface) => {
 | 
					 | 
				
			||||||
                let iface = match self.interfaces.get_mut(req.index as usize) {
 | 
					 | 
				
			||||||
                    Some(iface) => iface,
 | 
					 | 
				
			||||||
                    None => return InResponse::Rejected,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                match &mut iface.handler {
 | 
					 | 
				
			||||||
                    Some(handler) => handler.control_in(req, buf),
 | 
					 | 
				
			||||||
                    None => InResponse::Rejected,
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            #[cfg(feature = "msos-descriptor")]
 | 
					            #[cfg(feature = "msos-descriptor")]
 | 
				
			||||||
            (RequestType::Vendor, Recipient::Device) => {
 | 
					            (RequestType::Vendor, Recipient::Device) => {
 | 
				
			||||||
                if !self.msos_descriptor.is_empty() {
 | 
					                if !self.msos_descriptor.is_empty()
 | 
				
			||||||
                    if req.request == self.msos_descriptor.vendor_code() && req.index == 7 {
 | 
					                    && req.request == self.msos_descriptor.vendor_code()
 | 
				
			||||||
                        // Index 7 retrieves the MS OS Descriptor Set
 | 
					                    && req.index == 7
 | 
				
			||||||
                        InResponse::Accepted(self.msos_descriptor.descriptor())
 | 
					                {
 | 
				
			||||||
                    } else {
 | 
					                    // Index 7 retrieves the MS OS Descriptor Set
 | 
				
			||||||
                        InResponse::Rejected
 | 
					                    InResponse::Accepted(self.msos_descriptor.descriptor())
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    InResponse::Rejected
 | 
					                    self.handle_control_in_delegated(req, buf)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => InResponse::Rejected,
 | 
					            _ => self.handle_control_in_delegated(req, buf),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn handle_control_out_delegated(&mut self, req: Request, data: &[u8]) -> OutResponse {
 | 
				
			||||||
 | 
					        for h in &mut self.handlers {
 | 
				
			||||||
 | 
					            if let Some(res) = h.control_out(req, data) {
 | 
				
			||||||
 | 
					                return res;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        OutResponse::Rejected
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
				
			||||||
 | 
					        unsafe fn extend_lifetime<'x, 'y>(r: InResponse<'x>) -> InResponse<'y> {
 | 
				
			||||||
 | 
					            core::mem::transmute(r)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for h in &mut self.handlers {
 | 
				
			||||||
 | 
					            if let Some(res) = h.control_in(req, buf) {
 | 
				
			||||||
 | 
					                // safety: the borrow checker isn't smart enough to know this pattern (returning a
 | 
				
			||||||
 | 
					                // borrowed value from inside the loop) is sound. Workaround by unsafely extending lifetime.
 | 
				
			||||||
 | 
					                // Also, Polonius (the WIP new borrow checker) does accept it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return unsafe { extend_lifetime(res) };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        InResponse::Rejected
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
					    fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
 | 
				
			||||||
        let (dtype, index) = req.descriptor_type_index();
 | 
					        let (dtype, index) = req.descriptor_type_index();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -649,30 +706,16 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
 | 
				
			|||||||
                        STRING_INDEX_PRODUCT => self.config.product,
 | 
					                        STRING_INDEX_PRODUCT => self.config.product,
 | 
				
			||||||
                        STRING_INDEX_SERIAL_NUMBER => self.config.serial_number,
 | 
					                        STRING_INDEX_SERIAL_NUMBER => self.config.serial_number,
 | 
				
			||||||
                        _ => {
 | 
					                        _ => {
 | 
				
			||||||
                            // Find out which iface owns this string index.
 | 
					                            let mut s = None;
 | 
				
			||||||
                            let mut index_left = index - STRING_INDEX_CUSTOM_START;
 | 
					                            for handler in &mut self.handlers {
 | 
				
			||||||
                            let mut the_iface = None;
 | 
					                                let index = StringIndex::new(index);
 | 
				
			||||||
                            for iface in &mut self.interfaces {
 | 
					                                let lang_id = req.index;
 | 
				
			||||||
                                if index_left < iface.num_strings {
 | 
					                                if let Some(res) = handler.get_string(index, lang_id) {
 | 
				
			||||||
                                    the_iface = Some(iface);
 | 
					                                    s = Some(res);
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                index_left -= iface.num_strings;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            if let Some(iface) = the_iface {
 | 
					 | 
				
			||||||
                                if let Some(handler) = &mut iface.handler {
 | 
					 | 
				
			||||||
                                    let index = StringIndex::new(index);
 | 
					 | 
				
			||||||
                                    let lang_id = req.index;
 | 
					 | 
				
			||||||
                                    handler.get_string(index, lang_id)
 | 
					 | 
				
			||||||
                                } else {
 | 
					 | 
				
			||||||
                                    warn!("String requested to an interface with no handler.");
 | 
					 | 
				
			||||||
                                    None
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            } else {
 | 
					 | 
				
			||||||
                                warn!("String requested but didn't match to an interface.");
 | 
					 | 
				
			||||||
                                None
 | 
					 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					                            s
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
//! USB types.
 | 
					//! USB types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A handle for a USB interface that contains its number.
 | 
					/// A handle for a USB interface that contains its number.
 | 
				
			||||||
#[derive(Copy, Clone, Eq, PartialEq)]
 | 
					#[derive(Debug, Copy, Clone, Eq, PartialEq)]
 | 
				
			||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
pub struct InterfaceNumber(pub(crate) u8);
 | 
					pub struct InterfaceNumber(pub u8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl InterfaceNumber {
 | 
					impl InterfaceNumber {
 | 
				
			||||||
    pub(crate) fn new(index: u8) -> InterfaceNumber {
 | 
					    pub(crate) fn new(index: u8) -> InterfaceNumber {
 | 
				
			||||||
@@ -20,7 +20,7 @@ impl From<InterfaceNumber> for u8 {
 | 
				
			|||||||
/// A handle for a USB string descriptor that contains its index.
 | 
					/// A handle for a USB string descriptor that contains its index.
 | 
				
			||||||
#[derive(Copy, Clone, Eq, PartialEq)]
 | 
					#[derive(Copy, Clone, Eq, PartialEq)]
 | 
				
			||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
pub struct StringIndex(u8);
 | 
					pub struct StringIndex(pub u8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl StringIndex {
 | 
					impl StringIndex {
 | 
				
			||||||
    pub(crate) fn new(index: u8) -> StringIndex {
 | 
					    pub(crate) fn new(index: u8) -> StringIndex {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,7 +82,6 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 128])[..],
 | 
					        &mut singleton!([0; 128])[..],
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Our MAC addr.
 | 
					    // Our MAC addr.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 | 
				
			|||||||
use embassy_sync::signal::Signal;
 | 
					use embassy_sync::signal::Signal;
 | 
				
			||||||
use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
 | 
					use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
 | 
				
			||||||
use embassy_usb::control::OutResponse;
 | 
					use embassy_usb::control::OutResponse;
 | 
				
			||||||
use embassy_usb::{Builder, Config, DeviceStateHandler};
 | 
					use embassy_usb::{Builder, Config, Handler};
 | 
				
			||||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
 | 
					use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
 | 
				
			||||||
use {defmt_rtt as _, panic_probe as _};
 | 
					use {defmt_rtt as _, panic_probe as _};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +52,7 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
    let mut bos_descriptor = [0; 256];
 | 
					    let mut bos_descriptor = [0; 256];
 | 
				
			||||||
    let mut control_buf = [0; 64];
 | 
					    let mut control_buf = [0; 64];
 | 
				
			||||||
    let request_handler = MyRequestHandler {};
 | 
					    let request_handler = MyRequestHandler {};
 | 
				
			||||||
    let device_state_handler = MyDeviceStateHandler::new();
 | 
					    let mut device_handler = MyDeviceHandler::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut state = State::new();
 | 
					    let mut state = State::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -63,9 +63,10 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        Some(&device_state_handler),
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    builder.handler(&mut device_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
    let config = embassy_usb::class::hid::Config {
 | 
					    let config = embassy_usb::class::hid::Config {
 | 
				
			||||||
        report_descriptor: KeyboardReport::desc(),
 | 
					        report_descriptor: KeyboardReport::desc(),
 | 
				
			||||||
@@ -164,20 +165,20 @@ impl RequestHandler for MyRequestHandler {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct MyDeviceStateHandler {
 | 
					struct MyDeviceHandler {
 | 
				
			||||||
    configured: AtomicBool,
 | 
					    configured: AtomicBool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl MyDeviceStateHandler {
 | 
					impl MyDeviceHandler {
 | 
				
			||||||
    fn new() -> Self {
 | 
					    fn new() -> Self {
 | 
				
			||||||
        MyDeviceStateHandler {
 | 
					        MyDeviceHandler {
 | 
				
			||||||
            configured: AtomicBool::new(false),
 | 
					            configured: AtomicBool::new(false),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl DeviceStateHandler for MyDeviceStateHandler {
 | 
					impl Handler for MyDeviceHandler {
 | 
				
			||||||
    fn enabled(&self, enabled: bool) {
 | 
					    fn enabled(&mut self, enabled: bool) {
 | 
				
			||||||
        self.configured.store(false, Ordering::Relaxed);
 | 
					        self.configured.store(false, Ordering::Relaxed);
 | 
				
			||||||
        SUSPENDED.store(false, Ordering::Release);
 | 
					        SUSPENDED.store(false, Ordering::Release);
 | 
				
			||||||
        if enabled {
 | 
					        if enabled {
 | 
				
			||||||
@@ -187,17 +188,17 @@ impl DeviceStateHandler for MyDeviceStateHandler {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn reset(&self) {
 | 
					    fn reset(&mut self) {
 | 
				
			||||||
        self.configured.store(false, Ordering::Relaxed);
 | 
					        self.configured.store(false, Ordering::Relaxed);
 | 
				
			||||||
        info!("Bus reset, the Vbus current limit is 100mA");
 | 
					        info!("Bus reset, the Vbus current limit is 100mA");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn addressed(&self, addr: u8) {
 | 
					    fn addressed(&mut self, addr: u8) {
 | 
				
			||||||
        self.configured.store(false, Ordering::Relaxed);
 | 
					        self.configured.store(false, Ordering::Relaxed);
 | 
				
			||||||
        info!("USB address set to: {}", addr);
 | 
					        info!("USB address set to: {}", addr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn configured(&self, configured: bool) {
 | 
					    fn configured(&mut self, configured: bool) {
 | 
				
			||||||
        self.configured.store(configured, Ordering::Relaxed);
 | 
					        self.configured.store(configured, Ordering::Relaxed);
 | 
				
			||||||
        if configured {
 | 
					        if configured {
 | 
				
			||||||
            info!("Device configured, it may now draw up to the configured current limit from Vbus.")
 | 
					            info!("Device configured, it may now draw up to the configured current limit from Vbus.")
 | 
				
			||||||
@@ -206,7 +207,7 @@ impl DeviceStateHandler for MyDeviceStateHandler {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn suspended(&self, suspended: bool) {
 | 
					    fn suspended(&mut self, suspended: bool) {
 | 
				
			||||||
        if suspended {
 | 
					        if suspended {
 | 
				
			||||||
            info!("Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled).");
 | 
					            info!("Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled).");
 | 
				
			||||||
            SUSPENDED.store(true, Ordering::Release);
 | 
					            SUSPENDED.store(true, Ordering::Release);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,7 +83,6 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
        &mut res.config_descriptor,
 | 
					        &mut res.config_descriptor,
 | 
				
			||||||
        &mut res.bos_descriptor,
 | 
					        &mut res.bos_descriptor,
 | 
				
			||||||
        &mut res.control_buf,
 | 
					        &mut res.control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,7 +65,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut msos_descriptor,
 | 
					        &mut msos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    builder.msos_descriptor(windows_version::WIN8_1, 2);
 | 
					    builder.msos_descriptor(windows_version::WIN8_1, 2);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,6 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 128])[..],
 | 
					        &mut singleton!([0; 128])[..],
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Our MAC addr.
 | 
					    // Our MAC addr.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,7 +53,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,7 +58,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,7 +82,6 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 128])[..],
 | 
					        &mut singleton!([0; 128])[..],
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Our MAC addr.
 | 
					    // Our MAC addr.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,7 +58,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,6 @@ async fn main(spawner: Spawner) {
 | 
				
			|||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 256])[..],
 | 
					        &mut singleton!([0; 256])[..],
 | 
				
			||||||
        &mut singleton!([0; 128])[..],
 | 
					        &mut singleton!([0; 128])[..],
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Our MAC addr.
 | 
					    // Our MAC addr.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,6 @@ async fn main(_spawner: Spawner) {
 | 
				
			|||||||
        &mut config_descriptor,
 | 
					        &mut config_descriptor,
 | 
				
			||||||
        &mut bos_descriptor,
 | 
					        &mut bos_descriptor,
 | 
				
			||||||
        &mut control_buf,
 | 
					        &mut control_buf,
 | 
				
			||||||
        None,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user