• 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 #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