xref: /aosp_15_r20/external/pigweed/pw_bluetooth/public/pw_bluetooth/l2cap_frames.emb (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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