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}