1use embassy_usb::{
2 Builder,
3 class::hid::{HidReaderWriter, HidWriter, State},
4 driver::Driver,
5};
6use rktk::{drivers::interface::usb::UsbReporterDriverBuilder, singleton};
7use usbd_hid::descriptor::{
8 KeyboardReport, MediaKeyboardReport, MouseReport, SerializedDescriptor as _,
9};
10
11use crate::usb::handler::UsbDeviceHandler;
12
13use super::{
14 CommonUsbDriverConfig, ReadySignal,
15 driver::CommonUsbDriver,
16 raw_hid::{RAW_HID_BUFFER_SIZE, RawHidReport},
17 rrp::{RRP_HID_BUFFER_SIZE, RrpReport},
18 task::*,
19};
20
21pub struct CommonUsbReporterBuilder<D: Driver<'static>> {
23 builder: Builder<'static, D>,
24 keyboard_hid: HidReaderWriter<'static, D, 1, 8>,
25 mouse_hid: HidWriter<'static, D, 8>,
26 media_key_hid: HidWriter<'static, D, 8>,
27 #[cfg(feature = "usb-remote-wakeup")]
28 wakeup_signal: &'static super::RemoteWakeupSignal,
29 ready_signal: &'static ReadySignal,
30 rrp_hid: HidReaderWriter<'static, D, RRP_HID_BUFFER_SIZE, RRP_HID_BUFFER_SIZE>,
31 raw_hid: HidReaderWriter<'static, D, RAW_HID_BUFFER_SIZE, RAW_HID_BUFFER_SIZE>,
32 #[cfg(feature = "defmt-usb")]
33 defmt_usb: embassy_usb::class::cdc_acm::CdcAcmClass<'static, D>,
34 #[cfg(feature = "defmt-usb")]
35 defmt_usb_use_dtr: bool,
36}
37
38impl<D: Driver<'static>> CommonUsbReporterBuilder<D> {
39 pub fn new(opts: CommonUsbDriverConfig<D>) -> Self {
40 #[cfg(feature = "usb-remote-wakeup")]
41 let wakeup_signal = singleton!(super::RemoteWakeupSignal::new(), super::RemoteWakeupSignal);
42 let ready_signal = singleton!(ReadySignal::new(), ReadySignal);
43
44 let mut builder = Builder::new(
45 opts.driver,
46 opts.driver_config,
47 singleton!([0; 256], [u8; 256]),
48 singleton!([0; 256], [u8; 256]),
49 singleton!([0; 256], [u8; 256]),
50 singleton!([0; 64], [u8; 64]),
51 );
52
53 builder.handler(singleton!(UsbDeviceHandler::new(), UsbDeviceHandler));
54
55 let keyboard_hid = {
56 let config = embassy_usb::class::hid::Config {
57 report_descriptor: KeyboardReport::desc(),
58 request_handler: None,
59 poll_ms: opts.keyboard_poll_interval,
60 max_packet_size: 64,
61 };
62 HidReaderWriter::<_, 1, 8>::new(&mut builder, singleton!(State::new(), State), config)
63 };
64 let mouse_hid = {
65 let config = embassy_usb::class::hid::Config {
66 report_descriptor: MouseReport::desc(),
67 request_handler: None,
68 poll_ms: opts.mouse_poll_interval,
69 max_packet_size: 64,
70 };
71 HidWriter::<_, 8>::new(&mut builder, singleton!(State::new(), State), config)
72 };
73 let media_key_hid = {
74 let config = embassy_usb::class::hid::Config {
75 report_descriptor: MediaKeyboardReport::desc(),
76 request_handler: None,
77 poll_ms: opts.keyboard_poll_interval,
78 max_packet_size: 64,
79 };
80 HidWriter::<_, 8>::new(&mut builder, singleton!(State::new(), State), config)
81 };
82
83 let rrp_hid = {
84 let config = embassy_usb::class::hid::Config {
85 report_descriptor: RrpReport::desc(),
86 request_handler: None,
87 poll_ms: 1,
88 max_packet_size: 64,
89 };
90 HidReaderWriter::<_, RRP_HID_BUFFER_SIZE, RRP_HID_BUFFER_SIZE>::new(
91 &mut builder,
92 singleton!(State::new(), State),
93 config,
94 )
95 };
96
97 let raw_hid = {
98 let config = embassy_usb::class::hid::Config {
99 report_descriptor: RawHidReport::desc(),
100 request_handler: None,
101 poll_ms: 1,
102 max_packet_size: 64,
103 };
104 HidReaderWriter::<_, RAW_HID_BUFFER_SIZE, RAW_HID_BUFFER_SIZE>::new(
105 &mut builder,
106 singleton!(State::new(), State),
107 config,
108 )
109 };
110
111 #[cfg(feature = "defmt-usb")]
112 let defmt_usb = embassy_usb::class::cdc_acm::CdcAcmClass::new(
113 &mut builder,
114 singleton!(
115 embassy_usb::class::cdc_acm::State::new(),
116 embassy_usb::class::cdc_acm::State
117 ),
118 64,
119 );
120
121 Self {
122 builder,
123 keyboard_hid,
124 mouse_hid,
125 media_key_hid,
126 rrp_hid,
127 #[cfg(feature = "usb-remote-wakeup")]
128 wakeup_signal,
129 ready_signal,
130 #[cfg(feature = "defmt-usb")]
131 defmt_usb,
132 #[cfg(feature = "defmt-usb")]
133 defmt_usb_use_dtr: opts.defmt_usb_use_dtr,
134 raw_hid,
135 }
136 }
137}
138
139impl<D: Driver<'static> + 'static> UsbReporterDriverBuilder for CommonUsbReporterBuilder<D> {
140 type Output = CommonUsbDriver;
141
142 type Error = embassy_executor::SpawnError;
143
144 #[allow(refining_impl_trait)]
145 async fn build(self) -> Result<(Self::Output, impl Future<Output = ()>), Self::Error> {
146 let usb = self.builder.build();
147
148 Ok((
149 CommonUsbDriver {
150 #[cfg(feature = "usb-remote-wakeup")]
151 wakeup_signal: self.wakeup_signal,
152 ready_signal: self.ready_signal,
153 },
154 usb_task(
155 usb,
156 #[cfg(feature = "usb-remote-wakeup")]
157 self.wakeup_signal,
158 self.ready_signal,
159 self.keyboard_hid,
160 self.media_key_hid,
161 self.mouse_hid,
162 self.rrp_hid,
163 self.raw_hid,
164 #[cfg(feature = "defmt-usb")]
165 self.defmt_usb,
166 #[cfg(feature = "defmt-usb")]
167 self.defmt_usb_use_dtr,
168 ),
169 ))
170 }
171}