capsules_extra/ieee802154/
virtual_mac.rs1use crate::ieee802154::{device, framer};
36use crate::net::ieee802154::{Header, KeyId, MacAddress, PanID, SecurityLevel};
37
38use kernel::collections::list::{List, ListLink, ListNode};
39use kernel::utilities::cells::{MapCell, OptionalCell};
40use kernel::ErrorCode;
41
42pub struct MuxMac<'a, M: device::MacDevice<'a>> {
46    mac: &'a M,
47    users: List<'a, MacUser<'a, M>>,
48    inflight: OptionalCell<&'a MacUser<'a, M>>,
49}
50
51impl<'a, M: device::MacDevice<'a>> device::TxClient for MuxMac<'a, M> {
52    fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) {
53        self.inflight.take().map(move |user| {
54            user.send_done(spi_buf, acked, result);
55        });
56        self.do_next_op_async();
57    }
58}
59
60impl<'a, M: device::MacDevice<'a>> device::RxClient for MuxMac<'a, M> {
61    fn receive<'b>(
62        &self,
63        buf: &'b [u8],
64        header: Header<'b>,
65        lqi: u8,
66        data_offset: usize,
67        data_len: usize,
68    ) {
69        for user in self.users.iter() {
70            user.receive(buf, header, lqi, data_offset, data_len);
71        }
72    }
73}
74
75impl<'a, M: device::MacDevice<'a>> MuxMac<'a, M> {
76    pub const fn new(mac: &'a M) -> MuxMac<'a, M> {
77        MuxMac {
78            mac,
79            users: List::new(),
80            inflight: OptionalCell::empty(),
81        }
82    }
83
84    pub fn add_user(&self, user: &'a MacUser<'a, M>) {
87        self.users.push_head(user);
88    }
89
90    fn get_next_op_if_idle(&self) -> Option<(&'a MacUser<'a, M>, Op)> {
93        if self.inflight.is_some() {
94            return None;
95        }
96
97        let mnode = self.users.iter().find(|node| {
98            node.operation.take().is_some_and(|op| {
99                let pending = op != Op::Idle;
100                node.operation.replace(op);
101                pending
102            })
103        });
104        mnode.and_then(|node| {
105            node.operation.take().map(|op| {
106                node.operation.replace(Op::Idle);
107                (node, op)
108            })
109        })
110    }
111
112    fn perform_op_async(&self, node: &'a MacUser<'a, M>, op: Op) {
116        if let Op::Transmit(frame) = op {
117            match self.mac.transmit(frame) {
118                Ok(()) => {
121                    self.inflight.set(node);
122                }
123                Err((ecode, buf)) => {
124                    node.send_done(buf, false, Err(ecode));
125                }
126            }
127        }
128    }
129
130    fn perform_op_sync(
133        &self,
134        node: &'a MacUser<'a, M>,
135        op: Op,
136    ) -> Option<Result<(), (ErrorCode, &'static mut [u8])>> {
137        if let Op::Transmit(frame) = op {
138            let result = self.mac.transmit(frame);
139            if result.is_ok() {
140                self.inflight.set(node);
141            }
142            Some(result)
143        } else {
144            None
145        }
146    }
147
148    fn do_next_op_async(&self) {
153        self.get_next_op_if_idle()
154            .map(|(node, op)| self.perform_op_async(node, op));
155    }
156
157    fn do_next_op_sync(
169        &self,
170        new_node: &MacUser<'a, M>,
171    ) -> Option<Result<(), (ErrorCode, &'static mut [u8])>> {
172        self.get_next_op_if_idle().and_then(|(node, op)| {
173            if core::ptr::eq(node, new_node) {
174                self.perform_op_sync(node, op)
177            } else {
178                self.perform_op_async(node, op);
181                None
182            }
183        })
184    }
185}
186
187#[derive(Eq, PartialEq, Debug)]
188enum Op {
189    Idle,
190    Transmit(framer::Frame),
191}
192
193pub struct MacUser<'a, M: device::MacDevice<'a>> {
204    mux: &'a MuxMac<'a, M>,
205    operation: MapCell<Op>,
206    next: ListLink<'a, MacUser<'a, M>>,
207    tx_client: OptionalCell<&'a dyn device::TxClient>,
208    rx_client: OptionalCell<&'a dyn device::RxClient>,
209}
210
211impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> {
212    pub const fn new(mux: &'a MuxMac<'a, M>) -> Self {
213        Self {
214            mux,
215            operation: MapCell::new(Op::Idle),
216            next: ListLink::empty(),
217            tx_client: OptionalCell::empty(),
218            rx_client: OptionalCell::empty(),
219        }
220    }
221}
222
223impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> {
224    fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) {
225        self.tx_client
226            .get()
227            .map(move |client| client.send_done(spi_buf, acked, result));
228    }
229
230    fn receive<'b>(
231        &self,
232        buf: &'b [u8],
233        header: Header<'b>,
234        lqi: u8,
235        data_offset: usize,
236        data_len: usize,
237    ) {
238        self.rx_client
239            .get()
240            .map(move |client| client.receive(buf, header, lqi, data_offset, data_len));
241    }
242}
243
244impl<'a, M: device::MacDevice<'a>> ListNode<'a, MacUser<'a, M>> for MacUser<'a, M> {
245    fn next(&'a self) -> &'a ListLink<'a, MacUser<'a, M>> {
246        &self.next
247    }
248}
249
250impl<'a, M: device::MacDevice<'a>> device::MacDevice<'a> for MacUser<'a, M> {
251    fn set_transmit_client(&self, client: &'a dyn device::TxClient) {
252        self.tx_client.set(client);
253    }
254
255    fn set_receive_client(&self, client: &'a dyn device::RxClient) {
256        self.rx_client.set(client);
257    }
258
259    fn get_address(&self) -> u16 {
260        self.mux.mac.get_address()
261    }
262
263    fn get_address_long(&self) -> [u8; 8] {
264        self.mux.mac.get_address_long()
265    }
266
267    fn get_pan(&self) -> u16 {
268        self.mux.mac.get_pan()
269    }
270
271    fn set_address(&self, addr: u16) {
272        self.mux.mac.set_address(addr)
273    }
274
275    fn set_address_long(&self, addr: [u8; 8]) {
276        self.mux.mac.set_address_long(addr)
277    }
278
279    fn set_pan(&self, id: u16) {
280        self.mux.mac.set_pan(id)
281    }
282
283    fn config_commit(&self) {
284        self.mux.mac.config_commit()
285    }
286
287    fn is_on(&self) -> bool {
288        self.mux.mac.is_on()
289    }
290
291    fn start(&self) -> Result<(), ErrorCode> {
292        self.mux.mac.start()
293    }
294
295    fn prepare_data_frame(
296        &self,
297        buf: &'static mut [u8],
298        dst_pan: PanID,
299        dst_addr: MacAddress,
300        src_pan: PanID,
301        src_addr: MacAddress,
302        security_needed: Option<(SecurityLevel, KeyId)>,
303    ) -> Result<framer::Frame, &'static mut [u8]> {
304        self.mux
305            .mac
306            .prepare_data_frame(buf, dst_pan, dst_addr, src_pan, src_addr, security_needed)
307    }
308
309    fn transmit(&self, frame: framer::Frame) -> Result<(), (ErrorCode, &'static mut [u8])> {
310        match self.operation.take() {
315            None => Err((ErrorCode::FAIL, frame.into_buf())),
316            Some(op) => match op {
317                Op::Idle => {
318                    self.operation.replace(Op::Transmit(frame));
319                    self.mux.do_next_op_sync(self).unwrap_or(Ok(()))
320                }
321                Op::Transmit(old_frame) => {
322                    self.operation.replace(Op::Transmit(old_frame));
323                    Err((ErrorCode::BUSY, frame.into_buf()))
324                }
325            },
326        }
327    }
328}