RKTK API Docs RKTK Home Repo

rktk_drivers_common/usb/
builder.rs

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
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            };
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}