usb-hid: add Config struct, to avoid too many params.

This commit is contained in:
Dario Nieuwenhuis 2022-04-16 02:07:03 +02:00
parent c0de54a341
commit f35bde684a
3 changed files with 49 additions and 61 deletions

View File

@ -41,6 +41,24 @@ const HID_REQ_SET_REPORT: u8 = 0x09;
const HID_REQ_GET_PROTOCOL: u8 = 0x03; const HID_REQ_GET_PROTOCOL: u8 = 0x03;
const HID_REQ_SET_PROTOCOL: u8 = 0x0b; const HID_REQ_SET_PROTOCOL: u8 = 0x0b;
pub struct Config<'d> {
/// HID report descriptor.
pub report_descriptor: &'d [u8],
/// Handler for control requests.
pub request_handler: Option<&'d dyn RequestHandler>,
/// 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 poll_ms: u8,
/// Max packet size for both the IN and OUT endpoints.
pub max_packet_size: u16,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ReportId { pub enum ReportId {
@ -82,23 +100,20 @@ pub struct HidReaderWriter<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N
fn build<'d, D: Driver<'d>>( fn build<'d, D: Driver<'d>>(
builder: &mut UsbDeviceBuilder<'d, D>, builder: &mut UsbDeviceBuilder<'d, D>,
state: &'d mut State<'d>, state: &'d mut State<'d>,
report_descriptor: &'static [u8], config: Config<'d>,
request_handler: Option<&'d dyn RequestHandler>,
poll_ms: u8,
max_packet_size: u16,
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( let control = state.control.write(Control::new(
report_descriptor, config.report_descriptor,
request_handler, config.request_handler,
&state.out_report_offset, &state.out_report_offset,
)); ));
let len = report_descriptor.len(); let len = config.report_descriptor.len();
let if_num = builder.alloc_interface_with_handler(control); let if_num = builder.alloc_interface_with_handler(control);
let ep_in = builder.alloc_interrupt_endpoint_in(max_packet_size, poll_ms); let ep_in = builder.alloc_interrupt_endpoint_in(config.max_packet_size, config.poll_ms);
let ep_out = if with_out_endpoint { let ep_out = if with_out_endpoint {
Some(builder.alloc_interrupt_endpoint_out(max_packet_size, poll_ms)) Some(builder.alloc_interrupt_endpoint_out(config.max_packet_size, config.poll_ms))
} else { } else {
None None
}; };
@ -145,27 +160,12 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize>
/// This will allocate one IN and one OUT endpoints. If you only need writing (sending) /// 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. /// 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
/// 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( pub fn new(
builder: &mut UsbDeviceBuilder<'d, D>, builder: &mut UsbDeviceBuilder<'d, D>,
state: &'d mut State<'d>, state: &'d mut State<'d>,
report_descriptor: &'static [u8], config: Config<'d>,
request_handler: Option<&'d dyn RequestHandler>,
poll_ms: u8,
max_packet_size: u16,
) -> Self { ) -> Self {
let (ep_out, ep_in, offset) = build( let (ep_out, ep_in, offset) = build(builder, state, config, true);
builder,
state,
report_descriptor,
request_handler,
poll_ms,
max_packet_size,
true,
);
Self { Self {
reader: HidReader { reader: HidReader {
@ -249,20 +249,9 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
pub fn new( pub fn new(
builder: &mut UsbDeviceBuilder<'d, D>, builder: &mut UsbDeviceBuilder<'d, D>,
state: &'d mut State<'d>, state: &'d mut State<'d>,
report_descriptor: &'static [u8], config: Config<'d>,
request_handler: Option<&'d dyn RequestHandler>,
poll_ms: u8,
max_packet_size: u16,
) -> Self { ) -> Self {
let (ep_out, ep_in, _offset) = build( let (ep_out, ep_in, _offset) = build(builder, state, config, false);
builder,
state,
report_descriptor,
request_handler,
poll_ms,
max_packet_size,
false,
);
assert!(ep_out.is_none()); assert!(ep_out.is_none());
@ -422,17 +411,17 @@ pub trait RequestHandler {
} }
struct Control<'d> { struct Control<'d> {
report_descriptor: &'static [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,
hid_descriptor: [u8; 9], hid_descriptor: [u8; 9],
} }
impl<'a> Control<'a> { impl<'d> Control<'d> {
fn new( fn new(
report_descriptor: &'static [u8], report_descriptor: &'d [u8],
request_handler: Option<&'a dyn RequestHandler>, request_handler: Option<&'d dyn RequestHandler>,
out_report_offset: &'a AtomicUsize, out_report_offset: &'d AtomicUsize,
) -> Self { ) -> Self {
Control { Control {
report_descriptor, report_descriptor,

View File

@ -88,14 +88,13 @@ async fn main(_spawner: Spawner, p: Peripherals) {
); );
// Create classes on the builder. // Create classes on the builder.
let hid = HidReaderWriter::<_, 1, 8>::new( let config = embassy_usb_hid::Config {
&mut builder, report_descriptor: KeyboardReport::desc(),
&mut state, request_handler: Some(&request_handler),
KeyboardReport::desc(), poll_ms: 60,
Some(&request_handler), max_packet_size: 64,
60, };
64, let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
);
// Build the builder. // Build the builder.
let mut usb = builder.build(); let mut usb = builder.build();

View File

@ -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::new(); let mut state = State::new();
let mut builder = UsbDeviceBuilder::new( let mut builder = UsbDeviceBuilder::new(
driver, driver,
@ -65,14 +65,14 @@ async fn main(_spawner: Spawner, p: Peripherals) {
); );
// Create classes on the builder. // Create classes on the builder.
let mut writer = HidWriter::<_, 5>::new( let config = embassy_usb_hid::Config {
&mut builder, report_descriptor: MouseReport::desc(),
&mut control, request_handler: Some(&request_handler),
MouseReport::desc(), poll_ms: 60,
Some(&request_handler), max_packet_size: 8,
60, };
8,
); let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config);
// Build the builder. // Build the builder.
let mut usb = builder.build(); let mut usb = builder.build();