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