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}