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