1# Copyright 2024 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# This file contains Emboss definitions for the logical link control and 16# adaptation protocol (l2cap) frames found in the Bluetooth core specification. 17# The Emboss compiler is used to generate a C++ header from this file. 18 19[$default byte_order: "LittleEndian"] 20[(cpp) namespace: "pw::bluetooth::emboss"] 21# ========================= Data Packet Format ================================= 22# Core Spec v6.0 Vol 3, Part A, Section 3 23 24 25struct BasicL2capHeader: 26 0 [+2] UInt pdu_length 27 -- For B-frames, the PDU Length equals the payload size. 28 29 $next [+2] UInt channel_id 30 -- The channel ID (CID) identifies the destination channel endpoint of the 31 -- packet. 32 [requires: this != 0] 33 34 35struct BFrame: 36 -- Defined in Core Spec v6.0 Vol 3, Part A, Section 3.1. 37 0 [+BasicL2capHeader.$size_in_bytes] BasicL2capHeader header 38 let pdu_length = header.pdu_length 39 let channel_id = header.channel_id 40 $next [+pdu_length] UInt:8[pdu_length] payload 41 42 43struct BFrameHeader: 44 # TODO: b/364711772 - Migrate clients to `BFrame` & delete. 45 -- 3.1 46 -- A frame header for a B-Frame. 47 -- In basic L2CAP mode, the L2CAP PDU on a connection-oriented channel is also 48 -- referred to as a "B-frame". 49 0 [+2] UInt pdu_length 50 -- For B-frames, the PDU Length equals the payload size. 51 52 $next [+2] UInt channel_id 53 -- The channel ID (CID) identifies the destination channel endpoint of the 54 -- packet. 55 56 57struct FirstKFrame: 58 -- Defined in Core Spec v6.0 Vol 3, Part A, Section 3.4. 59 [requires: 0 <= payload_size <= 65533] 60 0 [+BasicL2capHeader.$size_in_bytes] BasicL2capHeader header 61 let pdu_length = header.pdu_length 62 let channel_id = header.channel_id 63 let payload_size = pdu_length-2 64 $next [+2] UInt sdu_length 65 -- The first K-Frame of an SDU contains an SDU length field following the 66 -- L2CAP header. Subsequent frames that are part of the same SDU do not 67 -- contain the SDU length field. 68 69 $next [+payload_size] UInt:8[payload_size] payload 70 71 72struct SubsequentKFrame: 73 -- Defined in Core Spec v6.0 Vol 3, Part A, Section 3.4. 74 [requires: 0 <= payload_size <= 65533] 75 0 [+BasicL2capHeader.$size_in_bytes] BasicL2capHeader header 76 let pdu_length = header.pdu_length 77 let channel_id = header.channel_id 78 let payload_size = pdu_length 79 $next [+payload_size] UInt:8[payload_size] payload 80 81 82struct KFrameSduHeader: 83 # TODO: b/364711772 - Migrate clients to `FirstKFrame` & delete. 84 -- 3.4.2 85 -- A frame header for a K-Frame (credit based flow control) SDU. 86 0 [+2] UInt sdu_length 87 88 89struct KFramePduHeader: 90 # TODO: b/364711772 - Migrate clients to `SubsequentKFrame` & delete. 91 -- 3.4.1 92 -- A frame header for a K-Frame (credit based flow control) PDU. 93 0 [+2] UInt pdu_length 94 $next [+2] UInt channel_id 95 96# ====================== Signaling Packet Formats ============================== 97# Core Spec v6.0 Vol 3, Part A, Section 4 98 99 100enum L2capSignalingPacketCode: 101 -- Possible values for the Code field of an L2CAP C-frame. See Core Spec v5.4, 102 -- Vol 3, Part A, Table 4.2 for a list of the codes. 103 [maximum_bits: 8] 104 COMMAND_REJECT_RSP = 0x01 105 CONNECTION_REQ = 0x02 106 CONNECTION_RSP = 0x03 107 CONFIGURATION_REQ = 0x04 108 CONFIGURATION_RSP = 0x05 109 DISCONNECTION_REQ = 0x06 110 DISCONNECTION_RSP = 0x07 111 ECHO_REQ = 0x08 112 ECHO_RSP = 0x09 113 INFORMATION_REQ = 0x0A 114 INFORMATION_RSP = 0x0B 115 CONNECTION_PARAMETER_UPDATE_REQ = 0x12 116 CONNECTION_PARAMETER_UPDATE_RSP = 0x13 117 LE_CREDIT_BASED_CONNECTION_REQ = 0x14 118 LE_CREDIT_BASED_CONNECTION_RSP = 0x15 119 FLOW_CONTROL_CREDIT_IND = 0x16 120 CREDIT_BASED_CONNECTION_REQ = 0x17 121 CREDIT_BASED_CONNECTION_RSP = 0x18 122 CREDIT_BASED_RECONFIGURE_REQ = 0x19 123 CREDIT_BASED_RECONFIGURE_RSP = 0x1A 124 125 126enum L2capFixedCid: 127 -- Possible fixed values for L2CAP channel ID. See Core Spec v6.0, Vol 3, 128 -- Part A, Table 2.1 129 [maximum_bits: 16] 130 ACL_U_SIGNALING = 0x0001 131 CONNECTIONLESS = 0x0002 # Applicable to ACL-U and APB-U 132 ACL_U_SECURITY_MANAGER = 0x0007 133 LE_U_ATTRIBUTE_PROTOCOL = 0x0004 134 LE_U_SIGNALING = 0x0005 135 LE_U_SECURITY_MANAGER = 0x0006 136 137 138enum L2capFixedPsmCode: 139 -- Possible fixed values for PSM or SPSM as assigned by Bluetooth SIG. See 140 -- Core Spec v5.4, Vol 3, Part A, Section 4.2 and Assigned_Numbers Section 2.5 141 [maximum_bits: 16] 142 SDP = 0x0001 # PSM 143 RFCOMM = 0x0003 # PSM 144 ATT = 0x001F # PSM 145 EATT = 0x0027 # PSM or SPSM 146 147 148enum L2capCommandRejectReasonCode: 149 -- Reported in L2CAP_COMMAND_REJECT_RSP packets. 150 [maximum_bits: 16] 151 NOT_UNDERSTOOD = 0x0000 152 SIG_MTU_EXCEEDED = 0x0001 153 INVALID_CID = 0x0002 154 -- Typically a channel is invalid because it does not exist. 155 156 157struct CFrame: 158 -- A Control Frame (C-frame) contains L2CAP signaling commands exchanged 159 -- between peer L2CAP entities. C-frames are exclusively used on the L2CAP 160 -- signaling channels. 161 0 [+BasicL2capHeader.$size_in_bytes] BasicL2capHeader header 162 let pdu_length = header.pdu_length 163 let channel_id = header.channel_id 164 $next [+pdu_length] UInt:8[pdu_length] payload 165 166 167struct L2capSignalingCommandHeader: 168 -- C-frame refers to an L2CAP PDU payload containing one or more signaling 169 -- commands. 170 0 [+1] L2capSignalingPacketCode code 171 $next [+1] UInt identifier 172 -- Matches responses with requests. 173 174 $next [+2] UInt data_length 175 176 177struct L2capSignalingCommand: 178 -- Generic L2CAP signaling command. 179 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 180 let data_length = command_header.data_length 181 $next [+data_length] UInt:8[data_length] payload 182 183 184struct L2capCommandRejectRsp: 185 -- Section 4.1 186 -- An L2CAP_COMMAND_REJECT_RSP packet shall be sent in response to a command 187 -- packet with an unknown command code or when sending the corresponding 188 -- response is inappropriate. 189 190 [requires: command_header.code == L2capSignalingPacketCode.COMMAND_REJECT_RSP] 191 192 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 193 194 $next [+2] L2capCommandRejectReasonCode reason 195 -- Describes why the request packet was rejected. 196 197 if reason == L2capCommandRejectReasonCode.SIG_MTU_EXCEEDED: 198 6 [+2] UInt actual_sig_mtu 199 200 if reason == L2capCommandRejectReasonCode.INVALID_CID: 201 # The local and remote endpoints of the disputed channel relative to the 202 # sender of this L2CAP_COMMAND_REJECT_RSP packet. If the rejected command 203 # contains only one of the channel endpoints, the other one shall be 204 # replaced by the null CID 0x0000. 205 6 [+2] UInt local_endpoint 206 -- The destination CID from the rejected command. 207 208 8 [+2] UInt remote_endpoint 209 -- The source CID from the rejected command. 210 211 212struct L2capConnectionReq: 213 -- Section 4.2 214 -- L2CAP_CONNECTION_REQ packets are sent to create an L2CAP channel between 215 -- two devices. 216 [requires: command_header.code == L2capSignalingPacketCode.CONNECTION_REQ] 217 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 218 $next [+2] UInt psm 219 -- Protocol/Service Multiplexer. 220 221 $next [+2] UInt source_cid 222 -- The channel endpoint on the device sending the request. 223 224 225enum L2capConnectionRspResultCode: 226 -- Reported in L2CAP_CONNECTION_RSP packets. 227 [maximum_bits: 16] 228 SUCCESSFUL = 0x0000 229 PENDING = 0x0001 230 PSM_NOT_SUPPORTED = 0x0002 231 SECURITY_BLOCK = 0x0003 232 NO_RESOURCES_AVAILABLE = 0x0004 233 INVALID_SOURCE_CID = 0x0005 234 SOURCE_CID_ALREADY_ALLOCATED = 0x0006 235 236 237enum L2capConnectionRspStatusCode: 238 -- Reported in L2CAP_CONNECTION_RSP packets if result is PENDING. 239 [maximum_bits: 16] 240 NO_INFORMATION = 0x0000 241 AUTHENTICATION_PENDING = 0x0001 242 AUTHORIZATION_PENDING = 0x0002 243 244 245struct L2capConnectionRsp: 246 -- Section 4.3 247 -- L2CAP_CONNECTION_RSP packets are sent in response to a L2CAP_CONNECTION_REQ 248 -- packet. 249 [requires: command_header.code == L2capSignalingPacketCode.CONNECTION_RSP] 250 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 251 $next [+2] UInt destination_cid 252 -- The channel endpoint on the device sending this response packet. 253 254 $next [+2] UInt source_cid 255 -- The channel endpoint on the device receiving the packet. 256 257 $next [+2] L2capConnectionRspResultCode result 258 -- The outcome of the connection request. 259 260 if result == L2capConnectionRspResultCode.PENDING: 261 $next [+2] L2capConnectionRspStatusCode status 262 -- The status of the connection. 263 264 265struct L2capDisconnectionReq: 266 -- Section 4.6 267 -- Once an L2CAP_DISCONNECTION_REQ packet is issued, all incoming data in 268 -- transit on this L2CAP channel shall be discarded and any new additional 269 -- outgoing data shall be discarded. 270 [requires: command_header.code == L2capSignalingPacketCode.DISCONNECTION_REQ] 271 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 272 $next [+2] UInt destination_cid 273 -- The endpoint of the channel to be disconnected on the device receiving 274 -- this request. 275 276 $next [+2] UInt source_cid 277 -- The endpoint of the channel to be disconnected on the device sending this 278 -- request. 279 280 281struct L2capDisconnectionRsp: 282 -- Section 4.7 283 -- L2CAP_DISCONNECTION_RSP packets shall be sent in response to each valid 284 -- L2CAP_DISCONNECTION_REQ packet. 285 [requires: command_header.code == L2capSignalingPacketCode.DISCONNECTION_RSP] 286 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 287 $next [+2] UInt destination_cid 288 -- The channel endpoint on the device sending the packet. 289 290 $next [+2] UInt source_cid 291 -- The channel endpoint on the device receiving the packet. 292 293 294struct L2capLeCreditBasedConnectionReq: 295 -- Section 4.22 296 -- L2CAP_LE_CREDIT_BASED_CONNECTION_REQ packets are sent to create and 297 -- configure an L2CAP channel between two devices using LE Credit Based Flow 298 -- Control mode. 299 [requires: command_header.code == L2capSignalingPacketCode.LE_CREDIT_BASED_CONNECTION_REQ] 300 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 301 -- `code` is expected to be LE_CREDIT_BASED_CONNECTION_REQ 302 303 $next [+2] UInt spsm 304 -- Simplified Protocol/Service Multiplexer. 305 306 $next [+2] UInt source_cid 307 -- Channel endpoint on the device sending the request. 308 309 let min_mtu = 23 310 $next [+2] UInt mtu 311 -- Maximum Transmission Unit 312 [requires: this >= L2capLeCreditBasedConnectionReq.min_mtu] 313 314 let min_mps = 23 315 let max_mps = 65533 316 $next [+2] UInt mps 317 -- Maximum PDU Payload Size 318 [requires: L2capLeCreditBasedConnectionReq.min_mps <= this <= L2capLeCreditBasedConnectionReq.max_mps] 319 320 let max_credit_value = 65535 321 $next [+2] UInt initial_credits 322 [requires: this <= L2capLeCreditBasedConnectionReq.max_credit_value] 323 324 325struct L2capFlowControlCreditInd: 326 -- Section 4.24 327 -- A device shall send an L2CAP_FLOW_CONTROL_CREDIT_IND packet when it is 328 -- capable of receiving additional K-frames (for example after it has 329 -- processed one or more K-frames) in LE Credit Based Flow Control mode and 330 -- Enhanced Credit Based Flow Control mode. 331 [requires: command_header.code == L2capSignalingPacketCode.FLOW_CONTROL_CREDIT_IND] 332 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 333 $next [+2] UInt cid 334 -- The source channel endpoint of the device sending the packet. 335 336 $next [+2] UInt credits 337 -- The credit value field represents number of credits the receiving device 338 -- can increment. 339 [requires: 1 <= this <= 65535] 340