• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 #pragma once
16 #include <cstddef>
17 #include <cstdint>
18 #include <type_traits>
19 
20 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/uint128.h"
22 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
23 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
24 
25 #pragma clang diagnostic ignored "-Wc99-extensions"
26 #pragma clang diagnostic ignored "-Wflexible-array-extensions"
27 
28 namespace bt::att {
29 
30 // v5.0, Vol 3, Part G, 5.1.2
31 constexpr uint16_t kLEMinMTU = 23;
32 
33 // v5.0, Vol 3, Part G, 5.1.1
34 constexpr uint16_t kBREDRMinMTU = 48;
35 
36 constexpr uint16_t kLEMaxMTU =
37     hci_spec::kMaxLEExtendedDataLength - sizeof(l2cap::BasicHeader);
38 
39 // The maximum length of an attribute value (v5.0, Vol 3, Part F, 3.2.9).
40 constexpr size_t kMaxAttributeValueLength = 512;
41 
42 // The ATT protocol transaction timeout.
43 // (see v5.0, Vol 3, Part F, Section 3.3.3).
44 constexpr pw::chrono::SystemClock::duration kTransactionTimeout =
45     std::chrono::seconds(30);
46 
47 // A server identifies each attribute using a 16-bit handle.
48 using Handle = uint16_t;
49 
50 constexpr Handle kInvalidHandle = 0x0000;
51 constexpr Handle kHandleMin = 0x0001;
52 constexpr Handle kHandleMax = 0xFFFF;
53 
54 // We represent the read and write permissions of an attribute using separate
55 // bitfields.
56 // clang-format off
57 constexpr uint8_t kAttributePermissionBitAllowed                = (1 << 0);
58 constexpr uint8_t kAttributePermissionBitEncryptionRequired     = (1 << 1);
59 constexpr uint8_t kAttributePermissionBitAuthenticationRequired = (1 << 2);
60 constexpr uint8_t kAttributePermissionBitAuthorizationRequired  = (1 << 3);
61 // clang-format on
62 
63 // The opcode identifies the protocol method being invoked.
64 using OpCode = uint8_t;
65 
66 // The flag bits of an ATT opcode. Bits 0-5 identify the protocol method.
67 constexpr OpCode kAuthenticationSignatureFlag = (1 << 7);
68 constexpr OpCode kCommandFlag = (1 << 6);
69 
70 // The length of an authentication signature used in a signed PDU.
71 constexpr size_t kAuthenticationSignatureLength = 12;
72 
73 // The maximum number of write requests that can be queued for submission in a
74 // ATT Prepare Write Request.
75 constexpr uint8_t kPrepareQueueMaxCapacity = 20;
76 
77 enum class MethodType {
78   kInvalid,
79   kRequest,
80   kResponse,
81   kCommand,
82   kNotification,
83   kIndication,
84   kConfirmation,
85 };
86 
87 struct Header {
88   OpCode opcode;
89 } __attribute__((packed));
90 
91 enum class ErrorCode : uint8_t {
92   kInvalidHandle = 0x01,
93   kReadNotPermitted = 0x02,
94   kWriteNotPermitted = 0x03,
95   kInvalidPDU = 0x04,
96   kInsufficientAuthentication = 0x05,
97   kRequestNotSupported = 0x06,
98   kInvalidOffset = 0x07,
99   kInsufficientAuthorization = 0x08,
100   kPrepareQueueFull = 0x09,
101   kAttributeNotFound = 0x0A,
102   kAttributeNotLong = 0x0B,
103   kInsufficientEncryptionKeySize = 0x0C,
104   kInvalidAttributeValueLength = 0x0D,
105   kUnlikelyError = 0x0E,
106   kInsufficientEncryption = 0x0F,
107   kUnsupportedGroupType = 0x10,
108   kInsufficientResources = 0x11,
109   kValueNotAllowed = 0x13,
110 };
111 
112 // Many ATT protocol PDUs allow using both a 16-bit and a 128-bit representation
113 // for the attribute type (which is a Bluetooth UUID).
114 //
115 // The assigned values can be used in a Find Information Response.
116 enum class UUIDType : uint8_t {
117   k16Bit = 0x01,
118   k128Bit = 0x02,
119 };
120 
121 template <UUIDType Type>
122 using AttributeType = typename std::
123     conditional<Type == UUIDType::k16Bit, uint16_t, UInt128>::type;
124 
125 using AttributeType16 = AttributeType<UUIDType::k16Bit>;
126 using AttributeType128 = AttributeType<UUIDType::k128Bit>;
127 
128 enum class ExecuteWriteFlag : uint8_t {
129   kCancelAll = 0x00,
130   kWritePending = 0x01,
131 };
132 
133 struct AttributeData {
134   AttributeData() = default;
135   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(AttributeData);
136 
137   Handle handle;
138   uint8_t value[];
139 } __attribute__((packed));
140 
141 // ============== ATT PDUs ==============
142 constexpr OpCode kInvalidOpCode = 0x00;
143 
144 // ==============
145 // Error Handling
146 constexpr OpCode kErrorResponse = 0x01;
147 struct ErrorResponseParams {
148   OpCode request_opcode;
149   Handle attribute_handle;
150   ErrorCode error_code;
151 } __attribute__((packed));
152 
153 // ============
154 // MTU Exchange
155 constexpr OpCode kExchangeMTURequest = 0x02;
156 constexpr OpCode kExchangeMTUResponse = 0x03;
157 
158 struct ExchangeMTURequestParams {
159   uint16_t client_rx_mtu;
160 } __attribute__((packed));
161 
162 struct ExchangeMTUResponseParams {
163   uint16_t server_rx_mtu;
164 } __attribute__((packed));
165 
166 // ================
167 // Find Information
168 constexpr OpCode kFindInformationRequest = 0x04;
169 constexpr OpCode kFindInformationResponse = 0x05;
170 
171 struct FindInformationRequestParams {
172   Handle start_handle;
173   Handle end_handle;
174 } __attribute__((packed));
175 
176 struct FindInformationResponseParams {
177   UUIDType format;
178 
179   // The type of the next member depends on the type of |format|.
180   // If type == InformationDataFormat::kUUID16:
181   // InformationData16 information_data[];
182   //
183   // If type == InformationDataFormat::kUUID28:
184   // InformationData128 information_data[];
185 } __attribute__((packed));
186 
187 template <UUIDType Format>
188 struct InformationData {
189   Handle handle;
190   AttributeType<Format> uuid;
191 } __attribute__((packed));
192 
193 using InformationData16 = InformationData<UUIDType::k16Bit>;
194 using InformationData128 = InformationData<UUIDType::k128Bit>;
195 
196 // ==================
197 // Find By Type Value
198 constexpr OpCode kFindByTypeValueRequest = 0x06;
199 constexpr OpCode kFindByTypeValueResponse = 0x07;
200 
201 struct FindByTypeValueRequestParams {
202   FindByTypeValueRequestParams() = default;
203   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(FindByTypeValueRequestParams);
204 
205   Handle start_handle;
206   Handle end_handle;
207   AttributeType16 type;
208   uint8_t value[];
209 } __attribute__((packed));
210 
211 struct HandlesInformationList {
212   Handle handle;
213   Handle group_end_handle;
214 } __attribute__((packed));
215 
216 struct FindByTypeValueResponseParams {
217   // Contains at least 1 entry
218   HandlesInformationList handles_information_list[1];
219 } __attribute__((packed));
220 
221 // ============
222 // Read By Type
223 constexpr OpCode kReadByTypeRequest = 0x08;
224 constexpr OpCode kReadByTypeResponse = 0x09;
225 
226 // (see Vol 3, Part F, 3.4.4.2)
227 constexpr uint8_t kMaxReadByTypeValueLength = 253;
228 
229 template <UUIDType Format>
230 struct ReadByTypeRequestParams {
231   Handle start_handle;
232   Handle end_handle;
233   AttributeType<Format> type;
234 } __attribute__((packed));
235 
236 using ReadByTypeRequestParams16 = ReadByTypeRequestParams<UUIDType::k16Bit>;
237 using ReadByTypeRequestParams128 = ReadByTypeRequestParams<UUIDType::k128Bit>;
238 
239 struct ReadByTypeResponseParams {
240   ReadByTypeResponseParams() = default;
241   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(ReadByTypeResponseParams);
242 
243   uint8_t length;
244   AttributeData attribute_data_list[];
245 } __attribute__((packed));
246 
247 // ====
248 // Read
249 constexpr OpCode kReadRequest = 0x0A;
250 constexpr OpCode kReadResponse = 0x0B;
251 
252 struct ReadRequestParams {
253   Handle handle;
254 } __attribute__((packed));
255 
256 // The Read Response PDU contains the attribute value requested.
257 
258 // =========
259 // Read Blob
260 constexpr OpCode kReadBlobRequest = 0x0C;
261 constexpr OpCode kReadBlobResponse = 0x0D;
262 
263 struct ReadBlobRequestParams {
264   Handle handle;
265   uint16_t offset;
266 } __attribute__((packed));
267 
268 // The Read Blob Response PDU contains the partial attribute value requested.
269 
270 // =============
271 // Read Multiple
272 constexpr OpCode kReadMultipleRequest = 0x0E;
273 constexpr OpCode kReadMultipleResponse = 0x0F;
274 
275 // The Read Multiple Request PDU contains 2 or more attribute handles.
276 // The Read Multiple Response PDU contains attribute values concatenated in the
277 // order requested.
278 
279 // ==================
280 // Read By Group Type
281 constexpr OpCode kReadByGroupTypeRequest = 0x10;
282 constexpr OpCode kReadByGroupTypeResponse = 0x11;
283 
284 // (see Vol 3, Part F, 3.4.4.10)
285 constexpr uint8_t kMaxReadByGroupTypeValueLength = 251;
286 
287 // The Read By Group Type and Read By Type requests use identical payloads.
288 using ReadByGroupTypeRequestParams16 = ReadByTypeRequestParams16;
289 using ReadByGroupTypeRequestParams128 = ReadByTypeRequestParams128;
290 
291 struct AttributeGroupDataEntry {
292   AttributeGroupDataEntry() = default;
293   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(AttributeGroupDataEntry);
294 
295   Handle start_handle;
296   Handle group_end_handle;
297   uint8_t value[];
298 } __attribute__((packed));
299 
300 struct ReadByGroupTypeResponseParams {
301   ReadByGroupTypeResponseParams() = default;
302   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(ReadByGroupTypeResponseParams);
303 
304   uint8_t length;
305   AttributeGroupDataEntry attribute_data_list[];
306 } __attribute__((packed));
307 
308 // =====
309 // Write
310 constexpr OpCode kWriteRequest = 0x12;
311 constexpr OpCode kWriteCommand = 0x52;
312 constexpr OpCode kSignedWriteCommand = 0xD2;
313 constexpr OpCode kWriteResponse = 0x13;
314 
315 using WriteRequestParams = AttributeData;
316 
317 // =============
318 // Prepare Write
319 constexpr OpCode kPrepareWriteRequest = 0x16;
320 constexpr OpCode kPrepareWriteResponse = 0x17;
321 
322 struct PrepareWriteRequestParams {
323   PrepareWriteRequestParams() = default;
324   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(PrepareWriteRequestParams);
325 
326   Handle handle;
327   uint16_t offset;
328   uint8_t part_value[];
329 } __attribute__((packed));
330 
331 using PrepareWriteResponseParams = PrepareWriteRequestParams;
332 
333 // =============
334 // Execute Write
335 constexpr OpCode kExecuteWriteRequest = 0x18;
336 constexpr OpCode kExecuteWriteResponse = 0x19;
337 
338 struct ExecuteWriteRequestParams {
339   ExecuteWriteFlag flags;
340 } __attribute__((packed));
341 
342 // =========================
343 // Handle Value Notification
344 constexpr OpCode kNotification = 0x1B;
345 using NotificationParams = AttributeData;
346 
347 // =========================
348 // Handle Value Indication
349 constexpr OpCode kIndication = 0x1D;
350 constexpr OpCode kConfirmation = 0x1E;
351 using IndicationParams = NotificationParams;
352 
353 }  // namespace bt::att
354