Skip to content

Commit 37adf70

Browse files
dwinkler2holtmann
authored andcommitted
Bluetooth: Add per-instance adv disable/remove
Add functionality to disable and remove advertising instances, and use that functionality in MGMT add/remove advertising calls. Currently, advertising is globally-disabled, i.e. all instances are disabled together, even if hardware offloading is available. This patch adds functionality to disable and remove individual adv instances, solving two issues: 1. On new advertisement registration, a global disable was done, and then only the new instance was enabled. This meant only the newest instance was actually enabled. 2. On advertisement removal, the structure was removed, but the instance was never disabled or removed, which is incorrect with hardware offload support. Signed-off-by: Daniel Winkler <[email protected]> Reviewed-by: Shyh-In Hwang <[email protected]> Reviewed-by: Alain Michaud <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 629b49c commit 37adf70

File tree

4 files changed

+59
-10
lines changed

4 files changed

+59
-10
lines changed

net/bluetooth/hci_conn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ static void hci_req_directed_advertising(struct hci_request *req,
931931
* So it is required to remove adv set for handle 0x00. since we use
932932
* instance 0 for directed adv.
933933
*/
934-
hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, sizeof(cp.handle), &cp.handle);
934+
__hci_req_remove_ext_adv_instance(req, cp.handle);
935935

936936
hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
937937

net/bluetooth/hci_request.c

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,13 +1179,8 @@ static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
11791179
void __hci_req_disable_advertising(struct hci_request *req)
11801180
{
11811181
if (ext_adv_capable(req->hdev)) {
1182-
struct hci_cp_le_set_ext_adv_enable cp;
1182+
__hci_req_disable_ext_adv_instance(req, 0x00);
11831183

1184-
cp.enable = 0x00;
1185-
/* Disable all sets since we only support one set at the moment */
1186-
cp.num_of_sets = 0x00;
1187-
1188-
hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(cp), &cp);
11891184
} else {
11901185
u8 enable = 0x00;
11911186

@@ -1950,13 +1945,59 @@ int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance)
19501945
return 0;
19511946
}
19521947

1948+
int __hci_req_disable_ext_adv_instance(struct hci_request *req, u8 instance)
1949+
{
1950+
struct hci_dev *hdev = req->hdev;
1951+
struct hci_cp_le_set_ext_adv_enable *cp;
1952+
struct hci_cp_ext_adv_set *adv_set;
1953+
u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
1954+
u8 req_size;
1955+
1956+
/* If request specifies an instance that doesn't exist, fail */
1957+
if (instance > 0 && !hci_find_adv_instance(hdev, instance))
1958+
return -EINVAL;
1959+
1960+
memset(data, 0, sizeof(data));
1961+
1962+
cp = (void *)data;
1963+
adv_set = (void *)cp->data;
1964+
1965+
/* Instance 0x00 indicates all advertising instances will be disabled */
1966+
cp->num_of_sets = !!instance;
1967+
cp->enable = 0x00;
1968+
1969+
adv_set->handle = instance;
1970+
1971+
req_size = sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets;
1972+
hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, req_size, data);
1973+
1974+
return 0;
1975+
}
1976+
1977+
int __hci_req_remove_ext_adv_instance(struct hci_request *req, u8 instance)
1978+
{
1979+
struct hci_dev *hdev = req->hdev;
1980+
1981+
/* If request specifies an instance that doesn't exist, fail */
1982+
if (instance > 0 && !hci_find_adv_instance(hdev, instance))
1983+
return -EINVAL;
1984+
1985+
hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, sizeof(instance), &instance);
1986+
1987+
return 0;
1988+
}
1989+
19531990
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
19541991
{
19551992
struct hci_dev *hdev = req->hdev;
1993+
struct adv_info *adv_instance = hci_find_adv_instance(hdev, instance);
19561994
int err;
19571995

1958-
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
1959-
__hci_req_disable_advertising(req);
1996+
/* If instance isn't pending, the chip knows about it, and it's safe to
1997+
* disable
1998+
*/
1999+
if (adv_instance && !adv_instance->pending)
2000+
__hci_req_disable_ext_adv_instance(req, instance);
19602001

19612002
err = __hci_req_setup_ext_adv_instance(req, instance);
19622003
if (err < 0)
@@ -2104,7 +2145,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
21042145
hci_dev_test_flag(hdev, HCI_ADVERTISING))
21052146
return;
21062147

2107-
if (next_instance)
2148+
if (next_instance && !ext_adv_capable(hdev))
21082149
__hci_req_schedule_adv_instance(req, next_instance->instance,
21092150
false);
21102151
}

net/bluetooth/hci_request.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
8686
int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
8787
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
8888
int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance);
89+
int __hci_req_disable_ext_adv_instance(struct hci_request *req, u8 instance);
90+
int __hci_req_remove_ext_adv_instance(struct hci_request *req, u8 instance);
8991
void __hci_req_clear_ext_adv_sets(struct hci_request *req);
9092
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
9193
bool use_rpa, struct adv_info *adv_instance,

net/bluetooth/mgmt.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7504,6 +7504,12 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
75047504

75057505
hci_req_init(&req, hdev);
75067506

7507+
/* If we use extended advertising, instance is disabled and removed */
7508+
if (ext_adv_capable(hdev)) {
7509+
__hci_req_disable_ext_adv_instance(&req, cp->instance);
7510+
__hci_req_remove_ext_adv_instance(&req, cp->instance);
7511+
}
7512+
75077513
hci_req_clear_adv_instance(hdev, sk, &req, cp->instance, true);
75087514

75097515
if (list_empty(&hdev->adv_instances))

0 commit comments

Comments
 (0)