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_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)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
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>>(
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,
config: Config<'d>,
with_out_endpoint: bool,
) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) {
let control = state.control.write(Control::new(
report_descriptor,
request_handler,
config.report_descriptor,
config.request_handler,
&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 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 {
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 {
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)
/// 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(
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,
config: Config<'d>,
) -> Self {
let (ep_out, ep_in, offset) = build(
builder,
state,
report_descriptor,
request_handler,
poll_ms,
max_packet_size,
true,
);
let (ep_out, ep_in, offset) = build(builder, state, config, true);
Self {
reader: HidReader {
@ -249,20 +249,9 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
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,
config: Config<'d>,
) -> Self {
let (ep_out, ep_in, _offset) = build(
builder,
state,
report_descriptor,
request_handler,
poll_ms,
max_packet_size,
false,
);
let (ep_out, ep_in, _offset) = build(builder, state, config, false);
assert!(ep_out.is_none());
@ -422,17 +411,17 @@ pub trait RequestHandler {
}
struct Control<'d> {
report_descriptor: &'static [u8],
report_descriptor: &'d [u8],
request_handler: Option<&'d dyn RequestHandler>,
out_report_offset: &'d AtomicUsize,
hid_descriptor: [u8; 9],
}
impl<'a> Control<'a> {
impl<'d> Control<'d> {
fn new(
report_descriptor: &'static [u8],
request_handler: Option<&'a dyn RequestHandler>,
out_report_offset: &'a AtomicUsize,
report_descriptor: &'d [u8],
request_handler: Option<&'d dyn RequestHandler>,
out_report_offset: &'d AtomicUsize,
) -> Self {
Control {
report_descriptor,

View File

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