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