• 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_.advertising_enable = false;
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.size() > 0) {
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.size() > 0) {
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 (advertiser.periodic_advertising_enable && false) {
536     // TODO
537     LOG_INFO(
538         "periodic advertising is enabled for the specified advertising set"
539         " and the secondary PHY does not match the periodic"
540         " advertising PHY");
541     return ErrorCode::COMMAND_DISALLOWED;
542   }
543 
544   // If the advertising set already contains advertising data or scan response
545   // data, extended advertising is being used, and the length of the data is
546   // greater than the maximum that the Controller can transmit within the
547   // longest possible auxiliary advertising segment consistent with the
548   // parameters, the Controller shall return the error code
549   // Packet Too Long (0x45). If advertising on the LE Coded PHY, the S=8
550   // coding shall be assumed.
551   if (extended_advertising &&
552       (advertiser.advertising_data.size() > max_extended_advertising_pdu_size ||
553        advertiser.scan_response_data.size() >
554            max_extended_advertising_pdu_size)) {
555     LOG_INFO(
556         "the advertising data contained in the set is larger than the"
557         " available PDU capacity");
558     return ErrorCode::PACKET_TOO_LONG;
559   }
560 
561   advertiser.advertising_event_properties = advertising_event_properties;
562   advertiser.primary_advertising_interval =
563       slots(primary_advertising_interval_min);
564   advertiser.primary_advertising_channel_map = primary_advertising_channel_map;
565   advertiser.own_address_type = own_address_type;
566   advertiser.peer_address_type = peer_address_type;
567   advertiser.peer_address = peer_address;
568   advertiser.advertising_filter_policy = advertising_filter_policy;
569   advertiser.advertising_tx_power = advertising_tx_power;
570   advertiser.primary_advertising_phy = primary_advertising_phy;
571   advertiser.secondary_max_skip = secondary_max_skip;
572   advertiser.secondary_advertising_phy = secondary_advertising_phy;
573   advertiser.advertising_sid = advertising_sid;
574   advertiser.scan_request_notification_enable =
575       scan_request_notification_enable;
576 
577   extended_advertisers_.insert_or_assign(advertising_handle,
578                                          std::move(advertiser));
579   return ErrorCode::SUCCESS;
580 }
581 
582 // 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)583 ErrorCode LinkLayerController::LeSetExtendedAdvertisingData(
584     uint8_t advertising_handle, Operation operation,
585     FragmentPreference fragment_preference,
586     const std::vector<uint8_t>& advertising_data) {
587   // Extended advertising commands are disallowed when legacy advertising
588   // commands were used since the last reset.
589   if (!SelectExtendedAdvertising()) {
590     LOG_INFO(
591         "extended advertising command rejected because legacy advertising"
592         " is being used");
593     return ErrorCode::COMMAND_DISALLOWED;
594   }
595 
596   // fragment_preference is unused for now.
597   (void)fragment_preference;
598 
599   // If the advertising set corresponding to the Advertising_Handle parameter
600   // does not exist, then the Controller shall return the error code
601   // Unknown Advertising Identifier (0x42).
602   // TODO(c++20) unordered_map<>::contains
603   if (extended_advertisers_.count(advertising_handle) == 0) {
604     LOG_INFO("no advertising set defined with handle %02x",
605              static_cast<int>(advertising_handle));
606     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
607   }
608 
609   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
610   const AdvertisingEventProperties& advertising_event_properties =
611       advertiser.advertising_event_properties;
612   uint16_t raw_advertising_event_properties =
613       ExtendedAdvertiser::GetRawAdvertisingEventProperties(
614           advertising_event_properties);
615 
616   bool can_have_advertising_data = (advertising_event_properties.legacy_ &&
617                                     !advertising_event_properties.directed_) ||
618                                    (!advertising_event_properties.legacy_ &&
619                                     !advertising_event_properties.scannable_);
620 
621   // If the advertising set specifies a type that does not support
622   // advertising data, the Controller shall return the error code
623   // Invalid HCI Command Parameters (0x12).
624   if (!can_have_advertising_data) {
625     LOG_INFO(
626         "advertising_event_properties (%02x) does not support"
627         " advertising data",
628         raw_advertising_event_properties);
629     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
630   }
631 
632   // If the advertising set uses legacy advertising PDUs that support
633   // advertising data and either Operation is not 0x03 or the
634   // Advertising_Data_Length parameter exceeds 31 octets, the Controller
635   // shall return the error code Invalid HCI Command Parameters (0x12).
636   if (advertising_event_properties.legacy_ &&
637       (operation != Operation::COMPLETE_ADVERTISEMENT ||
638        advertising_data.size() > max_legacy_advertising_pdu_size)) {
639     LOG_INFO(
640         "advertising_event_properties (%02x) is legacy and"
641         " and an incomplete operation was used or the advertising data"
642         " is larger than 31",
643         raw_advertising_event_properties);
644     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
645   }
646 
647   // If Operation is 0x04 and:
648   //    • advertising is currently disabled for the advertising set;
649   //    • the advertising set contains no data;
650   //    • the advertising set uses legacy PDUs; or
651   //    • Advertising_Data_Length is not zero;
652   // then the Controller shall return the error code Invalid HCI Command
653   // Parameters (0x12).
654   if (operation == Operation::UNCHANGED_DATA &&
655       (!advertiser.advertising_enable ||
656        advertiser.advertising_data.size() == 0 ||
657        advertising_event_properties.legacy_ || advertising_data.size() != 0)) {
658     LOG_INFO(
659         "Unchanged_Data operation is used but advertising is disabled;"
660         " or the advertising set contains no data;"
661         " or the advertising set uses legacy PDUs;"
662         " or the advertising data is not empty");
663     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
664   }
665 
666   // If Operation is not 0x03 or 0x04 and Advertising_Data_Length is zero,
667   // the Controller shall return the error code Invalid HCI
668   // Command Parameters (0x12).
669   if (operation != Operation::COMPLETE_ADVERTISEMENT &&
670       operation != Operation::UNCHANGED_DATA && advertising_data.size() == 0) {
671     LOG_INFO(
672         "operation (%02x) is not Complete_Advertisement or Unchanged_Data"
673         " but the advertising data is empty",
674         static_cast<int>(operation));
675     return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
676   }
677 
678   // If advertising is currently enabled for the specified advertising set and
679   // Operation does not have the value 0x03 or 0x04, the Controller shall
680   // return the error code Command Disallowed (0x0C).
681   if (advertiser.advertising_enable &&
682       operation != Operation::COMPLETE_ADVERTISEMENT &&
683       operation != Operation::UNCHANGED_DATA) {
684     LOG_INFO(
685         "operation (%02x) is used but advertising is enabled for the"
686         " specified advertising set",
687         static_cast<int>(operation));
688     return ErrorCode::COMMAND_DISALLOWED;
689   }
690 
691   switch (operation) {
692     case Operation::INTERMEDIATE_FRAGMENT:
693       advertiser.advertising_data.insert(advertiser.advertising_data.end(),
694                                          advertising_data.begin(),
695                                          advertising_data.end());
696       advertiser.partial_advertising_data = true;
697       break;
698 
699     case Operation::FIRST_FRAGMENT:
700       advertiser.advertising_data = advertising_data;
701       advertiser.partial_advertising_data = true;
702       break;
703 
704     case Operation::LAST_FRAGMENT:
705       advertiser.advertising_data.insert(advertiser.advertising_data.end(),
706                                          advertising_data.begin(),
707                                          advertising_data.end());
708       advertiser.partial_advertising_data = false;
709       break;
710 
711     case Operation::COMPLETE_ADVERTISEMENT:
712       advertiser.advertising_data = advertising_data;
713       advertiser.partial_advertising_data = false;
714       break;
715 
716     case Operation::UNCHANGED_DATA:
717       break;
718 
719     default:
720       LOG_INFO("unknown operation (%x)", static_cast<int>(operation));
721       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
722   }
723 
724   // If the combined length of the data exceeds the capacity of the
725   // advertising set identified by the Advertising_Handle parameter
726   // (see Section 7.8.57 LE Read Maximum Advertising Data Length command)
727   // or the amount of memory currently available, all the data
728   // shall be discarded and the Controller shall return the error code Memory
729   // Capacity Exceeded (0x07).
730   if (advertiser.advertising_data.size() >
731       properties_.le_max_advertising_data_length) {
732     LOG_INFO(
733         "the combined length %zu of the advertising data exceeds the"
734         " advertising set capacity %d",
735         advertiser.advertising_data.size(),
736         properties_.le_max_advertising_data_length);
737     advertiser.advertising_data.clear();
738     advertiser.partial_advertising_data = false;
739     return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
740   }
741 
742   // If advertising is currently enabled for the specified advertising set,
743   // the advertising set uses extended advertising, and the length of the
744   // data is greater than the maximum that the Controller can transmit within
745   // the longest possible auxiliary advertising segment consistent with the
746   // current parameters of the advertising set, the Controller shall return
747   // the error code Packet Too Long (0x45). If advertising on the
748   // LE Coded PHY, the S=8 coding shall be assumed.
749   size_t max_advertising_data_length =
750       ExtendedAdvertiser::GetMaxAdvertisingDataLength(
751           advertising_event_properties);
752   if (advertiser.advertising_enable &&
753       advertiser.advertising_data.size() > max_advertising_data_length) {
754     LOG_INFO(
755         "the advertising data contained in the set is larger than the"
756         " available PDU capacity");
757     advertiser.advertising_data.clear();
758     advertiser.partial_advertising_data = false;
759     return ErrorCode::PACKET_TOO_LONG;
760   }
761 
762   return ErrorCode::SUCCESS;
763 }
764 
765 // 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)766 ErrorCode LinkLayerController::LeSetExtendedScanResponseData(
767     uint8_t advertising_handle, Operation operation,
768     FragmentPreference fragment_preference,
769     const std::vector<uint8_t>& scan_response_data) {
770   // Extended advertising commands are disallowed when legacy advertising
771   // commands were used since the last reset.
772   if (!SelectExtendedAdvertising()) {
773     LOG_INFO(
774         "extended advertising command rejected because legacy advertising"
775         " is being used");
776     return ErrorCode::COMMAND_DISALLOWED;
777   }
778 
779   // fragment_preference is unused for now.
780   (void)fragment_preference;
781 
782   // If the advertising set corresponding to the Advertising_Handle parameter
783   // does not exist, then the Controller shall return the error code
784   // Unknown Advertising Identifier (0x42).
785   // TODO(c++20) unordered_map<>::contains
786   if (extended_advertisers_.count(advertising_handle) == 0) {
787     LOG_INFO("no advertising set defined with handle %02x",
788              static_cast<int>(advertising_handle));
789     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
790   }
791 
792   ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle];
793   const AdvertisingEventProperties& advertising_event_properties =
794       advertiser.advertising_event_properties;
795   uint16_t raw_advertising_event_properties =
796       ExtendedAdvertiser::GetRawAdvertisingEventProperties(
797           advertising_event_properties);
798 
799   // If the advertising set is non-scannable and the Host uses this
800   // command other than to discard existing data, the Controller shall
801   // return the error code Invalid HCI Command Parameters (0x12).
802   if (!advertising_event_properties.scannable_ &&
803       scan_response_data.size() > 0) {
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.size() == 0) {
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.size() == 0) {
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.size() == 0) {
979     for (auto& advertiser : extended_advertisers_) {
980       advertiser.second.advertising_enable = false;
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.size() == 0) {
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.advertising_enable = false;
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     if (connectable_advertising && directed_advertising &&
1019         high_duty_cycle_advertising &&
1020         (set.duration_ == 0 ||
1021          slots(set.duration_) > adv_direct_ind_high_timeout)) {
1022       LOG_INFO(
1023           "extended advertising is high duty cycle connectable directed"
1024           " but the duration is either 0 or larger than 1.28 seconds");
1025       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1026     }
1027 
1028     // If the advertising set contains partial advertising data or partial
1029     // scan response data, the Controller shall return the error code
1030     // Command Disallowed (0x0C).
1031     if (advertiser.partial_advertising_data ||
1032         advertiser.partial_scan_response_data) {
1033       LOG_INFO(
1034           "advertising set contains partial advertising"
1035           " or scan response data");
1036       return ErrorCode::COMMAND_DISALLOWED;
1037     }
1038 
1039     // If the advertising set uses scannable extended advertising PDUs and no
1040     // scan response data is currently provided, the Controller shall return the
1041     // error code Command Disallowed (0x0C).
1042     if (extended_advertising && scannable_advertising &&
1043         advertiser.scan_response_data.size() == 0) {
1044       LOG_INFO(
1045           "advertising set uses scannable extended advertising PDUs"
1046           " but no scan response data is provided");
1047       return ErrorCode::COMMAND_DISALLOWED;
1048     }
1049 
1050     // If the advertising set uses connectable extended advertising PDUs and the
1051     // advertising data in the advertising set will not fit in the
1052     // AUX_ADV_IND PDU, the Controller shall return the error code
1053     // Invalid HCI Command Parameters (0x12).
1054     if (extended_advertising && connectable_advertising &&
1055         advertiser.advertising_data.size() >
1056             ExtendedAdvertiser::GetMaxAdvertisingDataLength(
1057                 advertising_event_properties)) {
1058       LOG_INFO(
1059           "advertising set uses connectable extended advertising PDUs"
1060           " but the advertising data does not fit in AUX_ADV_IND PDUs");
1061       return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1062     }
1063 
1064     // If extended advertising is being used and the length of any advertising
1065     // data or of any scan response data is greater than the maximum that the
1066     // Controller can transmit within the longest possible auxiliary
1067     // advertising segment consistent with the chosen advertising interval,
1068     // the Controller shall return the error code Packet Too Long (0x45).
1069     // If advertising on the LE Coded PHY, the S=8 coding shall be assumed.
1070     if (extended_advertising && (advertiser.advertising_data.size() >
1071                                      max_extended_advertising_pdu_size ||
1072                                  advertiser.scan_response_data.size() >
1073                                      max_extended_advertising_pdu_size)) {
1074       LOG_INFO(
1075           "advertising set uses extended advertising PDUs"
1076           " but the advertising data does not fit in advertising PDUs");
1077       return ErrorCode::PACKET_TOO_LONG;
1078     }
1079 
1080     AddressWithType peer_address = PeerDeviceAddress(
1081         advertiser.peer_address, advertiser.peer_address_type);
1082     AddressWithType public_address{address_,
1083                                    AddressType::PUBLIC_DEVICE_ADDRESS};
1084     AddressWithType random_address{
1085         advertiser.random_address.value_or(Address::kEmpty),
1086         AddressType::RANDOM_DEVICE_ADDRESS};
1087     std::optional<AddressWithType> resolvable_address =
1088         GenerateResolvablePrivateAddress(peer_address, IrkSelection::Local);
1089 
1090     // TODO: additional checks would apply in the case of a LE only Controller
1091     // with no configured public device address.
1092 
1093     switch (advertiser.own_address_type) {
1094       case OwnAddressType::PUBLIC_DEVICE_ADDRESS:
1095         advertiser.advertising_address = public_address;
1096         break;
1097 
1098       case OwnAddressType::RANDOM_DEVICE_ADDRESS:
1099         // If the advertising set's Own_Address_Type parameter is set to 0x01
1100         // and the random address for the advertising set has not been
1101         // initialized using the HCI_LE_Set_Advertising_Set_Random_Address
1102         // command, the Controller shall return the error code
1103         // Invalid HCI Command Parameters (0x12).
1104         if (random_address.GetAddress() == Address::kEmpty) {
1105           LOG_INFO(
1106               "own_address_type is Random_Device_Address but the Random_Address"
1107               " has not been initialized");
1108           return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1109         }
1110         advertiser.advertising_address = random_address;
1111         break;
1112 
1113       case OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS:
1114         advertiser.advertising_address =
1115             resolvable_address.value_or(public_address);
1116         break;
1117 
1118       case OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS:
1119         // If the advertising set's Own_Address_Type parameter is set to 0x03,
1120         // the controller's resolving list did not contain a matching entry,
1121         // and the random address for the advertising set has not been
1122         // initialized using the HCI_LE_Set_Advertising_Set_Random_Address
1123         // command, the Controller shall return the error code
1124         // Invalid HCI Command Parameters (0x12).
1125         if (resolvable_address) {
1126           advertiser.advertising_address = resolvable_address.value();
1127         } else if (random_address.GetAddress() == Address::kEmpty) {
1128           LOG_INFO(
1129               "own_address_type is Resolvable_Or_Random_Address but the"
1130               " Resolving_List does not contain a matching entry and the"
1131               " Random_Address is not initialized");
1132           return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
1133         } else {
1134           advertiser.advertising_address = random_address;
1135         }
1136         break;
1137     }
1138   }
1139 
1140   for (auto& set : sets) {
1141     ExtendedAdvertiser& advertiser =
1142         extended_advertisers_[set.advertising_handle_];
1143 
1144     advertiser.num_completed_extended_advertising_events = 0;
1145     advertiser.advertising_enable = true;
1146     advertiser.next_event = std::chrono::steady_clock::now() +
1147                             advertiser.primary_advertising_interval;
1148   }
1149 
1150   return ErrorCode::SUCCESS;
1151 }
1152 
1153 // HCI command LE_Remove_Advertising_Set (Vol 4, Part E § 7.8.59).
LeRemoveAdvertisingSet(uint8_t advertising_handle)1154 ErrorCode LinkLayerController::LeRemoveAdvertisingSet(
1155     uint8_t advertising_handle) {
1156   // If the advertising set corresponding to the Advertising_Handle parameter
1157   // does not exist, then the Controller shall return the error code
1158   // Unknown Advertising Identifier (0x42).
1159   auto advertiser = extended_advertisers_.find(advertising_handle);
1160   if (advertiser == extended_advertisers_.end()) {
1161     LOG_INFO("no advertising set defined with handle %02x",
1162              static_cast<int>(advertising_handle));
1163     return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER;
1164   }
1165 
1166   // If advertising or periodic advertising on the advertising set is
1167   // enabled, then the Controller shall return the error code
1168   // Command Disallowed (0x0C).
1169   if (advertiser->second.advertising_enable) {
1170     LOG_INFO("the advertising set defined with handle %02x is enabled",
1171              static_cast<int>(advertising_handle));
1172     return ErrorCode::COMMAND_DISALLOWED;
1173   }
1174 
1175   extended_advertisers_.erase(advertiser);
1176   return ErrorCode::SUCCESS;
1177 }
1178 
1179 // HCI command LE_Clear_Advertising_Sets (Vol 4, Part E § 7.8.60).
LeClearAdvertisingSets()1180 ErrorCode LinkLayerController::LeClearAdvertisingSets() {
1181   // If advertising or periodic advertising is enabled on any advertising set,
1182   // then the Controller shall return the error code Command Disallowed (0x0C).
1183   for (auto& advertiser : extended_advertisers_) {
1184     if (advertiser.second.advertising_enable) {
1185       LOG_INFO("the advertising set with handle %02x is enabled",
1186                static_cast<int>(advertiser.second.advertising_enable));
1187       return ErrorCode::COMMAND_DISALLOWED;
1188     }
1189   }
1190 
1191   extended_advertisers_.clear();
1192   return ErrorCode::SUCCESS;
1193 }
1194 
GetMaxAdvertisingDataLength(const AdvertisingEventProperties & properties)1195 uint16_t ExtendedAdvertiser::GetMaxAdvertisingDataLength(
1196     const AdvertisingEventProperties& properties) {
1197   // The PDU AdvData size is defined in the following sections:
1198   // - Vol 6, Part B § 2.3.1.1 ADV_IND
1199   // - Vol 6, Part B § 2.3.1.2 ADV_DIRECT_IND
1200   // - Vol 6, Part B § 2.3.1.3 ADV_NONCONN_IND
1201   // - Vol 6, Part B § 2.3.1.4 ADV_SCAN_IND
1202   // - Vol 6, Part B § 2.3.1.5 ADV_EXT_IND
1203   // - Vol 6, Part B § 2.3.1.6 AUX_ADV_IND
1204   // - Vol 6, Part B § 2.3.1.8 AUX_CHAIN_IND
1205   // - Vol 6, Part B § 2.3.4 Common Extended Advertising Payload Format
1206   uint16_t max_advertising_data_length;
1207 
1208   if (properties.legacy_ && properties.directed_) {
1209     // Directed legacy advertising PDUs do not have AdvData payload.
1210     max_advertising_data_length = 0;
1211   } else if (properties.legacy_) {
1212     max_advertising_data_length = max_legacy_advertising_pdu_size;
1213   } else if (properties.scannable_) {
1214     // Scannable extended advertising PDUs do not have AdvData payload.
1215     max_advertising_data_length = 0;
1216   } else if (!properties.connectable_) {
1217     // When extended advertising is non-scannable and non-connectable,
1218     // AUX_CHAIN_IND PDUs can be used, and the advertising data may be
1219     // fragmented over multiple PDUs; the length is still capped at 1650
1220     // as stated in Vol 6, Part B § 2.3.4.9 Host Advertising Data.
1221     max_advertising_data_length = max_extended_advertising_pdu_size;
1222   } else {
1223     // When extended advertising is either scannable or connectable,
1224     // AUX_CHAIN_IND PDUs may not be used, and the maximum advertising data
1225     // length is 254. Extended payload header fields eat into the
1226     // available space.
1227     max_advertising_data_length = 254;
1228     max_advertising_data_length -= 6;                         // AdvA
1229     max_advertising_data_length -= 2;                         // ADI
1230     max_advertising_data_length -= 6 * properties.directed_;  // TargetA
1231     max_advertising_data_length -= 1 * properties.tx_power_;  // TxPower
1232     // TODO(pedantic): configure the ACAD field in order to leave the least
1233     // amount of AdvData space to the user (191).
1234   }
1235 
1236   return max_advertising_data_length;
1237 }
1238 
GetMaxScanResponseDataLength(const AdvertisingEventProperties & properties)1239 uint16_t ExtendedAdvertiser::GetMaxScanResponseDataLength(
1240     const AdvertisingEventProperties& properties) {
1241   // The PDU AdvData size is defined in the following sections:
1242   // - Vol 6, Part B § 2.3.2.2 SCAN_RSP
1243   // - Vol 6, Part B § 2.3.2.3 AUX_SCAN_RSP
1244   // - Vol 6, Part B § 2.3.1.8 AUX_CHAIN_IND
1245   // - Vol 6, Part B § 2.3.4 Common Extended Advertising Payload Format
1246   uint16_t max_scan_response_data_length;
1247 
1248   if (!properties.scannable_) {
1249     max_scan_response_data_length = 0;
1250   } else if (properties.legacy_) {
1251     max_scan_response_data_length = max_legacy_advertising_pdu_size;
1252   } else {
1253     // Extended scan response data may be sent over AUX_CHAIN_PDUs, and
1254     // the advertising data may be fragmented over multiple PDUs; the length
1255     // is still capped at 1650 as stated in
1256     // Vol 6, Part B § 2.3.4.9 Host Advertising Data.
1257     max_scan_response_data_length = max_extended_advertising_pdu_size;
1258   }
1259 
1260   return max_scan_response_data_length;
1261 }
1262 
GetRawAdvertisingEventProperties(const AdvertisingEventProperties & properties)1263 uint16_t ExtendedAdvertiser::GetRawAdvertisingEventProperties(
1264     const AdvertisingEventProperties& properties) {
1265   uint16_t mask = 0;
1266   if (properties.connectable_) mask |= 0x1;
1267   if (properties.scannable_) mask |= 0x2;
1268   if (properties.directed_) mask |= 0x4;
1269   if (properties.high_duty_cycle_) mask |= 0x8;
1270   if (properties.legacy_) mask |= 0x10;
1271   if (properties.anonymous_) mask |= 0x20;
1272   if (properties.tx_power_) mask |= 0x40;
1273   return mask;
1274 }
1275 
1276 // =============================================================================
1277 //  Advertising Routines
1278 // =============================================================================
1279 
LeAdvertising()1280 void LinkLayerController::LeAdvertising() {
1281   chrono::time_point now = std::chrono::steady_clock::now();
1282 
1283   // Legacy Advertising Timeout
1284 
1285   // Generate HCI Connection Complete or Enhanced HCI Connection Complete
1286   // events with Advertising Timeout error code when the advertising
1287   // type is ADV_DIRECT_IND and the connection failed to be established.
1288   if (legacy_advertiser_.IsEnabled() && legacy_advertiser_.timeout &&
1289       now >= legacy_advertiser_.timeout.value()) {
1290     // If the Advertising_Type parameter is 0x01 (ADV_DIRECT_IND, high duty
1291     // cycle) and the directed advertising fails to create a connection, an
1292     // HCI_LE_Connection_Complete or HCI_LE_Enhanced_Connection_Complete
1293     // event shall be generated with the Status code set to
1294     // Advertising Timeout (0x3C).
1295     LOG_INFO("Directed Advertising Timeout");
1296     legacy_advertiser_.Disable();
1297 
1298     // TODO: The PTS tool expects an LE_Connection_Complete event in this
1299     // case and will fail the test GAP/DISC/GENP/BV-05-C if
1300     // LE_Enhanced_Connection_Complete is sent instead.
1301     //
1302     // Note: HCI_LE_Connection_Complete is not sent if the
1303     // HCI_LE_Enhanced_Connection_Complete event (see Section 7.7.65.10)
1304     // is unmasked.
1305 #if 0
1306     if (IsLeEventUnmasked(SubeventCode::ENHANCED_CONNECTION_COMPLETE)) {
1307       send_event_(bluetooth::hci::LeEnhancedConnectionCompleteBuilder::Create(
1308           ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1309           AddressType::PUBLIC_DEVICE_ADDRESS, Address(), Address(), Address(),
1310           0, 0, 0, ClockAccuracy::PPM_500));
1311     } else
1312 #endif
1313     if (IsLeEventUnmasked(SubeventCode::CONNECTION_COMPLETE)) {
1314       send_event_(bluetooth::hci::LeConnectionCompleteBuilder::Create(
1315           ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1316           AddressType::PUBLIC_DEVICE_ADDRESS, Address(), 0, 0, 0,
1317           ClockAccuracy::PPM_500));
1318     }
1319   }
1320 
1321   // Legacy Advertising Event
1322 
1323   // Generate Link Layer Advertising events when advertising is enabled
1324   // and a full interval has passed since the last event.
1325   if (legacy_advertiser_.IsEnabled() && now >= legacy_advertiser_.next_event) {
1326     legacy_advertiser_.next_event += legacy_advertiser_.advertising_interval;
1327     model::packets::LegacyAdvertisingType type;
1328     bool attach_advertising_data = true;
1329     switch (legacy_advertiser_.advertising_type) {
1330       case AdvertisingType::ADV_IND:
1331         type = model::packets::LegacyAdvertisingType::ADV_IND;
1332         break;
1333       case AdvertisingType::ADV_DIRECT_IND_HIGH:
1334       case AdvertisingType::ADV_DIRECT_IND_LOW:
1335         attach_advertising_data = false;
1336         type = model::packets::LegacyAdvertisingType::ADV_DIRECT_IND;
1337         break;
1338       case AdvertisingType::ADV_SCAN_IND:
1339         type = model::packets::LegacyAdvertisingType::ADV_SCAN_IND;
1340         break;
1341       case AdvertisingType::ADV_NONCONN_IND:
1342         type = model::packets::LegacyAdvertisingType::ADV_NONCONN_IND;
1343         break;
1344     }
1345 
1346     SendLeLinkLayerPacketWithRssi(
1347         legacy_advertiser_.advertising_address.GetAddress(),
1348         legacy_advertiser_.target_address.GetAddress(),
1349         properties_.le_advertising_physical_channel_tx_power,
1350         model::packets::LeLegacyAdvertisingPduBuilder::Create(
1351             legacy_advertiser_.advertising_address.GetAddress(),
1352             legacy_advertiser_.target_address.GetAddress(),
1353             static_cast<model::packets::AddressType>(
1354                 legacy_advertiser_.advertising_address.GetAddressType()),
1355             static_cast<model::packets::AddressType>(
1356                 legacy_advertiser_.target_address.GetAddressType()),
1357             type,
1358             attach_advertising_data ? legacy_advertiser_.advertising_data
1359                                     : std::vector<uint8_t>{}));
1360   }
1361 
1362   for (auto& [_, advertiser] : extended_advertisers_) {
1363     // Extended Advertising Timeouts
1364 
1365     if (advertiser.IsEnabled() && advertiser.timeout &&
1366         now >= advertiser.timeout.value()) {
1367       // If the Duration[i] parameter is set to a value other than 0x0000, an
1368       // HCI_LE_Advertising_Set_Terminated event shall be generated when the
1369       // duration specified in the Duration[i] parameter expires.
1370       // However, if the advertising set is for high duty cycle connectable
1371       // directed advertising and no connection is created before the duration
1372       // expires, an HCI_LE_Connection_Complete or
1373       // HCI_LE_Enhanced_Connection_Complete event with the Status parameter
1374       // set to the error code Advertising Timeout (0x3C) may be generated
1375       // instead of or in addition to the HCI_LE_Advertising_Set_Terminated
1376       // event.
1377       LOG_INFO("Extended Advertising Timeout");
1378       advertiser.Disable();
1379 
1380       bool high_duty_cycle_connectable_directed_advertising =
1381           advertiser.advertising_event_properties.directed_ &&
1382           advertiser.advertising_event_properties.connectable_ &&
1383           advertiser.advertising_event_properties.high_duty_cycle_;
1384 
1385       // Note: HCI_LE_Connection_Complete is not sent if the
1386       // HCI_LE_Enhanced_Connection_Complete event (see Section 7.7.65.10)
1387       // is unmasked.
1388       if (high_duty_cycle_connectable_directed_advertising &&
1389           IsLeEventUnmasked(SubeventCode::ENHANCED_CONNECTION_COMPLETE)) {
1390         send_event_(bluetooth::hci::LeEnhancedConnectionCompleteBuilder::Create(
1391             ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1392             AddressType::PUBLIC_DEVICE_ADDRESS, Address(), Address(), Address(),
1393             0, 0, 0, ClockAccuracy::PPM_500));
1394       } else if (high_duty_cycle_connectable_directed_advertising &&
1395                  IsLeEventUnmasked(SubeventCode::CONNECTION_COMPLETE)) {
1396         send_event_(bluetooth::hci::LeConnectionCompleteBuilder::Create(
1397             ErrorCode::ADVERTISING_TIMEOUT, 0, Role::CENTRAL,
1398             AddressType::PUBLIC_DEVICE_ADDRESS, Address(), 0, 0, 0,
1399             ClockAccuracy::PPM_500));
1400       }
1401 
1402       if (IsLeEventUnmasked(SubeventCode::ADVERTISING_SET_TERMINATED)) {
1403         send_event_(bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
1404             ErrorCode::ADVERTISING_TIMEOUT, advertiser.advertising_handle, 0,
1405             advertiser.num_completed_extended_advertising_events));
1406       }
1407     }
1408 
1409     if (advertiser.IsEnabled() && advertiser.max_extended_advertising_events &&
1410         advertiser.num_completed_extended_advertising_events >=
1411             advertiser.max_extended_advertising_events) {
1412       // If the Max_Extended_Advertising_Events[i] parameter is set to a value
1413       // other than 0x00, an HCI_LE_Advertising_Set_Terminated event shall be
1414       // generated when the maximum number of extended advertising events has
1415       // been transmitted by the Controller.
1416       LOG_INFO("Max Extended Advertising count reached");
1417       advertiser.Disable();
1418 
1419       if (IsLeEventUnmasked(SubeventCode::ADVERTISING_SET_TERMINATED)) {
1420         send_event_(bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
1421             ErrorCode::ADVERTISING_TIMEOUT, advertiser.advertising_handle, 0,
1422             advertiser.num_completed_extended_advertising_events));
1423       }
1424     }
1425 
1426     // Extended Advertising Event
1427 
1428     // Generate Link Layer Advertising events when advertising is enabled
1429     // and a full interval has passed since the last event.
1430     if (advertiser.IsEnabled() && now >= advertiser.next_event) {
1431       advertiser.next_event += advertiser.primary_advertising_interval;
1432       advertiser.num_completed_extended_advertising_events++;
1433 
1434       if (advertiser.advertising_event_properties.legacy_) {
1435         model::packets::LegacyAdvertisingType type;
1436         uint16_t raw_advertising_event_properties =
1437             ExtendedAdvertiser::GetRawAdvertisingEventProperties(
1438                 advertiser.advertising_event_properties);
1439         switch (static_cast<LegacyAdvertisingEventProperties>(
1440             raw_advertising_event_properties & 0xf)) {
1441           case LegacyAdvertisingEventProperties::ADV_IND:
1442             type = model::packets::LegacyAdvertisingType::ADV_IND;
1443             break;
1444           case LegacyAdvertisingEventProperties::ADV_DIRECT_IND_HIGH:
1445           case LegacyAdvertisingEventProperties::ADV_DIRECT_IND_LOW:
1446             type = model::packets::LegacyAdvertisingType::ADV_DIRECT_IND;
1447             break;
1448           case LegacyAdvertisingEventProperties::ADV_SCAN_IND:
1449             type = model::packets::LegacyAdvertisingType::ADV_SCAN_IND;
1450             break;
1451           case LegacyAdvertisingEventProperties::ADV_NONCONN_IND:
1452             type = model::packets::LegacyAdvertisingType::ADV_NONCONN_IND;
1453             break;
1454           default:
1455             ASSERT(
1456                 "unexpected raw advertising event properties;"
1457                 " please check the extended advertising parameter validation");
1458             break;
1459         }
1460 
1461         SendLeLinkLayerPacketWithRssi(
1462             advertiser.advertising_address.GetAddress(),
1463             advertiser.target_address.GetAddress(),
1464             advertiser.advertising_tx_power,
1465             model::packets::LeLegacyAdvertisingPduBuilder::Create(
1466                 advertiser.advertising_address.GetAddress(),
1467                 advertiser.target_address.GetAddress(),
1468                 static_cast<model::packets::AddressType>(
1469                     advertiser.advertising_address.GetAddressType()),
1470                 static_cast<model::packets::AddressType>(
1471                     advertiser.target_address.GetAddressType()),
1472                 type, advertiser.advertising_data));
1473       } else {
1474         SendLeLinkLayerPacketWithRssi(
1475             advertiser.advertising_address.GetAddress(),
1476             advertiser.target_address.GetAddress(),
1477             advertiser.advertising_tx_power,
1478             model::packets::LeExtendedAdvertisingPduBuilder::Create(
1479                 advertiser.advertising_address.GetAddress(),
1480                 advertiser.target_address.GetAddress(),
1481                 static_cast<model::packets::AddressType>(
1482                     advertiser.advertising_address.GetAddressType()),
1483                 static_cast<model::packets::AddressType>(
1484                     advertiser.target_address.GetAddressType()),
1485                 advertiser.advertising_event_properties.connectable_,
1486                 advertiser.advertising_event_properties.scannable_,
1487                 advertiser.advertising_event_properties.directed_,
1488                 advertiser.advertising_sid, advertiser.advertising_tx_power,
1489                 static_cast<model::packets::PrimaryPhyType>(
1490                     advertiser.primary_advertising_phy),
1491                 static_cast<model::packets::SecondaryPhyType>(
1492                     advertiser.secondary_advertising_phy),
1493                 advertiser.advertising_data));
1494       }
1495     }
1496   }
1497 }
1498 
1499 }  // namespace rootcanal
1500