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