rubble/link/
data.rs

1//! Data Channel structures.
2
3use crate::link::{llcp::ControlPdu, SeqNum};
4use crate::{bytes::*, Error};
5use core::{convert::TryInto, fmt};
6
7/// 16-bit data channel header preceding the payload.
8///
9/// Layout (in Bluetooth 4.2):
10///
11/// ```notrust
12/// LSB                                                                MSB
13/// +----------+---------+---------+---------+------------+--------------+
14/// |   LLID   |  NESN   |   SN    |   MD    |     -      |    Length    |
15/// | (2 bits) | (1 bit) | (1 bit) | (1 bit) |  (3 bits)  |   (8 bits)   |
16/// +----------+---------+---------+---------+------------+--------------+
17/// ```
18///
19/// Payload format depends on the value of the 2-bit `LLID` field:
20///
21/// * `0b00`: Reserved value.
22/// * `0b01`: LL Data PDU Continuation fragment or empty PDU.
23/// * `0b10`: LL Data PDU Start of L2CAP message (or complete message if no fragmentation
24///   necessary).
25/// * `0b11`: LL Control PDU.
26///
27/// The `NESN` field specifies the **N**ext **E**xpected **S**equence **N**umber. The `SN` field
28/// specifies the **S**equence **N**umber of this PDU.
29///
30/// The `MD` field specifies that the device sending the packet has more data to send during this
31/// *connection event*. When both slave and master send a packet with the `MD` bit set to 0, the
32/// connection event ends.
33///
34/// The `Length` field specifies the length of payload **and `MIC`**. Prior to Bluetooth 4.2, this
35/// was a 5-bit field, resulting in payloads + MICs of up to 31 Bytes. With Bluetooth 4.2, devices
36/// can communicate their buffer sizes and optionally transmit larger packets.
37///
38/// ## Sequence Numbers
39///
40/// The `NESN` and `SN` fields are used for retransmission and acknowledgement. The link layer
41/// stores two 1-bit parameters for an established connection, called `transmitSeqNum` and
42/// `nextExpectedSeqNum`. When a connection is established, both start out as 0. Both parameters are
43/// repeatedly incremented by 1 when data is transmitted, using wrapping arithmetic.
44///
45/// When a data channel packet is sent for the first time (ie. not retransmitted), the `SN` field is
46/// set to `transmitSeqNum`. When the packet is resent, the `SN` field is not modified. In both
47/// cases, the `NESN` bit is set to `nextExpectedSeqNum`.
48///
49/// The `NESN` bit tells the receiver whether its last packet has arrived: When a packet is
50/// received with an `NESN` value equal to the receiver's `transmitSeqNum`, the receiver has already
51/// sent a packet with the expected `SN`, but the other side hasn't received it yet. The receiver
52/// must resend the last data channel PDU. No other data channel PDU must be sent by it.
53///
54/// When the received packet's `NESN` bit is different from `transmitSeqNum`, the last PDU has been
55/// acknowledged and the receiver should increment `transmitSeqNum` by 1.
56///
57/// Similarly, the `SN` bit is used to distinguish retransmitted and new packets: When a packet is
58/// received with an `SN` value equal to the receiver's `nextExpectedSeqNum` value, the packet is
59/// new (not a retransmission), and `nextExpectedSeqNum` should be incremented by 1. If the value is
60/// not equal to `nextExpectedSeqNum`, this packet is a retransmission, so `nextExpectedSeqNum`
61/// should not be changed.
62#[derive(Copy, Clone)]
63pub struct Header(u16);
64
65impl Header {
66    /// Creates a header with the given LLID field and all other fields set to 0 (including the
67    /// payload length).
68    pub fn new(llid: Llid) -> Self {
69        Header(llid as u16)
70    }
71
72    /// Parses a header from raw bytes.
73    ///
74    /// Panics when `raw` contains less than 2 Bytes.
75    pub fn parse(raw: &[u8]) -> Self {
76        let bytes: [u8; 2] = raw[..2].try_into().expect("raw has fewer than 2 bytes");
77        Header(u16::from_le_bytes(bytes))
78    }
79
80    /// Returns the raw representation of the header.
81    ///
82    /// The returned `u16` must be transmitted LSB and LSb first as the first 2 octets of the PDU.
83    pub fn to_u16(&self) -> u16 {
84        self.0
85    }
86
87    /// Returns the length of the payload in octets as specified in the `Length` field.
88    pub fn payload_length(&self) -> u8 {
89        ((self.0 & 0b11111111_00000000) >> 8) as u8
90    }
91
92    /// Sets the payload length field to `len`.
93    ///
94    /// Note that BLE <4.2 is restricted to 5-bit payload lengths.
95    pub fn set_payload_length(&mut self, len: u8) {
96        self.0 = (u16::from(len) << 8) | (self.0 & 0x00ff);
97    }
98
99    /// Returns the `LLID` field (PDU type).
100    pub fn llid(&self) -> Llid {
101        let bits = self.0 & 0b11;
102        match bits {
103            0b00 => Llid::Reserved,
104            0b01 => Llid::DataCont,
105            0b10 => Llid::DataStart,
106            0b11 => Llid::Control,
107            _ => unreachable!(),
108        }
109    }
110
111    /// Returns the value of the `NESN` field (Next Expected Sequence Number).
112    pub fn nesn(&self) -> SeqNum {
113        let bit = self.0 & 0b0100;
114        if bit == 0 {
115            SeqNum::ZERO
116        } else {
117            SeqNum::ONE
118        }
119    }
120
121    /// Sets the value of the `NESN` field.
122    pub fn set_nesn(&mut self, nesn: SeqNum) {
123        if nesn == SeqNum::ONE {
124            self.0 |= 0b0100;
125        } else {
126            self.0 &= !0b0100;
127        }
128    }
129
130    /// Returns the value of the `SN` field (Sequence Number).
131    pub fn sn(&self) -> SeqNum {
132        let bit = self.0 & 0b1000;
133        if bit == 0 {
134            SeqNum::ZERO
135        } else {
136            SeqNum::ONE
137        }
138    }
139
140    /// Sets the value of the `SN` field.
141    pub fn set_sn(&mut self, sn: SeqNum) {
142        if sn == SeqNum::ONE {
143            self.0 |= 0b1000;
144        } else {
145            self.0 &= !0b1000;
146        }
147    }
148
149    /// Returns whether the `MD` field is set (More Data).
150    pub fn md(&self) -> bool {
151        let bit = self.0 & 0b10000;
152        bit != 0
153    }
154
155    /// Sets the value of the `MD` field.
156    pub fn set_md(&mut self, md: bool) {
157        if md {
158            self.0 |= 0b10000;
159        } else {
160            self.0 &= !0b10000;
161        }
162    }
163}
164
165impl fmt::Debug for Header {
166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167        f.debug_struct("Header")
168            .field("LLID", &self.llid())
169            .field("NESN", &self.nesn())
170            .field("SN", &self.sn())
171            .field("MD", &self.md())
172            .field("Length", &self.payload_length())
173            .finish()
174    }
175}
176
177impl<'a> FromBytes<'a> for Header {
178    fn from_bytes(bytes: &mut ByteReader<'a>) -> Result<Self, Error> {
179        let raw = bytes.read_u16_le()?;
180        Ok(Header(raw))
181    }
182}
183
184impl ToBytes for Header {
185    fn to_bytes(&self, writer: &mut ByteWriter<'_>) -> Result<(), Error> {
186        writer.write_u16_le(self.to_u16())
187    }
188}
189
190/// Values of the LLID field in `Header`.
191#[derive(Copy, Clone, Debug, PartialEq, Eq)]
192pub enum Llid {
193    /// Reserved for future use.
194    Reserved = 0b00,
195
196    /// Continuation of L2CAP message, or empty PDU.
197    DataCont = 0b01,
198
199    /// Start of L2CAP message.
200    DataStart = 0b10,
201
202    /// LL control PDU.
203    Control = 0b11,
204}
205
206/// Structured representation of a data channel PDU.
207#[derive(Debug)]
208pub enum Pdu<'a, L> {
209    /// Continuation of an L2CAP message (or empty PDU).
210    DataCont { message: L },
211
212    /// Start of an L2CAP message (must not be empty).
213    DataStart { message: L },
214
215    /// LL Control PDU for controlling the Link-Layer connection.
216    Control { data: BytesOr<'a, ControlPdu<'a>> },
217}
218
219impl<'a> Pdu<'a, &'a [u8]> {
220    /// Creates an empty PDU that carries no message.
221    ///
222    /// This PDU can be sent whenever there's no actual data to be transferred.
223    pub fn empty() -> Self {
224        Pdu::DataCont { message: &[] }
225    }
226}
227
228impl<'a, L> Pdu<'a, L> {
229    /// Returns the `LLID` field to use for this PDU.
230    pub fn llid(&self) -> Llid {
231        match self {
232            Pdu::DataCont { .. } => Llid::DataCont,
233            Pdu::DataStart { .. } => Llid::DataStart,
234            Pdu::Control { .. } => Llid::Control,
235        }
236    }
237}
238
239impl<'a, L: FromBytes<'a> + ?Sized> Pdu<'a, L> {
240    /// Parses a PDU from a `Header` and raw payload.
241    pub fn parse(header: Header, payload: &'a [u8]) -> Result<Self, Error> {
242        match header.llid() {
243            Llid::DataCont => Ok(Pdu::DataCont {
244                message: L::from_bytes(&mut ByteReader::new(payload))?,
245            }),
246            Llid::DataStart => Ok(Pdu::DataStart {
247                message: L::from_bytes(&mut ByteReader::new(payload))?,
248            }),
249            Llid::Control => Ok(Pdu::Control {
250                data: BytesOr::from_bytes(&mut ByteReader::new(payload))?,
251            }),
252            Llid::Reserved => Err(Error::InvalidValue),
253        }
254    }
255}
256
257impl<'a> From<&'a ControlPdu<'a>> for Pdu<'a, &'a [u8]> {
258    fn from(c: &'a ControlPdu<'a>) -> Self {
259        Pdu::Control { data: c.into() }
260    }
261}
262
263/// Serializes the payload of the PDU to bytes.
264///
265/// The PDU header must be constructed using Link-Layer state (and `Pdu::llid`).
266impl<'a, L: ToBytes> ToBytes for Pdu<'a, L> {
267    fn to_bytes(&self, buffer: &mut ByteWriter<'_>) -> Result<(), Error> {
268        match self {
269            Pdu::DataCont { message } | Pdu::DataStart { message } => message.to_bytes(buffer),
270            Pdu::Control { data } => data.to_bytes(buffer),
271        }
272    }
273}