• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include <endian.h>
17 
18 #include <cstdint>
19 #include <type_traits>
20 
21 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
22 
23 namespace bt::l2cap::internal {
24 
25 // The definitions within this namespace don't directly map to full frame
26 // formats. Rather, they provide access to mode-specific headers beyond the
27 // L2CAP basic frame header.
28 //
29 // The structs can be used in two ways: to parse inbound data, or to format
30 // outbound data. When used to parse inbound data, the structs due not provide
31 // any validation. When used to format outbound data, the structs initialize
32 // bits to 0, or (if appropriate) a value appropriate for that struct.
33 
34 // For Retransmission and Flow Control Modes. (Vol 3, Part A, Sec 3.3.2)
35 using StandardControlField = uint16_t;
36 
37 // See Vol 3, Part A, Sec 3.3.2, Table 3.4.
38 enum class SegmentationStatus {
39   Unsegmented = 0b00,
40   FirstSegment = 0b01,  // AKA "Start of L2CAP SDU"
41   LastSegment = 0b10,   // AKA "End of L2CAP SDU"
42   MiddleSegment = 0b11  // AKA "Continuation of L2CAP SDU"
43 };
44 
45 // For Enhanced Retransmission and Streaming Modes _without_ Extended Window
46 // Size. (Vol 3, Part A, Sec 3.3.2)
47 struct EnhancedControlField {
48   // See Core Spec v5, Vol 3, Part A, Sec 8.3.
49   static constexpr auto kMaxSeqNum{63};
50 
EnhancedControlFieldEnhancedControlField51   EnhancedControlField() : raw_value(0) {}
52 
designates_information_frameEnhancedControlField53   bool designates_information_frame() const {
54     return !(le16toh(raw_value) & 0b1);
55   }
designates_supervisory_frameEnhancedControlField56   bool designates_supervisory_frame() const { return le16toh(raw_value) & 0x1; }
designates_start_of_segmented_sduEnhancedControlField57   bool designates_start_of_segmented_sdu() const {
58     return designates_information_frame() &&
59            ((le16toh(raw_value) & (0b11 << 14)) == (0b01 << 14));
60   }
61   // Returns true for all segmented frames, including the start-of-segment frame
62   // (even though the start-of-segment frame has a different header format).
designates_part_of_segmented_sduEnhancedControlField63   bool designates_part_of_segmented_sdu() const {
64     return designates_information_frame() &&
65            (le16toh(raw_value) & (0b11 << 14));
66   }
67 
set_supervisory_frameEnhancedControlField68   void set_supervisory_frame() {
69     // See Vol 3, Part A, Section 3.3.2, Table 3.2.
70     raw_value = htole16(le16toh(raw_value) | 0x1);
71   }
72 
receive_seq_numEnhancedControlField73   uint8_t receive_seq_num() const {
74     // "Receive Sequence Number - ReqSeq" Vol 3, Part A, Section 3.3.2,
75     // Table 3.2.
76     return (le16toh(raw_value) >> 8) & 0b11'1111;
77   }
78 
79   bool is_poll_response() const {
80     // See Vol 3, Part A, Sec 3.3.2, Table 3.2. The spec calls this the 'final'
81     // bit. But poll response seems more intuitive.
82     return le16toh(raw_value) & 0b1000'0000;
83   }
84 
set_receive_seq_numEnhancedControlField85   void set_receive_seq_num(uint8_t seq_num) {
86     BT_DEBUG_ASSERT(seq_num <= kMaxSeqNum);
87     // "Receive Sequence Number - ReqSeq" Vol 3, Part A, Section 3.3.2,
88     // Table 3.2.
89     raw_value = htole16(le16toh(raw_value) | (seq_num << 8));
90   }
91 
set_is_poll_responseEnhancedControlField92   void set_is_poll_response() {
93     // See Vol 3, Part A, Sec 3.3.2, Table 3.2. The spec calls this the 'final'
94     // bit. But poll response seems more intuitive.
95     raw_value = htole16(le16toh(raw_value) | 0b1000'0000);
96   }
97 
98   void set_segmentation_status(SegmentationStatus status) {
99     // "Segmentation and Reassembly - SAR" Vol 3, Part A, Section 3.3.2,
100     // Table 3.4.
101     raw_value = htole16((le16toh(raw_value) & 0b0011'1111'1111'1111) |
102                         (static_cast<uint8_t>(status) << 14));
103   }
104 
105  protected:
106   uint16_t raw_value;  // In protocol byte-order (little-endian).
107 } __attribute__((packed));
108 
109 // For Enhanced Retransmission and Streaming Modes _with_ Extended Window
110 // Size. (Vol 3, Part A, Secs 3.3.2 and 5.7. Feature 2/39.)
111 using ExtendedControlField = uint32_t;
112 
113 // Represents an I-frame header for:
114 // * a channel operating in Enhanced Retransmission or
115 //   Streaming Mode, where
116 // * the Extended Window Size and Frame Checksum options are
117 //   disabled, and
118 // * the frame is _not_ a "Start of L2CAP SDU" frame.
119 // Omits the Basic L2CAP header. See Vol 3, Part A, Sec 3.3.
120 struct SimpleInformationFrameHeader : public EnhancedControlField {
121   SimpleInformationFrameHeader() = default;
122 
SimpleInformationFrameHeaderSimpleInformationFrameHeader123   explicit SimpleInformationFrameHeader(uint8_t tx_seq) {
124     BT_DEBUG_ASSERT(tx_seq <= kMaxSeqNum);
125     raw_value = htole16(le16toh(raw_value) | (tx_seq << 1));
126   }
127 
tx_seqSimpleInformationFrameHeader128   uint8_t tx_seq() const {
129     BT_DEBUG_ASSERT(!designates_supervisory_frame());
130     return (le16toh(raw_value) & (0b0111'1110)) >> 1;
131   }
132 } __attribute__((packed));
133 
134 // Represents an I-frame header for:
135 // * a channel operating in Enhanced Retransmission or
136 //   Streaming Mode, where
137 // * the Extended Window Size and Frame Checksum options are
138 //   disabled, and
139 // * the frame _is_ a "Start of L2CAP SDU" frame.
140 // Omits the Basic L2CAP header. See Vol 3, Part A, Sec 3.3.
141 struct SimpleStartOfSduFrameHeader : public SimpleInformationFrameHeader {
142   SimpleStartOfSduFrameHeader() = default;
143 
144   explicit SimpleStartOfSduFrameHeader(uint8_t tx_seq)
145       : SimpleInformationFrameHeader(tx_seq), sdu_len(0) {
146     set_segmentation_status(SegmentationStatus::FirstSegment);
147   }
148   uint16_t sdu_len;
149 } __attribute__((packed));
150 
151 // See Vol 3, Part A, Sec 3.3.2, Table 3.5.
152 enum class SupervisoryFunction {
153   ReceiverReady = 0,
154   Reject = 1,
155   ReceiverNotReady = 2,
156   SelectiveReject = 3
157 };
158 
159 // Represents an S-frame for:
160 // * a channel operating in Enhanced Retransmission or
161 //   Streaming Mode, where
162 // * the Extended Window Size and Frame Checksum options are
163 //   disabled
164 // Omits the Basic L2CAP header. See Vol 3, Part A, Sec 3.3.
165 struct SimpleSupervisoryFrame : public EnhancedControlField {
166   SimpleSupervisoryFrame() = default;
167 
168   explicit SimpleSupervisoryFrame(SupervisoryFunction sfunc) {
169     BT_DEBUG_ASSERT(sfunc <= SupervisoryFunction::SelectiveReject);
170     set_supervisory_frame();
171     // See Vol 3, Part A, Sec 3.3.2, Table 3.2.
172     raw_value =
173         htole16(le16toh(raw_value) | (static_cast<uint8_t>(sfunc) << 2));
174   }
175 
176   bool is_poll_request() const {
177     return le16toh(raw_value) &
178            0b1'0000;  // See Vol 3, Part A, Sec 3.3.2, Table 3.2.
179   }
180 
functionSimpleSupervisoryFrame181   SupervisoryFunction function() const {
182     // See Vol 3, Part A, Sec 3.3.2, Table 3.2.
183     return static_cast<SupervisoryFunction>((le16toh(raw_value) >> 2) & 0b11);
184   }
185 
set_is_poll_requestSimpleSupervisoryFrame186   void set_is_poll_request() {
187     // See Vol 3, Part A, Sec 3.3.2, Table 3.2.
188     raw_value = htole16(le16toh(raw_value) | 0b1'0000);
189   }
190 } __attribute__((packed));
191 
192 struct SimpleReceiverReadyFrame : public SimpleSupervisoryFrame {
193   SimpleReceiverReadyFrame()
194       : SimpleSupervisoryFrame(SupervisoryFunction::ReceiverReady) {}
195 } __attribute__((packed));
196 
197 }  // namespace bt::l2cap::internal
198