Skip to main content
RKTK API Docs RKTK Home Repo

rktk_drivers_common/usb/
builder.rs

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
21/// General usb driver using embassy-usb.
22pub 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}