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                upcalls
542                    .schedule_upcall(
543                        upcall::FRAME_TRANSMITTED,
544                        (
545                            kernel::errorcode::into_statuscode(
546                                self.saved_result.unwrap_or_panic(), // Unwrap fail = missing result
547                            ),
548                            0,
549                            0,
550                        ),
551                    )
552                    .ok();
553            });
554    }
555
556    fn register(&'static self) {
557        self.deferred_call.register(self);
558    }
559}
560
561impl<'a, M: device::MacDevice<'a>> framer::DeviceProcedure for RadioDriver<'a, M> {
562    /// Gets the long address corresponding to the neighbor that matches the given
563    /// MAC address. If no such neighbor exists, returns `None`.
564    fn lookup_addr_long(&self, addr: MacAddress) -> Option<[u8; 8]> {
565        self.neighbors
566            .and_then(|neighbors| {
567                neighbors[..self.num_neighbors.get()]
568                    .iter()
569                    .find(|neighbor| match addr {
570                        MacAddress::Short(addr) => addr == neighbor.short_addr,
571                        MacAddress::Long(addr) => addr == neighbor.long_addr,
572                    })
573                    .map(|neighbor| neighbor.long_addr)
574            })
575            .map_or_else(
576                // This serves the same purpose as the KeyProcedure lookup (see comment).
577                // This is kept as a remnant of 15.4, but should potentially be removed moving forward
578                // as Thread does not have a use to add a Device procedure.
579                || {
580                    self.backup_device_procedure
581                        .and_then(|procedure| procedure.lookup_addr_long(addr))
582                },
583                |res| Some(res),
584            )
585    }
586}
587
588impl<'a, M: device::MacDevice<'a>> framer::KeyProcedure for RadioDriver<'a, M> {
589    /// Gets the key corresponding to the key that matches the given security
590    /// level `level` and key ID `key_id`. If no such key matches, returns
591    /// `None`.
592    fn lookup_key(&self, level: SecurityLevel, key_id: KeyId) -> Option<[u8; 16]> {
593        self.keys
594            .and_then(|keys| {
595                keys[..self.num_keys.get()]
596                    .iter()
597                    .find(|key| key.level == level && key.key_id == key_id)
598                    .map(|key| key.key)
599            })
600            .map_or_else(
601                // Thread needs to add a MAC key to the 15.4 network keys so that the 15.4 framer
602                // can decrypt incoming Thread 15.4 frames. The backup_device_procedure was added
603                // so that if the lookup procedure failed to find a key here, it would check a
604                // "backup" procedure (Thread in this case). This is somewhat clunky and removing
605                // the network keys being stored in the 15.4 driver is a longer term TODO.
606                || {
607                    self.backup_key_procedure.and_then(|procedure| {
608                        // TODO: security_level / keyID are hardcoded for now
609                        procedure.lookup_key(SecurityLevel::EncMic32, KeyId::Index(2))
610                    })
611                },
612                |res| Some(res),
613            )
614    }
615}
616
617impl<'a, M: device::MacDevice<'a>> SyscallDriver for RadioDriver<'a, M> {
618    /// IEEE 802.15.4 MAC device control.
619    ///
620    /// For some of the below commands, one 32-bit argument is not enough to
621    /// contain the desired input parameters or output data. For those commands,
622    /// the config slice `app_cfg` (RW allow num 1) is used as a channel to shuffle information
623    /// between kernel space and user space. The expected size of the slice
624    /// varies by command, and acts essentially like a custom FFI. That is, the
625    /// userspace library MUST `allow()` a buffer of the correct size, otherwise
626    /// the call is INVAL. When used, the expected format is described below.
627    ///
628    /// ### `command_num`
629    ///
630    /// - `0`: Driver existence check.
631    /// - `1`: Return radio status. Ok(())/OFF = on/off.
632    /// - `2`: Set short MAC address.
633    /// - `3`: Set long MAC address. app_cfg (in): 8 bytes: the long MAC
634    ///   address.
635    /// - `4`: Set PAN ID.
636    /// - `5`: Set channel.
637    /// - `6`: Set transmission power.
638    /// - `7`: Commit any configuration changes.
639    /// - `8`: Get the short MAC address.
640    /// - `9`: Get the long MAC address. app_cfg (out): 8 bytes: the long MAC
641    ///   address.
642    /// - `10`: Get the PAN ID.
643    /// - `11`: Get the channel.
644    /// - `12`: Get the transmission power.
645    /// - `13`: Get the maximum number of neighbors.
646    /// - `14`: Get the current number of neighbors.
647    /// - `15`: Get the short address of the neighbor at an index.
648    /// - `16`: Get the long address of the neighbor at an index. app_cfg (out):
649    ///   8 bytes: the long MAC address.
650    /// - `17`: Add a new neighbor with the given short and long address.
651    ///   app_cfg (in): 8 bytes: the long MAC address.
652    /// - `18`: Remove the neighbor at an index.
653    /// - `19`: Get the maximum number of keys.
654    /// - `20`: Get the current number of keys.
655    /// - `21`: Get the security level of the key at an index.
656    /// - `22`: Get the key id of the key at an index. app_cfg (out): 1 byte:
657    ///   the key ID mode + up to 9 bytes: the key ID.
658    /// - `23`: Get the key at an index. app_cfg (out): 16 bytes: the key.
659    /// - `24`: Add a new key with the given description. app_cfg (in): 1 byte:
660    ///   the security level + 1 byte: the key ID mode + 9 bytes: the key ID
661    ///   (might not use all bytes) + 16 bytes: the key.
662    /// - `25`: Remove the key at an index.
663    /// - `26`: Transmit a frame (parse required). Take the provided payload and
664    ///   parameters to encrypt, form headers, and transmit the frame.
665    /// - `28`: Set long address.
666    /// - `29`: Get the long MAC address.
667    /// - `30`: Turn the radio on.
668    fn command(
669        &self,
670        command_number: usize,
671        arg1: usize,
672        arg2: usize,
673        processid: ProcessId,
674    ) -> CommandReturn {
675        match command_number {
676            0 => CommandReturn::success(),
677            1 => {
678                if self.mac.is_on() {
679                    CommandReturn::success()
680                } else {
681                    CommandReturn::failure(ErrorCode::OFF)
682                }
683            }
684            2 => {
685                self.mac.set_address(arg1 as u16);
686                CommandReturn::success()
687            }
688            3 => self
689                .apps
690                .enter(processid, |_, kernel_data| {
691                    kernel_data
692                        .get_readwrite_processbuffer(rw_allow::CFG)
693                        .and_then(|cfg| {
694                            cfg.enter(|cfg| {
695                                if cfg.len() != 8 {
696                                    return CommandReturn::failure(ErrorCode::SIZE);
697                                }
698                                let mut addr_long = [0u8; 8];
699                                cfg.copy_to_slice(&mut addr_long);
700                                self.mac.set_address_long(addr_long);
701                                CommandReturn::success()
702                            })
703                        })
704                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
705                })
706                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
707            4 => {
708                self.mac.set_pan(arg1 as u16);
709                CommandReturn::success()
710            }
711            // XXX: Setting channel DEPRECATED by MAC layer channel control
712            5 => CommandReturn::failure(ErrorCode::NOSUPPORT),
713            // XXX: Setting tx power DEPRECATED by MAC layer tx power control
714            6 => CommandReturn::failure(ErrorCode::NOSUPPORT),
715            7 => {
716                self.mac.config_commit();
717                CommandReturn::success()
718            }
719            8 => {
720                // Guarantee that address is positive by adding 1
721                let addr = self.mac.get_address();
722                CommandReturn::success_u32(addr as u32 + 1)
723            }
724            9 => self
725                .apps
726                .enter(processid, |_, kernel_data| {
727                    kernel_data
728                        .get_readwrite_processbuffer(rw_allow::CFG)
729                        .and_then(|cfg| {
730                            cfg.mut_enter(|cfg| {
731                                if cfg.len() != 8 {
732                                    return CommandReturn::failure(ErrorCode::SIZE);
733                                }
734                                cfg.copy_from_slice(&self.mac.get_address_long());
735                                CommandReturn::success()
736                            })
737                        })
738                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
739                })
740                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
741            10 => {
742                // Guarantee that the PAN is positive by adding 1
743                let pan = self.mac.get_pan();
744                CommandReturn::success_u32(pan as u32 + 1)
745            }
746            // XXX: Getting channel DEPRECATED by MAC layer channel control
747            11 => CommandReturn::failure(ErrorCode::NOSUPPORT),
748            // XXX: Getting tx power DEPRECATED by MAC layer tx power control
749            12 => CommandReturn::failure(ErrorCode::NOSUPPORT),
750            13 => {
751                // Guarantee that it is positive by adding 1
752                CommandReturn::success_u32(MAX_NEIGHBORS as u32 + 1)
753            }
754            14 => {
755                // Guarantee that it is positive by adding 1
756                CommandReturn::success_u32(self.num_neighbors.get() as u32 + 1)
757            }
758            15 => self
759                .get_neighbor(arg1)
760                .map_or(CommandReturn::failure(ErrorCode::INVAL), |neighbor| {
761                    CommandReturn::success_u32(neighbor.short_addr as u32 + 1)
762                }),
763            16 => self
764                .apps
765                .enter(processid, |_, kernel_data| {
766                    kernel_data
767                        .get_readwrite_processbuffer(rw_allow::CFG)
768                        .and_then(|cfg| {
769                            cfg.mut_enter(|cfg| {
770                                if cfg.len() != 8 {
771                                    return CommandReturn::failure(ErrorCode::SIZE);
772                                }
773                                self.get_neighbor(arg1).map_or(
774                                    CommandReturn::failure(ErrorCode::INVAL),
775                                    |neighbor| {
776                                        cfg.copy_from_slice(&neighbor.long_addr);
777                                        CommandReturn::success()
778                                    },
779                                )
780                            })
781                        })
782                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
783                })
784                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
785            17 => self
786                .apps
787                .enter(processid, |_, kernel_data| {
788                    kernel_data
789                        .get_readwrite_processbuffer(rw_allow::CFG)
790                        .and_then(|cfg| {
791                            cfg.enter(|cfg| {
792                                if cfg.len() != 8 {
793                                    return CommandReturn::failure(ErrorCode::SIZE);
794                                }
795                                let mut new_neighbor: DeviceDescriptor =
796                                    DeviceDescriptor::default();
797                                new_neighbor.short_addr = arg1 as u16;
798                                cfg.copy_to_slice(&mut new_neighbor.long_addr);
799                                self.add_neighbor(new_neighbor)
800                                    .map_or(CommandReturn::failure(ErrorCode::INVAL), |index| {
801                                        CommandReturn::success_u32(index as u32 + 1)
802                                    })
803                            })
804                        })
805                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
806                })
807                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
808
809            18 => match self.remove_neighbor(arg1) {
810                Ok(()) => CommandReturn::success(),
811                Err(e) => CommandReturn::failure(e),
812            },
813            19 => {
814                // Guarantee that it is positive by adding 1
815                CommandReturn::success_u32(MAX_KEYS as u32 + 1)
816            }
817            20 => {
818                // Guarantee that it is positive by adding 1
819                CommandReturn::success_u32(self.num_keys.get() as u32 + 1)
820            }
821            21 => self
822                .get_key(arg1)
823                .map_or(CommandReturn::failure(ErrorCode::INVAL), |key| {
824                    CommandReturn::success_u32(key.level as u32 + 1)
825                }),
826            22 => self
827                .apps
828                .enter(processid, |_, kernel_data| {
829                    kernel_data
830                        .get_readwrite_processbuffer(rw_allow::CFG)
831                        .and_then(|cfg| {
832                            cfg.mut_enter(|cfg| {
833                                if cfg.len() != 10 {
834                                    return CommandReturn::failure(ErrorCode::SIZE);
835                                }
836
837                                let mut tmp_cfg: [u8; 10] = [0; 10];
838                                let res = self
839                                    .get_key(arg1)
840                                    .and_then(|key| encode_key_id(&key.key_id, &mut tmp_cfg).done())
841                                    .map_or(CommandReturn::failure(ErrorCode::INVAL), |_| {
842                                        CommandReturn::success()
843                                    });
844                                cfg.copy_from_slice(&tmp_cfg);
845
846                                res
847                            })
848                        })
849                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
850                })
851                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
852            23 => self
853                .apps
854                .enter(processid, |_, kernel_data| {
855                    kernel_data
856                        .get_readwrite_processbuffer(rw_allow::CFG)
857                        .and_then(|cfg| {
858                            cfg.mut_enter(|cfg| {
859                                if cfg.len() != 16 {
860                                    return CommandReturn::failure(ErrorCode::SIZE);
861                                }
862                                self.get_key(arg1).map_or(
863                                    CommandReturn::failure(ErrorCode::INVAL),
864                                    |key| {
865                                        cfg.copy_from_slice(&key.key);
866                                        CommandReturn::success()
867                                    },
868                                )
869                            })
870                        })
871                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
872                })
873                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
874            24 => self
875                .apps
876                .enter(processid, |_, kernel_data| {
877                    kernel_data
878                        .get_readwrite_processbuffer(rw_allow::CFG)
879                        .and_then(|cfg| {
880                            cfg.mut_enter(|cfg| {
881                                if cfg.len() != 27 {
882                                    return CommandReturn::failure(ErrorCode::SIZE);
883                                }
884
885                                // The cfg userspace buffer is exactly 27
886                                // bytes long, copy it into a proper slice
887                                // for decoding
888                                let mut tmp_cfg: [u8; 27] = [0; 27];
889                                cfg.copy_to_slice(&mut tmp_cfg);
890
891                                KeyDescriptor::decode(&tmp_cfg)
892                                    .done()
893                                    .and_then(|(_, new_key)| self.add_key(new_key))
894                                    .map_or(CommandReturn::failure(ErrorCode::INVAL), |index| {
895                                        CommandReturn::success_u32(index as u32 + 1)
896                                    })
897                            })
898                        })
899                        .unwrap_or(CommandReturn::failure(ErrorCode::INVAL))
900                })
901                .unwrap_or_else(|err| CommandReturn::failure(err.into())),
902
903            25 => self.remove_key(arg1).into(),
904            26 => {
905                self.apps
906                    .enter(processid, |app, kernel_data| {
907                        if app.pending_tx.is_some() {
908                            // Cannot support more than one pending tx per process.
909                            return Err(ErrorCode::BUSY);
910                        }
911                        let next_tx = kernel_data
912                            .get_readwrite_processbuffer(rw_allow::CFG)
913                            .and_then(|cfg| {
914                                cfg.enter(|cfg| {
915                                    if cfg.len() != 11 {
916                                        return None;
917                                    }
918                                    let dst_addr = arg1 as u16;
919                                    let level = match SecurityLevel::from_scf(cfg[0].get()) {
920                                        Some(level) => level,
921                                        None => {
922                                            return None;
923                                        }
924                                    };
925                                    if level == SecurityLevel::None {
926                                        Some((dst_addr, None))
927                                    } else {
928                                        let mut tmp_key_id_buffer: [u8; 10] = [0; 10];
929                                        cfg[1..].copy_to_slice(&mut tmp_key_id_buffer);
930                                        let key_id = match decode_key_id(&tmp_key_id_buffer).done()
931                                        {
932                                            Some((_, key_id)) => key_id,
933                                            None => {
934                                                return None;
935                                            }
936                                        };
937                                        Some((dst_addr, Some((level, key_id))))
938                                    }
939                                })
940                            })
941                            .unwrap_or(None);
942                        if next_tx.is_none() {
943                            return Err(ErrorCode::INVAL);
944                        }
945                        app.pending_tx = next_tx;
946                        Ok(())
947                    })
948                    .map_or_else(
949                        |err| CommandReturn::failure(err.into()),
950                        |setup_tx| match setup_tx {
951                            Ok(()) => self.do_next_tx_sync(processid).into(),
952                            Err(e) => CommandReturn::failure(e),
953                        },
954                    )
955            }
956            28 => {
957                let addr_upper: u64 = arg2 as u64;
958                let addr_lower: u64 = arg1 as u64;
959                let addr = addr_upper << 32 | addr_lower;
960                self.mac.set_address_long(addr.to_be_bytes());
961                CommandReturn::success()
962            }
963            29 => {
964                let addr = u64::from_be_bytes(self.mac.get_address_long());
965                CommandReturn::success_u64(addr)
966            }
967            30 => self.mac.start().into(),
968            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
969        }
970    }
971
972    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
973        self.apps.enter(processid, |_, _| {})
974    }
975}
976
977impl<'a, M: device::MacDevice<'a>> device::TxClient for RadioDriver<'a, M> {
978    fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) {
979        self.kernel_tx.replace(spi_buf);
980        self.current_app.take().map(|processid| {
981            let _ = self.apps.enter(processid, |_app, upcalls| {
982                upcalls
983                    .schedule_upcall(
984                        upcall::FRAME_TRANSMITTED,
985                        (
986                            kernel::errorcode::into_statuscode(result),
987                            acked as usize,
988                            0,
989                        ),
990                    )
991                    .ok();
992            });
993        });
994        self.do_next_tx_async();
995    }
996}
997
998impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> {
999    fn receive<'b>(
1000        &self,
1001        buf: &'b [u8],
1002        header: Header<'b>,
1003        lqi: u8,
1004        data_offset: usize,
1005        data_len: usize,
1006    ) {
1007        self.apps.each(|_, _, kernel_data| {
1008            let read_present = kernel_data
1009                .get_readwrite_processbuffer(rw_allow::READ)
1010                .and_then(|read| {
1011                    read.mut_enter(|rbuf| {
1012                        ///////////////////////////////////////////////////////////////////////////////////////////
1013                        // NOTE: context for the ring buffer and assumptions regarding the ring buffer
1014                        // format and usage can be found in the detailed comment at the top of this file.
1015                        //      Ring buffer format:
1016                        //          | read index | write index | user_frame 0 | user_frame 1 | ... | user_frame n |
1017                        //      user_frame format:
1018                        //          | header_len | payload_len | mic_len | 15.4 frame |
1019                        ///////////////////////////////////////////////////////////////////////////////////////////
1020
1021                        // 2 bytes for the readwrite buffer metadata (read / write index)
1022                        const RING_BUF_METADATA_SIZE: usize = 2;
1023
1024                        // Confirm the availability of the buffer. A buffer of len 0 is indicative
1025                        // of the userprocess not allocating a readwrite buffer. We must also
1026                        // confirm that the userprocess correctly formatted the buffer to be of length
1027                        // 2 + n * USER_FRAME_MAX_SIZE, where n is the number of user frames that the
1028                        // buffer can store. We combine checking the buffer's non-zero length and the
1029                        // case of the buffer being shorter than the `RING_BUF_METADATA_SIZE` as an
1030                        // invalid buffer (e.g. of length 1) may otherwise errantly pass the second
1031                        // conditional check (due to unsigned integer arithmetic).
1032                        if rbuf.len() <= RING_BUF_METADATA_SIZE
1033                            || (rbuf.len() - RING_BUF_METADATA_SIZE) % USER_FRAME_MAX_SIZE != 0
1034                        {
1035                            // kernel::debug!("[15.4 Driver] Error - improperly formatted readwrite buffer provided");
1036                            return false;
1037                        }
1038
1039                        let mic_len = header.security.map_or(0, |sec| sec.level.mic_len());
1040                        let frame_len = data_offset + data_len + mic_len;
1041
1042                        let mut read_index = rbuf[0].get() as usize;
1043                        let mut write_index = rbuf[1].get() as usize;
1044
1045                        let max_pending_rx =
1046                            (rbuf.len() - RING_BUF_METADATA_SIZE) / USER_FRAME_MAX_SIZE;
1047
1048                        // confirm user modifiable metadata is valid (i.e. within bounds of the provided buffer)
1049                        if read_index >= max_pending_rx || write_index >= max_pending_rx {
1050                            // kernel::debug!("[15.4 driver] Invalid read or write index");
1051                            return false;
1052                        }
1053
1054                        let offset = RING_BUF_METADATA_SIZE + (write_index * USER_FRAME_MAX_SIZE);
1055
1056                        // Copy the entire frame over to userland, preceded by three metadata bytes:
1057                        // the header length, the data length, and the MIC length.
1058                        rbuf[(offset + USER_FRAME_METADATA_SIZE)
1059                            ..(offset + frame_len + USER_FRAME_METADATA_SIZE)]
1060                            .copy_from_slice(&buf[..frame_len]);
1061
1062                        rbuf[offset].set(data_offset as u8);
1063                        rbuf[offset + 1].set(data_len as u8);
1064                        rbuf[offset + 2].set(mic_len as u8);
1065
1066                        // Prepare the ring buffer for the next write. The current design favors newness;
1067                        // newly received packets will begin to overwrite the oldest data in the event
1068                        // of the buffer becoming full. The read index must always point to the "oldest"
1069                        // data. If we have overwritten the oldest data, the next oldest data is now at
1070                        // the read index + 1. We must update the read index to reflect this.
1071                        write_index = (write_index + 1) % max_pending_rx;
1072                        if write_index == read_index {
1073                            read_index = (read_index + 1) % max_pending_rx;
1074                            rbuf[0].set(read_index as u8);
1075                            // kernel::debug!("[15.4 driver] Provided RX buffer is full");
1076                        }
1077
1078                        // update write index metadata (we do not modify the read index
1079                        // in the recv functionality so we do not need to update this metadata)
1080                        rbuf[1].set(write_index as u8);
1081                        true
1082                    })
1083                })
1084                .unwrap_or(false);
1085            if read_present {
1086                // Place lqi as argument to be included in upcall.
1087                kernel_data
1088                    .schedule_upcall(upcall::FRAME_RECEIVED, (lqi as usize, 0, 0))
1089                    .ok();
1090            }
1091        });
1092    }
1093}