capsules_extra/ieee802154/
device.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//! The contract satisfied by an implementation of an IEEE 802.15.4 MAC device.
6//! Any IEEE 802.15.4 MAC device should expose the following high-level
7//! functionality:
8//!
9//! - Configuration of addresses and transmit power
10//! - Preparing frames (data frame, command frames, beacon frames)
11//! - Transmitting and receiving frames
12//!
13//! Outlining this in a trait allows other implementations of MAC devices that
14//! divide the responsibilities of software and hardware differently. For
15//! example, a radio chip might be able to completely inline the frame security
16//! procedure in hardware, as opposed to requiring a software implementation.
17
18use crate::ieee802154::framer::Frame;
19use crate::net::ieee802154::{Header, KeyId, MacAddress, PanID, SecurityLevel};
20use kernel::ErrorCode;
21
22pub trait MacDevice<'a> {
23    /// Sets the transmission client of this MAC device
24    fn set_transmit_client(&self, client: &'a dyn TxClient);
25    /// Sets the receive client of this MAC device
26    fn set_receive_client(&self, client: &'a dyn RxClient);
27
28    /// The short 16-bit address of the MAC device
29    fn get_address(&self) -> u16;
30    /// The long 64-bit address (EUI-64) of the MAC device
31    fn get_address_long(&self) -> [u8; 8];
32    /// The 16-bit PAN ID of the MAC device
33    fn get_pan(&self) -> u16;
34
35    /// Set the short 16-bit address of the MAC device
36    fn set_address(&self, addr: u16);
37    /// Set the long 64-bit address (EUI-64) of the MAC device
38    fn set_address_long(&self, addr: [u8; 8]);
39    /// Set the 16-bit PAN ID of the MAC device
40    fn set_pan(&self, id: u16);
41
42    /// This method must be called after one or more calls to `set_*`. If
43    /// `set_*` is called without calling `config_commit`, there is no guarantee
44    /// that the underlying hardware configuration (addresses, pan ID) is in
45    /// line with this MAC device implementation.
46    fn config_commit(&self);
47
48    /// Returns if the MAC device is currently on.
49    fn is_on(&self) -> bool;
50
51    /// Start the radio.
52    ///
53    /// This serves as a passthrough to the underlying radio's `start` method.
54    ///
55    /// ## Return
56    ///
57    /// `Ok(())` on success. On `Err()`, valid errors are:
58    ///
59    /// - `ErrorCode::FAIL`: Internal error occurred.
60    fn start(&self) -> Result<(), ErrorCode>;
61
62    /// Prepares a mutable buffer slice as an 802.15.4 frame by writing the appropriate
63    /// header bytes into the buffer. This needs to be done before adding the
64    /// payload because the length of the header is not fixed.
65    ///
66    /// - `buf`: The mutable buffer slice to use
67    /// - `dst_pan`: The destination PAN ID
68    /// - `dst_addr`: The destination MAC address
69    /// - `src_pan`: The source PAN ID
70    /// - `src_addr`: The source MAC address
71    /// - `security_needed`: Whether or not this frame should be secured. This
72    /// needs to be specified beforehand so that the auxiliary security header
73    /// can be pre-inserted.
74    ///
75    /// Returns either a Frame that is ready to have payload appended to it, or
76    /// the mutable buffer if the frame cannot be prepared for any reason
77    fn prepare_data_frame(
78        &self,
79        buf: &'static mut [u8],
80        dst_pan: PanID,
81        dst_addr: MacAddress,
82        src_pan: PanID,
83        src_addr: MacAddress,
84        security_needed: Option<(SecurityLevel, KeyId)>,
85    ) -> Result<Frame, &'static mut [u8]>;
86
87    /// Transmits a frame that has been prepared by the above process. If the
88    /// transmission process fails, the buffer inside the frame is returned so
89    /// that it can be re-used.
90    fn transmit(&self, frame: Frame) -> Result<(), (ErrorCode, &'static mut [u8])>;
91}
92
93/// Trait to be implemented by any user of the IEEE 802.15.4 device that
94/// transmits frames. Contains a callback through which the static mutable
95/// reference to the frame buffer is returned to the client.
96pub trait TxClient {
97    /// When transmission is complete or fails, return the buffer used for
98    /// transmission to the client. `result` indicates whether or not
99    /// the transmission was successful.
100    ///
101    /// - `spi_buf`: The buffer used to contain the transmitted frame is
102    /// returned to the client here.
103    /// - `acked`: Whether the transmission was acknowledged.
104    /// - `result`: This is `Ok(())` if the frame was transmitted,
105    /// otherwise an error occurred in the transmission pipeline.
106    fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>);
107}
108
109/// Trait to be implemented by users of the IEEE 802.15.4 device that wish to
110/// receive frames.
111///
112/// The callback is triggered whenever a valid frame is received,
113/// verified and unsecured (via the IEEE 802.15.4 security procedure)
114/// successfully.
115pub trait RxClient {
116    /// When a frame is received, this callback is triggered. The client only
117    /// receives an immutable borrow of the buffer. Only completely valid,
118    /// unsecured frames that have passed the incoming security procedure are
119    /// exposed to the client.
120    ///
121    /// - `buf`: The entire buffer containing the frame, including extra bytes
122    /// in front used for the physical layer.
123    /// - `header`: A fully-parsed representation of the MAC header, with the
124    /// caveat that the auxiliary security header is still included if the frame
125    /// was previously secured.
126    /// - `lqi`: The link quality indicator of the received frame.
127    /// - `data_offset`: Offset of the data payload relative to
128    /// `buf`, so that the payload of the frame is contained in
129    /// `buf[data_offset..data_offset + data_len]`.
130    /// - `data_len`: Length of the data payload
131    fn receive<'a>(
132        &self,
133        buf: &'a [u8],
134        header: Header<'a>,
135        lqi: u8,
136        data_offset: usize,
137        data_len: usize,
138    );
139}