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