usb-hid: Simplify API.
- Renamed structs to HidReaderWriter, HidReader, HidWriter. - Removed unused const generics on `State`. - Simplified generics on `HidReaderWriter`. The class type previously was `HidClass<D, Driver<'d, USBD>, ReportReader<'d, Driver<'d, USBD>, OUT_N>, IN_N>` It's now `HidClass<D, Driver<'d, USBD>, IN_N, OUT_N>`. Note that the driver type `Driver<'d, USBD>` is no longer repeated. - Constructors are now: `HidWriter::new()` for IN-only, `HidReaderWriter::new()` for IN+OUT. No complicated bounds. - HidReaderWriter has all the methods from HidReader, HidWriter.
This commit is contained in:
		
							parent
							
								
									94090e068e
								
							
						
					
					
						commit
						c0de54a341
					
				@ -60,12 +60,12 @@ impl ReportId {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct State<'a, const IN_N: usize, const OUT_N: usize> {
 | 
					pub struct State<'d> {
 | 
				
			||||||
    control: MaybeUninit<Control<'a>>,
 | 
					    control: MaybeUninit<Control<'d>>,
 | 
				
			||||||
    out_report_offset: AtomicUsize,
 | 
					    out_report_offset: AtomicUsize,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'a, const IN_N: usize, const OUT_N: usize> State<'a, IN_N, OUT_N> {
 | 
					impl<'d> State<'d> {
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        State {
 | 
					        State {
 | 
				
			||||||
            control: MaybeUninit::uninit(),
 | 
					            control: MaybeUninit::uninit(),
 | 
				
			||||||
@ -74,107 +74,146 @@ impl<'a, const IN_N: usize, const OUT_N: usize> State<'a, IN_N, OUT_N> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct HidClass<'d, D: Driver<'d>, T, const IN_N: usize> {
 | 
					pub struct HidReaderWriter<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> {
 | 
				
			||||||
    input: ReportWriter<'d, D, IN_N>,
 | 
					    reader: HidReader<'d, D, READ_N>,
 | 
				
			||||||
    output: T,
 | 
					    writer: HidWriter<'d, D, WRITE_N>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, D: Driver<'d>, const IN_N: usize> HidClass<'d, D, (), IN_N> {
 | 
					fn build<'d, D: Driver<'d>>(
 | 
				
			||||||
    /// Creates a new HidClass.
 | 
					    builder: &mut UsbDeviceBuilder<'d, D>,
 | 
				
			||||||
    ///
 | 
					    state: &'d mut State<'d>,
 | 
				
			||||||
    /// poll_ms configures how frequently the host should poll for reading/writing
 | 
					    report_descriptor: &'static [u8],
 | 
				
			||||||
    /// HID reports. A lower value means better throughput & latency, at the expense
 | 
					    request_handler: Option<&'d dyn RequestHandler>,
 | 
				
			||||||
    /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
 | 
					    poll_ms: u8,
 | 
				
			||||||
    /// high performance uses, and a value of 255 is good for best-effort usecases.
 | 
					    max_packet_size: u16,
 | 
				
			||||||
    ///
 | 
					    with_out_endpoint: bool,
 | 
				
			||||||
    /// This allocates an IN endpoint only.
 | 
					) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) {
 | 
				
			||||||
    pub fn new<const OUT_N: usize>(
 | 
					    let control = state.control.write(Control::new(
 | 
				
			||||||
        builder: &mut UsbDeviceBuilder<'d, D>,
 | 
					        report_descriptor,
 | 
				
			||||||
        state: &'d mut State<'d, IN_N, OUT_N>,
 | 
					        request_handler,
 | 
				
			||||||
        report_descriptor: &'static [u8],
 | 
					        &state.out_report_offset,
 | 
				
			||||||
        request_handler: Option<&'d dyn RequestHandler>,
 | 
					    ));
 | 
				
			||||||
        poll_ms: u8,
 | 
					 | 
				
			||||||
        max_packet_size: u16,
 | 
					 | 
				
			||||||
    ) -> Self {
 | 
					 | 
				
			||||||
        let ep_in = builder.alloc_interrupt_endpoint_in(max_packet_size, poll_ms);
 | 
					 | 
				
			||||||
        let control = state.control.write(Control::new(
 | 
					 | 
				
			||||||
            report_descriptor,
 | 
					 | 
				
			||||||
            request_handler,
 | 
					 | 
				
			||||||
            &state.out_report_offset,
 | 
					 | 
				
			||||||
        ));
 | 
					 | 
				
			||||||
        control.build(builder, None, &ep_in);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self {
 | 
					    let len = report_descriptor.len();
 | 
				
			||||||
            input: ReportWriter { ep_in },
 | 
					    let if_num = builder.alloc_interface_with_handler(control);
 | 
				
			||||||
            output: (),
 | 
					    let ep_in = builder.alloc_interrupt_endpoint_in(max_packet_size, poll_ms);
 | 
				
			||||||
        }
 | 
					    let ep_out = if with_out_endpoint {
 | 
				
			||||||
 | 
					        Some(builder.alloc_interrupt_endpoint_out(max_packet_size, poll_ms))
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    builder.config_descriptor.interface(
 | 
				
			||||||
 | 
					        if_num,
 | 
				
			||||||
 | 
					        USB_CLASS_HID,
 | 
				
			||||||
 | 
					        USB_SUBCLASS_NONE,
 | 
				
			||||||
 | 
					        USB_PROTOCOL_NONE,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // HID descriptor
 | 
				
			||||||
 | 
					    builder.config_descriptor.write(
 | 
				
			||||||
 | 
					        HID_DESC_DESCTYPE_HID,
 | 
				
			||||||
 | 
					        &[
 | 
				
			||||||
 | 
					            // HID Class spec version
 | 
				
			||||||
 | 
					            HID_DESC_SPEC_1_10[0],
 | 
				
			||||||
 | 
					            HID_DESC_SPEC_1_10[1],
 | 
				
			||||||
 | 
					            // Country code not supported
 | 
				
			||||||
 | 
					            HID_DESC_COUNTRY_UNSPEC,
 | 
				
			||||||
 | 
					            // Number of following descriptors
 | 
				
			||||||
 | 
					            1,
 | 
				
			||||||
 | 
					            // We have a HID report descriptor the host should read
 | 
				
			||||||
 | 
					            HID_DESC_DESCTYPE_HID_REPORT,
 | 
				
			||||||
 | 
					            // HID report descriptor size,
 | 
				
			||||||
 | 
					            (len & 0xFF) as u8,
 | 
				
			||||||
 | 
					            (len >> 8 & 0xFF) as u8,
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    builder.config_descriptor.endpoint(ep_in.info());
 | 
				
			||||||
 | 
					    if let Some(ep_out) = &ep_out {
 | 
				
			||||||
 | 
					        builder.config_descriptor.endpoint(ep_out.info());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (ep_out, ep_in, &state.out_report_offset)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, D: Driver<'d>, T, const IN_N: usize> HidClass<'d, D, T, IN_N> {
 | 
					impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize>
 | 
				
			||||||
    /// Gets the [`ReportWriter`] for input reports.
 | 
					    HidReaderWriter<'d, D, READ_N, WRITE_N>
 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// **Note:** If the `HidClass` was created with [`new_ep_out()`](Self::new_ep_out)
 | 
					 | 
				
			||||||
    /// this writer will be useless as no endpoint is availabe to send reports.
 | 
					 | 
				
			||||||
    pub fn input(&mut self) -> &mut ReportWriter<'d, D, IN_N> {
 | 
					 | 
				
			||||||
        &mut self.input
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'d, D: Driver<'d>, const IN_N: usize, const OUT_N: usize>
 | 
					 | 
				
			||||||
    HidClass<'d, D, ReportReader<'d, D, OUT_N>, IN_N>
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// Creates a new HidClass.
 | 
					    /// Creates a new HidReaderWriter.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// This will allocate one IN and one OUT endpoints. If you only need writing (sending)
 | 
				
			||||||
 | 
					    /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// poll_ms configures how frequently the host should poll for reading/writing
 | 
					    /// poll_ms configures how frequently the host should poll for reading/writing
 | 
				
			||||||
    /// HID reports. A lower value means better throughput & latency, at the expense
 | 
					    /// HID reports. A lower value means better throughput & latency, at the expense
 | 
				
			||||||
    /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
 | 
					    /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
 | 
				
			||||||
    /// high performance uses, and a value of 255 is good for best-effort usecases.
 | 
					    /// high performance uses, and a value of 255 is good for best-effort usecases.
 | 
				
			||||||
    ///
 | 
					    pub fn new(
 | 
				
			||||||
    /// This allocates two endpoints (IN and OUT).
 | 
					 | 
				
			||||||
    pub fn with_output_ep(
 | 
					 | 
				
			||||||
        builder: &mut UsbDeviceBuilder<'d, D>,
 | 
					        builder: &mut UsbDeviceBuilder<'d, D>,
 | 
				
			||||||
        state: &'d mut State<'d, IN_N, OUT_N>,
 | 
					        state: &'d mut State<'d>,
 | 
				
			||||||
        report_descriptor: &'static [u8],
 | 
					        report_descriptor: &'static [u8],
 | 
				
			||||||
        request_handler: Option<&'d dyn RequestHandler>,
 | 
					        request_handler: Option<&'d dyn RequestHandler>,
 | 
				
			||||||
        poll_ms: u8,
 | 
					        poll_ms: u8,
 | 
				
			||||||
        max_packet_size: u16,
 | 
					        max_packet_size: u16,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        let ep_out = builder.alloc_interrupt_endpoint_out(max_packet_size, poll_ms);
 | 
					        let (ep_out, ep_in, offset) = build(
 | 
				
			||||||
        let ep_in = builder.alloc_interrupt_endpoint_in(max_packet_size, poll_ms);
 | 
					            builder,
 | 
				
			||||||
 | 
					            state,
 | 
				
			||||||
        let control = state.control.write(Control::new(
 | 
					 | 
				
			||||||
            report_descriptor,
 | 
					            report_descriptor,
 | 
				
			||||||
            request_handler,
 | 
					            request_handler,
 | 
				
			||||||
            &state.out_report_offset,
 | 
					            poll_ms,
 | 
				
			||||||
        ));
 | 
					            max_packet_size,
 | 
				
			||||||
        control.build(builder, Some(&ep_out), &ep_in);
 | 
					            true,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            input: ReportWriter { ep_in },
 | 
					            reader: HidReader {
 | 
				
			||||||
            output: ReportReader {
 | 
					                ep_out: ep_out.unwrap(),
 | 
				
			||||||
                ep_out,
 | 
					                offset,
 | 
				
			||||||
                offset: &state.out_report_offset,
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            writer: HidWriter { ep_in },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Gets the [`ReportReader`] for output reports.
 | 
					    /// Splits into seperate readers/writers for input and output reports.
 | 
				
			||||||
    pub fn output(&mut self) -> &mut ReportReader<'d, D, OUT_N> {
 | 
					    pub fn split(self) -> (HidReader<'d, D, READ_N>, HidWriter<'d, D, WRITE_N>) {
 | 
				
			||||||
        &mut self.output
 | 
					        (self.reader, self.writer)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Splits this `HidClass` into seperate readers/writers for input and output reports.
 | 
					    /// Waits for both IN and OUT endpoints to be enabled.
 | 
				
			||||||
    pub fn split(self) -> (ReportWriter<'d, D, IN_N>, ReportReader<'d, D, OUT_N>) {
 | 
					    pub async fn ready(&mut self) -> () {
 | 
				
			||||||
        (self.input, self.output)
 | 
					        self.reader.ready().await;
 | 
				
			||||||
 | 
					        self.writer.ready().await;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Writes an input report by serializing the given report structure.
 | 
				
			||||||
 | 
					    #[cfg(feature = "usbd-hid")]
 | 
				
			||||||
 | 
					    pub async fn write_serialize<IR: AsInputReport>(
 | 
				
			||||||
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        r: &IR,
 | 
				
			||||||
 | 
					    ) -> Result<(), EndpointError> {
 | 
				
			||||||
 | 
					        self.writer.write_serialize(r).await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Writes `report` to its interrupt endpoint.
 | 
				
			||||||
 | 
					    pub async fn write(&mut self, report: &[u8]) -> Result<(), EndpointError> {
 | 
				
			||||||
 | 
					        self.writer.write(report).await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Reads an output report from the Interrupt Out pipe.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// See [`HidReader::read`].
 | 
				
			||||||
 | 
					    pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, ReadError> {
 | 
				
			||||||
 | 
					        self.reader.read(buf).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ReportWriter<'d, D: Driver<'d>, const N: usize> {
 | 
					pub struct HidWriter<'d, D: Driver<'d>, const N: usize> {
 | 
				
			||||||
    ep_in: D::EndpointIn,
 | 
					    ep_in: D::EndpointIn,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ReportReader<'d, D: Driver<'d>, const N: usize> {
 | 
					pub struct HidReader<'d, D: Driver<'d>, const N: usize> {
 | 
				
			||||||
    ep_out: D::EndpointOut,
 | 
					    ep_out: D::EndpointOut,
 | 
				
			||||||
    offset: &'d AtomicUsize,
 | 
					    offset: &'d AtomicUsize,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -197,17 +236,50 @@ impl From<embassy_usb::driver::EndpointError> for ReadError {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, D: Driver<'d>, const N: usize> ReportWriter<'d, D, N> {
 | 
					impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
 | 
				
			||||||
 | 
					    /// Creates a new HidWriter.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// This will allocate one IN endpoint only, so the host won't be able to send
 | 
				
			||||||
 | 
					    /// reports to us. If you need that, consider using [`HidReaderWriter::new`] instead.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// poll_ms configures how frequently the host should poll for reading/writing
 | 
				
			||||||
 | 
					    /// HID reports. A lower value means better throughput & latency, at the expense
 | 
				
			||||||
 | 
					    /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
 | 
				
			||||||
 | 
					    /// high performance uses, and a value of 255 is good for best-effort usecases.
 | 
				
			||||||
 | 
					    pub fn new(
 | 
				
			||||||
 | 
					        builder: &mut UsbDeviceBuilder<'d, D>,
 | 
				
			||||||
 | 
					        state: &'d mut State<'d>,
 | 
				
			||||||
 | 
					        report_descriptor: &'static [u8],
 | 
				
			||||||
 | 
					        request_handler: Option<&'d dyn RequestHandler>,
 | 
				
			||||||
 | 
					        poll_ms: u8,
 | 
				
			||||||
 | 
					        max_packet_size: u16,
 | 
				
			||||||
 | 
					    ) -> Self {
 | 
				
			||||||
 | 
					        let (ep_out, ep_in, _offset) = build(
 | 
				
			||||||
 | 
					            builder,
 | 
				
			||||||
 | 
					            state,
 | 
				
			||||||
 | 
					            report_descriptor,
 | 
				
			||||||
 | 
					            request_handler,
 | 
				
			||||||
 | 
					            poll_ms,
 | 
				
			||||||
 | 
					            max_packet_size,
 | 
				
			||||||
 | 
					            false,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert!(ep_out.is_none());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Self { ep_in }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Waits for the interrupt in endpoint to be enabled.
 | 
					    /// Waits for the interrupt in endpoint to be enabled.
 | 
				
			||||||
    pub async fn ready(&mut self) -> () {
 | 
					    pub async fn ready(&mut self) -> () {
 | 
				
			||||||
        self.ep_in.wait_enabled().await
 | 
					        self.ep_in.wait_enabled().await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Tries to write an input report by serializing the given report structure.
 | 
					    /// Writes an input report by serializing the given report structure.
 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Panics if no endpoint is available.
 | 
					 | 
				
			||||||
    #[cfg(feature = "usbd-hid")]
 | 
					    #[cfg(feature = "usbd-hid")]
 | 
				
			||||||
    pub async fn serialize<IR: AsInputReport>(&mut self, r: &IR) -> Result<(), EndpointError> {
 | 
					    pub async fn write_serialize<IR: AsInputReport>(
 | 
				
			||||||
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        r: &IR,
 | 
				
			||||||
 | 
					    ) -> Result<(), EndpointError> {
 | 
				
			||||||
        let mut buf: [u8; N] = [0; N];
 | 
					        let mut buf: [u8; N] = [0; N];
 | 
				
			||||||
        let size = match serialize(&mut buf, r) {
 | 
					        let size = match serialize(&mut buf, r) {
 | 
				
			||||||
            Ok(size) => size,
 | 
					            Ok(size) => size,
 | 
				
			||||||
@ -217,8 +289,6 @@ impl<'d, D: Driver<'d>, const N: usize> ReportWriter<'d, D, N> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Writes `report` to its interrupt endpoint.
 | 
					    /// Writes `report` to its interrupt endpoint.
 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Panics if no endpoint is available.
 | 
					 | 
				
			||||||
    pub async fn write(&mut self, report: &[u8]) -> Result<(), EndpointError> {
 | 
					    pub async fn write(&mut self, report: &[u8]) -> Result<(), EndpointError> {
 | 
				
			||||||
        assert!(report.len() <= N);
 | 
					        assert!(report.len() <= N);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -236,16 +306,13 @@ impl<'d, D: Driver<'d>, const N: usize> ReportWriter<'d, D, N> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, D: Driver<'d>, const N: usize> ReportReader<'d, D, N> {
 | 
					impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> {
 | 
				
			||||||
    /// Waits for the interrupt out endpoint to be enabled.
 | 
					    /// Waits for the interrupt out endpoint to be enabled.
 | 
				
			||||||
    pub async fn ready(&mut self) -> () {
 | 
					    pub async fn ready(&mut self) -> () {
 | 
				
			||||||
        self.ep_out.wait_enabled().await
 | 
					        self.ep_out.wait_enabled().await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Starts a task to deliver output reports from the Interrupt Out pipe to
 | 
					    /// Delivers output reports from the Interrupt Out pipe to `handler`.
 | 
				
			||||||
    /// `handler`.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Terminates when the interface becomes disabled.
 | 
					 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// If `use_report_ids` is true, the first byte of the report will be used as
 | 
					    /// If `use_report_ids` is true, the first byte of the report will be used as
 | 
				
			||||||
    /// the `ReportId` value. Otherwise the `ReportId` value will be 0.
 | 
					    /// the `ReportId` value. Otherwise the `ReportId` value will be 0.
 | 
				
			||||||
@ -391,47 +458,6 @@ impl<'a> Control<'a> {
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn build<'d, D: Driver<'d>>(
 | 
					 | 
				
			||||||
        &'d mut self,
 | 
					 | 
				
			||||||
        builder: &mut UsbDeviceBuilder<'d, D>,
 | 
					 | 
				
			||||||
        ep_out: Option<&D::EndpointOut>,
 | 
					 | 
				
			||||||
        ep_in: &D::EndpointIn,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        let len = self.report_descriptor.len();
 | 
					 | 
				
			||||||
        let if_num = builder.alloc_interface_with_handler(self);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        builder.config_descriptor.interface(
 | 
					 | 
				
			||||||
            if_num,
 | 
					 | 
				
			||||||
            USB_CLASS_HID,
 | 
					 | 
				
			||||||
            USB_SUBCLASS_NONE,
 | 
					 | 
				
			||||||
            USB_PROTOCOL_NONE,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // HID descriptor
 | 
					 | 
				
			||||||
        builder.config_descriptor.write(
 | 
					 | 
				
			||||||
            HID_DESC_DESCTYPE_HID,
 | 
					 | 
				
			||||||
            &[
 | 
					 | 
				
			||||||
                // HID Class spec version
 | 
					 | 
				
			||||||
                HID_DESC_SPEC_1_10[0],
 | 
					 | 
				
			||||||
                HID_DESC_SPEC_1_10[1],
 | 
					 | 
				
			||||||
                // Country code not supported
 | 
					 | 
				
			||||||
                HID_DESC_COUNTRY_UNSPEC,
 | 
					 | 
				
			||||||
                // Number of following descriptors
 | 
					 | 
				
			||||||
                1,
 | 
					 | 
				
			||||||
                // We have a HID report descriptor the host should read
 | 
					 | 
				
			||||||
                HID_DESC_DESCTYPE_HID_REPORT,
 | 
					 | 
				
			||||||
                // HID report descriptor size,
 | 
					 | 
				
			||||||
                (len & 0xFF) as u8,
 | 
					 | 
				
			||||||
                (len >> 8 & 0xFF) as u8,
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        builder.config_descriptor.endpoint(ep_in.info());
 | 
					 | 
				
			||||||
        if let Some(ep) = ep_out {
 | 
					 | 
				
			||||||
            builder.config_descriptor.endpoint(ep.info());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d> ControlHandler for Control<'d> {
 | 
					impl<'d> ControlHandler for Control<'d> {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ use embassy_nrf::usb::Driver;
 | 
				
			|||||||
use embassy_nrf::Peripherals;
 | 
					use embassy_nrf::Peripherals;
 | 
				
			||||||
use embassy_usb::control::OutResponse;
 | 
					use embassy_usb::control::OutResponse;
 | 
				
			||||||
use embassy_usb::{Config, DeviceStateHandler, UsbDeviceBuilder};
 | 
					use embassy_usb::{Config, DeviceStateHandler, UsbDeviceBuilder};
 | 
				
			||||||
use embassy_usb_hid::{HidClass, ReportId, RequestHandler, State};
 | 
					use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State};
 | 
				
			||||||
use futures::future::join;
 | 
					use futures::future::join;
 | 
				
			||||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
 | 
					use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -75,7 +75,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    let request_handler = MyRequestHandler {};
 | 
					    let request_handler = MyRequestHandler {};
 | 
				
			||||||
    let device_state_handler = MyDeviceStateHandler::new();
 | 
					    let device_state_handler = MyDeviceStateHandler::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut state = State::<8, 1>::new();
 | 
					    let mut state = State::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut builder = UsbDeviceBuilder::new(
 | 
					    let mut builder = UsbDeviceBuilder::new(
 | 
				
			||||||
        driver,
 | 
					        driver,
 | 
				
			||||||
@ -88,7 +88,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
    let hid = HidClass::with_output_ep(
 | 
					    let hid = HidReaderWriter::<_, 1, 8>::new(
 | 
				
			||||||
        &mut builder,
 | 
					        &mut builder,
 | 
				
			||||||
        &mut state,
 | 
					        &mut state,
 | 
				
			||||||
        KeyboardReport::desc(),
 | 
					        KeyboardReport::desc(),
 | 
				
			||||||
@ -135,7 +135,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let mut button = Input::new(p.P0_11.degrade(), Pull::Up);
 | 
					    let mut button = Input::new(p.P0_11.degrade(), Pull::Up);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (mut hid_in, hid_out) = hid.split();
 | 
					    let (reader, mut writer) = hid.split();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Do stuff with the class!
 | 
					    // Do stuff with the class!
 | 
				
			||||||
    let in_fut = async {
 | 
					    let in_fut = async {
 | 
				
			||||||
@ -153,7 +153,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
                    modifier: 0,
 | 
					                    modifier: 0,
 | 
				
			||||||
                    reserved: 0,
 | 
					                    reserved: 0,
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                match hid_in.serialize(&report).await {
 | 
					                match writer.write_serialize(&report).await {
 | 
				
			||||||
                    Ok(()) => {}
 | 
					                    Ok(()) => {}
 | 
				
			||||||
                    Err(e) => warn!("Failed to send report: {:?}", e),
 | 
					                    Err(e) => warn!("Failed to send report: {:?}", e),
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
@ -167,7 +167,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
                modifier: 0,
 | 
					                modifier: 0,
 | 
				
			||||||
                reserved: 0,
 | 
					                reserved: 0,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            match hid_in.serialize(&report).await {
 | 
					            match writer.write_serialize(&report).await {
 | 
				
			||||||
                Ok(()) => {}
 | 
					                Ok(()) => {}
 | 
				
			||||||
                Err(e) => warn!("Failed to send report: {:?}", e),
 | 
					                Err(e) => warn!("Failed to send report: {:?}", e),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
@ -175,7 +175,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let out_fut = async {
 | 
					    let out_fut = async {
 | 
				
			||||||
        hid_out.run(false, &request_handler).await;
 | 
					        reader.run(false, &request_handler).await;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let power_irq = interrupt::take!(POWER_CLOCK);
 | 
					    let power_irq = interrupt::take!(POWER_CLOCK);
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ use embassy_nrf::usb::Driver;
 | 
				
			|||||||
use embassy_nrf::Peripherals;
 | 
					use embassy_nrf::Peripherals;
 | 
				
			||||||
use embassy_usb::control::OutResponse;
 | 
					use embassy_usb::control::OutResponse;
 | 
				
			||||||
use embassy_usb::{Config, UsbDeviceBuilder};
 | 
					use embassy_usb::{Config, UsbDeviceBuilder};
 | 
				
			||||||
use embassy_usb_hid::{HidClass, ReportId, RequestHandler, State};
 | 
					use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State};
 | 
				
			||||||
use futures::future::join;
 | 
					use futures::future::join;
 | 
				
			||||||
use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
 | 
					use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -52,7 +52,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    let mut control_buf = [0; 16];
 | 
					    let mut control_buf = [0; 16];
 | 
				
			||||||
    let request_handler = MyRequestHandler {};
 | 
					    let request_handler = MyRequestHandler {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut control = State::<5, 0>::new();
 | 
					    let mut control = State::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut builder = UsbDeviceBuilder::new(
 | 
					    let mut builder = UsbDeviceBuilder::new(
 | 
				
			||||||
        driver,
 | 
					        driver,
 | 
				
			||||||
@ -65,7 +65,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create classes on the builder.
 | 
					    // Create classes on the builder.
 | 
				
			||||||
    let mut hid = HidClass::new(
 | 
					    let mut writer = HidWriter::<_, 5>::new(
 | 
				
			||||||
        &mut builder,
 | 
					        &mut builder,
 | 
				
			||||||
        &mut control,
 | 
					        &mut control,
 | 
				
			||||||
        MouseReport::desc(),
 | 
					        MouseReport::desc(),
 | 
				
			||||||
@ -94,7 +94,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
                wheel: 0,
 | 
					                wheel: 0,
 | 
				
			||||||
                pan: 0,
 | 
					                pan: 0,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            match hid.input().serialize(&report).await {
 | 
					            match writer.write_serialize(&report).await {
 | 
				
			||||||
                Ok(()) => {}
 | 
					                Ok(()) => {}
 | 
				
			||||||
                Err(e) => warn!("Failed to send report: {:?}", e),
 | 
					                Err(e) => warn!("Failed to send report: {:?}", e),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user