capsules_extra/ieee802154/
driver.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! IEEE 802.15.4 userspace interface for configuration and transmit/receive.
6//!
7//! Implements a userspace interface for sending and receiving IEEE 802.15.4
8//! frames. Also provides a minimal list-based interface for managing keys and
9//! known link neighbors, which is needed for 802.15.4 security.
10//!
11//! The driver functionality can be divided into three aspects: sending
12//! packets, receiving packets, and managing the 15.4 state (i.e. keys, neighbors,
13//! buffers, addressing, etc). The general design and procedure for sending and
14//! receiving is discussed below.
15//!
16//! Sending - The driver supports two modes of sending: Raw and Parse. In Raw mode,
17//! the userprocess fully forms the 15.4 frame and passes it to the driver. In Parse
18//! mode, the userprocess provides the payload and relevant metadata. From this
19//! the driver forms the 15.4 header and secures the payload. To send a packet,
20//! the userprocess issues the respective send command syscall (corresponding to
21//! raw or parse mode of sending). The 15.4 capsule will then schedule an upcall,
22//! upon completion of the transmission, to notify the process.
23//!
24//! Receiving - The driver receives 15.4 frames and passes them to the userprocess.
25//! To accomplish this, the userprocess must first `allow` a read/write ring buffer
26//! to the kernel. The kernel will then fill this buffer with received frames and
27//! schedule an upcall upon receipt of the first packet. When handling the upcall
28//! the userprocess must first `unallow` the buffer as described in section 4.4 of
29//! TRD104-syscalls. After unallowing the buffer, the userprocess must then immediately
30//! clear all pending/scheduled receive upcalls. This is done by either unsubscribing
31//! the receive upcall or subscribing a new receive upcall. Because the userprocess
32//! provides the buffer, it is responsible for adhering to this procedure. Failure
33//! to comply may result in dropped or malformed packets.
34//!
35//! The ring buffer provided by the userprocess must be of the form:
36//!
37//! ```text
38//! | read index | write index | user_frame 0 | user_frame 1 | ... | user_frame n |
39//! ```
40//!
41//! `user_frame` denotes the 15.4 frame in addition to the relevant 3 bytes of
42//! metadata (offset to data payload, length of data payload, and the MIC len). The
43//! capsule assumes that this is the form of the buffer. Errors or deviation in
44//! the form of the provided buffer will likely result in incomplete or dropped packets.
45//!
46//! Because the scheduled receive upcall must be handled by the userprocess, there is
47//! no guarantee as to when this will occur and if additional packets will be received
48//! prior to the upcall being handled. Without a ring buffer (or some equivalent data
49//! structure), the original packet will be lost. The ring buffer allows for the upcall
50//! to be scheduled and for all received packets to be passed to the process. The ring
51//! buffer is designed to overwrite old packets if the buffer becomes full. If the
52//! userprocess notices a high number of "dropped" packets, this may be the cause. The
53//! userproceess can mitigate this issue by increasing the size of the ring buffer
54//! provided to the capsule.
55
56use crate::ieee802154::{device, framer};
57use crate::net::ieee802154::{Header, KeyId, MacAddress, SecurityLevel};
58use crate::net::stream::{decode_bytes, decode_u8, encode_bytes, encode_u8, SResult};
59
60use core::cell::Cell;
61
62use kernel::deferred_call::{DeferredCall, DeferredCallClient};
63use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
64use kernel::hil::radio;
65use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
66use kernel::syscall::{CommandReturn, SyscallDriver};
67use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell};
68use kernel::{ErrorCode, ProcessId};
69
70const MAX_NEIGHBORS: usize = 4;
71const MAX_KEYS: usize = 4;
72
73const USER_FRAME_METADATA_SIZE: usize = 3; // 3B metadata (offset, len, mic_len)
74const USER_FRAME_MAX_SIZE: usize = USER_FRAME_METADATA_SIZE + radio::MAX_FRAME_SIZE; // 3B metadata + 127B max payload
75
76/// IDs for subscribed upcalls.
77mod upcall {
78    /// Frame is received
79    pub const FRAME_RECEIVED: usize = 0;
80    /// Frame is transmitted
81    pub const FRAME_TRANSMITTED: usize = 1;
82    /// Number of upcalls.
83    pub const COUNT: u8 = 2;
84}
85
86/// Ids for read-only allow buffers
87mod ro_allow {
88    /// Write buffer. Contains the frame payload to be transmitted.
89    pub const WRITE: usize = 0;
90    /// The number of allow buffers the kernel stores for this grant
91    pub const COUNT: u8 = 1;
92}
93
94/// Ids for read-write allow buffers
95mod rw_allow {
96    /// Read buffer. Will contain the received frame.
97    pub const READ: usize = 0;
98    /// Config buffer.
99    ///
100    /// Used to contain miscellaneous data associated with some commands because
101    /// the system call parameters / return codes are not enough to convey the
102    /// desired information.
103    pub const CFG: usize = 1;
104    /// The number of allow buffers the kernel stores for this grant
105    pub const COUNT: u8 = 2;
106}
107
108use capsules_core::driver;
109pub const DRIVER_NUM: usize = driver::NUM::Ieee802154 as usize;
110
111#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
112struct DeviceDescriptor {
113    short_addr: u16,
114    long_addr: [u8; 8],
115}
116
117/// The Key ID mode mapping expected by the userland driver
118#[repr(u8)]
119#[derive(Copy, Clone, Eq, PartialEq, Debug)]
120enum KeyIdModeUserland {
121    Implicit = 0,
122    Index = 1,
123    Source4Index = 2,
124    Source8Index = 3,
125}
126
127impl KeyIdModeUserland {
128    pub fn from_u8(byte: u8) -> Option<KeyIdModeUserland> {
129        match byte {
130            0 => Some(KeyIdModeUserland::Implicit),
131            1 => Some(KeyIdModeUserland::Index),
132            2 => Some(KeyIdModeUserland::Source4Index),
133            3 => Some(KeyIdModeUserland::Source8Index),
134            _ => None,
135        }
136    }
137}
138
139/// Encodes a key ID into a buffer in the format expected by the userland driver.
140fn encode_key_id(key_id: &KeyId, buf: &mut [u8]) -> SResult {
141    let off = enc_consume!(buf; encode_u8, KeyIdModeUserland::from(key_id) as u8);
142    let off = match *key_id {
143        KeyId::Implicit => 0,
144        KeyId::Index(index) => enc_consume!(buf, off; encode_u8, index),
145        KeyId::Source4Index(ref src, index) => {
146            let off = enc_consume!(buf, off; encode_bytes, src);
147            enc_consume!(buf, off; encode_u8, index)
148        }
149        KeyId::Source8Index(ref src, index) => {
150            let off = enc_consume!(buf, off; encode_bytes, src);
151            enc_consume!(buf, off; encode_u8, index)
152        }
153    };
154    stream_done!(off);
155}
156
157/// Decodes a key ID that is in the format produced by the userland driver.
158fn decode_key_id(buf: &[u8]) -> SResult<KeyId> {
159    stream_len_cond!(buf, 1);
160    let mode = stream_from_option!(KeyIdModeUserland::from_u8(buf[0]));
161    match mode {
162        KeyIdModeUserland::Implicit => stream_done!(0, KeyId::Implicit),
163        KeyIdModeUserland::Index => {
164            let (off, index) = dec_try!(buf; decode_u8);
165            stream_done!(off, KeyId::Index(index));
166        }
167        KeyIdModeUserland::Source4Index => {
168            let mut src = [0u8; 4];
169            let off = dec_consume!(buf; decode_bytes, &mut src);
170            let (off, index) = dec_try!(buf, off; decode_u8);
171            stream_done!(off, KeyId::Source4Index(src, index));
172        }
173        KeyIdModeUserland::Source8Index => {
174            let mut src = [0u8; 8];
175            let off = dec_consume!(buf; decode_bytes, &mut src);
176            let (off, index) = dec_try!(buf, off; decode_u8);
177            stream_done!(off, KeyId::Source8Index(src, index));
178        }
179    }
180}
181
182impl From<&KeyId> for KeyIdModeUserland {
183    fn from(key_id: &KeyId) -> Self {
184        match *key_id {
185            KeyId::Implicit => KeyIdModeUserland::Implicit,
186            KeyId::Index(_) => KeyIdModeUserland::Index,
187            KeyId::Source4Index(_, _) => KeyIdModeUserland::Source4Index,
188            KeyId::Source8Index(_, _) => KeyIdModeUserland::Source8Index,
189        }
190    }
191}
192
193#[derive(Copy, Clone, Eq, PartialEq, Debug)]
194struct KeyDescriptor {
195    level: SecurityLevel,
196    key_id: KeyId,
197    key: [u8; 16],
198}
199
200impl Default for KeyDescriptor {
201    fn default() -> Self {
202        KeyDescriptor {
203            level: SecurityLevel::None,
204            key_id: KeyId::Implicit,
205            key: [0; 16],
206        }
207    }
208}
209
210impl KeyDescriptor {
211    fn decode(buf: &[u8]) -> SResult<KeyDescriptor> {
212        stream_len_cond!(buf, 27);
213        let level = stream_from_option!(SecurityLevel::from_scf(buf[0]));
214        let (_, key_id) = dec_try!(buf, 1; decode_key_id);
215        let mut key = [0u8; 16];
216        let off = dec_consume!(buf, 11; decode_bytes, &mut key);
217        stream_done!(off, KeyDescriptor { level, key_id, key });
218    }
219}
220
221#[derive(Default)]
222pub struct App {
223    pending_tx: Option<(u16, Option<(SecurityLevel, KeyId)>)>,
224}
225
226pub struct RadioDriver<'a, M: device::MacDevice<'a>> {
227    /// Underlying MAC device, possibly multiplexed
228    mac: &'a M,
229
230    /// List of (short address, long address) pairs representing IEEE 802.15.4
231    /// neighbors.
232    neighbors: MapCell<[DeviceDescriptor; MAX_NEIGHBORS]>,
233    /// Actual number of neighbors in the fixed size array of neighbors.
234    num_neighbors: Cell<usize>,
235
236    /// List of (security level, key_id, key) tuples representing IEEE 802.15.4
237    /// key descriptors.
238    keys: MapCell<[KeyDescriptor; MAX_KEYS]>,
239    /// Actual number of keys in the fixed size array of keys.
240    num_keys: Cell<usize>,
241
242    /// Grant of apps that use this radio driver.
243    apps: Grant<
244        App,
245        UpcallCount<{ upcall::COUNT }>,
246        AllowRoCount<{ ro_allow::COUNT }>,
247        AllowRwCount<{ rw_allow::COUNT }>,
248    >,
249    /// ID of app whose transmission request is being processed.
250    current_app: OptionalCell<ProcessId>,
251
252    /// Buffer that stores the IEEE 802.15.4 frame to be transmitted.
253    kernel_tx: TakeCell<'static, [u8]>,
254
255    /// Used to ensure callbacks are delivered during upcalls
256    deferred_call: DeferredCall,
257
258    /// Used to deliver callbacks to the correct app during deferred calls
259    saved_processid: OptionalCell<ProcessId>,
260
261    /// Used to save result for passing a callback from a deferred call.
262    saved_result: OptionalCell<Result<(), ErrorCode>>,
263
264    /// Used to allow Thread to specify a key procedure for 15.4 to use for link layer encryption
265    backup_key_procedure: OptionalCell<&'a dyn framer::KeyProcedure>,
266
267    /// Used to allow Thread to specify the 15.4 device procedure as used in nonce generation
268    backup_device_procedure: OptionalCell<&'a dyn framer::DeviceProcedure>,
269}
270
271impl<'a, M: device::MacDevice<'a>> RadioDriver<'a, M> {
272    pub fn new(
273        mac: &'a M,
274        grant: Grant<
275            App,
276            UpcallCount<{ upcall::COUNT }>,
277            AllowRoCount<{ ro_allow::COUNT }>,
278            AllowRwCount<{ rw_allow::COUNT }>,
279        >,
280        kernel_tx: &'static mut [u8],
281    ) -> Self {
282        Self {
283            mac,
284            neighbors: MapCell::new(Default::default()),
285            num_neighbors: Cell::new(0),
286            keys: MapCell::new(Default::default()),
287            num_keys: Cell::new(0),
288            apps: grant,
289            current_app: OptionalCell::empty(),
290            kernel_tx: TakeCell::new(kernel_tx),
291            deferred_call: DeferredCall::new(),
292            saved_processid: OptionalCell::empty(),
293            saved_result: OptionalCell::empty(),
294            backup_key_procedure: OptionalCell::empty(),
295            backup_device_procedure: OptionalCell::empty(),
296        }
297    }
298
299    pub fn set_key_procedure(&self, key_procedure: &'a dyn framer::KeyProcedure) {
300        self.backup_key_procedure.set(key_procedure);
301    }
302
303    pub fn set_device_procedure(&self, device_procedure: &'a dyn framer::DeviceProcedure) {
304        self.backup_device_procedure.set(device_procedure);
305    }
306
307    // Neighbor management functions
308
309    /// Add a new neighbor to the end of the list if there is still space
310    /// for one, returning its new index. If the neighbor already exists,
311    /// returns the index of the existing neighbor. Returns `None` if there is
312    /// no remaining space.
313    fn add_neighbor(&self, new_neighbor: DeviceDescriptor) -> Option<usize> {
314        self.neighbors.and_then(|neighbors| {
315            let num_neighbors = self.num_neighbors.get();
316            let position = neighbors[..num_neighbors]
317                .iter()
318                .position(|neighbor| *neighbor == new_neighbor);
319            match position {
320                Some(index) => Some(index),
321                None => {
322                    if num_neighbors == MAX_NEIGHBORS {
323                        None
324                    } else {
325                        neighbors[num_neighbors] = new_neighbor;
326                        self.num_neighbors.set(num_neighbors + 1);
327                        Some(num_neighbors)
328                    }
329                }
330            }
331        })
332    }
333
334    /// Deletes the neighbor at `index` if `index` is valid, returning
335    /// `Ok()`. Otherwise, returns `Err(ErrorCode::INVAL)`.  Ensures
336    /// that the `neighbors` list is compact by shifting forward any elements
337    /// after the index.
338    fn remove_neighbor(&self, index: usize) -> Result<(), ErrorCode> {
339        let num_neighbors = self.num_neighbors.get();
340        if index < num_neighbors {
341            self.neighbors.map(|neighbors| {
342                for i in index..(num_neighbors - 1) {
343                    neighbors[i] = neighbors[i + 1];
344                }
345            });
346            self.num_neighbors.set(num_neighbors - 1);
347            Ok(())
348        } else {
349            Err(ErrorCode::INVAL)
350        }
351    }
352
353    /// Gets the `DeviceDescriptor` corresponding to the neighbor at a
354    /// particular `index`, if the `index` is valid. Otherwise, returns `None`
355    fn get_neighbor(&self, index: usize) -> Option<DeviceDescriptor> {
356        if index < self.num_neighbors.get() {
357            self.neighbors.map(|neighbors| neighbors[index])
358        } else {
359            None
360        }
361    }
362
363    // Key management functions
364
365    /// Add a new key to the end of the list if there is still space
366    /// for one, returning its new index. If the key already exists,
367    /// returns the index of the existing key. Returns `None` if there
368    /// is no remaining space.
369    fn add_key(&self, new_key: KeyDescriptor) -> Option<usize> {
370        self.keys.and_then(|keys| {
371            let num_keys = self.num_keys.get();
372            let position = keys[..num_keys].iter().position(|key| *key == new_key);
373            match position {
374                Some(index) => Some(index),
375                None => {
376                    if num_keys == MAX_KEYS {
377                        None
378                    } else {
379                        keys[num_keys] = new_key;
380                        self.num_keys.set(num_keys + 1);
381                        Some(num_keys)
382                    }
383                }
384            }
385        })
386    }
387
388    /// Deletes the key at `index` if `index` is valid, returning
389    /// `Ok(())`. Otherwise, returns `Err(ErrorCode::INVAL)`.  Ensures
390    /// that the `keys` list is compact by shifting forward any elements
391    /// after the index.
392    fn remove_key(&self, index: usize) -> Result<(), ErrorCode> {
393        let num_keys = self.num_keys.get();
394        if index < num_keys {
395            self.keys.map(|keys| {
396                for i in index..(num_keys - 1) {
397                    keys[i] = keys[i + 1];
398                }
399            });
400            self.num_keys.set(num_keys - 1);
401            Ok(())
402        } else {
403            Err(ErrorCode::INVAL)
404        }
405    }
406
407    /// Gets the `DeviceDescriptor` corresponding to the key at a
408    /// particular `index`, if the `index` is valid. Otherwise, returns `None`
409    fn get_key(&self, index: usize) -> Option<KeyDescriptor> {
410        if index < self.num_keys.get() {
411            self.keys.map(|keys| keys[index])
412        } else {
413            None
414        }
415    }
416
417    /// If the driver is currently idle and there are pending transmissions,
418    /// pick an app with a pending transmission and return its `ProcessId`.
419    fn get_next_tx_if_idle(&self) -> Option<ProcessId> {
420        if self.current_app.is_some() {
421            return None;
422        }
423        let mut pending_app = None;
424        for app in self.apps.iter() {
425            let processid = app.processid();
426            app.enter(|app, _| {
427                if app.pending_tx.is_some() {
428                    pending_app = Some(processid);
429                }
430            });
431            if pending_app.is_some() {
432                break;
433            }
434        }
435        pending_app
436    }
437
438    /// Performs `processid`'s pending transmission asynchronously. If the
439    /// transmission is not successful, the error is returned to the app via its
440    /// `tx_callback`. Assumes that the driver is currently idle and the app has
441    /// a pending transmission.
442    #[inline]
443    fn perform_tx_async(&self, processid: ProcessId) {
444        let result = self.perform_tx_sync(processid);
445        if result != Ok(()) {
446            self.saved_processid.set(processid);
447            self.saved_result.set(result);
448            self.deferred_call.set();
449        }
450    }
451
452    /// Performs `processid`'s pending transmission synchronously. The result is
453    /// returned immediately to the app. Assumes that the driver is currently
454    /// idle and the app has a pending transmission.
455    #[inline]
456    fn perform_tx_sync(&self, processid: ProcessId) -> Result<(), ErrorCode> {
457        self.apps.enter(processid, |app, kerel_data| {
458            let (dst_addr, security_needed) = match app.pending_tx.take() {
459                Some(pending_tx) => pending_tx,
460                None => {
461                    return Ok(());
462                }
463            };
464            let result = self.kernel_tx.take().map_or(Err(ErrorCode::NOMEM), |kbuf| {
465                // Prepare the frame headers
466                let pan = self.mac.get_pan();
467                let dst_addr = MacAddress::Short(dst_addr);
468                let src_addr = MacAddress::Short(self.mac.get_address());
469                let mut frame = match self.mac.prepare_data_frame(
470                    kbuf,
471                    pan,
472                    dst_addr,
473                    pan,
474                    src_addr,
475                    security_needed,
476                ) {
477                    Ok(frame) => frame,
478                    Err(kbuf) => {
479                        self.kernel_tx.replace(kbuf);
480                        return Err(ErrorCode::FAIL);
481                    }
482                };
483
484                // Append the payload: there must be one
485                let result = kerel_data
486                    .get_readonly_processbuffer(ro_allow::WRITE)
487                    .and_then(|write| write.enter(|payload| frame.append_payload_process(payload)))
488                    .unwrap_or(Err(ErrorCode::INVAL));
489                if result != Ok(()) {
490                    return result;
491                }
492
493                // Finally, transmit the frame
494                match self.mac.transmit(frame) {
495                    Ok(()) => Ok(()),
496                    Err((ecode, buf)) => {
497                        self.kernel_tx.put(Some(buf));
498                        Err(ecode)
499                    }
500                }
501            });
502            if result == Ok(()) {
503                self.current_app.set(processid);
504            }
505            result
506        })?
507    }
508
509    /// Schedule the next transmission if there is one pending. Performs the
510    /// transmission asynchronously, returning any errors via callbacks.
511    #[inline]
512    fn do_next_tx_async(&self) {
513        self.get_next_tx_if_idle()
514            .map(|processid| self.perform_tx_async(processid));
515    }
516
517    /// Schedule the next transmission if there is one pending. If the next
518    /// transmission happens to be the one that was just queued, then the
519    /// transmission is synchronous. Hence, errors must be returned immediately.
520    /// On the other hand, if it is some other app, then return any errors via
521    /// callbacks.
522    #[inline]
523    fn do_next_tx_sync(&self, new_processid: ProcessId) -> Result<(), ErrorCode> {
524        self.get_next_tx_if_idle().map_or(Ok(()), |processid| {
525            if processid == new_processid {
526                self.perform_tx_sync(processid)
527            } else {
528                self.perform_tx_async(processid);
529                Ok(())
530            }
531        })
532    }
533}
534
535impl<'a, M: device::MacDevice<'a>> DeferredCallClient for RadioDriver<'a, M> {
536    fn handle_deferred_call(&self) {
537        let _ = self
538            .apps
539            .enter(self.saved_processid.unwrap_or_panic(), |_app, upcalls| {
540                // Unwrap fail = missing processid
541                let _ = upcalls.schedule_upcall(
542                    upcall::FRAME_TRANSMITTED,
543                    (
544                        kernel::errorcode::into_statuscode(
545                            self.saved_result.unwrap_or_panic(), // Unwrap fail = missing result
546                        ),
547                        0,
548                        0,
549                    ),
550                );
551            });
552    }
553
554    fn register(&'static self) {
555        self.deferred_call.register(self);
556    }
557}
558
559impl<'a, M: device::MacDevice<'a>> framer::DeviceProcedure for RadioDriver<'a, M> {
560    /// Gets the long address corresponding to the neighbor that matches the given
561    /// MAC address. If no such neighbor exists, returns `None`.
562    fn lookup_addr_long(&self, addr: MacAddress) -> Option<[u8; 8]> {
563        self.neighbors
564            .and_then(|neighbors| {
565                neighbors[..self.num_neighbors.get()]
566                    .iter()
567                    .find(|neighbor| match addr {
568                        MacAddress::Short(addr) => addr == neighbor.short_addr,
569                        MacAddress::Long(addr) => addr == neighbor.long_addr,
570                    })
571                    .map(|neighbor| neighbor.long_addr)
572            })
573            .map_or_else(
574                // This serves the same purpose as the KeyProcedure lookup (see comment).
575                // This is kept as a remnant of 15.4, but should potentially be removed moving forward
576                // as Thread does not have a use to add a Device procedure.
577                || {
578                    self.backup_device_procedure
579                        .and_then(|procedure| procedure.lookup_addr_long(addr))
580                },
581                Some,
582            )
583    }
584}
585
586impl<'a, M: device::MacDevice<'a>> framer::KeyProcedure for RadioDriver<'a, M> {
587    /// Gets the key corresponding to the key that matches the given security
588    /// level `level` and key ID `key_id`. If no such key matches, returns
589    /// `None`.
590    fn lookup_key(&self, level: SecurityLevel, key_id: KeyId) -> Option<[u8; 16]> {
591        self.keys
592            .and_then(|keys| {
593                keys[..self.num_keys.get()]
594                    .iter()
595                    .find(|key| key.level == level && key.key_id == key_id)
596                    .map(|key| key.key)
597            })
598            .map_or_else(
599                // Thread needs to add a MAC key to the 15.4 network keys so that the 15.4 framer
600                // can decrypt incoming Thread 15.4 frames. The backup_device_procedure was added
601                // so that if the lookup procedure failed to find a key here, it would check a
602                // "backup" procedure (Thread in this case). This is somewhat clunky and removing
603                // the network keys being stored in the 15.4 driver is a longer term TODO.
604                || {
605                    self.backup_key_procedure.and_then(|procedure| {
606                        // TODO: security_level / keyID are hardcoded for now
607                        procedure.lookup_key(SecurityLevel::EncMic32, KeyId::Index(2))
608                    })
609                },
610                Some,
611            )
612    }
613}
614
615impl<'a, M: device::MacDevice<'a>> SyscallDriver for RadioDriver<'a, M> {
616    /// IEEE 802.15.4 MAC device control.
617    ///
618    /// For some of the below commands, one 32-bit argument is not enough to
619    /// contain the desired input parameters or output data. For those commands,
620    /// the config slice `app_cfg` (RW allow num 1) is used as a channel to shuffle information
621    /// between kernel space and user space. The expected size of the slice
622    /// varies by command, and acts essentially like a custom FFI. That is, the
623    /// userspace library MUST `allow()` a buffer of the correct size, otherwise
624    /// the call is INVAL. When used, the expected format is described below.
625    ///
626    /// ### `command_num`
627    ///
628    /// - `0`: Driver existence check.
629    /// - `1`: Return radio status. Ok(())/OFF = on/off.
630    /// - `2`: Set short MAC address.
631    /// - `3`: Set long MAC address. app_cfg (in): 8 bytes: the long MAC
632    ///   address.
633    /// - `4`: Set PAN ID.
634    /// - `5`: Set channel.
635    /// - `6`: Set transmission power.
636    /// - `7`: Commit any configuration changes.
637    /// - `8`: Get the short MAC address.
638    /// - `9`: Get the long MAC address. app_cfg (out): 8 bytes: the long MAC
639    ///   address.
640    /// - `10`: Get the PAN ID.
641    /// - `11`: Get the channel.
642    /// - `12`: Get the transmission power.
643    /// - `13`: Get the maximum number of neighbors.
644    /// - `14`: Get the current number of neighbors.
645    /// - `15`: Get the short address of the neighbor at an index.
646    /// - `16`: Get the long address of the neighbor at an index. app_cfg (out):
647    ///   8 bytes: the long MAC address.
648    /// - `17`: Add a new neighbor with the given short and long address.
649    ///   app_cfg (in): 8 bytes: the long MAC address.
650    /// - `18`: Remove the neighbor at an index.
651    /// - `19`: Get the maximum number of keys.
652    /// - `20`: Get the current number of keys.
653    /// - `21`: Get the security level of the key at an index.
654    /// - `22`: Get the key id of the key at an index. app_cfg (out): 1 byte:
655    ///   the key ID mode + up to 9 bytes: the key ID.
656    /// - `23`: Get the key at an index. app_cfg (out): 16 bytes: the key.
657    /// - `24`: Add a new key with the given description. app_cfg (in): 1 byte:
658    ///   the security level + 1 byte: the key ID mode + 9 bytes: the key ID
659    ///   (might not use all bytes) + 16 bytes: the key.
660    /// - `25`: Remove the key at an index.
661    /// - `26`: Transmit a frame (parse required). Take the provided payload and
662    ///   parameters to encrypt, form headers, and transmit the frame.
663    /// - `28`: Set long address.
664    /// - `29`: Get the long MAC address.
665    /// - `30`: Turn the radio on.
666    fn command(
667        &self,
668        command_number: usize,
669        arg1: usize,
670        arg2: usize,
671        processid: ProcessId,
672    ) -> CommandReturn {
673        match command_number {
674            0 => CommandReturn::success(),
675            1 => {
676                if self.mac.is_on() {
677                    CommandReturn::success()
678                } else {
679                    CommandReturn::failure(ErrorCode::OFF)
680                }
681            }
682            2 => {
683                self.mac.set_address(arg1 as u16);
684                CommandReturn::success()
685            }
686            3 => self
687                .apps
688                .enter(processid, |_, kernel_data| {
689                    kernel_data
690                        .get_readwrite_processbuffer(rw_allow::CFG)
691                        .and_then(|cfg| {
692                            cfg.enter(|cfg| {
693                                if cfg.len() != 8 {
694                                    return CommandReturn::failure(ErrorCode::SIZE);
695                                }
696                                let mut addr_long = [0u8; 8];
697                                cfg.copy_to_slice(&mut addr_long);
698                                self.mac.set_address_long(addr_long);
699                                CommandReturn::success()
700                            })
701                        })
702                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
703                })
704                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
705            4 => {
706                self.mac.set_pan(arg1 as u16);
707                CommandReturn::success()
708            }
709            // XXX: Setting channel DEPRECATED by MAC layer channel control
710            5 => CommandReturn::failure(ErrorCode::NOSUPPORT),
711            // XXX: Setting tx power DEPRECATED by MAC layer tx power control
712            6 => CommandReturn::failure(ErrorCode::NOSUPPORT),
713            7 => {
714                self.mac.config_commit();
715                CommandReturn::success()
716            }
717            8 => {
718                // Guarantee that address is positive by adding 1
719                let addr = self.mac.get_address();
720                CommandReturn::success_u32(addr as u32 + 1)
721            }
722            9 => self
723                .apps
724                .enter(processid, |_, kernel_data| {
725                    kernel_data
726                        .get_readwrite_processbuffer(rw_allow::CFG)
727                        .and_then(|cfg| {
728                            cfg.mut_enter(|cfg| {
729                                if cfg.len() != 8 {
730                                    return CommandReturn::failure(ErrorCode::SIZE);
731                                }
732                                cfg.copy_from_slice(&self.mac.get_address_long());
733                                CommandReturn::success()
734                            })
735                        })
736                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
737                })
738                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
739            10 => {
740                // Guarantee that the PAN is positive by adding 1
741                let pan = self.mac.get_pan();
742                CommandReturn::success_u32(pan as u32 + 1)
743            }
744            // XXX: Getting channel DEPRECATED by MAC layer channel control
745            11 => CommandReturn::failure(ErrorCode::NOSUPPORT),
746            // XXX: Getting tx power DEPRECATED by MAC layer tx power control
747            12 => CommandReturn::failure(ErrorCode::NOSUPPORT),
748            13 => {
749                // Guarantee that it is positive by adding 1
750                CommandReturn::success_u32(MAX_NEIGHBORS as u32 + 1)
751            }
752            14 => {
753                // Guarantee that it is positive by adding 1
754                CommandReturn::success_u32(self.num_neighbors.get() as u32 + 1)
755            }
756            15 => self
757                .get_neighbor(arg1)
758                .map_or(CommandReturn::failure(ErrorCode::INVAL), |neighbor| {
759                    CommandReturn::success_u32(neighbor.short_addr as u32 + 1)
760                }),
761            16 => self
762                .apps
763                .enter(processid, |_, kernel_data| {
764                    kernel_data
765                        .get_readwrite_processbuffer(rw_allow::CFG)
766                        .and_then(|cfg| {
767                            cfg.mut_enter(|cfg| {
768                                if cfg.len() != 8 {
769                                    return CommandReturn::failure(ErrorCode::SIZE);
770                                }
771                                self.get_neighbor(arg1).map_or(
772                                    CommandReturn::failure(ErrorCode::INVAL),
773                                    |neighbor| {
774                                        cfg.copy_from_slice(&neighbor.long_addr);
775                                        CommandReturn::success()
776                                    },
777                                )
778                            })
779                        })
780                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
781                })
782                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
783            17 => self
784                .apps
785                .enter(processid, |_, kernel_data| {
786                    kernel_data
787                        .get_readwrite_processbuffer(rw_allow::CFG)
788                        .and_then(|cfg| {
789                            cfg.enter(|cfg| {
790                                if cfg.len() != 8 {
791                                    return CommandReturn::failure(ErrorCode::SIZE);
792                                }
793                                let mut new_neighbor = DeviceDescriptor {
794                                    short_addr: arg1 as u16,
795                                    ..Default::default()
796                                };
797                                cfg.copy_to_slice(&mut new_neighbor.long_addr);
798                                self.add_neighbor(new_neighbor)
799                                    .map_or(CommandReturn::failure(ErrorCode::INVAL), |index| {
800                                        CommandReturn::success_u32(index as u32 + 1)
801                                    })
802                            })
803                        })
804                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
805                })
806                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
807
808            18 => match self.remove_neighbor(arg1) {
809                Ok(()) => CommandReturn::success(),
810                Err(e) => CommandReturn::failure(e),
811            },
812            19 => {
813                // Guarantee that it is positive by adding 1
814                CommandReturn::success_u32(MAX_KEYS as u32 + 1)
815            }
816            20 => {
817                // Guarantee that it is positive by adding 1
818                CommandReturn::success_u32(self.num_keys.get() as u32 + 1)
819            }
820            21 => self
821                .get_key(arg1)
822                .map_or(CommandReturn::failure(ErrorCode::INVAL), |key| {
823                    CommandReturn::success_u32(key.level as u32 + 1)
824                }),
825            22 => self
826                .apps
827                .enter(processid, |_, kernel_data| {
828                    kernel_data
829                        .get_readwrite_processbuffer(rw_allow::CFG)
830                        .and_then(|cfg| {
831                            cfg.mut_enter(|cfg| {
832                                if cfg.len() != 10 {
833                                    return CommandReturn::failure(ErrorCode::SIZE);
834                                }
835
836                                let mut tmp_cfg: [u8; 10] = [0; 10];
837                                let res = self
838                                    .get_key(arg1)
839                                    .and_then(|key| encode_key_id(&key.key_id, &mut tmp_cfg).done())
840                                    .map_or(CommandReturn::failure(ErrorCode::INVAL), |_| {
841                                        CommandReturn::success()
842                                    });
843                                cfg.copy_from_slice(&tmp_cfg);
844
845                                res
846                            })
847                        })
848                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
849                })
850                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
851            23 => self
852                .apps
853                .enter(processid, |_, kernel_data| {
854                    kernel_data
855                        .get_readwrite_processbuffer(rw_allow::CFG)
856                        .and_then(|cfg| {
857                            cfg.mut_enter(|cfg| {
858                                if cfg.len() != 16 {
859                                    return CommandReturn::failure(ErrorCode::SIZE);
860                                }
861                                self.get_key(arg1).map_or(
862                                    CommandReturn::failure(ErrorCode::INVAL),
863                                    |key| {
864                                        cfg.copy_from_slice(&key.key);
865                                        CommandReturn::success()
866                                    },
867                                )
868                            })
869                        })
870                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
871                })
872                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
873            24 => self
874                .apps
875                .enter(processid, |_, kernel_data| {
876                    kernel_data
877                        .get_readwrite_processbuffer(rw_allow::CFG)
878                        .and_then(|cfg| {
879                            cfg.mut_enter(|cfg| {
880                                if cfg.len() != 27 {
881                                    return CommandReturn::failure(ErrorCode::SIZE);
882                                }
883
884                                // The cfg userspace buffer is exactly 27
885                                // bytes long, copy it into a proper slice
886                                // for decoding
887                                let mut tmp_cfg: [u8; 27] = [0; 27];
888                                cfg.copy_to_slice(&mut tmp_cfg);
889
890                                KeyDescriptor::decode(&tmp_cfg)
891                                    .done()
892                                    .and_then(|(_, new_key)| self.add_key(new_key))
893                                    .map_or(CommandReturn::failure(ErrorCode::INVAL), |index| {
894                                        CommandReturn::success_u32(index as u32 + 1)
895                                    })
896                            })
897                        })
898                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
899                })
900                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
901
902            25 => self.remove_key(arg1).into(),
903            26 => {
904                self.apps
905                    .enter(processid, |app, kernel_data| {
906                        if app.pending_tx.is_some() {
907                            // Cannot support more than one pending tx per process.
908                            return Err(ErrorCode::BUSY);
909                        }
910                        let next_tx = kernel_data
911                            .get_readwrite_processbuffer(rw_allow::CFG)
912                            .and_then(|cfg| {
913                                cfg.enter(|cfg| {
914                                    if cfg.len() != 11 {
915                                        return None;
916                                    }
917                                    let dst_addr = arg1 as u16;
918                                    let level = match SecurityLevel::from_scf(cfg[0].get()) {
919                                        Some(level) => level,
920                                        None => {
921                                            return None;
922                                        }
923                                    };
924                                    if level == SecurityLevel::None {
925                                        Some((dst_addr, None))
926                                    } else {
927                                        let mut tmp_key_id_buffer: [u8; 10] = [0; 10];
928                                        cfg[1..].copy_to_slice(&mut tmp_key_id_buffer);
929                                        let key_id = match decode_key_id(&tmp_key_id_buffer).done()
930                                        {
931                                            Some((_, key_id)) => key_id,
932                                            None => {
933                                                return None;
934                                            }
935                                        };
936                                        Some((dst_addr, Some((level, key_id))))
937                                    }
938                                })
939                            })
940                            .unwrap_or(None);
941                        if next_tx.is_none() {
942                            return Err(ErrorCode::INVAL);
943                        }
944                        app.pending_tx = next_tx;
945                        Ok(())
946                    })
947                    .map_or_else(
948                        |err| CommandReturn::failure(err.into()),
949                        |setup_tx| match setup_tx {
950                            Ok(()) => self.do_next_tx_sync(processid).into(),
951                            Err(e) => CommandReturn::failure(e),
952                        },
953                    )
954            }
955            28 => {
956                let addr_upper: u64 = arg2 as u64;
957                let addr_lower: u64 = arg1 as u64;
958                let addr = addr_upper << 32 | addr_lower;
959                self.mac.set_address_long(addr.to_be_bytes());
960                CommandReturn::success()
961            }
962            29 => {
963                let addr = u64::from_be_bytes(self.mac.get_address_long());
964                CommandReturn::success_u64(addr)
965            }
966            30 => self.mac.start().into(),
967            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
968        }
969    }
970
971    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
972        self.apps.enter(processid, |_, _| {})
973    }
974}
975
976impl<'a, M: device::MacDevice<'a>> device::TxClient for RadioDriver<'a, M> {
977    fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) {
978        self.kernel_tx.replace(spi_buf);
979        self.current_app.take().map(|processid| {
980            let _ = self.apps.enter(processid, |_app, upcalls| {
981                let _ = upcalls.schedule_upcall(
982                    upcall::FRAME_TRANSMITTED,
983                    (
984                        kernel::errorcode::into_statuscode(result),
985                        acked as usize,
986                        0,
987                    ),
988                );
989            });
990        });
991        self.do_next_tx_async();
992    }
993}
994
995impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> {
996    fn receive<'b>(
997        &self,
998        buf: &'b [u8],
999        header: Header<'b>,
1000        lqi: u8,
1001        data_offset: usize,
1002        data_len: usize,
1003    ) {
1004        self.apps.each(|_, _, kernel_data| {
1005            let read_present = kernel_data
1006                .get_readwrite_processbuffer(rw_allow::READ)
1007                .and_then(|read| {
1008                    read.mut_enter(|rbuf| {
1009                        ///////////////////////////////////////////////////////////////////////////////////////////
1010                        // NOTE: context for the ring buffer and assumptions regarding the ring buffer
1011                        // format and usage can be found in the detailed comment at the top of this file.
1012                        //      Ring buffer format:
1013                        //          | read index | write index | user_frame 0 | user_frame 1 | ... | user_frame n |
1014                        //      user_frame format:
1015                        //          | header_len | payload_len | mic_len | 15.4 frame |
1016                        ///////////////////////////////////////////////////////////////////////////////////////////
1017
1018                        // 2 bytes for the readwrite buffer metadata (read / write index)
1019                        const RING_BUF_METADATA_SIZE: usize = 2;
1020
1021                        // Confirm the availability of the buffer. A buffer of len 0 is indicative
1022                        // of the userprocess not allocating a readwrite buffer. We must also
1023                        // confirm that the userprocess correctly formatted the buffer to be of length
1024                        // 2 + n * USER_FRAME_MAX_SIZE, where n is the number of user frames that the
1025                        // buffer can store. We combine checking the buffer's non-zero length and the
1026                        // case of the buffer being shorter than the `RING_BUF_METADATA_SIZE` as an
1027                        // invalid buffer (e.g. of length 1) may otherwise errantly pass the second
1028                        // conditional check (due to unsigned integer arithmetic).
1029                        if rbuf.len() <= RING_BUF_METADATA_SIZE
1030                            || (rbuf.len() - RING_BUF_METADATA_SIZE) % USER_FRAME_MAX_SIZE != 0
1031                        {
1032                            // kernel::debug!("[15.4 Driver] Error - improperly formatted readwrite buffer provided");
1033                            return false;
1034                        }
1035
1036                        let mic_len = header.security.map_or(0, |sec| sec.level.mic_len());
1037                        let frame_len = data_offset + data_len + mic_len;
1038
1039                        let mut read_index = rbuf[0].get() as usize;
1040                        let mut write_index = rbuf[1].get() as usize;
1041
1042                        let max_pending_rx =
1043                            (rbuf.len() - RING_BUF_METADATA_SIZE) / USER_FRAME_MAX_SIZE;
1044
1045                        // confirm user modifiable metadata is valid (i.e. within bounds of the provided buffer)
1046                        if read_index >= max_pending_rx || write_index >= max_pending_rx {
1047                            // kernel::debug!("[15.4 driver] Invalid read or write index");
1048                            return false;
1049                        }
1050
1051                        let offset = RING_BUF_METADATA_SIZE + (write_index * USER_FRAME_MAX_SIZE);
1052
1053                        // Copy the entire frame over to userland, preceded by three metadata bytes:
1054                        // the header length, the data length, and the MIC length.
1055                        rbuf[(offset + USER_FRAME_METADATA_SIZE)
1056                            ..(offset + frame_len + USER_FRAME_METADATA_SIZE)]
1057                            .copy_from_slice(&buf[..frame_len]);
1058
1059                        rbuf[offset].set(data_offset as u8);
1060                        rbuf[offset + 1].set(data_len as u8);
1061                        rbuf[offset + 2].set(mic_len as u8);
1062
1063                        // Prepare the ring buffer for the next write. The current design favors newness;
1064                        // newly received packets will begin to overwrite the oldest data in the event
1065                        // of the buffer becoming full. The read index must always point to the "oldest"
1066                        // data. If we have overwritten the oldest data, the next oldest data is now at
1067                        // the read index + 1. We must update the read index to reflect this.
1068                        write_index = (write_index + 1) % max_pending_rx;
1069                        if write_index == read_index {
1070                            read_index = (read_index + 1) % max_pending_rx;
1071                            rbuf[0].set(read_index as u8);
1072                            // kernel::debug!("[15.4 driver] Provided RX buffer is full");
1073                        }
1074
1075                        // update write index metadata (we do not modify the read index
1076                        // in the recv functionality so we do not need to update this metadata)
1077                        rbuf[1].set(write_index as u8);
1078                        true
1079                    })
1080                })
1081                .unwrap_or(false);
1082            if read_present {
1083                // Place lqi as argument to be included in upcall.
1084                let _ = kernel_data.schedule_upcall(upcall::FRAME_RECEIVED, (lqi as usize, 0, 0));
1085            }
1086        });
1087    }
1088}