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