1use capsules_core::button::Button;
36use core::mem::MaybeUninit;
37use kernel::capabilities;
38use kernel::component::Component;
39use kernel::create_capability;
40use kernel::hil::gpio;
41use kernel::hil::gpio::InterruptWithValue;
42
43#[macro_export]
44macro_rules! button_component_helper_owned {
45    ($Pin:ty, $(($P:expr, $M:expr, $F:expr)),+ $(,)?) => {
46        $crate::button_component_helper!(
47            $Pin,
48            $((
49                static_init!($Pin, $P),
50                $M,
51                $F
52            ),)*
53        )
54    };
55}
56
57#[macro_export]
58macro_rules! button_component_helper {
59    ($Pin:ty, $(($P:expr, $M:expr, $F:expr)),+ $(,)?) => {{
60        use kernel::static_init;
61        use kernel::count_expressions;
62        use kernel::hil::gpio::InterruptValueWrapper;
63        const NUM_BUTTONS: usize = count_expressions!($($P),+);
64
65        static_init!(
66            [(&'static InterruptValueWrapper<'static, $Pin>, kernel::hil::gpio::ActivationMode, kernel::hil::gpio::FloatingState); NUM_BUTTONS],
67            [
68                $(
69                    (static_init!(InterruptValueWrapper<$Pin>, InterruptValueWrapper::new($P))
70                    .finalize(),
71                    $M,
72                    $F
73                    ),
74                )*
75            ]
76        )
77    };};
78}
79
80#[macro_export]
81macro_rules! button_component_static {
82    ($Pin:ty $(,)?) => {{
83        kernel::static_buf!(capsules_core::button::Button<'static, $Pin>)
84    };};
85}
86
87pub type ButtonComponentType<IP> = capsules_core::button::Button<'static, IP>;
88
89pub struct ButtonComponent<IP: 'static + gpio::InterruptPin<'static>> {
90    board_kernel: &'static kernel::Kernel,
91    driver_num: usize,
92    button_pins: &'static [(
93        &'static gpio::InterruptValueWrapper<'static, IP>,
94        gpio::ActivationMode,
95        gpio::FloatingState,
96    )],
97}
98
99impl<IP: 'static + gpio::InterruptPin<'static>> ButtonComponent<IP> {
100    pub fn new(
101        board_kernel: &'static kernel::Kernel,
102        driver_num: usize,
103        button_pins: &'static [(
104            &'static gpio::InterruptValueWrapper<'static, IP>,
105            gpio::ActivationMode,
106            gpio::FloatingState,
107        )],
108    ) -> Self {
109        Self {
110            board_kernel,
111            driver_num,
112            button_pins,
113        }
114    }
115}
116
117impl<IP: 'static + gpio::InterruptPin<'static>> Component for ButtonComponent<IP> {
118    type StaticInput = &'static mut MaybeUninit<Button<'static, IP>>;
119    type Output = &'static Button<'static, IP>;
120
121    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
122        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
123        let button = static_buffer.write(capsules_core::button::Button::new(
124            self.button_pins,
125            self.board_kernel.create_grant(self.driver_num, &grant_cap),
126        ));
127        for (pin, _, _) in self.button_pins.iter() {
128            pin.set_client(button);
129        }
130
131        button
132    }
133}