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 #include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
18 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
20 #include "pw_bluetooth_sapphire/internal/host/hci/bredr_connection_request.h"
21 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
22
23 namespace bt::testing {
24
25 namespace hci_android = bt::hci_spec::vendor::android;
26
27 // clang-format off
28 #define COMMAND_STATUS_RSP(opcode, statuscode) \
29 StaticByteBuffer( hci_spec::kCommandStatusEventCode, 0x04, \
30 (statuscode), 0xF0, \
31 LowerBits((opcode)), UpperBits((opcode)))
32
33 #define UINT32_TO_LE(bits) \
34 static_cast<uint32_t>(bits), \
35 static_cast<uint32_t>(bits) >> CHAR_BIT, \
36 static_cast<uint32_t>(bits) >> 2 * CHAR_BIT, \
37 static_cast<uint32_t>(bits) >> 3 * CHAR_BIT
38 // clang-format on
39
EmptyCommandPacket(hci_spec::OpCode opcode)40 DynamicByteBuffer EmptyCommandPacket(hci_spec::OpCode opcode) {
41 return DynamicByteBuffer(
42 StaticByteBuffer(LowerBits(opcode), UpperBits(opcode), /*length=*/0));
43 }
44
CommandCompletePacket(hci_spec::OpCode opcode,pw::bluetooth::emboss::StatusCode status)45 DynamicByteBuffer CommandCompletePacket(
46 hci_spec::OpCode opcode, pw::bluetooth::emboss::StatusCode status) {
47 return DynamicByteBuffer(StaticByteBuffer(hci_spec::kCommandCompleteEventCode,
48 0x04, // size
49 0x01, // Num HCI command packets
50 LowerBits(opcode),
51 UpperBits(opcode), // Op code
52 status));
53 }
54
AcceptConnectionRequestPacket(DeviceAddress address)55 DynamicByteBuffer AcceptConnectionRequestPacket(DeviceAddress address) {
56 const auto addr = address.value().bytes();
57 return DynamicByteBuffer(StaticByteBuffer(
58 LowerBits(hci_spec::kAcceptConnectionRequest),
59 UpperBits(hci_spec::kAcceptConnectionRequest),
60 0x07, // parameter_total_size (7 bytes)
61 addr[0],
62 addr[1],
63 addr[2],
64 addr[3],
65 addr[4],
66 addr[5], // peer address
67 0x00 // role (become central)
68 ));
69 }
70
RejectConnectionRequestPacket(DeviceAddress address,pw::bluetooth::emboss::StatusCode reason)71 DynamicByteBuffer RejectConnectionRequestPacket(
72 DeviceAddress address, pw::bluetooth::emboss::StatusCode reason) {
73 const auto addr = address.value().bytes();
74 return DynamicByteBuffer(StaticByteBuffer(
75 LowerBits(hci_spec::kRejectConnectionRequest),
76 UpperBits(hci_spec::kRejectConnectionRequest),
77 0x07, // parameter_total_size (7 bytes)
78 addr[0],
79 addr[1],
80 addr[2],
81 addr[3],
82 addr[4],
83 addr[5], // peer address
84 reason // reason
85 ));
86 }
87
AuthenticationRequestedPacket(hci_spec::ConnectionHandle conn)88 DynamicByteBuffer AuthenticationRequestedPacket(
89 hci_spec::ConnectionHandle conn) {
90 return DynamicByteBuffer(StaticByteBuffer(
91 LowerBits(hci_spec::kAuthenticationRequested),
92 UpperBits(hci_spec::kAuthenticationRequested),
93 0x02, // parameter_total_size (2 bytes)
94 LowerBits(conn),
95 UpperBits(conn) // Connection_Handle
96 ));
97 }
98
ConnectionRequestPacket(DeviceAddress address,hci_spec::LinkType link_type)99 DynamicByteBuffer ConnectionRequestPacket(DeviceAddress address,
100 hci_spec::LinkType link_type) {
101 const auto addr = address.value().bytes();
102 return DynamicByteBuffer(StaticByteBuffer(
103 hci_spec::kConnectionRequestEventCode,
104 0x0A, // parameter_total_size (10 byte payload)
105 addr[0],
106 addr[1],
107 addr[2],
108 addr[3],
109 addr[4],
110 addr[5], // peer address
111 0x00,
112 0x1F,
113 0x00, // class_of_device (unspecified)
114 link_type // link_type
115 ));
116 }
117
CreateConnectionPacket(DeviceAddress address)118 DynamicByteBuffer CreateConnectionPacket(DeviceAddress address) {
119 auto addr = address.value().bytes();
120 return DynamicByteBuffer(StaticByteBuffer(
121 LowerBits(hci_spec::kCreateConnection),
122 UpperBits(hci_spec::kCreateConnection),
123 0x0d, // parameter_total_size (13 bytes)
124 addr[0],
125 addr[1],
126 addr[2],
127 addr[3],
128 addr[4],
129 addr[5], // peer address
130 LowerBits(hci::kEnableAllPacketTypes), // allowable packet types
131 UpperBits(hci::kEnableAllPacketTypes), // allowable packet types
132 0x02, // page_scan_repetition_mode (R2)
133 0x00, // reserved
134 0x00,
135 0x00, // clock_offset
136 0x00 // allow_role_switch (don't)
137 ));
138 }
139
ConnectionCompletePacket(DeviceAddress address,hci_spec::ConnectionHandle conn,pw::bluetooth::emboss::StatusCode status)140 DynamicByteBuffer ConnectionCompletePacket(
141 DeviceAddress address,
142 hci_spec::ConnectionHandle conn,
143 pw::bluetooth::emboss::StatusCode status) {
144 auto addr = address.value().bytes();
145 return DynamicByteBuffer(StaticByteBuffer(
146 hci_spec::kConnectionCompleteEventCode,
147 0x0B, // parameter_total_size (11 byte payload)
148 status, // status
149 LowerBits(conn),
150 UpperBits(conn), // Little-Endian Connection_handle
151 addr[0],
152 addr[1],
153 addr[2],
154 addr[3],
155 addr[4],
156 addr[5], // peer address
157 0x01, // link_type (ACL)
158 0x00 // encryption not enabled
159 ));
160 }
161
DisconnectPacket(hci_spec::ConnectionHandle conn,pw::bluetooth::emboss::StatusCode reason)162 DynamicByteBuffer DisconnectPacket(hci_spec::ConnectionHandle conn,
163 pw::bluetooth::emboss::StatusCode reason) {
164 return DynamicByteBuffer(StaticByteBuffer(
165 LowerBits(hci_spec::kDisconnect),
166 UpperBits(hci_spec::kDisconnect),
167 0x03, // parameter_total_size (3 bytes)
168 LowerBits(conn),
169 UpperBits(conn), // Little-Endian Connection_handle
170 reason // Reason
171 ));
172 }
173
DisconnectStatusResponsePacket()174 DynamicByteBuffer DisconnectStatusResponsePacket() {
175 return DynamicByteBuffer(COMMAND_STATUS_RSP(
176 hci_spec::kDisconnect, pw::bluetooth::emboss::StatusCode::SUCCESS));
177 }
178
DisconnectionCompletePacket(hci_spec::ConnectionHandle conn,pw::bluetooth::emboss::StatusCode reason)179 DynamicByteBuffer DisconnectionCompletePacket(
180 hci_spec::ConnectionHandle conn, pw::bluetooth::emboss::StatusCode reason) {
181 return DynamicByteBuffer(StaticByteBuffer(
182 hci_spec::kDisconnectionCompleteEventCode,
183 0x04, // parameter_total_size (4 bytes)
184 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
185 LowerBits(conn),
186 UpperBits(conn), // Little-Endian Connection_handle
187 reason // Reason
188 ));
189 }
190
EncryptionChangeEventPacket(pw::bluetooth::emboss::StatusCode status_code,hci_spec::ConnectionHandle conn,hci_spec::EncryptionStatus encryption_enabled)191 DynamicByteBuffer EncryptionChangeEventPacket(
192 pw::bluetooth::emboss::StatusCode status_code,
193 hci_spec::ConnectionHandle conn,
194 hci_spec::EncryptionStatus encryption_enabled) {
195 return DynamicByteBuffer(StaticByteBuffer(
196 hci_spec::kEncryptionChangeEventCode,
197 0x04, // parameter_total_size (4 bytes)
198 status_code, // status
199 LowerBits(conn),
200 UpperBits(conn), // Little-Endian Connection_Handle
201 static_cast<uint8_t>(encryption_enabled) // Encryption_Enabled
202 ));
203 }
204
EnhancedAcceptSynchronousConnectionRequestPacket(DeviceAddress peer_address,bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter> params)205 DynamicByteBuffer EnhancedAcceptSynchronousConnectionRequestPacket(
206 DeviceAddress peer_address,
207 bt::StaticPacket<
208 pw::bluetooth::emboss::SynchronousConnectionParametersWriter> params) {
209 auto packet = hci::EmbossCommandPacket::New<
210 pw::bluetooth::emboss::
211 EnhancedAcceptSynchronousConnectionRequestCommandWriter>(
212 hci_spec::kEnhancedAcceptSynchronousConnectionRequest);
213 auto view = packet.view_t();
214
215 view.bd_addr().CopyFrom(peer_address.value().view());
216 view.connection_parameters().CopyFrom(params.view());
217
218 return DynamicByteBuffer(packet.data());
219 }
220
EnhancedSetupSynchronousConnectionPacket(hci_spec::ConnectionHandle conn,bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter> params)221 DynamicByteBuffer EnhancedSetupSynchronousConnectionPacket(
222 hci_spec::ConnectionHandle conn,
223 bt::StaticPacket<
224 pw::bluetooth::emboss::SynchronousConnectionParametersWriter> params) {
225 auto packet = hci::EmbossCommandPacket::New<
226 pw::bluetooth::emboss::EnhancedSetupSynchronousConnectionCommandWriter>(
227 hci_spec::kEnhancedSetupSynchronousConnection);
228
229 auto view = packet.view_t();
230 view.connection_handle().Write(conn);
231 view.connection_parameters().CopyFrom(params.view());
232
233 return DynamicByteBuffer(packet.data());
234 }
235
NumberOfCompletedPacketsPacket(hci_spec::ConnectionHandle conn,uint16_t num_packets)236 DynamicByteBuffer NumberOfCompletedPacketsPacket(
237 hci_spec::ConnectionHandle conn, uint16_t num_packets) {
238 return DynamicByteBuffer(StaticByteBuffer(
239 0x13,
240 0x05, // Number Of Completed Packet HCI event header, parameters length
241 0x01, // Number of handles
242 LowerBits(conn),
243 UpperBits(conn),
244 LowerBits(num_packets),
245 UpperBits(num_packets)));
246 }
247
CommandStatusPacket(hci_spec::OpCode op_code,pw::bluetooth::emboss::StatusCode status_code)248 DynamicByteBuffer CommandStatusPacket(
249 hci_spec::OpCode op_code, pw::bluetooth::emboss::StatusCode status_code) {
250 return DynamicByteBuffer(
251 StaticByteBuffer(hci_spec::kCommandStatusEventCode,
252 0x04, // parameter size (4 bytes)
253 status_code,
254 0xF0, // number of HCI command packets allowed to be
255 // sent to controller (240)
256 LowerBits(op_code),
257 UpperBits(op_code)));
258 }
259
RemoteNameRequestPacket(DeviceAddress address)260 DynamicByteBuffer RemoteNameRequestPacket(DeviceAddress address) {
261 auto addr = address.value().bytes();
262 return DynamicByteBuffer(StaticByteBuffer(
263 LowerBits(hci_spec::kRemoteNameRequest),
264 UpperBits(hci_spec::kRemoteNameRequest),
265 0x0a, // parameter_total_size (10 bytes)
266 addr[0],
267 addr[1],
268 addr[2],
269 addr[3],
270 addr[4],
271 addr[5], // peer address
272 0x00, // page_scan_repetition_mode (R0)
273 0x00, // reserved
274 0x00,
275 0x00 // clock_offset
276 ));
277 }
278
RemoteNameRequestCompletePacket(DeviceAddress address,const std::string & name)279 DynamicByteBuffer RemoteNameRequestCompletePacket(DeviceAddress address,
280 const std::string& name) {
281 auto addr = address.value().bytes();
282 auto event = DynamicByteBuffer(
283 pw::bluetooth::emboss::RemoteNameRequestCompleteEventView::
284 IntrinsicSizeInBytes()
285 .Read());
286 event.SetToZeros();
287 const StaticByteBuffer header(
288 hci_spec::kRemoteNameRequestCompleteEventCode,
289 0xff, // parameter_total_size (255)
290 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
291 addr[0],
292 addr[1],
293 addr[2],
294 addr[3],
295 addr[4],
296 addr[5] // peer address
297 );
298 header.Copy(&event);
299 event.Write(reinterpret_cast<const uint8_t*>(name.data()),
300 name.size(),
301 header.size());
302 return event;
303 }
304
ReadRemoteVersionInfoPacket(hci_spec::ConnectionHandle conn)305 DynamicByteBuffer ReadRemoteVersionInfoPacket(hci_spec::ConnectionHandle conn) {
306 return DynamicByteBuffer(StaticByteBuffer(
307 LowerBits(hci_spec::kReadRemoteVersionInfo),
308 UpperBits(hci_spec::kReadRemoteVersionInfo),
309 0x02, // Parameter_total_size (2 bytes)
310 LowerBits(conn),
311 UpperBits(conn) // Little-Endian Connection_handle
312 ));
313 }
314
ReadRemoteVersionInfoCompletePacket(hci_spec::ConnectionHandle conn)315 DynamicByteBuffer ReadRemoteVersionInfoCompletePacket(
316 hci_spec::ConnectionHandle conn) {
317 return DynamicByteBuffer(StaticByteBuffer(
318 hci_spec::kReadRemoteVersionInfoCompleteEventCode,
319 0x08, // parameter_total_size (8 bytes)
320 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
321 LowerBits(conn),
322 UpperBits(conn), // Little-Endian Connection_handle
323 pw::bluetooth::emboss::CoreSpecificationVersion::V4_2, // version
324 0xE0,
325 0x00, // company_identifier (Google)
326 0xAD,
327 0xDE // subversion (anything)
328 ));
329 }
330
ReadRemoteSupportedFeaturesPacket(hci_spec::ConnectionHandle conn)331 DynamicByteBuffer ReadRemoteSupportedFeaturesPacket(
332 hci_spec::ConnectionHandle conn) {
333 return DynamicByteBuffer(
334 StaticByteBuffer(LowerBits(hci_spec::kReadRemoteSupportedFeatures),
335 UpperBits(hci_spec::kReadRemoteSupportedFeatures),
336 0x02, // parameter_total_size (2 bytes)
337 LowerBits(conn), // Little-Endian Connection_handle
338 UpperBits(conn)));
339 }
340
ReadRemoteSupportedFeaturesCompletePacket(hci_spec::ConnectionHandle conn,bool extended_features)341 DynamicByteBuffer ReadRemoteSupportedFeaturesCompletePacket(
342 hci_spec::ConnectionHandle conn, bool extended_features) {
343 return DynamicByteBuffer(StaticByteBuffer(
344 hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode,
345 0x0B, // parameter_total_size (11 bytes)
346 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
347 LowerBits(conn),
348 UpperBits(conn), // Little-Endian Connection_handle
349 0xFF,
350 0x00,
351 0x00,
352 0x00,
353 0x02,
354 0x00,
355 0x00,
356 (extended_features ? 0x80 : 0x00)
357 // lmp_features
358 // Set: 3 slot packets, 5 slot packets, Encryption,
359 // Timing Accuracy, Role Switch, Hold Mode, Sniff Mode,
360 // LE Supported Extended Features if enabled
361 ));
362 }
363
RejectSynchronousConnectionRequest(DeviceAddress address,pw::bluetooth::emboss::StatusCode status_code)364 DynamicByteBuffer RejectSynchronousConnectionRequest(
365 DeviceAddress address, pw::bluetooth::emboss::StatusCode status_code) {
366 auto addr_bytes = address.value().bytes();
367 return DynamicByteBuffer(StaticByteBuffer(
368 LowerBits(hci_spec::kRejectSynchronousConnectionRequest),
369 UpperBits(hci_spec::kRejectSynchronousConnectionRequest),
370 0x07, // parameter total size
371 addr_bytes[0],
372 addr_bytes[1],
373 addr_bytes[2],
374 addr_bytes[3],
375 addr_bytes[4],
376 addr_bytes[5], // peer address
377 status_code // reason
378 ));
379 }
380
RoleChangePacket(DeviceAddress address,pw::bluetooth::emboss::ConnectionRole role,pw::bluetooth::emboss::StatusCode status)381 DynamicByteBuffer RoleChangePacket(DeviceAddress address,
382 pw::bluetooth::emboss::ConnectionRole role,
383 pw::bluetooth::emboss::StatusCode status) {
384 auto addr_bytes = address.value().bytes();
385 return DynamicByteBuffer(StaticByteBuffer(hci_spec::kRoleChangeEventCode,
386 0x08, // parameter_total_size
387 status, // status
388 addr_bytes[0],
389 addr_bytes[1],
390 addr_bytes[2],
391 addr_bytes[3],
392 addr_bytes[4],
393 addr_bytes[5], // peer address
394 role));
395 }
396
SetConnectionEncryption(hci_spec::ConnectionHandle conn,bool enable)397 DynamicByteBuffer SetConnectionEncryption(hci_spec::ConnectionHandle conn,
398 bool enable) {
399 return DynamicByteBuffer(
400 StaticByteBuffer(LowerBits(hci_spec::kSetConnectionEncryption),
401 UpperBits(hci_spec::kSetConnectionEncryption),
402 0x03, // parameter total size (3 bytes)
403 LowerBits(conn),
404 UpperBits(conn),
405 static_cast<uint8_t>(enable)));
406 }
407
SynchronousConnectionCompletePacket(hci_spec::ConnectionHandle conn,DeviceAddress address,hci_spec::LinkType link_type,pw::bluetooth::emboss::StatusCode status)408 DynamicByteBuffer SynchronousConnectionCompletePacket(
409 hci_spec::ConnectionHandle conn,
410 DeviceAddress address,
411 hci_spec::LinkType link_type,
412 pw::bluetooth::emboss::StatusCode status) {
413 auto addr_bytes = address.value().bytes();
414 return DynamicByteBuffer(StaticByteBuffer(
415 hci_spec::kSynchronousConnectionCompleteEventCode,
416 0x11, // parameter_total_size (17 bytes)
417 status,
418 LowerBits(conn),
419 UpperBits(conn),
420 addr_bytes[0],
421 addr_bytes[1],
422 addr_bytes[2],
423 addr_bytes[3],
424 addr_bytes[4],
425 addr_bytes[5],
426 link_type, // peer address
427 0x00, // transmission interval
428 0x00, // retransmission window
429 0x00,
430 0x00, // rx packet length
431 0x00,
432 0x00, // tx packet length
433 0x00 // coding format
434 ));
435 }
436
LEReadRemoteFeaturesPacket(hci_spec::ConnectionHandle conn)437 DynamicByteBuffer LEReadRemoteFeaturesPacket(hci_spec::ConnectionHandle conn) {
438 return DynamicByteBuffer(
439 StaticByteBuffer(LowerBits(hci_spec::kLEReadRemoteFeatures),
440 UpperBits(hci_spec::kLEReadRemoteFeatures),
441 0x02, // parameter_total_size (2 bytes)
442 LowerBits(conn), // Little-Endian Connection_handle
443 UpperBits(conn)));
444 }
445
LEReadRemoteFeaturesCompletePacket(hci_spec::ConnectionHandle conn,hci_spec::LESupportedFeatures le_features)446 DynamicByteBuffer LEReadRemoteFeaturesCompletePacket(
447 hci_spec::ConnectionHandle conn,
448 hci_spec::LESupportedFeatures le_features) {
449 const BufferView features(&le_features, sizeof(le_features));
450 return DynamicByteBuffer(
451 StaticByteBuffer(hci_spec::kLEMetaEventCode,
452 0x0c, // parameter total size (12 bytes)
453 hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode,
454 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
455 // Little-Endian connection handle
456 LowerBits(conn),
457 UpperBits(conn),
458 // bit mask of LE features
459 features[0],
460 features[1],
461 features[2],
462 features[3],
463 features[4],
464 features[5],
465 features[6],
466 features[7]));
467 }
468
LEStartEncryptionPacket(hci_spec::ConnectionHandle conn,uint64_t random_number,uint16_t encrypted_diversifier,UInt128 ltk)469 DynamicByteBuffer LEStartEncryptionPacket(hci_spec::ConnectionHandle conn,
470 uint64_t random_number,
471 uint16_t encrypted_diversifier,
472 UInt128 ltk) {
473 const BufferView rand(&random_number, sizeof(random_number));
474 return DynamicByteBuffer(
475 StaticByteBuffer(LowerBits(hci_spec::kLEStartEncryption),
476 UpperBits(hci_spec::kLEStartEncryption),
477 0x1c, // parameter total size (28 bytes)
478 LowerBits(conn),
479 UpperBits(conn), // Connection_handle
480 rand[0],
481 rand[1],
482 rand[2],
483 rand[3],
484 rand[4],
485 rand[5],
486 rand[6],
487 rand[7],
488 LowerBits(encrypted_diversifier),
489 UpperBits(encrypted_diversifier),
490 // LTK
491 ltk[0],
492 ltk[1],
493 ltk[2],
494 ltk[3],
495 ltk[4],
496 ltk[5],
497 ltk[6],
498 ltk[7],
499 ltk[8],
500 ltk[9],
501 ltk[10],
502 ltk[11],
503 ltk[12],
504 ltk[13],
505 ltk[14],
506 ltk[15]));
507 }
508
ReadRemoteExtended1Packet(hci_spec::ConnectionHandle conn)509 DynamicByteBuffer ReadRemoteExtended1Packet(hci_spec::ConnectionHandle conn) {
510 return DynamicByteBuffer(StaticByteBuffer(
511 LowerBits(hci_spec::kReadRemoteExtendedFeatures),
512 UpperBits(hci_spec::kReadRemoteExtendedFeatures),
513 0x03, // parameter_total_size (3 bytes)
514 LowerBits(conn), // Little-Endian Connection_handle
515 UpperBits(conn),
516 0x01 // page_number (1)
517 ));
518 }
519
ReadRemoteExtended1CompletePacket(hci_spec::ConnectionHandle conn)520 DynamicByteBuffer ReadRemoteExtended1CompletePacket(
521 hci_spec::ConnectionHandle conn) {
522 return DynamicByteBuffer(StaticByteBuffer(
523 hci_spec::kReadRemoteExtendedFeaturesCompleteEventCode,
524 0x0D, // parameter_total_size (13 bytes)
525 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
526 LowerBits(conn),
527 UpperBits(conn), // Little-Endian Connection_handle
528 0x01, // page_number
529 0x03, // max_page_number (3 pages)
530 0x0F,
531 0x00,
532 0x00,
533 0x00,
534 0x02,
535 0x00,
536 0x00,
537 0x00
538 // lmp_features (page 1)
539 // Set: Secure Simple Pairing (Host Support), LE Supported (Host),
540 // SimultaneousLEAndBREDR, Secure Connections (Host Support)
541 ));
542 }
543
ReadRemoteExtended2Packet(hci_spec::ConnectionHandle conn)544 DynamicByteBuffer ReadRemoteExtended2Packet(hci_spec::ConnectionHandle conn) {
545 return DynamicByteBuffer(StaticByteBuffer(
546 LowerBits(hci_spec::kReadRemoteExtendedFeatures),
547 UpperBits(hci_spec::kReadRemoteExtendedFeatures),
548 0x03, // parameter_total_size (3 bytes)
549 LowerBits(conn),
550 UpperBits(conn), // Little-Endian Connection_handle
551 0x02 // page_number (2)
552 ));
553 }
554
ReadRemoteExtended2CompletePacket(hci_spec::ConnectionHandle conn)555 DynamicByteBuffer ReadRemoteExtended2CompletePacket(
556 hci_spec::ConnectionHandle conn) {
557 return DynamicByteBuffer(StaticByteBuffer(
558 hci_spec::kReadRemoteExtendedFeaturesCompleteEventCode,
559 0x0D, // parameter_total_size (13 bytes)
560 pw::bluetooth::emboss::StatusCode::SUCCESS, // status
561 LowerBits(conn),
562 UpperBits(conn), // Little-Endian Connection_handle
563 0x02, // page_number
564 0x03, // max_page_number (3 pages)
565 0x00,
566 0x00,
567 0x00,
568 0x00,
569 0x02,
570 0x00,
571 0xFF,
572 0x00
573 // lmp_features - All the bits should be ignored.
574 ));
575 }
576
WriteAutomaticFlushTimeoutPacket(hci_spec::ConnectionHandle conn,uint16_t flush_timeout)577 DynamicByteBuffer WriteAutomaticFlushTimeoutPacket(
578 hci_spec::ConnectionHandle conn, uint16_t flush_timeout) {
579 return DynamicByteBuffer(StaticByteBuffer(
580 LowerBits(hci_spec::kWriteAutomaticFlushTimeout),
581 UpperBits(hci_spec::kWriteAutomaticFlushTimeout),
582 0x04, // parameter_total_size (4 bytes)
583 LowerBits(conn),
584 UpperBits(conn), // Little-Endian Connection_Handle
585 LowerBits(flush_timeout),
586 UpperBits(flush_timeout) // Little-Endian Flush_Timeout
587 ));
588 }
589
WritePageTimeoutPacket(uint16_t page_timeout)590 DynamicByteBuffer WritePageTimeoutPacket(uint16_t page_timeout) {
591 return DynamicByteBuffer(StaticByteBuffer(
592 LowerBits(hci_spec::kWritePageTimeout),
593 UpperBits(hci_spec::kWritePageTimeout),
594 0x02, // parameter_total_size (2 bytes)
595 LowerBits(page_timeout),
596 UpperBits(page_timeout) // Little-Endian Page_Timeout
597 ));
598 }
599
ScoDataPacket(hci_spec::ConnectionHandle conn,hci_spec::SynchronousDataPacketStatusFlag flag,const BufferView & payload,std::optional<uint8_t> payload_length_override)600 DynamicByteBuffer ScoDataPacket(
601 hci_spec::ConnectionHandle conn,
602 hci_spec::SynchronousDataPacketStatusFlag flag,
603 const BufferView& payload,
604 std::optional<uint8_t> payload_length_override) {
605 // Flag is bits 4-5 in the higher octet of |handle_and_flags|, i.e.
606 // 0b00xx000000000000.
607 conn |= static_cast<uint8_t>(flag) << 12;
608 StaticByteBuffer header(
609 LowerBits(conn),
610 UpperBits(conn),
611 payload_length_override ? *payload_length_override : payload.size());
612 DynamicByteBuffer out(header.size() + payload.size());
613 header.Copy(&out);
614 MutableBufferView payload_view = out.mutable_view(header.size());
615 payload.Copy(&payload_view);
616 return out;
617 }
618
StartA2dpOffloadRequest(const l2cap::A2dpOffloadManager::Configuration & config,hci_spec::ConnectionHandle connection_handle,l2cap::ChannelId l2cap_channel_id,uint16_t l2cap_mtu_size)619 DynamicByteBuffer StartA2dpOffloadRequest(
620 const l2cap::A2dpOffloadManager::Configuration& config,
621 hci_spec::ConnectionHandle connection_handle,
622 l2cap::ChannelId l2cap_channel_id,
623 uint16_t l2cap_mtu_size) {
624 uint8_t
625 codec_information_bytes[sizeof(hci_android::A2dpOffloadCodecInformation)];
626 memset(codec_information_bytes, 0, sizeof(codec_information_bytes));
627
628 switch (config.codec) {
629 case hci_android::A2dpCodecType::kSbc:
630 codec_information_bytes[0] =
631 config.codec_information.sbc.blocklen_subbands_alloc_method;
632 codec_information_bytes[1] =
633 config.codec_information.sbc.min_bitpool_value;
634 codec_information_bytes[2] =
635 config.codec_information.sbc.max_bitpool_value;
636 codec_information_bytes[3] =
637 config.codec_information.sbc.sampling_freq_channel_mode;
638 break;
639 case hci_android::A2dpCodecType::kAac:
640 codec_information_bytes[0] = config.codec_information.aac.object_type;
641 codec_information_bytes[1] =
642 static_cast<uint8_t>(config.codec_information.aac.variable_bit_rate);
643 break;
644 case hci_android::A2dpCodecType::kLdac:
645 codec_information_bytes[0] =
646 static_cast<uint32_t>(config.codec_information.ldac.vendor_id),
647 codec_information_bytes[1] =
648 static_cast<uint32_t>(config.codec_information.ldac.vendor_id) >>
649 CHAR_BIT,
650 codec_information_bytes[2] =
651 static_cast<uint32_t>(config.codec_information.ldac.vendor_id) >>
652 2 * CHAR_BIT,
653 codec_information_bytes[3] =
654 static_cast<uint32_t>(config.codec_information.ldac.vendor_id) >>
655 3 * CHAR_BIT,
656 codec_information_bytes[4] =
657 LowerBits(config.codec_information.ldac.codec_id);
658 codec_information_bytes[5] =
659 UpperBits(config.codec_information.ldac.codec_id);
660 codec_information_bytes[6] =
661 static_cast<uint8_t>(config.codec_information.ldac.bitrate_index);
662 codec_information_bytes[7] =
663 static_cast<uint8_t>(config.codec_information.ldac.ldac_channel_mode);
664 break;
665 default:
666 break;
667 }
668
669 return DynamicByteBuffer(StaticByteBuffer(
670 // clang-format off
671 LowerBits(hci_android::kA2dpOffloadCommand), UpperBits(hci_android::kA2dpOffloadCommand),
672 0x39, // parameter_total_size (57 bytes)
673 hci_android::kStartA2dpOffloadCommandSubopcode,
674 UINT32_TO_LE(config.codec),
675 LowerBits(config.max_latency), UpperBits(config.max_latency),
676 config.scms_t_enable.enabled, config.scms_t_enable.header,
677 UINT32_TO_LE(config.sampling_frequency),
678 config.bits_per_sample,
679 config.channel_mode,
680 UINT32_TO_LE(config.encoded_audio_bit_rate),
681 LowerBits(connection_handle), UpperBits(connection_handle),
682 LowerBits(l2cap_channel_id), UpperBits(l2cap_channel_id),
683 LowerBits(l2cap_mtu_size), UpperBits(l2cap_mtu_size),
684 codec_information_bytes[0], codec_information_bytes[1], codec_information_bytes[2],
685 codec_information_bytes[3], codec_information_bytes[4], codec_information_bytes[5],
686 codec_information_bytes[6], codec_information_bytes[7], codec_information_bytes[8],
687 codec_information_bytes[9], codec_information_bytes[10], codec_information_bytes[11],
688 codec_information_bytes[12], codec_information_bytes[13], codec_information_bytes[14],
689 codec_information_bytes[15], codec_information_bytes[16], codec_information_bytes[17],
690 codec_information_bytes[18], codec_information_bytes[19], codec_information_bytes[20],
691 codec_information_bytes[21], codec_information_bytes[22], codec_information_bytes[23],
692 codec_information_bytes[24], codec_information_bytes[25], codec_information_bytes[26],
693 codec_information_bytes[27], codec_information_bytes[28], codec_information_bytes[29],
694 codec_information_bytes[30], codec_information_bytes[31]));
695 // clang-format on
696 }
697
StopA2dpOffloadRequest()698 DynamicByteBuffer StopA2dpOffloadRequest() {
699 return DynamicByteBuffer(StaticByteBuffer(
700 // clang-format off
701 LowerBits(hci_android::kA2dpOffloadCommand), UpperBits(hci_android::kA2dpOffloadCommand),
702 0x01, // parameter_total_size (1 byte)
703 hci_android::kStopA2dpOffloadCommandSubopcode));
704 // clang-format on
705 }
706
707 } // namespace bt::testing
708