• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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