xref: /aosp_15_r20/external/pigweed/pw_bluetooth/public/pw_bluetooth/rfcomm_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# ========================= RFCOMM Frame Format =================================
22# RFCOMM Spec v1.2
23# Also see: ETSI TS 101 369 V7.1.0 (1999-11) and
24# GSM 07.10 version 7.1.0 Release 1998
25
26
27enum RfcommFrameType:
28  -- ETSI TS section 5.2.1.3
29  [maximum_bits: 8]
30  SET_ASYNC_BALANCED_MODE                                 = 0x2f
31  UNNUMBERED_ACK                                          = 0x63
32  DISCONNECT_MODE                                         = 0x0f
33  DISCONNECT                                              = 0xc3
34  UNNUMBERED_INFORMATION_WITH_HEADER_CHECK                = 0xef
35  UNNUMBERED_INFORMATION_WITH_HEADER_CHECK_AND_POLL_FINAL = 0xff
36    -- RFCOMM extension. With Poll/Final bit set in UIH control byte, a credits
37    -- field is the first byte of the payload.
38
39
40enum RfcommFixedChannel:
41  -- ETSI TS section 5.6
42  [maximum_bits: 8]
43  CONTROL = 0
44
45
46enum RfcommCommandResponseAndDirection:
47  -- RFCOMM Spec v1.2 Section 5.4
48  -- GSM 07.10 section 5.2.1.2
49  -- Commands and responses from the responder have C/R = 0. Commands and
50  -- responses from the initiator have C/R = 1.
51  -- For an RFCOMM session, the initiating device is given the direction bit D=1
52  -- (and conversely, D=0 in the other device)
53  [maximum_bits: 2]
54  COMMAND_FROM_INITIATOR  = 0b11
55  COMMAND_FROM_RESPONDER  = 0b00
56  RESPONSE_FROM_INITIATOR = 0b01
57  RESPONSE_FROM_RESPONDER = 0b10
58
59
60enum RfcommLengthExtended:
61  -- ETSI TS section 5.2.1.5
62  [maximum_bits: 1]
63  NORMAL   = 1
64  EXTENDED = 0
65
66
67struct RfcommFrame:
68  -- RFCOMM adaptation of ETSI TS section 5.2 frame
69
70  [requires: extended_address == true]
71
72  0                  [+1]  bits:
73
74    0                  [+1]                 Flag                               extended_address
75
76    1                  [+2]                 RfcommCommandResponseAndDirection  command_response_direction
77
78    3                  [+5]                 UInt                               channel
79      -- ETSI TS 07.10 section 5.2.1.2
80
81  1                  [+1]                   RfcommFrameType                    control
82    -- ETSI TS 07.10 section 5.2.1.3
83
84  let uih = control == RfcommFrameType.UNNUMBERED_INFORMATION_WITH_HEADER_CHECK || control == RfcommFrameType.UNNUMBERED_INFORMATION_WITH_HEADER_CHECK_AND_POLL_FINAL
85    -- Helper flag to check whether frame is UIH type, regardless of whether credits are in use.
86
87  2                  [+1]  bits:
88
89    0                  [+1]                 RfcommLengthExtended               length_extended_flag
90
91    1                  [+7]                 UInt                               length
92      -- ETSI TS 07.10 section 5.2.1.4
93
94  if length_extended_flag == RfcommLengthExtended.EXTENDED:
95    2                  [+2]  bits:
96
97      1                  [+15]              UInt                               length_extended
98        -- ETSI TS 07.10 section 5.2.1.4
99        -- Note: this is defined as overlapping field with first length byte.
100
101  let information_length = $present(length_extended) ? length_extended : length
102    -- Length of the '5.2.1.4 Information Field'.
103    -- Special consideration when RFCOMM credit based flow control is active:
104    -- (RFCOMM spec v1.2 section 6.5.2)
105    -- The length indicator field (as always) indicates the number of
106    -- information octets in the following information field; however, the
107    -- maximum number of allowable information octets is decreased by one to
108    -- compensate for the credit field. (This is to keep the maximum L2CAP
109    -- payload size constant).
110
111  let credits_offset = $present(length_extended) ? 4 : 3
112
113  if control == RfcommFrameType.UNNUMBERED_INFORMATION_WITH_HEADER_CHECK_AND_POLL_FINAL && channel != 0:
114    credits_offset     [+1]                 UInt                               credits
115      -- Credits field can appears as first byte of information when Poll/Final
116      -- bit is set on UIH frames and channel is not control (0).
117      -- Credits field is _not_ counted as part of information_length.
118
119  let information_offset = $present(credits) ? credits_offset+1 : credits_offset
120
121  information_offset [+information_length]  UInt:8[information_length]         information
122    -- Payload is the RFCOMM payload contained in the 'Information Field' which
123    -- may start with credits.
124
125  let fcs_offset = information_offset+information_length
126
127  fcs_offset         [+1]                   UInt                               fcs
128    -- Frame checksum. See: GSM 07.10 TS 101 369 V6.3.0
129    -- SABM, DISC, UA, DM frame types:
130    --   FCS should be calculated over address, control and length fields.
131    -- UIH frame type:
132    --   FCS should be calculated over address and control fields.
133