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