capsules_extra/ieee802154/
mac.rs1use crate::net::ieee802154::{Header, MacAddress};
19use kernel::hil::radio::{self, MAX_FRAME_SIZE, PSDU_OFFSET};
20use kernel::utilities::cells::OptionalCell;
21use kernel::ErrorCode;
22
23pub trait Mac<'a> {
24    fn initialize(&self) -> Result<(), ErrorCode>;
26
27    fn set_config_client(&self, client: &'a dyn radio::ConfigClient);
29    fn set_transmit_client(&self, client: &'a dyn radio::TxClient);
31    fn set_receive_client(&self, client: &'a dyn radio::RxClient);
33    fn set_receive_buffer(&self, buffer: &'static mut [u8]);
35
36    fn get_address(&self) -> u16;
38    fn get_address_long(&self) -> [u8; 8];
40    fn get_pan(&self) -> u16;
42
43    fn set_address(&self, addr: u16);
45    fn set_address_long(&self, addr: [u8; 8]);
47    fn set_pan(&self, id: u16);
49
50    fn config_commit(&self);
56
57    fn is_on(&self) -> bool;
59
60    fn start(&self) -> Result<(), ErrorCode>;
70
71    fn transmit(
74        &self,
75        full_mac_frame: &'static mut [u8],
76        frame_len: usize,
77    ) -> Result<(), (ErrorCode, &'static mut [u8])>;
78}
79
80pub struct AwakeMac<'a, R: radio::Radio<'a>> {
86    radio: &'a R,
87
88    tx_client: OptionalCell<&'a dyn radio::TxClient>,
89    rx_client: OptionalCell<&'a dyn radio::RxClient>,
90}
91
92impl<'a, R: radio::Radio<'a>> AwakeMac<'a, R> {
93    pub fn new(radio: &'a R) -> AwakeMac<'a, R> {
94        AwakeMac {
95            radio,
96            tx_client: OptionalCell::empty(),
97            rx_client: OptionalCell::empty(),
98        }
99    }
100}
101
102impl<'a, R: radio::Radio<'a>> Mac<'a> for AwakeMac<'a, R> {
103    fn initialize(&self) -> Result<(), ErrorCode> {
104        Ok(())
106    }
107
108    fn is_on(&self) -> bool {
109        self.radio.is_on()
110    }
111
112    fn start(&self) -> Result<(), ErrorCode> {
113        self.radio.start()
114    }
115
116    fn set_config_client(&self, client: &'a dyn radio::ConfigClient) {
117        self.radio.set_config_client(client)
118    }
119
120    fn set_address(&self, addr: u16) {
121        self.radio.set_address(addr)
122    }
123
124    fn set_address_long(&self, addr: [u8; 8]) {
125        self.radio.set_address_long(addr)
126    }
127
128    fn set_pan(&self, id: u16) {
129        self.radio.set_pan(id)
130    }
131
132    fn get_address(&self) -> u16 {
133        self.radio.get_address()
134    }
135
136    fn get_address_long(&self) -> [u8; 8] {
137        self.radio.get_address_long()
138    }
139
140    fn get_pan(&self) -> u16 {
141        self.radio.get_pan()
142    }
143
144    fn config_commit(&self) {
145        self.radio.config_commit()
146    }
147
148    fn set_transmit_client(&self, client: &'a dyn radio::TxClient) {
149        self.tx_client.set(client);
150    }
151
152    fn set_receive_client(&self, client: &'a dyn radio::RxClient) {
153        self.rx_client.set(client);
154    }
155
156    fn set_receive_buffer(&self, buffer: &'static mut [u8]) {
157        self.radio.set_receive_buffer(buffer);
158    }
159
160    fn transmit(
161        &self,
162        full_mac_frame: &'static mut [u8],
163        frame_len: usize,
164    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
165        if full_mac_frame.len() < frame_len + PSDU_OFFSET {
170            return Err((ErrorCode::NOMEM, full_mac_frame));
171        }
172
173        if frame_len > MAX_FRAME_SIZE {
174            return Err((ErrorCode::INVAL, full_mac_frame));
175        }
176
177        full_mac_frame.copy_within(0..frame_len, PSDU_OFFSET);
178        self.radio.transmit(full_mac_frame, frame_len)
179    }
180}
181
182impl<'a, R: radio::Radio<'a>> radio::TxClient for AwakeMac<'a, R> {
183    fn send_done(&self, buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) {
184        self.tx_client.map(move |c| {
185            c.send_done(buf, acked, result);
186        });
187    }
188}
189
190impl<'a, R: radio::Radio<'a>> radio::RxClient for AwakeMac<'a, R> {
191    fn receive(
192        &self,
193        buf: &'static mut [u8],
194        frame_len: usize,
195        lqi: u8,
196        crc_valid: bool,
197        result: Result<(), ErrorCode>,
198    ) {
199        let mut addr_match = false;
201        if let Some((_, (header, _))) = Header::decode(&buf[radio::PSDU_OFFSET..], false).done() {
202            if let Some(dst_addr) = header.dst_addr {
203                addr_match = match dst_addr {
204                    MacAddress::Short(addr) => {
205                        (addr == self.radio.get_address()) || (addr == 0xFFFF)
207                    }
208                    MacAddress::Long(long_addr) => long_addr == self.radio.get_address_long(),
209                };
210            }
211        }
212        if addr_match {
213            self.rx_client.map(move |c| {
215                c.receive(buf, frame_len, lqi, crc_valid, result);
216            });
217        } else {
218            self.radio.set_receive_buffer(buf);
220        }
221    }
222}