1 /****************************************************************************** 2 * 3 * Copyright (C) 2017 The Android Open Source Project 4 * Copyright (C) 2014 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20 #include <base/bind.h> 21 #include <base/logging.h> 22 #include <base/strings/string_number_conversions.h> 23 #include <string.h> 24 #include <queue> 25 #include <vector> 26 27 #include "bt_target.h" 28 #include "device/include/controller.h" 29 #include "osi/include/alarm.h" 30 31 #include "ble_advertiser.h" 32 #include "ble_advertiser_hci_interface.h" 33 #include "btm_int_types.h" 34 35 using base::Bind; 36 using RegisterCb = 37 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>; 38 using IdTxPowerStatusCb = base::Callback<void( 39 uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>; 40 extern void btm_gen_resolvable_private_addr( 41 base::Callback<void(uint8_t[8])> cb); 42 extern fixed_queue_t* btu_general_alarm_queue; 43 44 constexpr int ADV_DATA_LEN_MAX = 251; 45 46 namespace { 47 48 bool is_connectable(uint16_t advertising_event_properties) { 49 return advertising_event_properties & 0x01; 50 } 51 52 struct AdvertisingInstance { 53 uint8_t inst_id; 54 bool in_use; 55 uint8_t advertising_event_properties; 56 alarm_t* adv_raddr_timer; 57 int8_t tx_power; 58 uint16_t duration; 59 uint8_t maxExtAdvEvents; 60 alarm_t* timeout_timer; 61 uint8_t own_address_type; 62 BD_ADDR own_address; 63 MultiAdvCb timeout_cb; 64 bool address_update_required; 65 66 /* When true, advertising set is enabled, or last scheduled call to "LE Set 67 * Extended Advertising Set Enable" is to enable this advertising set. Any 68 * command scheduled when in this state will execute when the set is enabled, 69 * unless enabling fails. 70 * 71 * When false, advertising set is disabled, or last scheduled call to "LE Set 72 * Extended Advertising Set Enable" is to disable this advertising set. Any 73 * command scheduled when in this state will execute when the set is disabled. 74 */ 75 bool enable_status; 76 77 bool IsEnabled() { return enable_status; } 78 79 bool IsConnectable() { return is_connectable(advertising_event_properties); } 80 81 AdvertisingInstance(int inst_id) 82 : inst_id(inst_id), 83 in_use(false), 84 advertising_event_properties(0), 85 tx_power(0), 86 duration(0), 87 timeout_timer(nullptr), 88 own_address_type(0), 89 own_address{0}, 90 address_update_required(false), 91 enable_status(false) { 92 adv_raddr_timer = alarm_new_periodic("btm_ble.adv_raddr_timer"); 93 } 94 95 ~AdvertisingInstance() { 96 alarm_free(adv_raddr_timer); 97 if (timeout_timer) alarm_free(timeout_timer); 98 } 99 }; 100 101 void btm_ble_adv_raddr_timer_timeout(void* data); 102 103 void DoNothing(uint8_t) {} 104 void DoNothing2(uint8_t, uint8_t) {} 105 106 struct closure_data { 107 base::Closure user_task; 108 tracked_objects::Location posted_from; 109 }; 110 111 static void alarm_closure_cb(void* p) { 112 closure_data* data = (closure_data*)p; 113 VLOG(1) << "executing timer scheduled at %s" << data->posted_from.ToString(); 114 data->user_task.Run(); 115 delete data; 116 } 117 118 // Periodic alarms are not supported, because we clean up data in callback 119 void alarm_set_closure_on_queue(const tracked_objects::Location& posted_from, 120 alarm_t* alarm, period_ms_t interval_ms, 121 base::Closure user_task, fixed_queue_t* queue) { 122 closure_data* data = new closure_data; 123 data->posted_from = posted_from; 124 data->user_task = std::move(user_task); 125 VLOG(1) << "scheduling timer %s" << data->posted_from.ToString(); 126 alarm_set_on_queue(alarm, interval_ms, alarm_closure_cb, data, queue); 127 } 128 129 class BleAdvertisingManagerImpl; 130 131 /* a temporary type for holding all the data needed in callbacks below*/ 132 struct CreatorParams { 133 uint8_t inst_id; 134 BleAdvertisingManagerImpl* self; 135 IdTxPowerStatusCb cb; 136 tBTM_BLE_ADV_PARAMS params; 137 std::vector<uint8_t> advertise_data; 138 std::vector<uint8_t> scan_response_data; 139 tBLE_PERIODIC_ADV_PARAMS periodic_params; 140 std::vector<uint8_t> periodic_data; 141 uint16_t duration; 142 uint8_t maxExtAdvEvents; 143 RegisterCb timeout_cb; 144 }; 145 146 using c_type = std::unique_ptr<CreatorParams>; 147 148 class BleAdvertisingManagerImpl 149 : public BleAdvertisingManager, 150 public BleAdvertiserHciInterface::AdvertisingEventObserver { 151 public: 152 BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface) { 153 this->hci_interface = interface; 154 hci_interface->ReadInstanceCount( 155 base::Bind(&BleAdvertisingManagerImpl::ReadInstanceCountCb, 156 base::Unretained(this))); 157 } 158 159 ~BleAdvertisingManagerImpl() { adv_inst.clear(); } 160 161 void GetOwnAddress(uint8_t inst_id, GetAddressCallback cb) override { 162 bt_bdaddr_t addr; 163 memcpy(addr.address, adv_inst[inst_id].own_address, BD_ADDR_LEN); 164 cb.Run(adv_inst[inst_id].own_address_type, addr); 165 } 166 167 void ReadInstanceCountCb(uint8_t instance_count) { 168 this->inst_count = instance_count; 169 adv_inst.reserve(inst_count); 170 /* Initialize adv instance indices and IDs. */ 171 for (uint8_t i = 0; i < inst_count; i++) { 172 adv_inst.emplace_back(i); 173 } 174 } 175 176 void OnRpaGenerationComplete(base::Callback<void(bt_bdaddr_t)> cb, 177 uint8_t rand[8]) { 178 VLOG(1) << __func__; 179 180 bt_bdaddr_t bda; 181 182 rand[2] &= (~BLE_RESOLVE_ADDR_MASK); 183 rand[2] |= BLE_RESOLVE_ADDR_MSB; 184 185 bda.address[2] = rand[0]; 186 bda.address[1] = rand[1]; 187 bda.address[0] = rand[2]; 188 189 BT_OCTET16 irk; 190 BTM_GetDeviceIDRoot(irk); 191 tSMP_ENC output; 192 193 if (!SMP_Encrypt(irk, BT_OCTET16_LEN, rand, 3, &output)) 194 LOG_ASSERT(false) << "SMP_Encrypt failed"; 195 196 /* set hash to be LSB of rpAddress */ 197 bda.address[5] = output.param_buf[0]; 198 bda.address[4] = output.param_buf[1]; 199 bda.address[3] = output.param_buf[2]; 200 201 cb.Run(bda); 202 } 203 204 void GenerateRpa(base::Callback<void(bt_bdaddr_t)> cb) { 205 btm_gen_resolvable_private_addr( 206 Bind(&BleAdvertisingManagerImpl::OnRpaGenerationComplete, 207 base::Unretained(this), std::move(cb))); 208 } 209 210 void ConfigureRpa(AdvertisingInstance* p_inst, MultiAdvCb configuredCb) { 211 /* Connectable advertising set must be disabled when updating RPA */ 212 bool restart = p_inst->IsEnabled() && p_inst->IsConnectable(); 213 214 // If there is any form of timeout on the set, schedule address update when 215 // the set stops, because there is no good way to compute new timeout value. 216 // Maximum duration value is around 10 minutes, so this is safe. 217 if (restart && (p_inst->duration || p_inst->maxExtAdvEvents)) { 218 p_inst->address_update_required = true; 219 configuredCb.Run(0x01); 220 return; 221 } 222 223 GenerateRpa(Bind( 224 [](AdvertisingInstance* p_inst, MultiAdvCb configuredCb, 225 bt_bdaddr_t bda) { 226 /* Connectable advertising set must be disabled when updating RPA */ 227 bool restart = p_inst->IsEnabled() && p_inst->IsConnectable(); 228 229 auto hci_interface = 230 ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get()) 231 ->GetHciInterface(); 232 233 if (restart) { 234 p_inst->enable_status = false; 235 hci_interface->Enable(false, p_inst->inst_id, 0x00, 0x00, 236 Bind(DoNothing)); 237 } 238 239 /* set it to controller */ 240 hci_interface->SetRandomAddress( 241 p_inst->inst_id, p_inst->own_address, 242 Bind( 243 [](AdvertisingInstance* p_inst, bt_bdaddr_t bda, 244 MultiAdvCb configuredCb, uint8_t status) { 245 memcpy(p_inst->own_address, &bda, BD_ADDR_LEN); 246 configuredCb.Run(0x00); 247 }, 248 p_inst, bda, configuredCb)); 249 250 if (restart) { 251 p_inst->enable_status = true; 252 hci_interface->Enable(true, p_inst->inst_id, 0x00, 0x00, 253 Bind(DoNothing)); 254 } 255 }, 256 p_inst, std::move(configuredCb))); 257 } 258 259 void RegisterAdvertiser( 260 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> cb) 261 override { 262 AdvertisingInstance* p_inst = &adv_inst[0]; 263 for (uint8_t i = 0; i < inst_count; i++, p_inst++) { 264 if (p_inst->in_use) continue; 265 266 p_inst->in_use = true; 267 268 // set up periodic timer to update address. 269 if (BTM_BleLocalPrivacyEnabled()) { 270 p_inst->own_address_type = BLE_ADDR_RANDOM; 271 GenerateRpa(Bind( 272 [](AdvertisingInstance* p_inst, 273 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> 274 cb, 275 bt_bdaddr_t bda) { 276 memcpy(p_inst->own_address, &bda, BD_ADDR_LEN); 277 278 alarm_set_on_queue(p_inst->adv_raddr_timer, 279 BTM_BLE_PRIVATE_ADDR_INT_MS, 280 btm_ble_adv_raddr_timer_timeout, p_inst, 281 btu_general_alarm_queue); 282 cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS); 283 }, 284 p_inst, cb)); 285 } else { 286 p_inst->own_address_type = BLE_ADDR_PUBLIC; 287 memcpy(p_inst->own_address, 288 controller_get_interface()->get_address()->address, BD_ADDR_LEN); 289 290 cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS); 291 } 292 return; 293 } 294 295 LOG(INFO) << "no free advertiser instance"; 296 cb.Run(0xFF, ADVERTISE_FAILED_TOO_MANY_ADVERTISERS); 297 } 298 299 void StartAdvertising(uint8_t advertiser_id, MultiAdvCb cb, 300 tBTM_BLE_ADV_PARAMS* params, 301 std::vector<uint8_t> advertise_data, 302 std::vector<uint8_t> scan_response_data, int duration, 303 MultiAdvCb timeout_cb) override { 304 /* a temporary type for holding all the data needed in callbacks below*/ 305 struct CreatorParams { 306 uint8_t inst_id; 307 BleAdvertisingManagerImpl* self; 308 MultiAdvCb cb; 309 tBTM_BLE_ADV_PARAMS params; 310 std::vector<uint8_t> advertise_data; 311 std::vector<uint8_t> scan_response_data; 312 int duration; 313 MultiAdvCb timeout_cb; 314 }; 315 316 std::unique_ptr<CreatorParams> c; 317 c.reset(new CreatorParams()); 318 319 c->self = this; 320 c->cb = std::move(cb); 321 c->params = *params; 322 c->advertise_data = std::move(advertise_data); 323 c->scan_response_data = std::move(scan_response_data); 324 c->duration = duration; 325 c->timeout_cb = std::move(timeout_cb); 326 c->inst_id = advertiser_id; 327 328 using c_type = std::unique_ptr<CreatorParams>; 329 330 // this code is intentionally left formatted this way to highlight the 331 // asynchronous flow 332 // clang-format off 333 c->self->SetParameters(c->inst_id, &c->params, Bind( 334 [](c_type c, uint8_t status, int8_t tx_power) { 335 if (status != 0) { 336 LOG(ERROR) << "setting parameters failed, status: " << +status; 337 c->cb.Run(status); 338 return; 339 } 340 341 c->self->adv_inst[c->inst_id].tx_power = tx_power; 342 343 BD_ADDR *rpa = &c->self->adv_inst[c->inst_id].own_address; 344 c->self->GetHciInterface()->SetRandomAddress(c->inst_id, *rpa, Bind( 345 [](c_type c, uint8_t status) { 346 if (status != 0) { 347 LOG(ERROR) << "setting random address failed, status: " << +status; 348 c->cb.Run(status); 349 return; 350 } 351 352 c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind( 353 [](c_type c, uint8_t status) { 354 if (status != 0) { 355 LOG(ERROR) << "setting advertise data failed, status: " << +status; 356 c->cb.Run(status); 357 return; 358 } 359 360 c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind( 361 [](c_type c, uint8_t status) { 362 if (status != 0) { 363 LOG(ERROR) << "setting scan response data failed, status: " << +status; 364 c->cb.Run(status); 365 return; 366 } 367 368 c->self->Enable(c->inst_id, true, c->cb, c->duration, 0, std::move(c->timeout_cb)); 369 370 }, base::Passed(&c))); 371 }, base::Passed(&c))); 372 }, base::Passed(&c))); 373 }, base::Passed(&c))); 374 // clang-format on 375 } 376 377 void StartAdvertisingSet(IdTxPowerStatusCb cb, tBTM_BLE_ADV_PARAMS* params, 378 std::vector<uint8_t> advertise_data, 379 std::vector<uint8_t> scan_response_data, 380 tBLE_PERIODIC_ADV_PARAMS* periodic_params, 381 std::vector<uint8_t> periodic_data, 382 uint16_t duration, uint8_t maxExtAdvEvents, 383 RegisterCb timeout_cb) override { 384 std::unique_ptr<CreatorParams> c; 385 c.reset(new CreatorParams()); 386 387 c->self = this; 388 c->cb = std::move(cb); 389 c->params = *params; 390 c->advertise_data = std::move(advertise_data); 391 c->scan_response_data = std::move(scan_response_data); 392 c->periodic_params = *periodic_params; 393 c->periodic_data = std::move(periodic_data); 394 c->duration = duration; 395 c->maxExtAdvEvents = maxExtAdvEvents; 396 c->timeout_cb = std::move(timeout_cb); 397 398 399 // this code is intentionally left formatted this way to highlight the 400 // asynchronous flow 401 // clang-format off 402 c->self->RegisterAdvertiser(Bind( 403 [](c_type c, uint8_t advertiser_id, uint8_t status) { 404 if (status != 0) { 405 LOG(ERROR) << "registering advertiser failed, status: " << +status; 406 c->cb.Run(0, 0, status); 407 return; 408 } 409 410 c->inst_id = advertiser_id; 411 412 c->self->SetParameters(c->inst_id, &c->params, Bind( 413 [](c_type c, uint8_t status, int8_t tx_power) { 414 if (status != 0) { 415 c->self->Unregister(c->inst_id); 416 LOG(ERROR) << "setting parameters failed, status: " << +status; 417 c->cb.Run(0, 0, status); 418 return; 419 } 420 421 c->self->adv_inst[c->inst_id].tx_power = tx_power; 422 423 BD_ADDR *rpa = &c->self->adv_inst[c->inst_id].own_address; 424 c->self->GetHciInterface()->SetRandomAddress(c->inst_id, *rpa, Bind( 425 [](c_type c, uint8_t status) { 426 if (status != 0) { 427 c->self->Unregister(c->inst_id); 428 LOG(ERROR) << "setting random address failed, status: " << +status; 429 c->cb.Run(0, 0, status); 430 return; 431 } 432 433 c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind( 434 [](c_type c, uint8_t status) { 435 if (status != 0) { 436 c->self->Unregister(c->inst_id); 437 LOG(ERROR) << "setting advertise data failed, status: " << +status; 438 c->cb.Run(0, 0, status); 439 return; 440 } 441 442 c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind( 443 [](c_type c, uint8_t status) { 444 if (status != 0) { 445 c->self->Unregister(c->inst_id); 446 LOG(ERROR) << "setting scan response data failed, status: " << +status; 447 c->cb.Run(0, 0, status); 448 return; 449 } 450 451 if (c->periodic_params.enable) { 452 c->self->StartAdvertisingSetPeriodicPart(std::move(c)); 453 } else { 454 c->self->StartAdvertisingSetFinish(std::move(c)); 455 } 456 }, base::Passed(&c))); 457 }, base::Passed(&c))); 458 }, base::Passed(&c))); 459 }, base::Passed(&c))); 460 }, base::Passed(&c))); 461 // clang-format on 462 } 463 464 void StartAdvertisingSetPeriodicPart(c_type c) { 465 // this code is intentionally left formatted this way to highlight the 466 // asynchronous flow 467 // clang-format off 468 c->self->SetPeriodicAdvertisingParameters(c->inst_id, &c->periodic_params, Bind( 469 [](c_type c, uint8_t status) { 470 if (status != 0) { 471 c->self->Unregister(c->inst_id); 472 LOG(ERROR) << "setting periodic parameters failed, status: " << +status; 473 c->cb.Run(0, 0, status); 474 return; 475 } 476 477 c->self->SetPeriodicAdvertisingData(c->inst_id, std::move(c->periodic_data), Bind( 478 [](c_type c, uint8_t status) { 479 if (status != 0) { 480 c->self->Unregister(c->inst_id); 481 LOG(ERROR) << "setting periodic parameters failed, status: " << +status; 482 c->cb.Run(0, 0, status); 483 return; 484 } 485 486 c->self->SetPeriodicAdvertisingEnable(c->inst_id, true, Bind( 487 [](c_type c, uint8_t status) { 488 if (status != 0) { 489 c->self->Unregister(c->inst_id); 490 LOG(ERROR) << "enabling periodic advertising failed, status: " << +status; 491 c->cb.Run(0, 0, status); 492 return; 493 } 494 495 c->self->StartAdvertisingSetFinish(std::move(c)); 496 497 }, base::Passed(&c))); 498 }, base::Passed(&c))); 499 }, base::Passed(&c))); 500 // clang-format on 501 } 502 503 void StartAdvertisingSetFinish(c_type c) { 504 uint8_t inst_id = c->inst_id; 505 uint16_t duration = c->duration; 506 uint8_t maxExtAdvEvents = c->maxExtAdvEvents; 507 RegisterCb timeout_cb = std::move(c->timeout_cb); 508 BleAdvertisingManagerImpl* self = c->self; 509 MultiAdvCb enable_cb = Bind( 510 [](c_type c, uint8_t status) { 511 if (status != 0) { 512 c->self->Unregister(c->inst_id); 513 LOG(ERROR) << "enabling advertiser failed, status: " << +status; 514 c->cb.Run(0, 0, status); 515 return; 516 } 517 int8_t tx_power = c->self->adv_inst[c->inst_id].tx_power; 518 c->cb.Run(c->inst_id, tx_power, status); 519 }, 520 base::Passed(&c)); 521 522 self->Enable(inst_id, true, std::move(enable_cb), duration, maxExtAdvEvents, 523 Bind(std::move(timeout_cb), inst_id)); 524 } 525 526 void EnableWithTimerCb(uint8_t inst_id, MultiAdvCb enable_cb, int duration, 527 MultiAdvCb timeout_cb, uint8_t status) { 528 VLOG(1) << __func__ << " inst_id: " << +inst_id; 529 AdvertisingInstance* p_inst = &adv_inst[inst_id]; 530 531 // Run the regular enable callback 532 enable_cb.Run(status); 533 534 p_inst->timeout_timer = alarm_new("btm_ble.adv_timeout"); 535 536 base::Closure cb = Bind(&BleAdvertisingManagerImpl::Enable, 537 base::Unretained(this), inst_id, 0 /* disable */, 538 std::move(timeout_cb), 0, 0, base::Bind(DoNothing)); 539 540 // schedule disable when the timeout passes 541 alarm_set_closure_on_queue(FROM_HERE, p_inst->timeout_timer, duration * 10, 542 std::move(cb), btu_general_alarm_queue); 543 } 544 545 void Enable(uint8_t inst_id, bool enable, MultiAdvCb cb, uint16_t duration, 546 uint8_t maxExtAdvEvents, MultiAdvCb timeout_cb) override { 547 VLOG(1) << __func__ << " inst_id: " << +inst_id; 548 if (inst_id >= inst_count) { 549 LOG(ERROR) << "bad instance id " << +inst_id; 550 return; 551 } 552 553 AdvertisingInstance* p_inst = &adv_inst[inst_id]; 554 VLOG(1) << __func__ << " enable: " << enable << ", duration: " << +duration; 555 if (!p_inst->in_use) { 556 LOG(ERROR) << "Invalid or no active instance"; 557 cb.Run(BTM_BLE_MULTI_ADV_FAILURE); 558 return; 559 } 560 561 if (enable && (duration || maxExtAdvEvents)) { 562 p_inst->timeout_cb = std::move(timeout_cb); 563 } 564 565 p_inst->duration = duration; 566 p_inst->maxExtAdvEvents = maxExtAdvEvents; 567 568 if (enable && p_inst->address_update_required) { 569 p_inst->address_update_required = false; 570 ConfigureRpa(p_inst, base::Bind(&BleAdvertisingManagerImpl::EnableFinish, 571 base::Unretained(this), p_inst, enable, 572 std::move(cb))); 573 return; 574 } 575 576 EnableFinish(p_inst, enable, std::move(cb), 0); 577 } 578 579 void EnableFinish(AdvertisingInstance* p_inst, bool enable, MultiAdvCb cb, 580 uint8_t status) { 581 if (enable && p_inst->duration) { 582 p_inst->enable_status = enable; 583 // TODO(jpawlowski): HCI implementation that can't do duration should 584 // emulate it, not EnableWithTimerCb. 585 GetHciInterface()->Enable( 586 enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents, 587 Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb, 588 base::Unretained(this), p_inst->inst_id, std::move(cb), 589 p_inst->duration, p_inst->timeout_cb)); 590 591 } else { 592 if (p_inst->timeout_timer) { 593 alarm_cancel(p_inst->timeout_timer); 594 alarm_free(p_inst->timeout_timer); 595 p_inst->timeout_timer = nullptr; 596 } 597 598 p_inst->enable_status = enable; 599 GetHciInterface()->Enable(enable, p_inst->inst_id, p_inst->duration, 600 p_inst->maxExtAdvEvents, std::move(cb)); 601 } 602 } 603 604 void SetParameters(uint8_t inst_id, tBTM_BLE_ADV_PARAMS* p_params, 605 ParametersCb cb) override { 606 VLOG(1) << __func__ << " inst_id: " << +inst_id; 607 if (inst_id >= inst_count) { 608 LOG(ERROR) << "bad instance id " << +inst_id; 609 return; 610 } 611 612 AdvertisingInstance* p_inst = &adv_inst[inst_id]; 613 if (!p_inst->in_use) { 614 LOG(ERROR) << "adv instance not in use" << +inst_id; 615 cb.Run(BTM_BLE_MULTI_ADV_FAILURE, 0); 616 return; 617 } 618 619 // TODO: disable only if was enabled, currently no use scenario needs that, 620 // we always set parameters before enabling 621 // GetHciInterface()->Enable(false, inst_id, Bind(DoNothing)); 622 p_inst->advertising_event_properties = 623 p_params->advertising_event_properties; 624 p_inst->tx_power = p_params->tx_power; 625 BD_ADDR peer_address = {0, 0, 0, 0, 0, 0}; 626 627 GetHciInterface()->SetParameters( 628 p_inst->inst_id, p_params->advertising_event_properties, 629 p_params->adv_int_min, p_params->adv_int_max, p_params->channel_map, 630 p_inst->own_address_type, p_inst->own_address, 0x00, peer_address, 631 p_params->adv_filter_policy, p_inst->tx_power, 632 p_params->primary_advertising_phy, 0x01, 633 p_params->secondary_advertising_phy, 0x01 /* TODO: proper SID */, 634 p_params->scan_request_notification_enable, cb); 635 636 // TODO: re-enable only if it was enabled, properly call 637 // SetParamsCallback 638 // currently no use scenario needs that 639 // GetHciInterface()->Enable(true, inst_id, BTM_BleUpdateAdvInstParamCb); 640 } 641 642 void SetData(uint8_t inst_id, bool is_scan_rsp, std::vector<uint8_t> data, 643 MultiAdvCb cb) override { 644 VLOG(1) << __func__ << " inst_id: " << +inst_id; 645 if (inst_id >= inst_count) { 646 LOG(ERROR) << "bad instance id " << +inst_id; 647 return; 648 } 649 650 AdvertisingInstance* p_inst = &adv_inst[inst_id]; 651 VLOG(1) << "is_scan_rsp = " << is_scan_rsp; 652 653 if (!is_scan_rsp && is_connectable(p_inst->advertising_event_properties)) { 654 uint8_t flags_val = BTM_GENERAL_DISCOVERABLE; 655 656 if (p_inst->duration) flags_val = BTM_LIMITED_DISCOVERABLE; 657 658 std::vector<uint8_t> flags; 659 flags.push_back(2); // length 660 flags.push_back(HCI_EIR_FLAGS_TYPE); 661 flags.push_back(flags_val); 662 663 data.insert(data.begin(), flags.begin(), flags.end()); 664 } 665 666 // Find and fill TX Power with the correct value 667 if (data.size()) { 668 size_t i = 0; 669 while (i < data.size()) { 670 uint8_t type = data[i + 1]; 671 if (type == HCI_EIR_TX_POWER_LEVEL_TYPE) { 672 data[i + 2] = adv_inst[inst_id].tx_power; 673 } 674 i += data[i] + 1; 675 } 676 } 677 678 VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size()); 679 DivideAndSendData( 680 inst_id, data, cb, 681 base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender, 682 base::Unretained(this), is_scan_rsp)); 683 } 684 685 void SetDataAdvDataSender(uint8_t is_scan_rsp, uint8_t inst_id, 686 uint8_t operation, uint8_t length, uint8_t* data, 687 MultiAdvCb cb) { 688 if (is_scan_rsp) 689 GetHciInterface()->SetScanResponseData(inst_id, operation, 0x01, length, 690 data, cb); 691 else 692 GetHciInterface()->SetAdvertisingData(inst_id, operation, 0x01, length, 693 data, cb); 694 } 695 696 using DataSender = base::Callback<void( 697 uint8_t /*inst_id*/, uint8_t /* operation */, uint8_t /* length */, 698 uint8_t* /* data */, MultiAdvCb /* done */)>; 699 700 void DivideAndSendData(int inst_id, std::vector<uint8_t> data, 701 MultiAdvCb done_cb, DataSender sender) { 702 DivideAndSendDataRecursively(true, inst_id, std::move(data), 0, 703 std::move(done_cb), std::move(sender), 0); 704 } 705 706 static void DivideAndSendDataRecursively(bool isFirst, int inst_id, 707 std::vector<uint8_t> data, 708 int offset, MultiAdvCb done_cb, 709 DataSender sender, uint8_t status) { 710 constexpr uint8_t INTERMEDIATE = 711 0x00; // Intermediate fragment of fragmented data 712 constexpr uint8_t FIRST = 0x01; // First fragment of fragmented data 713 constexpr uint8_t LAST = 0x02; // Last fragment of fragmented data 714 constexpr uint8_t COMPLETE = 0x03; // Complete extended advertising data 715 716 int dataSize = (int)data.size(); 717 if (status != 0 || (!isFirst && offset == dataSize)) { 718 /* if we got error writing data, or reached the end of data */ 719 done_cb.Run(status); 720 return; 721 } 722 723 bool moreThanOnePacket = dataSize - offset > ADV_DATA_LEN_MAX; 724 uint8_t operation = isFirst ? moreThanOnePacket ? FIRST : COMPLETE 725 : moreThanOnePacket ? INTERMEDIATE : LAST; 726 int length = moreThanOnePacket ? ADV_DATA_LEN_MAX : dataSize - offset; 727 int newOffset = offset + length; 728 729 sender.Run( 730 inst_id, operation, length, data.data() + offset, 731 Bind(&BleAdvertisingManagerImpl::DivideAndSendDataRecursively, false, 732 inst_id, std::move(data), newOffset, std::move(done_cb), sender)); 733 } 734 735 void SetPeriodicAdvertisingParameters(uint8_t inst_id, 736 tBLE_PERIODIC_ADV_PARAMS* params, 737 MultiAdvCb cb) override { 738 VLOG(1) << __func__ << " inst_id: " << +inst_id; 739 740 GetHciInterface()->SetPeriodicAdvertisingParameters( 741 inst_id, params->min_interval, params->max_interval, 742 params->periodic_advertising_properties, cb); 743 } 744 745 void SetPeriodicAdvertisingData(uint8_t inst_id, std::vector<uint8_t> data, 746 MultiAdvCb cb) override { 747 VLOG(1) << __func__ << " inst_id: " << +inst_id; 748 749 VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size()); 750 751 DivideAndSendData( 752 inst_id, data, cb, 753 base::Bind(&BleAdvertiserHciInterface::SetPeriodicAdvertisingData, 754 base::Unretained(GetHciInterface()))); 755 } 756 757 void SetPeriodicAdvertisingEnable(uint8_t inst_id, uint8_t enable, 758 MultiAdvCb cb) override { 759 VLOG(1) << __func__ << " inst_id: " << +inst_id << ", enable: " << +enable; 760 761 GetHciInterface()->SetPeriodicAdvertisingEnable(enable, inst_id, cb); 762 } 763 764 void Unregister(uint8_t inst_id) override { 765 AdvertisingInstance* p_inst = &adv_inst[inst_id]; 766 767 VLOG(1) << __func__ << " inst_id: " << +inst_id; 768 if (inst_id >= inst_count) { 769 LOG(ERROR) << "bad instance id " << +inst_id; 770 return; 771 } 772 773 if (adv_inst[inst_id].IsEnabled()) { 774 p_inst->enable_status = false; 775 GetHciInterface()->Enable(false, inst_id, 0x00, 0x00, Bind(DoNothing)); 776 } 777 778 alarm_cancel(p_inst->adv_raddr_timer); 779 p_inst->in_use = false; 780 GetHciInterface()->RemoveAdvertisingSet(inst_id, Bind(DoNothing)); 781 p_inst->address_update_required = false; 782 } 783 784 void OnAdvertisingSetTerminated( 785 uint8_t status, uint8_t advertising_handle, uint16_t connection_handle, 786 uint8_t num_completed_extended_adv_events) override { 787 AdvertisingInstance* p_inst = &adv_inst[advertising_handle]; 788 VLOG(1) << __func__ << "status: 0x" << std::hex << +status 789 << ", advertising_handle: 0x" << std::hex << +advertising_handle 790 << ", connection_handle: 0x" << std::hex << +connection_handle; 791 792 if (status == 0x43 || status == 0x3C) { 793 // either duration elapsed, or maxExtAdvEvents reached 794 p_inst->enable_status = false; 795 796 if (p_inst->timeout_cb.is_null()) { 797 LOG(INFO) << __func__ << "No timeout callback"; 798 return; 799 } 800 801 p_inst->timeout_cb.Run(status); 802 return; 803 } 804 805 if (BTM_BleLocalPrivacyEnabled() && 806 advertising_handle <= BTM_BLE_MULTI_ADV_MAX) { 807 btm_acl_update_conn_addr(connection_handle, p_inst->own_address); 808 } 809 810 VLOG(1) << "reneabling advertising"; 811 812 if (p_inst->in_use == true) { 813 // TODO(jpawlowski): we don't really allow to do directed advertising 814 // right now. This should probably be removed, check with Andre. 815 if ((p_inst->advertising_event_properties & 0x0C) == 816 0 /* directed advertising bits not set */) { 817 GetHciInterface()->Enable(true, advertising_handle, 0x00, 0x00, 818 Bind(DoNothing)); 819 } else { 820 /* mark directed adv as disabled if adv has been stopped */ 821 p_inst->in_use = false; 822 } 823 } 824 } 825 826 private: 827 BleAdvertiserHciInterface* GetHciInterface() { return hci_interface; } 828 829 BleAdvertiserHciInterface* hci_interface = nullptr; 830 std::vector<AdvertisingInstance> adv_inst; 831 uint8_t inst_count; 832 }; 833 834 BleAdvertisingManager* instance; 835 836 void btm_ble_adv_raddr_timer_timeout(void* data) { 837 ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get()) 838 ->ConfigureRpa((AdvertisingInstance*)data, base::Bind(DoNothing)); 839 } 840 } // namespace 841 842 void BleAdvertisingManager::Initialize(BleAdvertiserHciInterface* interface) { 843 instance = new BleAdvertisingManagerImpl(interface); 844 } 845 846 BleAdvertisingManager* BleAdvertisingManager::Get() { 847 CHECK(instance); 848 return instance; 849 }; 850 851 void BleAdvertisingManager::CleanUp() { 852 delete instance; 853 instance = nullptr; 854 }; 855 856 /** 857 * This function initialize the advertising manager. 858 **/ 859 void btm_ble_adv_init() { 860 BleAdvertiserHciInterface::Initialize(); 861 BleAdvertisingManager::Initialize(BleAdvertiserHciInterface::Get()); 862 BleAdvertiserHciInterface::Get()->SetAdvertisingEventObserver( 863 (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get()); 864 865 if (BleAdvertiserHciInterface::Get()->QuirkAdvertiserZeroHandle()) { 866 // If handle 0 can't be used, register advertiser for it, but never use it. 867 BleAdvertisingManager::Get()->RegisterAdvertiser(Bind(DoNothing2)); 868 } 869 } 870 871 /******************************************************************************* 872 * 873 * Function btm_ble_multi_adv_cleanup 874 * 875 * Description This function cleans up multi adv control block. 876 * 877 * Parameters 878 * Returns void 879 * 880 ******************************************************************************/ 881 void btm_ble_multi_adv_cleanup(void) { 882 BleAdvertisingManager::CleanUp(); 883 BleAdvertiserHciInterface::CleanUp(); 884 } 885