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}