1use core::mem::MaybeUninit;
28
29use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
30use kernel::component::Component;
31use kernel::hil;
32use kernel::hil::time::Alarm;
33
34#[macro_export]
36macro_rules! cdc_acm_component_static {
37    ($U:ty, $A:ty $(,)?) => {{
38        let alarm = kernel::static_buf!(
39            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
40        );
41        let cdc = kernel::static_buf!(
42            capsules_extra::usb::cdc::CdcAcm<
43                'static,
44                $U,
45                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
46            >
47        );
48
49        (alarm, cdc)
50    };};
51}
52
53pub struct CdcAcmComponent<
54    U: 'static + hil::usb::UsbController<'static>,
55    A: 'static + Alarm<'static>,
56> {
57    usb: &'static U,
58    max_ctrl_packet_size: u8,
59    vendor_id: u16,
60    product_id: u16,
61    strings: &'static [&'static str; 3],
62    alarm_mux: &'static MuxAlarm<'static, A>,
63    host_initiated_function: Option<&'static (dyn Fn() + 'static)>,
64}
65
66impl<U: 'static + hil::usb::UsbController<'static>, A: 'static + Alarm<'static>>
67    CdcAcmComponent<U, A>
68{
69    pub fn new(
70        usb: &'static U,
71        max_ctrl_packet_size: u8,
72        vendor_id: u16,
73        product_id: u16,
74        strings: &'static [&'static str; 3],
75        alarm_mux: &'static MuxAlarm<'static, A>,
76        host_initiated_function: Option<&'static (dyn Fn() + 'static)>,
77    ) -> Self {
78        Self {
79            usb,
80            max_ctrl_packet_size,
81            vendor_id,
82            product_id,
83            strings,
84            alarm_mux,
85            host_initiated_function,
86        }
87    }
88}
89
90impl<U: 'static + hil::usb::UsbController<'static>, A: 'static + Alarm<'static>> Component
91    for CdcAcmComponent<U, A>
92{
93    type StaticInput = (
94        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
95        &'static mut MaybeUninit<
96            capsules_extra::usb::cdc::CdcAcm<'static, U, VirtualMuxAlarm<'static, A>>,
97        >,
98    );
99    type Output =
100        &'static capsules_extra::usb::cdc::CdcAcm<'static, U, VirtualMuxAlarm<'static, A>>;
101
102    fn finalize(self, s: Self::StaticInput) -> Self::Output {
103        let cdc_alarm = s.0.write(VirtualMuxAlarm::new(self.alarm_mux));
104        cdc_alarm.setup();
105
106        let cdc = s.1.write(capsules_extra::usb::cdc::CdcAcm::new(
107            self.usb,
108            self.max_ctrl_packet_size,
109            self.vendor_id,
110            self.product_id,
111            self.strings,
112            cdc_alarm,
113            self.host_initiated_function,
114        ));
115        kernel::deferred_call::DeferredCallClient::register(cdc);
116        self.usb.set_client(cdc);
117        cdc_alarm.set_alarm_client(cdc);
118
119        cdc
120    }
121}