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