1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "model/controller/le_advertiser.h"
18 
19 #include <array>
20 #include <chrono>
21 #include <cstddef>
22 #include <cstdint>
23 #include <optional>
24 #include <utility>
25 #include <vector>
26 
27 #include "hci/address_with_type.h"
28 #include "log.h"
29 #include "model/controller/link_layer_controller.h"
30 #include "packets/hci_packets.h"
31 #include "packets/link_layer_packets.h"
32 
33 using namespace bluetooth::hci;
34 using namespace std::literals;
35 
36 namespace rootcanal {
37 
38 namespace chrono {
39 using duration = std::chrono::steady_clock::duration;
40 using time_point = std::chrono::steady_clock::time_point;
41 };  // namespace chrono
42 
operator ""_slots(unsigned long long count)43 slots operator"" _slots(unsigned long long count) { return slots(count); }
44 
45 // =============================================================================
46 //  Constants
47 // =============================================================================
48 
49 // Vol 6, Part B § 4.4.2.4.3 High duty cycle connectable directed advertising.
50 // NB: The interval is specified to be 3.75ms, but it does not make sense to
51 // use this value with the timer tick at 5ms.
52 const chrono::duration adv_direct_ind_high_timeout = 1280ms;
53 const chrono::duration adv_direct_ind_high_interval = 10ms /*3750us*/;
54 
55 // Vol 6, Part B § 2.3.4.9 Host Advertising Data.
56 const uint16_t max_legacy_advertising_pdu_size = 31;
57 const uint16_t max_extended_advertising_pdu_size = 1650;
58 
59 // =============================================================================
60 //  Legacy Advertising Commands
61 // =============================================================================
62 
63 // HCI command LE_Set_Advertising_Parameters (Vol 4, Part E § 7.8.5).
LeSetAdvertisingParameters(uint16_t advertising_interval_min,uint16_t advertising_interval_max,AdvertisingType advertising_type,OwnAddressType own_address_type,PeerAddressType peer_address_type,Address peer_address,uint8_t advertising_channel_map,AdvertisingFilterPolicy advertising_filter_policy)64 ErrorCode LinkLayerController::LeSetAdvertisingParameters(
65     uint16_t advertising_interval_min, uint16_t advertising_interval_max,
66     AdvertisingType advertising_type, OwnAddressType own_address_type,
67     PeerAddressType peer_address_type, Address peer_address,
68     uint8_t advertising_channel_map,
69     AdvertisingFilterPolicy advertising_filter_policy) {
70   // Legacy advertising commands are disallowed when extended advertising
71   // commands were used since the last reset.
72   if (!SelectLegacyAdvertising()) {
73     INFO(id_,
74          "legacy advertising command rejected because extended advertising"
75          " is being used");
76     return ErrorCode::COMMAND_DISALLOWED;
77   }
78 
79   // Clear reserved bits.
80   advertising_channel_map &= 0x7;
81 
82   // For high duty cycle directed advertising, i.e. when
83   // Advertising_Type is 0x01 (ADV_DIRECT_IND, high duty cycle),
84   // the Advertising_Interval_Min and Advertising_Interval_Max parameters
85   // are not used and shall be ignored.
86   if (advertising_type == AdvertisingType::ADV_DIRECT_IND_HIGH) {
87     advertising_interval_min = 0x800;  // Default interval value
88     advertising_interval_max = 0x800;
89   }
90 
91   // The Host shall not issue this command when advertising is enabled in the
92   // Controller; if it is the Command Disallowed error code shall be used.
93   if (legacy_advertiser_.advertising_enable) {
94     INFO(id_, "legacy advertising is enabled");
95     return ErrorCode::COMMAND_DISALLOWED;
96   }
97 
98   // At least one channel bit shall be set in the
99   // Advertising_Channel_Map parameter.
100   if (advertising_channel_map == 0) {
101     INFO(id_,
102          "advertising_channel_map (0x{:04x}) does not enable any"
103          " advertising channel",
104          advertising_channel_map);
105     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
106   }
107 
108   // If the advertising interval range provided by the Host
109   // (Advertising_Interval_Min, Advertising_Interval_Max) is outside the
110   // advertising interval range supported by the Controller, then the
111   // Controller shall return the Unsupported Feature or Parameter Value (0x11)
112   // error code.
113   if (advertising_interval_min < 0x0020 || advertising_interval_min > 0x4000 ||
114       advertising_interval_max < 0x0020 || advertising_interval_max > 0x4000) {
115     INFO(id_,
116          "advertising_interval_min (0x{:04x}) and/or"
117          " advertising_interval_max (0x{:04x}) are outside the range"
118          " of supported values (0x0020 - 0x4000)",
119          advertising_interval_min, advertising_interval_max);
120     return ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
121   }
122 
123   // The Advertising_Interval_Min shall be less than or equal to the
124   // Advertising_Interval_Max.
125   if (advertising_interval_min > advertising_interval_max) {
126     INFO(id_,
127          "advertising_interval_min (0x{:04x}) is larger than"
128          " advertising_interval_max (0x{:04x})",
129          advertising_interval_min, advertising_interval_max);
130     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
131   }
132 
133   legacy_advertiser_.advertising_interval =
134       advertising_type == AdvertisingType::ADV_DIRECT_IND_HIGH
135           ? std::chrono::duration_cast<slots>(adv_direct_ind_high_interval)
136           : slots(advertising_interval_min);
137   legacy_advertiser_.advertising_type = advertising_type;
138   legacy_advertiser_.own_address_type = own_address_type;
139   legacy_advertiser_.peer_address_type = peer_address_type;
140   legacy_advertiser_.peer_address = peer_address;
141   legacy_advertiser_.advertising_channel_map = advertising_channel_map;
142   legacy_advertiser_.advertising_filter_policy = advertising_filter_policy;
143   return ErrorCode::SUCCESS;
144 }
145 
146 // HCI command LE_Set_Advertising_Data (Vol 4, Part E § 7.8.7).
LeSetAdvertisingData(const std::vector<uint8_t> & advertising_data)147 ErrorCode LinkLayerController::LeSetAdvertisingData(
148     const std::vector<uint8_t>& advertising_data) {
149   // Legacy advertising commands are disallowed when extended advertising
150   // commands were used since the last reset.
151   if (!SelectLegacyAdvertising()) {
152     INFO(id_,
153          "legacy advertising command rejected because extended advertising"
154          " is being used");
155     return ErrorCode::COMMAND_DISALLOWED;
156   }
157 
158   legacy_advertiser_.advertising_data = advertising_data;
159   return ErrorCode::SUCCESS;
160 }
161 
162 // HCI command LE_Set_Scan_Response_Data (Vol 4, Part E § 7.8.8).
LeSetScanResponseData(const std::vector<uint8_t> & scan_response_data)163 ErrorCode LinkLayerController::LeSetScanResponseData(
164     const std::vector<uint8_t>& scan_response_data) {
165   // Legacy advertising commands are disallowed when extended advertising
166   // commands were used since the last reset.
167   if (!SelectLegacyAdvertising()) {
168     INFO(id_,
169          "legacy advertising command rejected because extended advertising"
170          " is being used");
171     return ErrorCode::COMMAND_DISALLOWED;
172   }
173 
174   legacy_advertiser_.scan_response_data = scan_response_data;
175   return ErrorCode::SUCCESS;
176 }
177 
178 // HCI command LE_Advertising_Enable (Vol 4, Part E § 7.8.9).
LeSetAdvertisingEnable(bool advertising_enable)179 ErrorCode LinkLayerController::LeSetAdvertisingEnable(bool advertising_enable) {
180   // Legacy advertising commands are disallowed when extended advertising
181   // commands were used since the last reset.
182   if (!SelectLegacyAdvertising()) {
183     INFO(id_,
184          "legacy advertising command rejected because extended advertising"
185          " is being used");
186     return ErrorCode::COMMAND_DISALLOWED;
187   }
188 
189   if (!advertising_enable) {
190     legacy_advertiser_.Disable();
191     return ErrorCode::SUCCESS;
192   }
193 
194   AddressWithType peer_address = PeerDeviceAddress(
195       legacy_advertiser_.peer_address, legacy_advertiser_.peer_address_type);
196   AddressWithType public_address{address_, AddressType::PUBLIC_DEVICE_ADDRESS};
197   AddressWithType random_address{random_address_,
198                                  AddressType::RANDOM_DEVICE_ADDRESS};
199   std::optional<AddressWithType> resolvable_address =
200       GenerateResolvablePrivateAddress(peer_address, IrkSelection::Local);
201 
202   // TODO: additional checks would apply in the case of a LE only Controller
203   // with no configured public device address.
204 
205   switch (legacy_advertiser_.own_address_type) {
206     case OwnAddressType::PUBLIC_DEVICE_ADDRESS:
207       legacy_advertiser_.advertising_address = public_address;
208       break;
209 
210     case OwnAddressType::RANDOM_DEVICE_ADDRESS:
211       // If Advertising_Enable is set to 0x01, the advertising parameters'
212       // Own_Address_Type parameter is set to 0x01, and the random address for
213       // the device has not been initialized using the HCI_LE_Set_Random_Address
214       // command, the Controller shall return the error code
215       // Invalid HCI Command Parameters (0x12).
216       if (random_address.GetAddress() == Address::kEmpty) {
217         INFO(id_,
218              "own_address_type is Random_Device_Address but the Random_Address"
219              " has not been initialized");
220         return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
221       }
222       legacy_advertiser_.advertising_address = random_address;
223       break;
224 
225     case OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS:
226       legacy_advertiser_.advertising_address =
227           resolvable_address.value_or(public_address);
228       break;
229 
230     case OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS:
231       // If Advertising_Enable is set to 0x01, the advertising parameters'
232       // Own_Address_Type parameter is set to 0x03, the controller's resolving
233       // list did not contain a matching entry, and the random address for the
234       // device has not been initialized using the HCI_LE_Set_Random_Address
235       // command, the Controller shall return the error code Invalid HCI Command
236       // Parameters (0x12).
237       if (resolvable_address) {
238         legacy_advertiser_.advertising_address = resolvable_address.value();
239       } else if (random_address.GetAddress() == Address::kEmpty) {
240         INFO(id_,
241              "own_address_type is Resolvable_Or_Random_Address but the"
242              " Resolving_List does not contain a matching entry and the"
243              " Random_Address is not initialized");
244         return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
245       } else {
246         legacy_advertiser_.advertising_address = random_address;
247       }
248       break;
249   }
250 
251   legacy_advertiser_.timeout = {};
252   legacy_advertiser_.target_address =
253       AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
254 
255   switch (legacy_advertiser_.advertising_type) {
256     case AdvertisingType::ADV_DIRECT_IND_HIGH:
257       // The Link Layer shall exit the Advertising state no later than 1.28 s
258       // after the Advertising state was entered.
259       legacy_advertiser_.timeout =
260           std::chrono::steady_clock::now() + adv_direct_ind_high_timeout;
261       [[fallthrough]];
262 
263     case AdvertisingType::ADV_DIRECT_IND_LOW: {
264       // Note: Vol 6, Part B § 6.2.2 Connectable directed event type
265       //
266       // If an IRK is available in the Link Layer Resolving
267       // List for the peer device, then the target’s device address
268       // (TargetA field) shall use a resolvable private address. If an IRK is
269       // not available in the Link Layer Resolving List or the IRK is set to
270       // zero for the peer device, then the target’s device address
271       // (TargetA field) shall use the Identity Address when entering the
272       // Advertising State and using connectable directed events.
273       std::optional<AddressWithType> peer_resolvable_address =
274           GenerateResolvablePrivateAddress(peer_address, IrkSelection::Peer);
275       legacy_advertiser_.target_address =
276           peer_resolvable_address.value_or(peer_address);
277       break;
278     }
279     default:
280       break;
281   }
282 
283   legacy_advertiser_.advertising_enable = true;
284   legacy_advertiser_.next_event = std::chrono::steady_clock::now() +
285                                   legacy_advertiser_.advertising_interval;
286   return ErrorCode::SUCCESS;
287 }
288 
289 // =============================================================================
290 //  Extended Advertising Commands
291 // =============================================================================
292 
293 // HCI command LE_Set_Advertising_Set_Random_Address (Vol 4, Part E § 7.8.52).
LeSetAdvertisingSetRandomAddress(uint8_t advertising_handle,Address random_address)294 ErrorCode LinkLayerController::LeSetAdvertisingSetRandomAddress(
295     uint8_t advertising_handle, Address random_address) {
296   // If the advertising set corresponding to the Advertising_Handle parameter
297   // does not exist, then the Controller shall return the error code
298   // Unknown Advertising Identifier (0x42).
299   // TODO(c++20) unordered_map<>::contains
300   if (extended_advertisers_.count(advertising_handle) == 0) {
301     INFO(id_, "no advertising set defined with handle {:02x}",
302          static_cast<int>(advertising_handle));
303     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
304   }
305 
306   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
307 
308   // If the Host issues this command while the advertising set identified by the
309   // Advertising_Handle parameter is using connectable advertising and is
310   // enabled, the Controller shall return the error code
311   // Command Disallowed (0x0C).
312   if (advertiser.advertising_enable) {
313     INFO(id_, "advertising is enabled for the specified advertising set");
314     return ErrorCode::COMMAND_DISALLOWED;
315   }
316 
317   advertiser.random_address = random_address;
318   return ErrorCode::SUCCESS;
319 }
320 
321 // HCI command LE_Set_Extended_Advertising_Parameters (Vol 4, Part E § 7.8.53).
LeSetExtendedAdvertisingParameters(uint8_t advertising_handle,AdvertisingEventProperties advertising_event_properties,uint16_t primary_advertising_interval_min,uint16_t primary_advertising_interval_max,uint8_t primary_advertising_channel_map,OwnAddressType own_address_type,PeerAddressType peer_address_type,Address peer_address,AdvertisingFilterPolicy advertising_filter_policy,uint8_t advertising_tx_power,PrimaryPhyType primary_advertising_phy,uint8_t secondary_max_skip,SecondaryPhyType secondary_advertising_phy,uint8_t advertising_sid,bool scan_request_notification_enable)322 ErrorCode LinkLayerController::LeSetExtendedAdvertisingParameters(
323     uint8_t advertising_handle,
324     AdvertisingEventProperties advertising_event_properties,
325     uint16_t primary_advertising_interval_min,
326     uint16_t primary_advertising_interval_max,
327     uint8_t primary_advertising_channel_map, OwnAddressType own_address_type,
328     PeerAddressType peer_address_type, Address peer_address,
329     AdvertisingFilterPolicy advertising_filter_policy,
330     uint8_t advertising_tx_power, PrimaryPhyType primary_advertising_phy,
331     uint8_t secondary_max_skip, SecondaryPhyType secondary_advertising_phy,
332     uint8_t advertising_sid, bool scan_request_notification_enable) {
333   // Extended advertising commands are disallowed when legacy advertising
334   // commands were used since the last reset.
335   if (!SelectExtendedAdvertising()) {
336     INFO(id_,
337          "extended advertising command rejected because legacy advertising"
338          " is being used");
339     return ErrorCode::COMMAND_DISALLOWED;
340   }
341 
342   bool legacy_advertising = advertising_event_properties.legacy_;
343   bool extended_advertising = !advertising_event_properties.legacy_;
344   bool connectable_advertising = advertising_event_properties.connectable_;
345   bool scannable_advertising = advertising_event_properties.scannable_;
346   bool directed_advertising = advertising_event_properties.directed_;
347   bool high_duty_cycle_advertising =
348       advertising_event_properties.high_duty_cycle_;
349   bool anonymous_advertising = advertising_event_properties.anonymous_;
350   uint16_t raw_advertising_event_properties =
351       ExtendedAdvertiser::GetRawAdvertisingEventProperties(
352           advertising_event_properties);
353 
354   // Clear reserved bits.
355   primary_advertising_channel_map &= 0x7;
356 
357   // If the Advertising_Handle does not identify an existing advertising set
358   // and the Controller is unable to support a new advertising set at present,
359   // the Controller shall return the error code Memory Capacity Exceeded (0x07).
360   ExtendedAdvertiser advertiser(advertising_handle);
361 
362   // TODO(c++20) unordered_map<>::contains
363   if (extended_advertisers_.count(advertising_handle) == 0) {
364     if (extended_advertisers_.size() >=
365         properties_.le_num_supported_advertising_sets) {
366       INFO(id_,
367            "no advertising set defined with handle {:02x} and"
368            " cannot allocate any more advertisers",
369            static_cast<int>(advertising_handle));
370       return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
371     }
372   } else {
373     advertiser = extended_advertisers_[advertising_handle];
374   }
375 
376   // If the Host issues this command when advertising is enabled for the
377   // specified advertising set, the Controller shall return the error code
378   // Command Disallowed (0x0C).
379   if (advertiser.advertising_enable) {
380     INFO(id_, "advertising is enabled for the specified advertising set");
381     return ErrorCode::COMMAND_DISALLOWED;
382   }
383 
384   // If legacy advertising PDU types are being used, then the parameter value
385   // shall be one of those specified in Table 7.2.
386   if (legacy_advertising &&
387       (raw_advertising_event_properties & ~0x10) !=
388           static_cast<uint16_t>(LegacyAdvertisingEventProperties::ADV_IND) &&
389       (raw_advertising_event_properties & ~0x10) !=
390           static_cast<uint16_t>(
391               LegacyAdvertisingEventProperties::ADV_DIRECT_IND_LOW) &&
392       (raw_advertising_event_properties & ~0x10) !=
393           static_cast<uint16_t>(
394               LegacyAdvertisingEventProperties::ADV_DIRECT_IND_HIGH) &&
395       (raw_advertising_event_properties & ~0x10) !=
396           static_cast<uint16_t>(
397               LegacyAdvertisingEventProperties::ADV_SCAN_IND) &&
398       (raw_advertising_event_properties & ~0x10) !=
399           static_cast<uint16_t>(
400               LegacyAdvertisingEventProperties::ADV_NONCONN_IND)) {
401     INFO(id_,
402          "advertising_event_properties (0x{:02x}) is legacy but does not"
403          " match valid legacy advertising event types",
404          raw_advertising_event_properties);
405     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
406   }
407 
408   bool can_have_advertising_data =
409       (legacy_advertising && !directed_advertising) ||
410       (extended_advertising && !scannable_advertising);
411 
412   // If the Advertising_Event_Properties parameter [..] specifies a type that
413   // does not support advertising data when the advertising set already
414   // contains some, the Controller shall return the error code
415   // Invalid HCI Command Parameters (0x12).
416   if (!can_have_advertising_data && !advertiser.advertising_data.empty()) {
417     INFO(id_,
418          "advertising_event_properties (0x{:02x}) specifies an event type"
419          " that does not support avertising data but the set contains some",
420          raw_advertising_event_properties);
421     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
422   }
423 
424   // Note: not explicitly specified in the specification but makes sense
425   // in the context of the other checks.
426   if (!scannable_advertising && !advertiser.scan_response_data.empty()) {
427     INFO(id_,
428          "advertising_event_properties (0x{:02x}) specifies an event type"
429          " that does not support scan response data but the set contains some",
430          raw_advertising_event_properties);
431     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
432   }
433 
434   // If the advertising set already contains data, the type shall be one that
435   // supports advertising data and the amount of data shall not
436   // exceed 31 octets.
437   if (legacy_advertising &&
438       (advertiser.advertising_data.size() > max_legacy_advertising_pdu_size ||
439        advertiser.scan_response_data.size() >
440            max_legacy_advertising_pdu_size)) {
441     INFO(id_,
442          "advertising_event_properties (0x{:02x}) is legacy and the"
443          " advertising data or scan response data exceeds the capacity"
444          " of legacy PDUs",
445          raw_advertising_event_properties);
446     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
447   }
448 
449   // If extended advertising PDU types are being used (bit 4 = 0) then:
450   // The advertisement shall not be both connectable and scannable.
451   if (extended_advertising && connectable_advertising &&
452       scannable_advertising) {
453     INFO(id_,
454          "advertising_event_properties (0x{:02x}) is extended and may not"
455          " be connectable and scannable at the same time",
456          raw_advertising_event_properties);
457     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
458   }
459 
460   // High duty cycle directed connectable advertising (≤ 3.75 ms
461   // advertising interval) shall not be used (bit 3 = 0).
462   if (extended_advertising && connectable_advertising && directed_advertising &&
463       high_duty_cycle_advertising) {
464     INFO(id_,
465          "advertising_event_properties (0x{:02x}) is extended and may not"
466          " be high-duty cycle directed connectable",
467          raw_advertising_event_properties);
468     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
469   }
470 
471   // If the primary advertising interval range provided by the Host
472   // (Primary_Advertising_Interval_Min, Primary_Advertising_Interval_Max) is
473   // outside the advertising interval range supported by the Controller, then
474   // the Controller shall return the error code Unsupported Feature or
475   // Parameter Value (0x11).
476   if (primary_advertising_interval_min < 0x20 ||
477       primary_advertising_interval_max < 0x20) {
478     INFO(id_,
479          "primary_advertising_interval_min (0x{:04x}) and/or"
480          " primary_advertising_interval_max (0x{:04x}) are outside the range"
481          " of supported values (0x0020 - 0xffff)",
482          primary_advertising_interval_min, primary_advertising_interval_max);
483     return ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
484   }
485 
486   // The Primary_Advertising_Interval_Min parameter shall be less than or equal
487   // to the Primary_Advertising_Interval_Max parameter.
488   if (primary_advertising_interval_min > primary_advertising_interval_max) {
489     INFO(id_,
490          "primary_advertising_interval_min (0x{:04x}) is larger than"
491          " primary_advertising_interval_max (0x{:04x})",
492          primary_advertising_interval_min, primary_advertising_interval_max);
493     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
494   }
495 
496   // At least one channel bit shall be set in the
497   // Primary_Advertising_Channel_Map parameter.
498   if (primary_advertising_channel_map == 0) {
499     INFO(id_,
500          "primary_advertising_channel_map does not enable any"
501          " advertising channel");
502     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
503   }
504 
505   // If legacy advertising PDUs are being used, the
506   // Primary_Advertising_PHY shall indicate the LE 1M PHY.
507   if (legacy_advertising && primary_advertising_phy != PrimaryPhyType::LE_1M) {
508     INFO(id_,
509          "advertising_event_properties (0x{:04x}) is legacy but"
510          " primary_advertising_phy ({:02x}) is not LE 1M",
511          raw_advertising_event_properties,
512          static_cast<uint8_t>(primary_advertising_phy));
513     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
514   }
515 
516   // If Constant Tone Extensions are enabled for the advertising set and
517   // Secondary_Advertising_PHY specifies a PHY that does not allow
518   // Constant Tone Extensions, the Controller shall
519   // return the error code Command Disallowed (0x0C).
520   if (advertiser.constant_tone_extensions &&
521       secondary_advertising_phy == SecondaryPhyType::LE_CODED) {
522     INFO(id_,
523          "constant tone extensions are enabled but"
524          " secondary_advertising_phy ({:02x}) does not support them",
525          static_cast<uint8_t>(secondary_advertising_phy));
526     return ErrorCode::COMMAND_DISALLOWED;
527   }
528 
529   // If the Host issues this command when periodic advertising is enabled for
530   // the specified advertising set and connectable, scannable, legacy,
531   // or anonymous advertising is specified, the Controller shall return the
532   // error code Invalid HCI Command Parameters (0x12).
533   if (advertiser.periodic_advertising_enable &&
534       (connectable_advertising || scannable_advertising || legacy_advertising ||
535        anonymous_advertising)) {
536     INFO(id_,
537          "periodic advertising is enabled for the specified advertising set"
538          " and advertising_event_properties (0x{:02x}) is either"
539          " connectable, scannable, legacy, or anonymous",
540          raw_advertising_event_properties);
541     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
542   }
543 
544   // If periodic advertising is enabled for the advertising set and the
545   // Secondary_Advertising_PHY parameter does not specify the PHY currently
546   // being used for the periodic advertising, the Controller shall return the
547   // error code Command Disallowed (0x0C).
548 #if 0
549   if (advertiser.periodic_advertising_enable) {
550     // TODO
551     INFO(id_,
552         "periodic advertising is enabled for the specified advertising set"
553         " and the secondary PHY does not match the periodic"
554         " advertising PHY");
555     return ErrorCode::COMMAND_DISALLOWED;
556   }
557 #endif
558 
559   // If the advertising set already contains advertising data or scan response
560   // data, extended advertising is being used, and the length of the data is
561   // greater than the maximum that the Controller can transmit within the
562   // longest possible auxiliary advertising segment consistent with the
563   // parameters, the Controller shall return the error code
564   // Packet Too Long (0x45). If advertising on the LE Coded PHY, the S=8
565   // coding shall be assumed.
566   if (extended_advertising &&
567       (advertiser.advertising_data.size() > max_extended_advertising_pdu_size ||
568        advertiser.scan_response_data.size() >
569            max_extended_advertising_pdu_size)) {
570     INFO(id_,
571          "the advertising data contained in the set is larger than the"
572          " available PDU capacity");
573     return ErrorCode::PACKET_TOO_LONG;
574   }
575 
576   advertiser.advertising_event_properties = advertising_event_properties;
577   advertiser.primary_advertising_interval =
578       slots(primary_advertising_interval_min);
579   advertiser.primary_advertising_channel_map = primary_advertising_channel_map;
580   advertiser.own_address_type = own_address_type;
581   advertiser.peer_address_type = peer_address_type;
582   advertiser.peer_address = peer_address;
583   advertiser.advertising_filter_policy = advertising_filter_policy;
584   advertiser.advertising_tx_power = advertising_tx_power;
585   advertiser.primary_advertising_phy = primary_advertising_phy;
586   advertiser.secondary_max_skip = secondary_max_skip;
587   advertiser.secondary_advertising_phy = secondary_advertising_phy;
588   advertiser.advertising_sid = advertising_sid;
589   advertiser.scan_request_notification_enable =
590       scan_request_notification_enable;
591 
592   extended_advertisers_.insert_or_assign(advertising_handle,
593                                          std::move(advertiser));
594   return ErrorCode::SUCCESS;
595 }
596 
597 // HCI command LE_Set_Extended_Advertising_Data (Vol 4, Part E § 7.8.54).
LeSetExtendedAdvertisingData(uint8_t advertising_handle,Operation operation,FragmentPreference fragment_preference,const std::vector<uint8_t> & advertising_data)598 ErrorCode LinkLayerController::LeSetExtendedAdvertisingData(
599     uint8_t advertising_handle, Operation operation,
600     FragmentPreference fragment_preference,
601     const std::vector<uint8_t>& advertising_data) {
602   // Extended advertising commands are disallowed when legacy advertising
603   // commands were used since the last reset.
604   if (!SelectExtendedAdvertising()) {
605     INFO(id_,
606          "extended advertising command rejected because legacy advertising"
607          " is being used");
608     return ErrorCode::COMMAND_DISALLOWED;
609   }
610 
611   // fragment_preference is unused for now.
612   (void)fragment_preference;
613 
614   // If the advertising set corresponding to the Advertising_Handle parameter
615   // does not exist, then the Controller shall return the error code
616   // Unknown Advertising Identifier (0x42).
617   // TODO(c++20) unordered_map<>::contains
618   if (extended_advertisers_.count(advertising_handle) == 0) {
619     INFO(id_, "no advertising set defined with handle {:02x}",
620          static_cast<int>(advertising_handle));
621     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
622   }
623 
624   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
625   const AdvertisingEventProperties& advertising_event_properties =
626       advertiser.advertising_event_properties;
627   uint16_t raw_advertising_event_properties =
628       ExtendedAdvertiser::GetRawAdvertisingEventProperties(
629           advertising_event_properties);
630 
631   bool can_have_advertising_data = (advertising_event_properties.legacy_ &&
632                                     !advertising_event_properties.directed_) ||
633                                    (!advertising_event_properties.legacy_ &&
634                                     !advertising_event_properties.scannable_);
635 
636   // If the advertising set specifies a type that does not support
637   // advertising data, the Controller shall return the error code
638   // Invalid HCI Command Parameters (0x12).
639   if (!can_have_advertising_data) {
640     INFO(id_,
641          "advertising_event_properties ({:02x}) does not support"
642          " advertising data",
643          raw_advertising_event_properties);
644     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
645   }
646 
647   // If the advertising set uses legacy advertising PDUs that support
648   // advertising data and either Operation is not 0x03 or the
649   // Advertising_Data_Length parameter exceeds 31 octets, the Controller
650   // shall return the error code Invalid HCI Command Parameters (0x12).
651   if (advertising_event_properties.legacy_ &&
652       (operation != Operation::COMPLETE_ADVERTISEMENT ||
653        advertising_data.size() > max_legacy_advertising_pdu_size)) {
654     INFO(id_,
655          "advertising_event_properties ({:02x}) is legacy and"
656          " and an incomplete operation was used or the advertising data"
657          " is larger than 31",
658          raw_advertising_event_properties);
659     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
660   }
661 
662   // If Operation is 0x04 and:
663   //    • advertising is currently disabled for the advertising set;
664   //    • the advertising set contains no data;
665   //    • the advertising set uses legacy PDUs; or
666   //    • Advertising_Data_Length is not zero;
667   // then the Controller shall return the error code Invalid HCI Command
668   // Parameters (0x12).
669   if (operation == Operation::UNCHANGED_DATA &&
670       (!advertiser.advertising_enable || advertiser.advertising_data.empty() ||
671        advertising_event_properties.legacy_ || !advertising_data.empty())) {
672     INFO(id_,
673          "Unchanged_Data operation is used but advertising is disabled;"
674          " or the advertising set contains no data;"
675          " or the advertising set uses legacy PDUs;"
676          " or the advertising data is not empty");
677     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
678   }
679 
680   // If Operation is not 0x03 or 0x04 and Advertising_Data_Length is zero,
681   // the Controller shall return the error code Invalid HCI
682   // Command Parameters (0x12).
683   if (operation != Operation::COMPLETE_ADVERTISEMENT &&
684       operation != Operation::UNCHANGED_DATA && advertising_data.empty()) {
685     INFO(id_,
686          "operation ({:02x}) is not Complete_Advertisement or Unchanged_Data"
687          " but the advertising data is empty",
688          static_cast<int>(operation));
689     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
690   }
691 
692   // If advertising is currently enabled for the specified advertising set and
693   // Operation does not have the value 0x03 or 0x04, the Controller shall
694   // return the error code Command Disallowed (0x0C).
695   if (advertiser.advertising_enable &&
696       operation != Operation::COMPLETE_ADVERTISEMENT &&
697       operation != Operation::UNCHANGED_DATA) {
698     INFO(id_,
699          "operation ({:02x}) is used but advertising is enabled for the"
700          " specified advertising set",
701          static_cast<int>(operation));
702     return ErrorCode::COMMAND_DISALLOWED;
703   }
704 
705   switch (operation) {
706     case Operation::INTERMEDIATE_FRAGMENT:
707       advertiser.advertising_data.insert(advertiser.advertising_data.end(),
708                                          advertising_data.begin(),
709                                          advertising_data.end());
710       advertiser.partial_advertising_data = true;
711       break;
712 
713     case Operation::FIRST_FRAGMENT:
714       advertiser.advertising_data = advertising_data;
715       advertiser.partial_advertising_data = true;
716       break;
717 
718     case Operation::LAST_FRAGMENT:
719       advertiser.advertising_data.insert(advertiser.advertising_data.end(),
720                                          advertising_data.begin(),
721                                          advertising_data.end());
722       advertiser.partial_advertising_data = false;
723       break;
724 
725     case Operation::COMPLETE_ADVERTISEMENT:
726       advertiser.advertising_data = advertising_data;
727       advertiser.partial_advertising_data = false;
728       break;
729 
730     case Operation::UNCHANGED_DATA:
731       break;
732 
733     default:
734       INFO(id_, "unknown operation ({})", static_cast<int>(operation));
735       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
736   }
737 
738   // If the combined length of the data exceeds the capacity of the
739   // advertising set identified by the Advertising_Handle parameter
740   // (see Section 7.8.57 LE Read Maximum Advertising Data Length command)
741   // or the amount of memory currently available, all the data
742   // shall be discarded and the Controller shall return the error code Memory
743   // Capacity Exceeded (0x07).
744   if (advertiser.advertising_data.size() >
745       properties_.le_max_advertising_data_length) {
746     INFO(id_,
747          "the combined length {} of the advertising data exceeds the"
748          " advertising set capacity {}",
749          advertiser.advertising_data.size(),
750          properties_.le_max_advertising_data_length);
751     advertiser.advertising_data.clear();
752     advertiser.partial_advertising_data = false;
753     return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
754   }
755 
756   // If advertising is currently enabled for the specified advertising set,
757   // the advertising set uses extended advertising, and the length of the
758   // data is greater than the maximum that the Controller can transmit within
759   // the longest possible auxiliary advertising segment consistent with the
760   // current parameters of the advertising set, the Controller shall return
761   // the error code Packet Too Long (0x45). If advertising on the
762   // LE Coded PHY, the S=8 coding shall be assumed.
763   size_t max_advertising_data_length =
764       ExtendedAdvertiser::GetMaxAdvertisingDataLength(
765           advertising_event_properties);
766   if (advertiser.advertising_enable &&
767       advertiser.advertising_data.size() > max_advertising_data_length) {
768     INFO(id_,
769          "the advertising data contained in the set is larger than the"
770          " available PDU capacity");
771     advertiser.advertising_data.clear();
772     advertiser.partial_advertising_data = false;
773     return ErrorCode::PACKET_TOO_LONG;
774   }
775 
776   return ErrorCode::SUCCESS;
777 }
778 
779 // HCI command LE_Set_Extended_Scan_Response_Data (Vol 4, Part E § 7.8.55).
LeSetExtendedScanResponseData(uint8_t advertising_handle,Operation operation,FragmentPreference fragment_preference,const std::vector<uint8_t> & scan_response_data)780 ErrorCode LinkLayerController::LeSetExtendedScanResponseData(
781     uint8_t advertising_handle, Operation operation,
782     FragmentPreference fragment_preference,
783     const std::vector<uint8_t>& scan_response_data) {
784   // Extended advertising commands are disallowed when legacy advertising
785   // commands were used since the last reset.
786   if (!SelectExtendedAdvertising()) {
787     INFO(id_,
788          "extended advertising command rejected because legacy advertising"
789          " is being used");
790     return ErrorCode::COMMAND_DISALLOWED;
791   }
792 
793   // fragment_preference is unused for now.
794   (void)fragment_preference;
795 
796   // If the advertising set corresponding to the Advertising_Handle parameter
797   // does not exist, then the Controller shall return the error code
798   // Unknown Advertising Identifier (0x42).
799   // TODO(c++20) unordered_map<>::contains
800   if (extended_advertisers_.count(advertising_handle) == 0) {
801     INFO(id_, "no advertising set defined with handle {:02x}",
802          static_cast<int>(advertising_handle));
803     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
804   }
805 
806   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
807   const AdvertisingEventProperties& advertising_event_properties =
808       advertiser.advertising_event_properties;
809   uint16_t raw_advertising_event_properties =
810       ExtendedAdvertiser::GetRawAdvertisingEventProperties(
811           advertising_event_properties);
812 
813   // If the advertising set is non-scannable and the Host uses this
814   // command other than to discard existing data, the Controller shall
815   // return the error code Invalid HCI Command Parameters (0x12).
816   if (!advertising_event_properties.scannable_ && !scan_response_data.empty()) {
817     INFO(id_,
818          "advertising_event_properties ({:02x}) is not scannable"
819          " but the scan response data is not empty",
820          raw_advertising_event_properties);
821     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
822   }
823 
824   // If the advertising set uses scannable legacy advertising PDUs and
825   // either Operation is not 0x03 or the Scan_Response_Data_Length
826   // parameter exceeds 31 octets, the Controller shall
827   // return the error code Invalid HCI Command Parameters (0x12).
828   if (advertising_event_properties.scannable_ &&
829       advertising_event_properties.legacy_ &&
830       (operation != Operation::COMPLETE_ADVERTISEMENT ||
831        scan_response_data.size() > max_legacy_advertising_pdu_size)) {
832     INFO(id_,
833          "advertising_event_properties ({:02x}) is scannable legacy"
834          " and an incomplete operation was used or the scan response data"
835          " is larger than 31",
836          raw_advertising_event_properties);
837     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
838   }
839 
840   // If Operation is not 0x03 and Scan_Response_Data_Length is zero, the
841   // Controller shall return the error code
842   // Invalid HCI Command Parameters (0x12).
843   if (operation != Operation::COMPLETE_ADVERTISEMENT &&
844       scan_response_data.empty()) {
845     INFO(id_,
846          "operation ({:02x}) is not Complete_Advertisement but the"
847          " scan response data is empty",
848          static_cast<int>(operation));
849     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
850   }
851 
852   // If advertising is currently enabled for the specified advertising set and
853   // Operation does not have the value 0x03, the Controller shall
854   // return the error code Command Disallowed (0x0C).
855   if (advertiser.advertising_enable &&
856       operation != Operation::COMPLETE_ADVERTISEMENT) {
857     INFO(id_,
858          "operation ({:02x}) is used but advertising is enabled for the"
859          " specified advertising set",
860          static_cast<int>(operation));
861     return ErrorCode::COMMAND_DISALLOWED;
862   }
863 
864   // If the advertising set uses scannable extended advertising PDUs,
865   // advertising is currently enabled for the specified advertising set,
866   // and Scan_Response_Data_Length is zero, the Controller shall return
867   // the error code Command Disallowed (0x0C).
868   if (advertiser.advertising_enable &&
869       advertising_event_properties.scannable_ &&
870       !advertising_event_properties.legacy_ && scan_response_data.empty()) {
871     INFO(id_,
872          "advertising_event_properties ({:02x}) is scannable extended,"
873          " advertising is enabled for the specified advertising set"
874          " and the scan response data is empty",
875          raw_advertising_event_properties);
876     return ErrorCode::COMMAND_DISALLOWED;
877   }
878 
879   switch (operation) {
880     case Operation::INTERMEDIATE_FRAGMENT:
881       advertiser.scan_response_data.insert(advertiser.scan_response_data.end(),
882                                            scan_response_data.begin(),
883                                            scan_response_data.end());
884       advertiser.partial_scan_response_data = true;
885       break;
886 
887     case Operation::FIRST_FRAGMENT:
888       advertiser.scan_response_data = scan_response_data;
889       advertiser.partial_scan_response_data = true;
890       break;
891 
892     case Operation::LAST_FRAGMENT:
893       advertiser.scan_response_data.insert(advertiser.scan_response_data.end(),
894                                            scan_response_data.begin(),
895                                            scan_response_data.end());
896       advertiser.partial_scan_response_data = false;
897       break;
898 
899     case Operation::COMPLETE_ADVERTISEMENT:
900       advertiser.scan_response_data = scan_response_data;
901       advertiser.partial_scan_response_data = false;
902       break;
903 
904     case Operation::UNCHANGED_DATA:
905       INFO(id_,
906            "the operation Unchanged_Data is only allowed"
907            " for Advertising_Data");
908       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
909 
910     default:
911       INFO(id_, "unknown operation ({})", static_cast<int>(operation));
912       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
913   }
914 
915   // If the combined length of the data exceeds the capacity of the
916   // advertising set identified by the Advertising_Handle parameter
917   // (see Section 7.8.57 LE Read Maximum Advertising Data Length command)
918   // or the amount of memory currently available, all the data shall be
919   // discarded and the Controller shall return the error code
920   // Memory Capacity Exceeded (0x07).
921   if (advertiser.scan_response_data.size() >
922       properties_.le_max_advertising_data_length) {
923     INFO(id_,
924          "the combined length of the scan response data exceeds the"
925          " advertising set capacity");
926     advertiser.scan_response_data.clear();
927     advertiser.partial_scan_response_data = false;
928     return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
929   }
930 
931   // If the advertising set uses extended advertising and the combined length
932   // of the data is greater than the maximum that the Controller can transmit
933   // within the longest possible auxiliary advertising segment consistent
934   // with the current parameters of the advertising set (using the current
935   // advertising interval if advertising is enabled), all the data shall be
936   // discarded and the Controller shall return the error code
937   // Packet Too Long (0x45). If advertising on the LE Coded PHY,
938   // the S=8 coding shall be assumed.
939   if (advertiser.scan_response_data.size() >
940       max_extended_advertising_pdu_size) {
941     INFO(id_,
942          "the scan response data contained in the set is larger than the"
943          " available PDU capacity");
944     advertiser.scan_response_data.clear();
945     advertiser.partial_scan_response_data = false;
946     return ErrorCode::PACKET_TOO_LONG;
947   }
948 
949   return ErrorCode::SUCCESS;
950 }
951 
952 // HCI command LE_Set_Extended_Advertising_Enable (Vol 4, Part E § 7.8.56).
LeSetExtendedAdvertisingEnable(bool enable,const std::vector<bluetooth::hci::EnabledSet> & sets)953 ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable(
954     bool enable, const std::vector<bluetooth::hci::EnabledSet>& sets) {
955   // Extended advertising commands are disallowed when legacy advertising
956   // commands were used since the last reset.
957   if (!SelectExtendedAdvertising()) {
958     INFO(id_,
959          "extended advertising command rejected because legacy advertising"
960          " is being used");
961     return ErrorCode::COMMAND_DISALLOWED;
962   }
963 
964   // Validate the advertising handles.
965   std::array<bool, UINT8_MAX> used_advertising_handles{};
966   for (auto& set : sets) {
967     // If the same advertising set is identified by more than one entry in the
968     // Advertising_Handle[i] arrayed parameter, then the Controller shall return
969     // the error code Invalid HCI Command Parameters (0x12).
970     if (used_advertising_handles[set.advertising_handle_]) {
971       INFO(id_, "advertising handle {:02x} is added more than once",
972            set.advertising_handle_);
973       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
974     }
975 
976     // If the advertising set corresponding to the Advertising_Handle[i]
977     // parameter does not exist, then the Controller shall return the error code
978     // Unknown Advertising Identifier (0x42).
979     if (extended_advertisers_.find(set.advertising_handle_) ==
980         extended_advertisers_.end()) {
981       INFO(id_, "advertising handle {:02x} is not defined",
982            set.advertising_handle_);
983       return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
984     }
985 
986     used_advertising_handles[set.advertising_handle_] = true;
987   }
988 
989   // If Enable and Num_Sets are both set to
990   // 0x00, then all advertising sets are disabled.
991   if (!enable && sets.empty()) {
992     for (auto& [_, advertiser] : extended_advertisers_) {
993       advertiser.Disable();
994     }
995     return ErrorCode::SUCCESS;
996   }
997 
998   // If Num_Sets is set to 0x00, the Controller shall return the error code
999   // Invalid HCI Command Parameters (0x12).
1000   if (sets.empty()) {
1001     INFO(id_, "enable is true but no advertising set is selected");
1002     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1003   }
1004 
1005   // No additional checks for disabling advertising sets.
1006   if (!enable) {
1007     for (auto& set : sets) {
1008       auto& advertiser = extended_advertisers_[set.advertising_handle_];
1009       advertiser.Disable();
1010     }
1011     return ErrorCode::SUCCESS;
1012   }
1013 
1014   // Validate the advertising parameters before enabling any set.
1015   for (auto& set : sets) {
1016     ExtendedAdvertiser& advertiser =
1017         extended_advertisers_[set.advertising_handle_];
1018     const AdvertisingEventProperties& advertising_event_properties =
1019         advertiser.advertising_event_properties;
1020 
1021     bool extended_advertising = !advertising_event_properties.legacy_;
1022     bool connectable_advertising = advertising_event_properties.connectable_;
1023     bool scannable_advertising = advertising_event_properties.scannable_;
1024     bool directed_advertising = advertising_event_properties.directed_;
1025     bool high_duty_cycle_advertising =
1026         advertising_event_properties.high_duty_cycle_;
1027 
1028     // If the advertising is high duty cycle connectable directed advertising,
1029     // then Duration[i] shall be less than or equal to 1.28 seconds and shall
1030     // not be equal to 0.
1031     std::chrono::milliseconds duration =
1032         std::chrono::milliseconds(set.duration_ * 10);
1033     if (connectable_advertising && directed_advertising &&
1034         high_duty_cycle_advertising &&
1035         (set.duration_ == 0 || duration > adv_direct_ind_high_timeout)) {
1036       INFO(id_,
1037            "extended advertising is high duty cycle connectable directed"
1038            " but the duration is either 0 or larger than 1.28 seconds");
1039       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1040     }
1041 
1042     // If the advertising set contains partial advertising data or partial
1043     // scan response data, the Controller shall return the error code
1044     // Command Disallowed (0x0C).
1045     if (advertiser.partial_advertising_data ||
1046         advertiser.partial_scan_response_data) {
1047       INFO(id_,
1048            "advertising set contains partial advertising"
1049            " or scan response data");
1050       return ErrorCode::COMMAND_DISALLOWED;
1051     }
1052 
1053     // If the advertising set uses scannable extended advertising PDUs and no
1054     // scan response data is currently provided, the Controller shall return the
1055     // error code Command Disallowed (0x0C).
1056     if (extended_advertising && scannable_advertising &&
1057         advertiser.scan_response_data.empty()) {
1058       INFO(id_,
1059            "advertising set uses scannable extended advertising PDUs"
1060            " but no scan response data is provided");
1061       return ErrorCode::COMMAND_DISALLOWED;
1062     }
1063 
1064     // If the advertising set uses connectable extended advertising PDUs and the
1065     // advertising data in the advertising set will not fit in the
1066     // AUX_ADV_IND PDU, the Controller shall return the error code
1067     // Invalid HCI Command Parameters (0x12).
1068     if (extended_advertising && connectable_advertising &&
1069         advertiser.advertising_data.size() >
1070             ExtendedAdvertiser::GetMaxAdvertisingDataLength(
1071                 advertising_event_properties)) {
1072       INFO(id_,
1073            "advertising set uses connectable extended advertising PDUs"
1074            " but the advertising data does not fit in AUX_ADV_IND PDUs");
1075       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1076     }
1077 
1078     // If extended advertising is being used and the length of any advertising
1079     // data or of any scan response data is greater than the maximum that the
1080     // Controller can transmit within the longest possible auxiliary
1081     // advertising segment consistent with the chosen advertising interval,
1082     // the Controller shall return the error code Packet Too Long (0x45).
1083     // If advertising on the LE Coded PHY, the S=8 coding shall be assumed.
1084     if (extended_advertising && (advertiser.advertising_data.size() >
1085                                      max_extended_advertising_pdu_size ||
1086                                  advertiser.scan_response_data.size() >
1087                                      max_extended_advertising_pdu_size)) {
1088       INFO(id_,
1089            "advertising set uses extended advertising PDUs"
1090            " but the advertising data does not fit in advertising PDUs");
1091       return ErrorCode::PACKET_TOO_LONG;
1092     }
1093 
1094     AddressWithType peer_address = PeerDeviceAddress(
1095         advertiser.peer_address, advertiser.peer_address_type);
1096     AddressWithType public_address{address_,
1097                                    AddressType::PUBLIC_DEVICE_ADDRESS};
1098     AddressWithType random_address{
1099         advertiser.random_address.value_or(Address::kEmpty),
1100         AddressType::RANDOM_DEVICE_ADDRESS};
1101     std::optional<AddressWithType> resolvable_address =
1102         GenerateResolvablePrivateAddress(peer_address, IrkSelection::Local);
1103 
1104     // TODO: additional checks would apply in the case of a LE only Controller
1105     // with no configured public device address.
1106 
1107     switch (advertiser.own_address_type) {
1108       case OwnAddressType::PUBLIC_DEVICE_ADDRESS:
1109         advertiser.advertising_address = public_address;
1110         break;
1111 
1112       case OwnAddressType::RANDOM_DEVICE_ADDRESS:
1113         // If the advertising set's Own_Address_Type parameter is set to 0x01
1114         // and the random address for the advertising set has not been
1115         // initialized using the HCI_LE_Set_Advertising_Set_Random_Address
1116         // command, the Controller shall return the error code
1117         // Invalid HCI Command Parameters (0x12).
1118         if (random_address.GetAddress() == Address::kEmpty) {
1119           INFO(
1120               id_,
1121               "own_address_type is Random_Device_Address but the Random_Address"
1122               " has not been initialized");
1123           return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1124         }
1125         advertiser.advertising_address = random_address;
1126         break;
1127 
1128       case OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS:
1129         advertiser.advertising_address =
1130             resolvable_address.value_or(public_address);
1131         break;
1132 
1133       case OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS:
1134         // If the advertising set's Own_Address_Type parameter is set to 0x03,
1135         // the controller's resolving list did not contain a matching entry,
1136         // and the random address for the advertising set has not been
1137         // initialized using the HCI_LE_Set_Advertising_Set_Random_Address
1138         // command, the Controller shall return the error code
1139         // Invalid HCI Command Parameters (0x12).
1140         if (resolvable_address) {
1141           advertiser.advertising_address = resolvable_address.value();
1142         } else if (random_address.GetAddress() == Address::kEmpty) {
1143           INFO(id_,
1144                "own_address_type is Resolvable_Or_Random_Address but the"
1145                " Resolving_List does not contain a matching entry and the"
1146                " Random_Address is not initialized");
1147           return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1148         } else {
1149           advertiser.advertising_address = random_address;
1150         }
1151         break;
1152     }
1153 
1154     // If an IRK is available in the Link Layer Resolving List for the peer
1155     // device, then the target’s device address (TargetA field) shall
1156     // use a resolvable private address. If an IRK is not available in the
1157     // Link Layer Resolving List or the IRK is set to zero for the peer device,
1158     // then the target’s device address (TargetA field) shall use the Identity
1159     // Address when entering the Advertising State and using connectable
1160     // directed events.
1161     if (advertiser.IsDirected()) {
1162       advertiser.target_address =
1163           GenerateResolvablePrivateAddress(peer_address, IrkSelection::Peer)
1164               .value_or(peer_address);
1165     }
1166   }
1167 
1168   for (auto& set : sets) {
1169     ExtendedAdvertiser& advertiser =
1170         extended_advertisers_[set.advertising_handle_];
1171 
1172     advertiser.max_extended_advertising_events =
1173         set.max_extended_advertising_events_;
1174     advertiser.num_completed_extended_advertising_events = 0;
1175     advertiser.Enable();
1176     if (set.duration_ > 0) {
1177       std::chrono::milliseconds duration =
1178           std::chrono::milliseconds(set.duration_ * 10);
1179       advertiser.timeout = std::chrono::steady_clock::now() + duration;
1180     } else {
1181       advertiser.timeout.reset();
1182     }
1183   }
1184 
1185   return ErrorCode::SUCCESS;
1186 }
1187 
1188 // HCI command LE_Remove_Advertising_Set (Vol 4, Part E § 7.8.59).
LeRemoveAdvertisingSet(uint8_t advertising_handle)1189 ErrorCode LinkLayerController::LeRemoveAdvertisingSet(
1190     uint8_t advertising_handle) {
1191   // If the advertising set corresponding to the Advertising_Handle parameter
1192   // does not exist, then the Controller shall return the error code
1193   // Unknown Advertising Identifier (0x42).
1194   auto advertiser = extended_advertisers_.find(advertising_handle);
1195   if (advertiser == extended_advertisers_.end()) {
1196     INFO(id_, "no advertising set defined with handle {:02x}",
1197          static_cast<int>(advertising_handle));
1198     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
1199   }
1200 
1201   // If advertising or periodic advertising on the advertising set is
1202   // enabled, then the Controller shall return the error code
1203   // Command Disallowed (0x0C).
1204   if (advertiser->second.advertising_enable) {
1205     INFO(id_, "the advertising set defined with handle {:02x} is enabled",
1206          static_cast<int>(advertising_handle));
1207     return ErrorCode::COMMAND_DISALLOWED;
1208   }
1209 
1210   extended_advertisers_.erase(advertiser);
1211   return ErrorCode::SUCCESS;
1212 }
1213 
1214 // HCI command LE_Clear_Advertising_Sets (Vol 4, Part E § 7.8.60).
LeClearAdvertisingSets()1215 ErrorCode LinkLayerController::LeClearAdvertisingSets() {
1216   // If advertising or periodic advertising is enabled on any advertising set,
1217   // then the Controller shall return the error code Command Disallowed (0x0C).
1218   for (auto& advertiser : extended_advertisers_) {
1219     if (advertiser.second.advertising_enable) {
1220       INFO(id_, "the advertising set with handle {:02x} is enabled",
1221            static_cast<int>(advertiser.second.advertising_enable));
1222       return ErrorCode::COMMAND_DISALLOWED;
1223     }
1224   }
1225 
1226   extended_advertisers_.clear();
1227   return ErrorCode::SUCCESS;
1228 }
1229 
GetMaxAdvertisingDataLength(const AdvertisingEventProperties & properties)1230 uint16_t ExtendedAdvertiser::GetMaxAdvertisingDataLength(
1231     const AdvertisingEventProperties& properties) {
1232   // The PDU AdvData size is defined in the following sections:
1233   // - Vol 6, Part B § 2.3.1.1 ADV_IND
1234   // - Vol 6, Part B § 2.3.1.2 ADV_DIRECT_IND
1235   // - Vol 6, Part B § 2.3.1.3 ADV_NONCONN_IND
1236   // - Vol 6, Part B § 2.3.1.4 ADV_SCAN_IND
1237   // - Vol 6, Part B § 2.3.1.5 ADV_EXT_IND
1238   // - Vol 6, Part B § 2.3.1.6 AUX_ADV_IND
1239   // - Vol 6, Part B § 2.3.1.8 AUX_CHAIN_IND
1240   // - Vol 6, Part B § 2.3.4 Common Extended Advertising Payload Format
1241   uint16_t max_advertising_data_length;
1242 
1243   if (properties.legacy_ && properties.directed_) {
1244     // Directed legacy advertising PDUs do not have AdvData payload.
1245     max_advertising_data_length = 0;
1246   } else if (properties.legacy_) {
1247     max_advertising_data_length = max_legacy_advertising_pdu_size;
1248   } else if (properties.scannable_) {
1249     // Scannable extended advertising PDUs do not have AdvData payload.
1250     max_advertising_data_length = 0;
1251   } else if (!properties.connectable_) {
1252     // When extended advertising is non-scannable and non-connectable,
1253     // AUX_CHAIN_IND PDUs can be used, and the advertising data may be
1254     // fragmented over multiple PDUs; the length is still capped at 1650
1255     // as stated in Vol 6, Part B § 2.3.4.9 Host Advertising Data.
1256     max_advertising_data_length = max_extended_advertising_pdu_size;
1257   } else {
1258     // When extended advertising is either scannable or connectable,
1259     // AUX_CHAIN_IND PDUs may not be used, and the maximum advertising data
1260     // length is 254. Extended payload header fields eat into the
1261     // available space.
1262     max_advertising_data_length = 254;
1263     max_advertising_data_length -= 6;                         // AdvA
1264     max_advertising_data_length -= 2;                         // ADI
1265     max_advertising_data_length -= 6 * properties.directed_;  // TargetA
1266     max_advertising_data_length -= 1 * properties.tx_power_;  // TxPower
1267     // TODO(pedantic): configure the ACAD field in order to leave the least
1268     // amount of AdvData space to the user (191).
1269   }
1270 
1271   return max_advertising_data_length;
1272 }
1273 
GetMaxScanResponseDataLength(const AdvertisingEventProperties & properties)1274 uint16_t ExtendedAdvertiser::GetMaxScanResponseDataLength(
1275     const AdvertisingEventProperties& properties) {
1276   // The PDU AdvData size is defined in the following sections:
1277   // - Vol 6, Part B § 2.3.2.2 SCAN_RSP
1278   // - Vol 6, Part B § 2.3.2.3 AUX_SCAN_RSP
1279   // - Vol 6, Part B § 2.3.1.8 AUX_CHAIN_IND
1280   // - Vol 6, Part B § 2.3.4 Common Extended Advertising Payload Format
1281   uint16_t max_scan_response_data_length;
1282 
1283   if (!properties.scannable_) {
1284     max_scan_response_data_length = 0;
1285   } else if (properties.legacy_) {
1286     max_scan_response_data_length = max_legacy_advertising_pdu_size;
1287   } else {
1288     // Extended scan response data may be sent over AUX_CHAIN_PDUs, and
1289     // the advertising data may be fragmented over multiple PDUs; the length
1290     // is still capped at 1650 as stated in
1291     // Vol 6, Part B § 2.3.4.9 Host Advertising Data.
1292     max_scan_response_data_length = max_extended_advertising_pdu_size;
1293   }
1294 
1295   return max_scan_response_data_length;
1296 }
1297 
GetRawAdvertisingEventProperties(const AdvertisingEventProperties & properties)1298 uint16_t ExtendedAdvertiser::GetRawAdvertisingEventProperties(
1299     const AdvertisingEventProperties& properties) {
1300   uint16_t mask = 0;
1301   if (properties.connectable_) {
1302     mask |= 0x1;
1303   }
1304   if (properties.scannable_) {
1305     mask |= 0x2;
1306   }
1307   if (properties.directed_) {
1308     mask |= 0x4;
1309   }
1310   if (properties.high_duty_cycle_) {
1311     mask |= 0x8;
1312   }
1313   if (properties.legacy_) {
1314     mask |= 0x10;
1315   }
1316   if (properties.anonymous_) {
1317     mask |= 0x20;
1318   }
1319   if (properties.tx_power_) {
1320     mask |= 0x40;
1321   }
1322   return mask;
1323 }
1324 
1325 // =============================================================================
1326 //  Periodic Advertising Commands
1327 // =============================================================================
1328 
1329 // HCI LE Set Periodic Advertising Parameters command (Vol 4, Part E § 7.8.61).
LeSetPeriodicAdvertisingParameters(uint8_t advertising_handle,uint16_t periodic_advertising_interval_min,uint16_t periodic_advertising_interval_max,bool)1330 ErrorCode LinkLayerController::LeSetPeriodicAdvertisingParameters(
1331     uint8_t advertising_handle, uint16_t periodic_advertising_interval_min,
1332     uint16_t periodic_advertising_interval_max, bool /*include_tx_power*/) {
1333   // The Advertising_Handle parameter identifies the advertising set whose
1334   // periodic advertising parameters are being configured. If the corresponding
1335   // advertising set does not already exist, then the Controller shall return
1336   // the error code Unknown Advertising Identifier (0x42).
1337   // TODO(c++20) unordered_map<>::contains
1338   if (extended_advertisers_.count(advertising_handle) == 0) {
1339     INFO(id_, "no advertising set defined with handle {:02x}",
1340          static_cast<int>(advertising_handle));
1341     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
1342   }
1343 
1344   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
1345 
1346   // The Periodic_Advertising_Interval_Min parameter shall be less than or
1347   // equal to the Periodic_Advertising_Interval_Max parameter.
1348   if (periodic_advertising_interval_min < 0x6 ||
1349       periodic_advertising_interval_max < 0x6 ||
1350       periodic_advertising_interval_max < periodic_advertising_interval_min) {
1351     INFO(id_, "invalid periodic advertising interval range {:04x} - {:04x}",
1352          periodic_advertising_interval_min, periodic_advertising_interval_max);
1353     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1354   }
1355 
1356   // If the advertising set identified by the Advertising_Handle specified
1357   // scannable, connectable, legacy, or anonymous advertising, the Controller
1358   // shall return the error code Invalid HCI Command Parameters (0x12).
1359   if (advertiser.advertising_event_properties.connectable_ ||
1360       advertiser.advertising_event_properties.scannable_ ||
1361       advertiser.advertising_event_properties.legacy_ ||
1362       advertiser.advertising_event_properties.anonymous_) {
1363     INFO(id_,
1364          "the periodic advertising set {:02x} specifies scannable,"
1365          " connectable, legacy or anonymous advertising",
1366          static_cast<int>(advertising_handle));
1367     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1368   }
1369 
1370   // If the Host issues this command when periodic advertising is enabled for
1371   // the specified advertising set, the Controller shall return the error code
1372   // Command Disallowed (0x0C).
1373   if (advertiser.periodic_advertising_enable) {
1374     INFO(id_, "periodic advertising is enabled for the set {:02x}",
1375          static_cast<int>(advertising_handle));
1376     return ErrorCode::COMMAND_DISALLOWED;
1377   }
1378 
1379   // If the Advertising_Handle does not identify an advertising set that is
1380   // already configured for periodic advertising and the Controller is unable
1381   // to support more periodic advertising at present, the Controller shall
1382   // return the error code Memory Capacity Exceeded (0x07)
1383   // TODO: add controller configuration for maximum number of periodic
1384   // advertising sets.
1385 
1386   // If the advertising set already contains periodic advertising data and the
1387   // length of the data is greater than the maximum that the Controller can
1388   // transmit within a periodic advertising interval of
1389   // Periodic_Advertising_Interval_Max, the Controller shall return the error
1390   // code Packet Too Long (0x45).
1391   if (advertiser.periodic_advertising_data.size() >
1392       ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength(
1393           slots(periodic_advertising_interval_max))) {
1394     INFO(id_,
1395          "the length of the periodic advertising data exceeds the maximum"
1396          " that the controller can transmit within the maximum periodic"
1397          " advertising interval");
1398     return ErrorCode::PACKET_TOO_LONG;
1399   }
1400 
1401   advertiser.periodic_advertising_interval =
1402       slots(periodic_advertising_interval_max);
1403   return ErrorCode::SUCCESS;
1404 }
1405 
1406 // HCI LE Set Periodic Advertising Data command (Vol 4, Part E § 7.8.62).
LeSetPeriodicAdvertisingData(uint8_t advertising_handle,bluetooth::hci::Operation operation,const std::vector<uint8_t> & advertising_data)1407 ErrorCode LinkLayerController::LeSetPeriodicAdvertisingData(
1408     uint8_t advertising_handle, bluetooth::hci::Operation operation,
1409     const std::vector<uint8_t>& advertising_data) {
1410   // If the advertising set corresponding to the Advertising_Handle parameter
1411   // does not exist, then the Controller shall return the error code
1412   // Unknown Advertising Identifier (0x42).
1413   // TODO(c++20) unordered_map<>::contains
1414   if (extended_advertisers_.count(advertising_handle) == 0) {
1415     INFO(id_, "no advertising set defined with handle {:02x}",
1416          static_cast<int>(advertising_handle));
1417     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
1418   }
1419 
1420   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
1421 
1422   // If the advertising set has not been configured for periodic advertising,
1423   // then the Controller shall return the error code Command Disallowed (0x0C).
1424   if (advertiser.periodic_advertising_interval.count() == 0) {
1425     INFO(id_, "periodic advertising is not configured for the set {:02x}",
1426          static_cast<int>(advertising_handle));
1427     return ErrorCode::COMMAND_DISALLOWED;
1428   }
1429 
1430   // If periodic advertising is currently enabled for the specified advertising
1431   // set and Operation does not have the value 0x03 or 0x04, then the Controller
1432   // shall return the error code Command Disallowed (0x0C).
1433   if (advertiser.periodic_advertising_enable &&
1434       operation != Operation::COMPLETE_ADVERTISEMENT &&
1435       operation != Operation::UNCHANGED_DATA) {
1436     INFO(id_,
1437          "periodic advertising is enabled and the operation is not"
1438          " Complete_Advertisement or Unchanged_Data");
1439     return ErrorCode::COMMAND_DISALLOWED;
1440   }
1441 
1442   // If Operation is not 0x03 or 0x04 and Advertising_Data_Length is zero,
1443   // then the Controller shall return the error code
1444   // Invalid HCI Command Parameters (0x12).
1445   if (advertising_data.empty() &&
1446       operation != Operation::COMPLETE_ADVERTISEMENT &&
1447       operation != Operation::UNCHANGED_DATA) {
1448     INFO(id_,
1449          "periodic advertising data is empty is enabled and the operation"
1450          " is not Complete_Advertisement or Unchanged_Data");
1451     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1452   }
1453 
1454   // If Operation is 0x04 and:
1455   // • periodic advertising is currently disabled for the advertising set;
1456   // • the periodic advertising set contains no data; or
1457   // • Advertising_Data_Length is not zero;
1458   // then the Controller shall return the error code
1459   // Invalid HCI Command Parameters (0x12).
1460   if (operation == Operation::UNCHANGED_DATA &&
1461       (!advertiser.periodic_advertising_enable ||
1462        advertiser.periodic_advertising_data.empty() ||
1463        !advertising_data.empty())) {
1464     INFO(
1465         id_,
1466         "Unchanged_Data operation is used but periodic advertising is disabled;"
1467         " or the periodic advertising set contains no data;"
1468         " or the advertising data is not empty");
1469     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1470   }
1471 
1472   switch (operation) {
1473     case Operation::INTERMEDIATE_FRAGMENT:
1474       advertiser.periodic_advertising_data.insert(
1475           advertiser.periodic_advertising_data.end(), advertising_data.begin(),
1476           advertising_data.end());
1477       advertiser.partial_periodic_advertising_data = true;
1478       break;
1479 
1480     case Operation::FIRST_FRAGMENT:
1481       advertiser.periodic_advertising_data = advertising_data;
1482       advertiser.partial_periodic_advertising_data = true;
1483       break;
1484 
1485     case Operation::LAST_FRAGMENT:
1486       advertiser.periodic_advertising_data.insert(
1487           advertiser.periodic_advertising_data.end(), advertising_data.begin(),
1488           advertising_data.end());
1489       advertiser.partial_periodic_advertising_data = false;
1490       break;
1491 
1492     case Operation::COMPLETE_ADVERTISEMENT:
1493       advertiser.periodic_advertising_data = advertising_data;
1494       advertiser.partial_periodic_advertising_data = false;
1495       break;
1496 
1497     case Operation::UNCHANGED_DATA:
1498       break;
1499 
1500     default:
1501       INFO(id_, "unknown operation ({})", static_cast<int>(operation));
1502       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1503   }
1504 
1505   // If the combined length of the data exceeds the capacity of the advertising
1506   // set identified by the Advertising_Handle parameter or the amount of memory
1507   // currently available, all the data shall be discarded and the Controller
1508   // shall return the error code Memory Capacity Exceeded (0x07).
1509   if (advertiser.periodic_advertising_data.size() >
1510       properties_.le_max_advertising_data_length) {
1511     INFO(id_,
1512          "the length of the combined periodic advertising data exceeds"
1513          " the maximum advertising data length");
1514     advertiser.periodic_advertising_data.clear();
1515     advertiser.partial_periodic_advertising_data = false;
1516     return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
1517   }
1518 
1519   // If the combined length of the data is greater than the maximum that the
1520   // Controller can transmit within the current periodic advertising interval
1521   // for the advertising set, all the data shall be discarded and the
1522   // Controller shall return the error code Packet Too Long (0x45).
1523   if (advertiser.periodic_advertising_data.size() >
1524       ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength(
1525           advertiser.periodic_advertising_interval)) {
1526     INFO(id_,
1527          "the length of the combined periodic advertising data exceeds"
1528          " the maximum that the controller can transmit within the current"
1529          " periodic advertising interval");
1530     advertiser.periodic_advertising_data.clear();
1531     advertiser.partial_periodic_advertising_data = false;
1532     return ErrorCode::PACKET_TOO_LONG;
1533   }
1534 
1535   return ErrorCode::SUCCESS;
1536 }
1537 
1538 // HCI LE Set Periodic Advertising Enable command (Vol 4, Part E § 7.8.63).
LeSetPeriodicAdvertisingEnable(bool enable,bool include_adi,uint8_t advertising_handle)1539 ErrorCode LinkLayerController::LeSetPeriodicAdvertisingEnable(
1540     bool enable, bool include_adi, uint8_t advertising_handle) {
1541   // If the advertising set corresponding to the Advertising_Handle parameter
1542   // does not exist, the Controller shall return the error code Unknown
1543   // Advertising Identifier (0x42).
1544   // TODO(c++20) unordered_map<>::contains
1545   if (extended_advertisers_.count(advertising_handle) == 0) {
1546     INFO(id_, "no advertising set defined with handle {:02x}",
1547          static_cast<int>(advertising_handle));
1548     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
1549   }
1550 
1551   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
1552 
1553   if (!enable) {
1554     advertiser.DisablePeriodic();
1555     return ErrorCode::SUCCESS;
1556   }
1557 
1558   // If bit 0 of Enable is set to 1 (periodic advertising is enabled) and the
1559   // advertising set contains partial periodic advertising data, the Controller
1560   // shall return the error code Command Disallowed (0x0C).
1561   if (advertiser.partial_periodic_advertising_data) {
1562     INFO(id_, "the advertising set contains partial periodic advertising data");
1563     return ErrorCode::COMMAND_DISALLOWED;
1564   }
1565 
1566   // If bit 0 of Enable is set to 1 and the Host has not issued the
1567   // HCI_LE_Set_Periodic_Advertising_Parameters command for the advertising set,
1568   // the Controller shall either use vendor-specified parameters or return the
1569   // error code Command Disallowed (0x0C).
1570   if (advertiser.periodic_advertising_interval.count() == 0) {
1571     INFO(id_, "periodic advertising is not configured for the set {:02x}",
1572          static_cast<int>(advertising_handle));
1573     return ErrorCode::COMMAND_DISALLOWED;
1574   }
1575 
1576   // If bit 0 of Enable is set to 1 and the length of the periodic advertising
1577   // data is greater than the maximum that the Controller can transmit within
1578   // the chosen periodic advertising interval, the Controller shall return the
1579   // error code Packet Too Long (0x45).
1580   if (advertiser.periodic_advertising_data.size() >
1581       ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength(
1582           advertiser.periodic_advertising_interval)) {
1583     INFO(id_,
1584          "the length of the combined periodic advertising data exceeds"
1585          " the maximum that the controller can transmit within the current"
1586          " periodic advertising interval");
1587     return ErrorCode::PACKET_TOO_LONG;
1588   }
1589 
1590   // If bit 0 of Enable is set to 1 and the advertising set identified by the
1591   // Advertising_Handle specified scannable, connectable, legacy, or anonymous
1592   // advertising, the Controller shall return the error code
1593   // Command Disallowed (0x0C).
1594   if (advertiser.advertising_event_properties.connectable_ ||
1595       advertiser.advertising_event_properties.scannable_ ||
1596       advertiser.advertising_event_properties.legacy_ ||
1597       advertiser.advertising_event_properties.anonymous_) {
1598     INFO(id_,
1599          "the periodic advertising set {:02x} specifies scannable,"
1600          " connectable, legacy or anonymous advertising",
1601          static_cast<int>(advertising_handle));
1602     return ErrorCode::COMMAND_DISALLOWED;
1603   }
1604 
1605   // If bit 1 of Enable is set to 1 and the Controller does not support the
1606   // Periodic Advertising ADI Support feature, the Controller shall return an
1607   // error which should use the error code Unsupported Feature or
1608   // Parameter Value (0x11).
1609   if (include_adi && !properties_.SupportsLLFeature(
1610                          LLFeaturesBits::PERIODIC_ADVERTISING_ADI_SUPPORT)) {
1611     INFO(id_,
1612          "include ADI is true but the controller does not support the"
1613          " Periodic Advertising ADI Supported feature",
1614          static_cast<int>(advertising_handle));
1615     return ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
1616   }
1617 
1618   advertiser.EnablePeriodic();
1619   return ErrorCode::SUCCESS;
1620 }
1621 
GetMaxPeriodicAdvertisingDataLength(slots)1622 uint16_t ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength(
1623     slots /*periodic_advertising_interval*/) {
1624   // TODO: evaluate the maximum length of the advertising PDU that can
1625   // be physically sent in the advertising interval.
1626   return max_extended_advertising_pdu_size;
1627 }
1628 
1629 // =============================================================================
1630 //  Advertising Routines
1631 // =============================================================================
1632 
LeAdvertising()1633 void LinkLayerController::LeAdvertising() {
1634   chrono::time_point now = std::chrono::steady_clock::now();
1635 
1636   // Legacy Advertising Timeout
1637 
1638   // Generate HCI Connection Complete or Enhanced HCI Connection Complete
1639   // events with Advertising Timeout error code when the advertising
1640   // type is ADV_DIRECT_IND and the connection failed to be established.
1641   if (legacy_advertiser_.IsEnabled() && legacy_advertiser_.timeout &&
1642       now >= legacy_advertiser_.timeout.value()) {
1643     // If the Advertising_Type parameter is 0x01 (ADV_DIRECT_IND, high duty
1644     // cycle) and the directed advertising fails to create a connection, an
1645     // HCI_LE_Connection_Complete or HCI_LE_Enhanced_Connection_Complete
1646     // event shall be generated with the Status code set to
1647     // Advertising Timeout (0x3C).
1648     INFO(id_, "Directed Advertising Timeout");
1649     legacy_advertiser_.Disable();
1650 
1651     // TODO: The PTS tool expects an LE_Connection_Complete event in this
1652     // case and will fail the test GAP/DISC/GENP/BV-05-C if
1653     // LE_Enhanced_Connection_Complete is sent instead.
1654     //
1655     // Note: HCI_LE_Connection_Complete is not sent if the
1656     // HCI_LE_Enhanced_Connection_Complete event (see Section 7.7.65.10)
1657     // is unmasked.
1658 #if 0
1659     if (IsLeEventUnmasked(SubeventCode::ENHANCED_CONNECTION_COMPLETE)) {
1660       send_event_(bluetooth::hci::LeEnhancedConnectionCompleteBuilder::Create(
1661           ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1662           AddressType::PUBLIC_DEVICE_ADDRESS, Address(), Address(), Address(),
1663           0, 0, 0, ClockAccuracy::PPM_500));
1664     } else
1665 #endif
1666     if (IsLeEventUnmasked(SubeventCode::CONNECTION_COMPLETE)) {
1667       send_event_(bluetooth::hci::LeConnectionCompleteBuilder::Create(
1668           ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1669           AddressType::PUBLIC_DEVICE_ADDRESS, Address(), 0, 0, 0,
1670           ClockAccuracy::PPM_500));
1671     }
1672   }
1673 
1674   // Legacy Advertising Event
1675 
1676   // Generate Link Layer Advertising events when advertising is enabled
1677   // and a full interval has passed since the last event.
1678   if (legacy_advertiser_.IsEnabled() && now >= legacy_advertiser_.next_event) {
1679     legacy_advertiser_.next_event =
1680         now + legacy_advertiser_.advertising_interval;
1681     model::packets::LegacyAdvertisingType type;
1682     bool attach_advertising_data = true;
1683     switch (legacy_advertiser_.advertising_type) {
1684       case AdvertisingType::ADV_IND:
1685         type = model::packets::LegacyAdvertisingType::ADV_IND;
1686         break;
1687       case AdvertisingType::ADV_DIRECT_IND_HIGH:
1688       case AdvertisingType::ADV_DIRECT_IND_LOW:
1689         attach_advertising_data = false;
1690         type = model::packets::LegacyAdvertisingType::ADV_DIRECT_IND;
1691         break;
1692       case AdvertisingType::ADV_SCAN_IND:
1693         type = model::packets::LegacyAdvertisingType::ADV_SCAN_IND;
1694         break;
1695       case AdvertisingType::ADV_NONCONN_IND:
1696         type = model::packets::LegacyAdvertisingType::ADV_NONCONN_IND;
1697         break;
1698     }
1699 
1700     SendLeLinkLayerPacket(
1701         model::packets::LeLegacyAdvertisingPduBuilder::Create(
1702             legacy_advertiser_.advertising_address.GetAddress(),
1703             legacy_advertiser_.target_address.GetAddress(),
1704             static_cast<model::packets::AddressType>(
1705                 legacy_advertiser_.advertising_address.GetAddressType()),
1706             static_cast<model::packets::AddressType>(
1707                 legacy_advertiser_.target_address.GetAddressType()),
1708             type,
1709             attach_advertising_data ? legacy_advertiser_.advertising_data
1710                                     : std::vector<uint8_t>{}),
1711         properties_.le_advertising_physical_channel_tx_power);
1712   }
1713 
1714   for (auto& [_, advertiser] : extended_advertisers_) {
1715     // Extended Advertising Timeouts
1716 
1717     if (advertiser.IsEnabled() && advertiser.timeout.has_value() &&
1718         now >= advertiser.timeout.value()) {
1719       // If the Duration[i] parameter is set to a value other than 0x0000, an
1720       // HCI_LE_Advertising_Set_Terminated event shall be generated when the
1721       // duration specified in the Duration[i] parameter expires.
1722       // However, if the advertising set is for high duty cycle connectable
1723       // directed advertising and no connection is created before the duration
1724       // expires, an HCI_LE_Connection_Complete or
1725       // HCI_LE_Enhanced_Connection_Complete event with the Status parameter
1726       // set to the error code Advertising Timeout (0x3C) may be generated
1727       // instead of or in addition to the HCI_LE_Advertising_Set_Terminated
1728       // event.
1729       INFO(id_, "Extended Advertising Timeout");
1730       advertiser.Disable();
1731 
1732       bool high_duty_cycle_connectable_directed_advertising =
1733           advertiser.advertising_event_properties.directed_ &&
1734           advertiser.advertising_event_properties.connectable_ &&
1735           advertiser.advertising_event_properties.high_duty_cycle_;
1736 
1737       // Note: HCI_LE_Connection_Complete is not sent if the
1738       // HCI_LE_Enhanced_Connection_Complete event (see Section 7.7.65.10)
1739       // is unmasked.
1740       if (high_duty_cycle_connectable_directed_advertising &&
1741           IsLeEventUnmasked(SubeventCode::ENHANCED_CONNECTION_COMPLETE)) {
1742         send_event_(bluetooth::hci::LeEnhancedConnectionCompleteBuilder::Create(
1743             ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1744             AddressType::PUBLIC_DEVICE_ADDRESS, Address(), Address(), Address(),
1745             0, 0, 0, ClockAccuracy::PPM_500));
1746       } else if (high_duty_cycle_connectable_directed_advertising &&
1747                  IsLeEventUnmasked(SubeventCode::CONNECTION_COMPLETE)) {
1748         send_event_(bluetooth::hci::LeConnectionCompleteBuilder::Create(
1749             ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1750             AddressType::PUBLIC_DEVICE_ADDRESS, Address(), 0, 0, 0,
1751             ClockAccuracy::PPM_500));
1752       }
1753 
1754       if (IsLeEventUnmasked(SubeventCode::ADVERTISING_SET_TERMINATED)) {
1755         // The parameter Num_Completed_Extended_Advertising_Events is set
1756         // only when Max_Extended_Advertising_Events was configured as
1757         // non-zero in the advertising parameters.
1758         uint8_t num_completed_extended_advertising_events =
1759             advertiser.max_extended_advertising_events != 0
1760                 ? advertiser.num_completed_extended_advertising_events
1761                 : 0;
1762         send_event_(bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
1763             ErrorCode::ADVERTISING_TIMEOUT, advertiser.advertising_handle, 0,
1764             num_completed_extended_advertising_events));
1765       }
1766     }
1767 
1768     if (advertiser.IsEnabled() && advertiser.max_extended_advertising_events &&
1769         advertiser.num_completed_extended_advertising_events >=
1770             advertiser.max_extended_advertising_events) {
1771       // If the Max_Extended_Advertising_Events[i] parameter is set to a value
1772       // other than 0x00, an HCI_LE_Advertising_Set_Terminated event shall be
1773       // generated when the maximum number of extended advertising events has
1774       // been transmitted by the Controller.
1775       INFO(id_, "Max Extended Advertising count reached");
1776       advertiser.Disable();
1777 
1778       if (IsLeEventUnmasked(SubeventCode::ADVERTISING_SET_TERMINATED)) {
1779         send_event_(bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
1780             ErrorCode::ADVERTISING_TIMEOUT, advertiser.advertising_handle, 0,
1781             advertiser.num_completed_extended_advertising_events));
1782       }
1783     }
1784 
1785     // Extended Advertising Event
1786 
1787     // Generate Link Layer Advertising events when advertising is enabled
1788     // and a full interval has passed since the last event.
1789     if (advertiser.IsEnabled() && now >= advertiser.next_event) {
1790       advertiser.next_event += advertiser.primary_advertising_interval;
1791       advertiser.num_completed_extended_advertising_events++;
1792 
1793       if (advertiser.advertising_event_properties.legacy_) {
1794         model::packets::LegacyAdvertisingType type;
1795         uint16_t raw_advertising_event_properties =
1796             ExtendedAdvertiser::GetRawAdvertisingEventProperties(
1797                 advertiser.advertising_event_properties);
1798         switch (static_cast<LegacyAdvertisingEventProperties>(
1799             raw_advertising_event_properties & 0xf)) {
1800           case LegacyAdvertisingEventProperties::ADV_IND:
1801             type = model::packets::LegacyAdvertisingType::ADV_IND;
1802             break;
1803           case LegacyAdvertisingEventProperties::ADV_DIRECT_IND_HIGH:
1804           case LegacyAdvertisingEventProperties::ADV_DIRECT_IND_LOW:
1805             type = model::packets::LegacyAdvertisingType::ADV_DIRECT_IND;
1806             break;
1807           case LegacyAdvertisingEventProperties::ADV_SCAN_IND:
1808             type = model::packets::LegacyAdvertisingType::ADV_SCAN_IND;
1809             break;
1810           case LegacyAdvertisingEventProperties::ADV_NONCONN_IND:
1811             type = model::packets::LegacyAdvertisingType::ADV_NONCONN_IND;
1812             break;
1813           default:
1814             FATAL(
1815                 id_,
1816                 "unexpected raw advertising event properties;"
1817                 " please check the extended advertising parameter validation");
1818             break;
1819         }
1820 
1821         SendLeLinkLayerPacket(
1822             model::packets::LeLegacyAdvertisingPduBuilder::Create(
1823                 advertiser.advertising_address.GetAddress(),
1824                 advertiser.target_address.GetAddress(),
1825                 static_cast<model::packets::AddressType>(
1826                     advertiser.advertising_address.GetAddressType()),
1827                 static_cast<model::packets::AddressType>(
1828                     advertiser.target_address.GetAddressType()),
1829                 type, advertiser.advertising_data),
1830             advertiser.advertising_tx_power);
1831       } else {
1832         SendLeLinkLayerPacket(
1833             model::packets::LeExtendedAdvertisingPduBuilder::Create(
1834                 advertiser.advertising_address.GetAddress(),
1835                 advertiser.target_address.GetAddress(),
1836                 static_cast<model::packets::AddressType>(
1837                     advertiser.advertising_address.GetAddressType()),
1838                 static_cast<model::packets::AddressType>(
1839                     advertiser.target_address.GetAddressType()),
1840                 advertiser.advertising_event_properties.connectable_,
1841                 advertiser.advertising_event_properties.scannable_,
1842                 advertiser.advertising_event_properties.directed_,
1843                 advertiser.advertising_sid, advertiser.advertising_tx_power,
1844                 static_cast<model::packets::PhyType>(
1845                     advertiser.primary_advertising_phy),
1846                 static_cast<model::packets::PhyType>(
1847                     advertiser.secondary_advertising_phy),
1848                 advertiser.periodic_advertising_interval.count(),
1849                 advertiser.advertising_data),
1850             advertiser.advertising_tx_power);
1851       }
1852     }
1853 
1854     // Periodic Advertising Event
1855 
1856     // Generate Link Layer Advertising events when advertising is enabled
1857     // and a full interval has passed since the last event.
1858     if (advertiser.IsPeriodicEnabled() &&
1859         now >= advertiser.next_periodic_event) {
1860       advertiser.next_periodic_event +=
1861           advertiser.periodic_advertising_interval;
1862       SendLeLinkLayerPacket(
1863           model::packets::LePeriodicAdvertisingPduBuilder::Create(
1864               advertiser.advertising_address.GetAddress(), Address(),
1865               static_cast<model::packets::AddressType>(
1866                   advertiser.advertising_address.GetAddressType()),
1867               advertiser.advertising_sid, advertiser.advertising_tx_power,
1868               advertiser.periodic_advertising_interval.count(),
1869               advertiser.periodic_advertising_data),
1870           advertiser.advertising_tx_power);
1871     }
1872   }
1873 }
1874 
1875 }  // namespace rootcanal
1876