components/
keyboard_hid.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2023.
4
5//! Component for USB HID keyboard support.
6//!
7//! Usage
8//! -----
9//!
10//! ```
11//! let strings = static_init!(
12//!     [&str; 3],
13//!     [
14//!         "Nordic Semiconductor", // Manufacturer
15//!         "nRF52840dk - TockOS",  // Product
16//!         "serial0001",           // Serial number
17//!     ]
18//! );
19//!
20//! let (keyboard_hid, keyboard_hid_driver) = components::keyboard_hid::KeyboardHidComponent::new(
21//!     board_kernel,
22//!     capsules_core::driver::KeyboardHid,
23//!     &nrf52840_peripherals.usbd,
24//!     0x1915, // Nordic Semiconductor
25//!     0x503a,
26//!     strings,
27//! )
28//! .finalize(components::keyboard_hid_component_static!(
29//!     nrf52840::usbd::Usbd
30//! ));
31//!
32//! keyboard_hid.enable();
33//! keyboard_hid.attach();
34//! ```
35
36use core::mem::MaybeUninit;
37use kernel::capabilities;
38use kernel::component::Component;
39use kernel::create_capability;
40use kernel::hil;
41
42// Setup static space for the objects.
43#[macro_export]
44macro_rules! keyboard_hid_component_static {
45    ($U:ty $(,)?) => {{
46        let hid = kernel::static_buf!(capsules_extra::usb::keyboard_hid::KeyboardHid<'static, $U>);
47        let driver = kernel::static_buf!(
48            capsules_extra::usb_hid_driver::UsbHidDriver<
49                'static,
50                capsules_extra::usb::keyboard_hid::KeyboardHid<'static, $U>,
51            >
52        );
53        let send_buffer = kernel::static_buf!([u8; 64]);
54        let recv_buffer = kernel::static_buf!([u8; 64]);
55
56        (hid, driver, send_buffer, recv_buffer)
57    };};
58}
59
60pub type KeyboardHidComponentType<U> = capsules_extra::usb_hid_driver::UsbHidDriver<
61    'static,
62    capsules_extra::usb::keyboard_hid::KeyboardHid<'static, U>,
63>;
64
65pub struct KeyboardHidComponent<U: 'static + hil::usb::UsbController<'static>> {
66    board_kernel: &'static kernel::Kernel,
67    driver_num: usize,
68    usb: &'static U,
69    vendor_id: u16,
70    product_id: u16,
71    strings: &'static [&'static str; 3],
72}
73
74impl<U: 'static + hil::usb::UsbController<'static>> KeyboardHidComponent<U> {
75    pub fn new(
76        board_kernel: &'static kernel::Kernel,
77        driver_num: usize,
78        usb: &'static U,
79        vendor_id: u16,
80        product_id: u16,
81        strings: &'static [&'static str; 3],
82    ) -> KeyboardHidComponent<U> {
83        KeyboardHidComponent {
84            board_kernel,
85            driver_num,
86            usb,
87            vendor_id,
88            product_id,
89            strings,
90        }
91    }
92}
93
94impl<U: 'static + hil::usb::UsbController<'static>> Component for KeyboardHidComponent<U> {
95    type StaticInput = (
96        &'static mut MaybeUninit<capsules_extra::usb::keyboard_hid::KeyboardHid<'static, U>>,
97        &'static mut MaybeUninit<
98            capsules_extra::usb_hid_driver::UsbHidDriver<
99                'static,
100                capsules_extra::usb::keyboard_hid::KeyboardHid<'static, U>,
101            >,
102        >,
103        &'static mut MaybeUninit<[u8; 64]>,
104        &'static mut MaybeUninit<[u8; 64]>,
105    );
106    type Output = (
107        &'static capsules_extra::usb::keyboard_hid::KeyboardHid<'static, U>,
108        &'static capsules_extra::usb_hid_driver::UsbHidDriver<
109            'static,
110            capsules_extra::usb::keyboard_hid::KeyboardHid<'static, U>,
111        >,
112    );
113
114    fn finalize(self, s: Self::StaticInput) -> Self::Output {
115        let keyboard_hid =
116            s.0.write(capsules_extra::usb::keyboard_hid::KeyboardHid::new(
117                self.usb,
118                self.vendor_id,
119                self.product_id,
120                self.strings,
121            ));
122        self.usb.set_client(keyboard_hid);
123
124        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
125
126        let send_buffer = s.2.write([0; 64]);
127        let recv_buffer = s.3.write([0; 64]);
128
129        let usb_hid_driver = s.1.write(capsules_extra::usb_hid_driver::UsbHidDriver::new(
130            keyboard_hid,
131            send_buffer,
132            recv_buffer,
133            self.board_kernel.create_grant(self.driver_num, &grant_cap),
134        ));
135
136        keyboard_hid.set_client(usb_hid_driver);
137
138        (keyboard_hid, usb_hid_driver)
139    }
140}