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 AVDTP = 0x0019 # PSM 145 ATT = 0x001F # PSM 146 EATT = 0x0027 # PSM or SPSM 147 148 149enum L2capCommandRejectReasonCode: 150 -- Reported in L2CAP_COMMAND_REJECT_RSP packets. 151 [maximum_bits: 16] 152 NOT_UNDERSTOOD = 0x0000 153 SIG_MTU_EXCEEDED = 0x0001 154 INVALID_CID = 0x0002 155 -- Typically a channel is invalid because it does not exist. 156 157 158struct CFrame: 159 -- A Control Frame (C-frame) contains L2CAP signaling commands exchanged 160 -- between peer L2CAP entities. C-frames are exclusively used on the L2CAP 161 -- signaling channels. 162 0 [+BasicL2capHeader.$size_in_bytes] BasicL2capHeader header 163 let pdu_length = header.pdu_length 164 let channel_id = header.channel_id 165 $next [+pdu_length] UInt:8[pdu_length] payload 166 167 168struct L2capSignalingCommandHeader: 169 -- C-frame refers to an L2CAP PDU payload containing one or more signaling 170 -- commands. 171 0 [+1] L2capSignalingPacketCode code 172 $next [+1] UInt identifier 173 -- Matches responses with requests. 174 175 $next [+2] UInt data_length 176 177 178struct L2capSignalingCommand: 179 -- Generic L2CAP signaling command. 180 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 181 let data_length = command_header.data_length 182 $next [+data_length] UInt:8[data_length] payload 183 184 185struct L2capCommandRejectRsp: 186 -- Section 4.1 187 -- An L2CAP_COMMAND_REJECT_RSP packet shall be sent in response to a command 188 -- packet with an unknown command code or when sending the corresponding 189 -- response is inappropriate. 190 191 [requires: command_header.code == L2capSignalingPacketCode.COMMAND_REJECT_RSP] 192 193 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 194 195 $next [+2] L2capCommandRejectReasonCode reason 196 -- Describes why the request packet was rejected. 197 198 if reason == L2capCommandRejectReasonCode.SIG_MTU_EXCEEDED: 199 6 [+2] UInt actual_sig_mtu 200 201 if reason == L2capCommandRejectReasonCode.INVALID_CID: 202 # The local and remote endpoints of the disputed channel relative to the 203 # sender of this L2CAP_COMMAND_REJECT_RSP packet. If the rejected command 204 # contains only one of the channel endpoints, the other one shall be 205 # replaced by the null CID 0x0000. 206 6 [+2] UInt local_endpoint 207 -- The destination CID from the rejected command. 208 209 8 [+2] UInt remote_endpoint 210 -- The source CID from the rejected command. 211 212 213struct L2capConnectionReq: 214 -- Section 4.2 215 -- L2CAP_CONNECTION_REQ packets are sent to create an L2CAP channel between 216 -- two devices. 217 [requires: command_header.code == L2capSignalingPacketCode.CONNECTION_REQ] 218 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 219 $next [+2] UInt psm 220 -- Protocol/Service Multiplexer. 221 222 $next [+2] UInt source_cid 223 -- The channel endpoint on the device sending the request. 224 225 226enum L2capConnectionRspResultCode: 227 -- Reported in L2CAP_CONNECTION_RSP packets. 228 [maximum_bits: 16] 229 SUCCESSFUL = 0x0000 230 PENDING = 0x0001 231 PSM_NOT_SUPPORTED = 0x0002 232 SECURITY_BLOCK = 0x0003 233 NO_RESOURCES_AVAILABLE = 0x0004 234 INVALID_SOURCE_CID = 0x0005 235 SOURCE_CID_ALREADY_ALLOCATED = 0x0006 236 237 238enum L2capConnectionRspStatusCode: 239 -- Reported in L2CAP_CONNECTION_RSP packets if result is PENDING. 240 [maximum_bits: 16] 241 NO_INFORMATION = 0x0000 242 AUTHENTICATION_PENDING = 0x0001 243 AUTHORIZATION_PENDING = 0x0002 244 245 246struct L2capConnectionRsp: 247 -- Section 4.3 248 -- L2CAP_CONNECTION_RSP packets are sent in response to a L2CAP_CONNECTION_REQ 249 -- packet. 250 [requires: command_header.code == L2capSignalingPacketCode.CONNECTION_RSP] 251 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 252 $next [+2] UInt destination_cid 253 -- The channel endpoint on the device sending this response packet. 254 255 $next [+2] UInt source_cid 256 -- The channel endpoint on the device receiving the packet. 257 258 $next [+2] L2capConnectionRspResultCode result 259 -- The outcome of the connection request. 260 261 if result == L2capConnectionRspResultCode.PENDING: 262 $next [+2] L2capConnectionRspStatusCode status 263 -- The status of the connection. 264 265 266struct L2capDisconnectionReq: 267 -- Section 4.6 268 -- Once an L2CAP_DISCONNECTION_REQ packet is issued, all incoming data in 269 -- transit on this L2CAP channel shall be discarded and any new additional 270 -- outgoing data shall be discarded. 271 [requires: command_header.code == L2capSignalingPacketCode.DISCONNECTION_REQ] 272 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 273 $next [+2] UInt destination_cid 274 -- The endpoint of the channel to be disconnected on the device receiving 275 -- this request. 276 277 $next [+2] UInt source_cid 278 -- The endpoint of the channel to be disconnected on the device sending this 279 -- request. 280 281 282struct L2capDisconnectionRsp: 283 -- Section 4.7 284 -- L2CAP_DISCONNECTION_RSP packets shall be sent in response to each valid 285 -- L2CAP_DISCONNECTION_REQ packet. 286 [requires: command_header.code == L2capSignalingPacketCode.DISCONNECTION_RSP] 287 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 288 $next [+2] UInt destination_cid 289 -- The channel endpoint on the device sending the packet. 290 291 $next [+2] UInt source_cid 292 -- The channel endpoint on the device receiving the packet. 293 294 295struct L2capLeCreditBasedConnectionReq: 296 -- Section 4.22 297 -- L2CAP_LE_CREDIT_BASED_CONNECTION_REQ packets are sent to create and 298 -- configure an L2CAP channel between two devices using LE Credit Based Flow 299 -- Control mode. 300 [requires: command_header.code == L2capSignalingPacketCode.LE_CREDIT_BASED_CONNECTION_REQ] 301 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 302 -- `code` is expected to be LE_CREDIT_BASED_CONNECTION_REQ 303 304 $next [+2] UInt spsm 305 -- Simplified Protocol/Service Multiplexer. 306 307 $next [+2] UInt source_cid 308 -- Channel endpoint on the device sending the request. 309 310 let min_mtu = 23 311 $next [+2] UInt mtu 312 -- Maximum Transmission Unit 313 [requires: this >= L2capLeCreditBasedConnectionReq.min_mtu] 314 315 let min_mps = 23 316 let max_mps = 65533 317 $next [+2] UInt mps 318 -- Maximum PDU Payload Size 319 [requires: L2capLeCreditBasedConnectionReq.min_mps <= this <= L2capLeCreditBasedConnectionReq.max_mps] 320 321 let max_credit_value = 65535 322 $next [+2] UInt initial_credits 323 [requires: this <= L2capLeCreditBasedConnectionReq.max_credit_value] 324 325 326struct L2capFlowControlCreditInd: 327 -- Section 4.24 328 -- A device shall send an L2CAP_FLOW_CONTROL_CREDIT_IND packet when it is 329 -- capable of receiving additional K-frames (for example after it has 330 -- processed one or more K-frames) in LE Credit Based Flow Control mode and 331 -- Enhanced Credit Based Flow Control mode. 332 [requires: command_header.code == L2capSignalingPacketCode.FLOW_CONTROL_CREDIT_IND] 333 0 [+L2capSignalingCommandHeader.$size_in_bytes] L2capSignalingCommandHeader command_header 334 $next [+2] UInt cid 335 -- The source channel endpoint of the device sending the packet. 336 337 $next [+2] UInt credits 338 -- The credit value field represents number of credits the receiving device 339 -- can increment. 340 [requires: 1 <= this <= 65535] 341