diff options
author | Arman Uguray <armansito@chromium.org> | 2015-03-23 18:57:12 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-03-23 20:53:46 -0400 |
commit | 24b4f38fc9ebf93af223c67169a946d6baf9db61 (patch) | |
tree | a8ca6f13c81224b2a9059e53eb386958770bb185 /net | |
parent | 203fea0178d7e165dbe834d1bdd9d243018fd5bf (diff) |
Bluetooth: Implement the Add Advertising command
This patch adds the most basic implementation for the
"Add Advertisement" command. All state updates between the
various HCI settings (POWERED, ADVERTISING, ADVERTISING_INSTANCE,
and LE_ENABLED) has been implemented. The command currently
supports only setting the advertising data fields, with no flags
and no scan response data.
Signed-off-by: Arman Uguray <armansito@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/mgmt.c | 283 |
1 files changed, 273 insertions, 10 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8c771e79d67d..7b4c0b027e90 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -100,6 +100,7 @@ static const u16 mgmt_commands[] = { | |||
100 | MGMT_OP_READ_LOCAL_OOB_EXT_DATA, | 100 | MGMT_OP_READ_LOCAL_OOB_EXT_DATA, |
101 | MGMT_OP_READ_EXT_INDEX_LIST, | 101 | MGMT_OP_READ_EXT_INDEX_LIST, |
102 | MGMT_OP_READ_ADV_FEATURES, | 102 | MGMT_OP_READ_ADV_FEATURES, |
103 | MGMT_OP_ADD_ADVERTISING, | ||
103 | }; | 104 | }; |
104 | 105 | ||
105 | static const u16 mgmt_events[] = { | 106 | static const u16 mgmt_events[] = { |
@@ -135,6 +136,8 @@ static const u16 mgmt_events[] = { | |||
135 | MGMT_EV_EXT_INDEX_ADDED, | 136 | MGMT_EV_EXT_INDEX_ADDED, |
136 | MGMT_EV_EXT_INDEX_REMOVED, | 137 | MGMT_EV_EXT_INDEX_REMOVED, |
137 | MGMT_EV_LOCAL_OOB_DATA_UPDATED, | 138 | MGMT_EV_LOCAL_OOB_DATA_UPDATED, |
139 | MGMT_EV_ADVERTISING_ADDED, | ||
140 | MGMT_EV_ADVERTISING_REMOVED, | ||
138 | }; | 141 | }; |
139 | 142 | ||
140 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) | 143 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) |
@@ -864,7 +867,7 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev) | |||
864 | return 0; | 867 | return 0; |
865 | } | 868 | } |
866 | 869 | ||
867 | static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr) | 870 | static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr) |
868 | { | 871 | { |
869 | u8 ad_len = 0, flags = 0; | 872 | u8 ad_len = 0, flags = 0; |
870 | 873 | ||
@@ -896,7 +899,18 @@ static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr) | |||
896 | return ad_len; | 899 | return ad_len; |
897 | } | 900 | } |
898 | 901 | ||
899 | static void update_adv_data(struct hci_request *req) | 902 | static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) |
903 | { | ||
904 | /* TODO: Set the appropriate entries based on advertising instance flags | ||
905 | * here once flags other than 0 are supported. | ||
906 | */ | ||
907 | memcpy(ptr, hdev->adv_instance.adv_data, | ||
908 | hdev->adv_instance.adv_data_len); | ||
909 | |||
910 | return hdev->adv_instance.adv_data_len; | ||
911 | } | ||
912 | |||
913 | static void update_adv_data_for_instance(struct hci_request *req, u8 instance) | ||
900 | { | 914 | { |
901 | struct hci_dev *hdev = req->hdev; | 915 | struct hci_dev *hdev = req->hdev; |
902 | struct hci_cp_le_set_adv_data cp; | 916 | struct hci_cp_le_set_adv_data cp; |
@@ -907,8 +921,12 @@ static void update_adv_data(struct hci_request *req) | |||
907 | 921 | ||
908 | memset(&cp, 0, sizeof(cp)); | 922 | memset(&cp, 0, sizeof(cp)); |
909 | 923 | ||
910 | len = create_adv_data(hdev, cp.data); | 924 | if (instance) |
925 | len = create_instance_adv_data(hdev, cp.data); | ||
926 | else | ||
927 | len = create_default_adv_data(hdev, cp.data); | ||
911 | 928 | ||
929 | /* There's nothing to do if the data hasn't changed */ | ||
912 | if (hdev->adv_data_len == len && | 930 | if (hdev->adv_data_len == len && |
913 | memcmp(cp.data, hdev->adv_data, len) == 0) | 931 | memcmp(cp.data, hdev->adv_data, len) == 0) |
914 | return; | 932 | return; |
@@ -921,6 +939,25 @@ static void update_adv_data(struct hci_request *req) | |||
921 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | 939 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
922 | } | 940 | } |
923 | 941 | ||
942 | static void update_adv_data(struct hci_request *req) | ||
943 | { | ||
944 | struct hci_dev *hdev = req->hdev; | ||
945 | u8 instance; | ||
946 | |||
947 | /* The "Set Advertising" setting supersedes the "Add Advertising" | ||
948 | * setting. Here we set the advertising data based on which | ||
949 | * setting was set. When neither apply, default to the global settings, | ||
950 | * represented by instance "0". | ||
951 | */ | ||
952 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | ||
953 | !hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
954 | instance = 0x01; | ||
955 | else | ||
956 | instance = 0x00; | ||
957 | |||
958 | update_adv_data_for_instance(req, instance); | ||
959 | } | ||
960 | |||
924 | int mgmt_update_adv_data(struct hci_dev *hdev) | 961 | int mgmt_update_adv_data(struct hci_dev *hdev) |
925 | { | 962 | { |
926 | struct hci_request req; | 963 | struct hci_request req; |
@@ -4374,10 +4411,17 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4374 | return err; | 4411 | return err; |
4375 | } | 4412 | } |
4376 | 4413 | ||
4414 | static void enable_advertising_instance(struct hci_dev *hdev, u8 status, | ||
4415 | u16 opcode) | ||
4416 | { | ||
4417 | BT_DBG("status %d", status); | ||
4418 | } | ||
4419 | |||
4377 | static void set_advertising_complete(struct hci_dev *hdev, u8 status, | 4420 | static void set_advertising_complete(struct hci_dev *hdev, u8 status, |
4378 | u16 opcode) | 4421 | u16 opcode) |
4379 | { | 4422 | { |
4380 | struct cmd_lookup match = { NULL, hdev }; | 4423 | struct cmd_lookup match = { NULL, hdev }; |
4424 | struct hci_request req; | ||
4381 | 4425 | ||
4382 | hci_dev_lock(hdev); | 4426 | hci_dev_lock(hdev); |
4383 | 4427 | ||
@@ -4402,6 +4446,21 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status, | |||
4402 | if (match.sk) | 4446 | if (match.sk) |
4403 | sock_put(match.sk); | 4447 | sock_put(match.sk); |
4404 | 4448 | ||
4449 | /* If "Set Advertising" was just disabled and instance advertising was | ||
4450 | * set up earlier, then enable the advertising instance. | ||
4451 | */ | ||
4452 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
4453 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
4454 | goto unlock; | ||
4455 | |||
4456 | hci_req_init(&req, hdev); | ||
4457 | |||
4458 | update_adv_data(&req); | ||
4459 | enable_advertising(&req); | ||
4460 | |||
4461 | if (hci_req_run(&req, enable_advertising_instance) < 0) | ||
4462 | BT_ERR("Failed to re-configure advertising"); | ||
4463 | |||
4405 | unlock: | 4464 | unlock: |
4406 | hci_dev_unlock(hdev); | 4465 | hci_dev_unlock(hdev); |
4407 | } | 4466 | } |
@@ -4484,10 +4543,13 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4484 | else | 4543 | else |
4485 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE); | 4544 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE); |
4486 | 4545 | ||
4487 | if (val) | 4546 | if (val) { |
4547 | /* Switch to instance "0" for the Set Advertising setting. */ | ||
4548 | update_adv_data_for_instance(&req, 0); | ||
4488 | enable_advertising(&req); | 4549 | enable_advertising(&req); |
4489 | else | 4550 | } else { |
4490 | disable_advertising(&req); | 4551 | disable_advertising(&req); |
4552 | } | ||
4491 | 4553 | ||
4492 | err = hci_req_run(&req, set_advertising_complete); | 4554 | err = hci_req_run(&req, set_advertising_complete); |
4493 | if (err < 0) | 4555 | if (err < 0) |
@@ -6299,12 +6361,21 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, | |||
6299 | struct mgmt_rp_read_adv_features *rp; | 6361 | struct mgmt_rp_read_adv_features *rp; |
6300 | size_t rp_len; | 6362 | size_t rp_len; |
6301 | int err; | 6363 | int err; |
6364 | bool instance; | ||
6302 | 6365 | ||
6303 | BT_DBG("%s", hdev->name); | 6366 | BT_DBG("%s", hdev->name); |
6304 | 6367 | ||
6305 | hci_dev_lock(hdev); | 6368 | hci_dev_lock(hdev); |
6306 | 6369 | ||
6307 | rp_len = sizeof(*rp); | 6370 | rp_len = sizeof(*rp); |
6371 | |||
6372 | /* Currently only one instance is supported, so just add 1 to the | ||
6373 | * response length. | ||
6374 | */ | ||
6375 | instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
6376 | if (instance) | ||
6377 | rp_len++; | ||
6378 | |||
6308 | rp = kmalloc(rp_len, GFP_ATOMIC); | 6379 | rp = kmalloc(rp_len, GFP_ATOMIC); |
6309 | if (!rp) { | 6380 | if (!rp) { |
6310 | hci_dev_unlock(hdev); | 6381 | hci_dev_unlock(hdev); |
@@ -6314,8 +6385,17 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, | |||
6314 | rp->supported_flags = cpu_to_le32(0); | 6385 | rp->supported_flags = cpu_to_le32(0); |
6315 | rp->max_adv_data_len = HCI_MAX_AD_LENGTH; | 6386 | rp->max_adv_data_len = HCI_MAX_AD_LENGTH; |
6316 | rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH; | 6387 | rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH; |
6317 | rp->max_instances = 0; | 6388 | rp->max_instances = 1; |
6318 | rp->num_instances = 0; | 6389 | |
6390 | /* Currently only one instance is supported, so simply return the | ||
6391 | * current instance number. | ||
6392 | */ | ||
6393 | if (instance) { | ||
6394 | rp->num_instances = 1; | ||
6395 | rp->instance[0] = 1; | ||
6396 | } else { | ||
6397 | rp->num_instances = 0; | ||
6398 | } | ||
6319 | 6399 | ||
6320 | hci_dev_unlock(hdev); | 6400 | hci_dev_unlock(hdev); |
6321 | 6401 | ||
@@ -6327,6 +6407,179 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, | |||
6327 | return err; | 6407 | return err; |
6328 | } | 6408 | } |
6329 | 6409 | ||
6410 | static bool adv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *adv_data, | ||
6411 | u8 adv_data_len) | ||
6412 | { | ||
6413 | u8 max_adv_len = HCI_MAX_AD_LENGTH; | ||
6414 | int i, cur_len; | ||
6415 | |||
6416 | /* TODO: Correctly reduce adv_len based on adv_flags. */ | ||
6417 | |||
6418 | if (adv_data_len > max_adv_len) | ||
6419 | return false; | ||
6420 | |||
6421 | /* Make sure that adv_data is correctly formatted. */ | ||
6422 | for (i = 0, cur_len = 0; i < adv_data_len; i += (cur_len + 1)) { | ||
6423 | cur_len = adv_data[i]; | ||
6424 | |||
6425 | /* If the current field length would exceed the total data | ||
6426 | * length, then it's invalid. | ||
6427 | */ | ||
6428 | if (i + cur_len >= adv_data_len) | ||
6429 | return false; | ||
6430 | } | ||
6431 | |||
6432 | return true; | ||
6433 | } | ||
6434 | |||
6435 | static void advertising_added(struct sock *sk, struct hci_dev *hdev, | ||
6436 | u8 instance) | ||
6437 | { | ||
6438 | struct mgmt_ev_advertising_added ev; | ||
6439 | |||
6440 | ev.instance = instance; | ||
6441 | |||
6442 | mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); | ||
6443 | } | ||
6444 | |||
6445 | static void advertising_removed(struct sock *sk, struct hci_dev *hdev, | ||
6446 | u8 instance) | ||
6447 | { | ||
6448 | struct mgmt_ev_advertising_removed ev; | ||
6449 | |||
6450 | ev.instance = instance; | ||
6451 | |||
6452 | mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); | ||
6453 | } | ||
6454 | |||
6455 | static void add_advertising_complete(struct hci_dev *hdev, u8 status, | ||
6456 | u16 opcode) | ||
6457 | { | ||
6458 | struct mgmt_pending_cmd *cmd; | ||
6459 | struct mgmt_rp_add_advertising rp; | ||
6460 | |||
6461 | BT_DBG("status %d", status); | ||
6462 | |||
6463 | hci_dev_lock(hdev); | ||
6464 | |||
6465 | cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev); | ||
6466 | |||
6467 | if (status) { | ||
6468 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
6469 | memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance)); | ||
6470 | advertising_removed(cmd ? cmd->sk : NULL, hdev, 1); | ||
6471 | } | ||
6472 | |||
6473 | if (!cmd) | ||
6474 | goto unlock; | ||
6475 | |||
6476 | rp.instance = 0x01; | ||
6477 | |||
6478 | if (status) | ||
6479 | mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, | ||
6480 | mgmt_status(status)); | ||
6481 | else | ||
6482 | mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, | ||
6483 | mgmt_status(status), &rp, sizeof(rp)); | ||
6484 | |||
6485 | mgmt_pending_remove(cmd); | ||
6486 | |||
6487 | unlock: | ||
6488 | hci_dev_unlock(hdev); | ||
6489 | } | ||
6490 | |||
6491 | static int add_advertising(struct sock *sk, struct hci_dev *hdev, | ||
6492 | void *data, u16 data_len) | ||
6493 | { | ||
6494 | struct mgmt_cp_add_advertising *cp = data; | ||
6495 | struct mgmt_rp_add_advertising rp; | ||
6496 | u32 flags; | ||
6497 | u8 status; | ||
6498 | int err; | ||
6499 | struct mgmt_pending_cmd *cmd; | ||
6500 | struct hci_request req; | ||
6501 | |||
6502 | BT_DBG("%s", hdev->name); | ||
6503 | |||
6504 | status = mgmt_le_support(hdev); | ||
6505 | if (status) | ||
6506 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | ||
6507 | status); | ||
6508 | |||
6509 | flags = __le32_to_cpu(cp->flags); | ||
6510 | |||
6511 | /* The current implementation only supports adding one instance and | ||
6512 | * doesn't support flags. | ||
6513 | */ | ||
6514 | if (cp->instance != 0x01 || flags) | ||
6515 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | ||
6516 | MGMT_STATUS_INVALID_PARAMS); | ||
6517 | |||
6518 | hci_dev_lock(hdev); | ||
6519 | |||
6520 | if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) || | ||
6521 | pending_find(MGMT_OP_SET_LE, hdev)) { | ||
6522 | err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | ||
6523 | MGMT_STATUS_BUSY); | ||
6524 | goto unlock; | ||
6525 | } | ||
6526 | |||
6527 | if (!adv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len)) { | ||
6528 | err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | ||
6529 | MGMT_STATUS_INVALID_PARAMS); | ||
6530 | goto unlock; | ||
6531 | } | ||
6532 | |||
6533 | hdev->adv_instance.flags = flags; | ||
6534 | hdev->adv_instance.adv_data_len = cp->adv_data_len; | ||
6535 | hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len; | ||
6536 | |||
6537 | if (cp->adv_data_len) | ||
6538 | memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len); | ||
6539 | |||
6540 | if (cp->scan_rsp_len) | ||
6541 | memcpy(hdev->adv_instance.scan_rsp_data, | ||
6542 | cp->data + cp->adv_data_len, cp->scan_rsp_len); | ||
6543 | |||
6544 | if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
6545 | advertising_added(sk, hdev, 1); | ||
6546 | |||
6547 | /* If the HCI_ADVERTISING flag is set or the device isn't powered then | ||
6548 | * we have no HCI communication to make. Simply return. | ||
6549 | */ | ||
6550 | if (!hdev_is_powered(hdev) || | ||
6551 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) { | ||
6552 | rp.instance = 0x01; | ||
6553 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | ||
6554 | MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); | ||
6555 | goto unlock; | ||
6556 | } | ||
6557 | |||
6558 | /* We're good to go, update advertising data, parameters, and start | ||
6559 | * advertising. | ||
6560 | */ | ||
6561 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data, | ||
6562 | data_len); | ||
6563 | if (!cmd) { | ||
6564 | err = -ENOMEM; | ||
6565 | goto unlock; | ||
6566 | } | ||
6567 | |||
6568 | hci_req_init(&req, hdev); | ||
6569 | |||
6570 | update_adv_data(&req); | ||
6571 | enable_advertising(&req); | ||
6572 | |||
6573 | err = hci_req_run(&req, add_advertising_complete); | ||
6574 | if (err < 0) | ||
6575 | mgmt_pending_remove(cmd); | ||
6576 | |||
6577 | unlock: | ||
6578 | hci_dev_unlock(hdev); | ||
6579 | |||
6580 | return err; | ||
6581 | } | ||
6582 | |||
6330 | static const struct hci_mgmt_handler mgmt_handlers[] = { | 6583 | static const struct hci_mgmt_handler mgmt_handlers[] = { |
6331 | { NULL }, /* 0x0000 (no command) */ | 6584 | { NULL }, /* 0x0000 (no command) */ |
6332 | { read_version, MGMT_READ_VERSION_SIZE, | 6585 | { read_version, MGMT_READ_VERSION_SIZE, |
@@ -6411,6 +6664,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = { | |||
6411 | HCI_MGMT_NO_HDEV | | 6664 | HCI_MGMT_NO_HDEV | |
6412 | HCI_MGMT_UNTRUSTED }, | 6665 | HCI_MGMT_UNTRUSTED }, |
6413 | { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE }, | 6666 | { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE }, |
6667 | { add_advertising, MGMT_ADD_ADVERTISING_SIZE, | ||
6668 | HCI_MGMT_VAR_LEN }, | ||
6414 | }; | 6669 | }; |
6415 | 6670 | ||
6416 | void mgmt_index_added(struct hci_dev *hdev) | 6671 | void mgmt_index_added(struct hci_dev *hdev) |
@@ -6582,7 +6837,8 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
6582 | update_scan_rsp_data(&req); | 6837 | update_scan_rsp_data(&req); |
6583 | } | 6838 | } |
6584 | 6839 | ||
6585 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 6840 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || |
6841 | hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
6586 | enable_advertising(&req); | 6842 | enable_advertising(&req); |
6587 | 6843 | ||
6588 | restart_le_actions(&req); | 6844 | restart_le_actions(&req); |
@@ -6694,7 +6950,13 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) | |||
6694 | sizeof(scan), &scan); | 6950 | sizeof(scan), &scan); |
6695 | } | 6951 | } |
6696 | update_class(&req); | 6952 | update_class(&req); |
6697 | update_adv_data(&req); | 6953 | |
6954 | /* Advertising instances don't use the global discoverable setting, so | ||
6955 | * only update AD if advertising was enabled using Set Advertising. | ||
6956 | */ | ||
6957 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
6958 | update_adv_data(&req); | ||
6959 | |||
6698 | hci_req_run(&req, NULL); | 6960 | hci_req_run(&req, NULL); |
6699 | 6961 | ||
6700 | hdev->discov_timeout = 0; | 6962 | hdev->discov_timeout = 0; |
@@ -7595,7 +7857,8 @@ void mgmt_reenable_advertising(struct hci_dev *hdev) | |||
7595 | { | 7857 | { |
7596 | struct hci_request req; | 7858 | struct hci_request req; |
7597 | 7859 | ||
7598 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 7860 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) && |
7861 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
7599 | return; | 7862 | return; |
7600 | 7863 | ||
7601 | hci_req_init(&req, hdev); | 7864 | hci_req_init(&req, hdev); |