1use core::mem::MaybeUninit;
35use kernel::capabilities;
36use kernel::component::Component;
37use kernel::create_capability;
38use kernel::hil;
39
40#[macro_export]
42macro_rules! ctap_component_static {
43    ($U:ty $(,)?) => {{
44        let hid = kernel::static_buf!(capsules_extra::usb::ctap::CtapHid<'static, $U>);
45        let driver = kernel::static_buf!(
46            capsules_extra::usb_hid_driver::UsbHidDriver<
47                'static,
48                capsules_extra::usb::usb_hid_driver::UsbHidDriver<'static, $U>,
49            >
50        );
51        let send_buffer = kernel::static_buf!([u8; 64]);
52        let recv_buffer = kernel::static_buf!([u8; 64]);
53
54        (hid, driver, send_buffer, recv_buffer)
55    };};
56}
57
58pub struct CtapComponent<U: 'static + hil::usb::UsbController<'static>> {
59    board_kernel: &'static kernel::Kernel,
60    driver_num: usize,
61    usb: &'static U,
62    vendor_id: u16,
63    product_id: u16,
64    strings: &'static [&'static str; 3],
65}
66
67impl<U: 'static + hil::usb::UsbController<'static>> CtapComponent<U> {
68    pub fn new(
69        board_kernel: &'static kernel::Kernel,
70        driver_num: usize,
71        usb: &'static U,
72        vendor_id: u16,
73        product_id: u16,
74        strings: &'static [&'static str; 3],
75    ) -> CtapComponent<U> {
76        CtapComponent {
77            board_kernel,
78            driver_num,
79            usb,
80            vendor_id,
81            product_id,
82            strings,
83        }
84    }
85}
86
87impl<U: 'static + hil::usb::UsbController<'static>> Component for CtapComponent<U> {
88    type StaticInput = (
89        &'static mut MaybeUninit<capsules_extra::usb::ctap::CtapHid<'static, U>>,
90        &'static mut MaybeUninit<
91            capsules_extra::usb_hid_driver::UsbHidDriver<
92                'static,
93                capsules_extra::usb::ctap::CtapHid<'static, U>,
94            >,
95        >,
96        &'static mut MaybeUninit<[u8; 64]>,
97        &'static mut MaybeUninit<[u8; 64]>,
98    );
99    type Output = (
100        &'static capsules_extra::usb::ctap::CtapHid<'static, U>,
101        &'static capsules_extra::usb_hid_driver::UsbHidDriver<
102            'static,
103            capsules_extra::usb::ctap::CtapHid<'static, U>,
104        >,
105    );
106
107    fn finalize(self, s: Self::StaticInput) -> Self::Output {
108        let ctap = s.0.write(capsules_extra::usb::ctap::CtapHid::new(
109            self.usb,
110            self.vendor_id,
111            self.product_id,
112            self.strings,
113        ));
114        self.usb.set_client(ctap);
115
116        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
117
118        let send_buffer = s.2.write([0; 64]);
119        let recv_buffer = s.3.write([0; 64]);
120
121        let ctap_driver = s.1.write(capsules_extra::usb_hid_driver::UsbHidDriver::new(
122            ctap,
123            send_buffer,
124            recv_buffer,
125            self.board_kernel.create_grant(self.driver_num, &grant_cap),
126        ));
127
128        ctap.set_client(ctap_driver);
129
130        (ctap, ctap_driver)
131    }
132}