1use embassy_usb::{
2 Builder,
3 class::hid::{HidBootProtocol, HidReaderWriter, HidSubclass, 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 hid_boot_protocol: HidBootProtocol::Keyboard,
62 hid_subclass: HidSubclass::Boot,
63 };
64 HidReaderWriter::<_, 1, 8>::new(&mut builder, singleton!(State::new(), State), config)
65 };
66 let mouse_hid = {
67 let config = embassy_usb::class::hid::Config {
68 report_descriptor: MouseReport::desc(),
69 request_handler: None,
70 poll_ms: opts.mouse_poll_interval,
71 max_packet_size: 64,
72 hid_boot_protocol: HidBootProtocol::Keyboard,
73 hid_subclass: HidSubclass::Boot,
74 };
75 HidWriter::<_, 8>::new(&mut builder, singleton!(State::new(), State), config)
76 };
77 let media_key_hid = {
78 let config = embassy_usb::class::hid::Config {
79 report_descriptor: MediaKeyboardReport::desc(),
80 request_handler: None,
81 poll_ms: opts.keyboard_poll_interval,
82 max_packet_size: 64,
83 hid_boot_protocol: HidBootProtocol::None,
84 hid_subclass: HidSubclass::No,
85 };
86 HidWriter::<_, 8>::new(&mut builder, singleton!(State::new(), State), config)
87 };
88
89 let rrp_hid = {
90 let config = embassy_usb::class::hid::Config {
91 report_descriptor: RrpReport::desc(),
92 request_handler: None,
93 poll_ms: 1,
94 max_packet_size: 64,
95 hid_boot_protocol: HidBootProtocol::None,
96 hid_subclass: HidSubclass::No,
97 };
98 HidReaderWriter::<_, RRP_HID_BUFFER_SIZE, RRP_HID_BUFFER_SIZE>::new(
99 &mut builder,
100 singleton!(State::new(), State),
101 config,
102 )
103 };
104
105 let raw_hid = {
106 let config = embassy_usb::class::hid::Config {
107 report_descriptor: RawHidReport::desc(),
108 request_handler: None,
109 poll_ms: 1,
110 max_packet_size: 64,
111 hid_boot_protocol: HidBootProtocol::None,
112 hid_subclass: HidSubclass::No,
113 };
114 HidReaderWriter::<_, RAW_HID_BUFFER_SIZE, RAW_HID_BUFFER_SIZE>::new(
115 &mut builder,
116 singleton!(State::new(), State),
117 config,
118 )
119 };
120
121 #[cfg(feature = "defmt-usb")]
122 let defmt_usb = embassy_usb::class::cdc_acm::CdcAcmClass::new(
123 &mut builder,
124 singleton!(
125 embassy_usb::class::cdc_acm::State::new(),
126 embassy_usb::class::cdc_acm::State
127 ),
128 64,
129 );
130
131 Self {
132 builder,
133 keyboard_hid,
134 mouse_hid,
135 media_key_hid,
136 rrp_hid,
137 #[cfg(feature = "usb-remote-wakeup")]
138 wakeup_signal,
139 ready_signal,
140 #[cfg(feature = "defmt-usb")]
141 defmt_usb,
142 #[cfg(feature = "defmt-usb")]
143 defmt_usb_use_dtr: opts.defmt_usb_use_dtr,
144 raw_hid,
145 }
146 }
147}
148
149impl<D: Driver<'static> + 'static> UsbReporterDriverBuilder for CommonUsbReporterBuilder<D> {
150 type Output = CommonUsbDriver;
151
152 type Error = embassy_executor::SpawnError;
153
154 #[allow(refining_impl_trait)]
155 async fn build(self) -> Result<(Self::Output, impl Future<Output = ()>), Self::Error> {
156 let usb = self.builder.build();
157
158 Ok((
159 CommonUsbDriver {
160 #[cfg(feature = "usb-remote-wakeup")]
161 wakeup_signal: self.wakeup_signal,
162 ready_signal: self.ready_signal,
163 },
164 usb_task(
165 usb,
166 #[cfg(feature = "usb-remote-wakeup")]
167 self.wakeup_signal,
168 self.ready_signal,
169 self.keyboard_hid,
170 self.media_key_hid,
171 self.mouse_hid,
172 self.rrp_hid,
173 self.raw_hid,
174 #[cfg(feature = "defmt-usb")]
175 self.defmt_usb,
176 #[cfg(feature = "defmt-usb")]
177 self.defmt_usb_use_dtr,
178 ),
179 ))
180 }
181}