Skip to content

Commit abfeea4

Browse files
Vudentzholtmann
authored andcommitted
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use hci_cmd_sync_queue so they no longer depend on hdev->discov_update work to send any commands. Tested with: tools/mgmt-tester -s "Start Discovery" Test Summary ------------ Start Discovery - Not powered 1 Passed Start Discovery - Invalid parameters 1 Passed Start Discovery - Not supported 1 Passed Start Discovery - Success 1 Passed Start Discovery - Success 2 Passed Start Discovery - Power Off 1 Passed Start Discovery BREDR LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Param) Passed Start Discovery - (2m, Scan Param) Passed Start Discovery - (coded, Scan Param) Passed Start Discovery - (1m, 2m, coded, Scan Param) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Start Service" Test Summary ------------ Start Service Discovery - Not powered 1 Passed Start Service Discovery - Invalid parameters 1 Passed Start Service Discovery - Not supported 1 Passed Start Service Discovery - Success 1 Passed Start Service Discovery - Success 2 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Stop Discovery" Test Summary ------------ Stop Discovery - Success 1 Passed Stop Discovery - BR/EDR (Inquiry) Success 1 Passed Stop Discovery - Rejected 1 Passed Stop Discovery - Invalid parameters 1 Passed Stop Discovery - (Ext Scan Disable) Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent cf75ad8 commit abfeea4

File tree

5 files changed

+310
-56
lines changed

5 files changed

+310
-56
lines changed

include/net/bluetooth/hci_sync.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance);
5959
int hci_start_ext_adv_sync(struct hci_dev *hdev, u8 instance);
6060
int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance);
6161
int hci_enable_advertising_sync(struct hci_dev *hdev);
62+
int hci_enable_advertising(struct hci_dev *hdev);
6263

6364
int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
6465
u8 instance, bool force);
@@ -72,3 +73,6 @@ int hci_dev_close_sync(struct hci_dev *hdev);
7273

7374
int hci_powered_update_sync(struct hci_dev *hdev);
7475
int hci_set_powered_sync(struct hci_dev *hdev, u8 val);
76+
77+
int hci_start_discovery_sync(struct hci_dev *hdev);
78+
int hci_stop_discovery_sync(struct hci_dev *hdev);

net/bluetooth/hci_conn.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,10 +915,10 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
915915
*/
916916
hci_update_passive_scan(hdev);
917917

918-
/* Re-enable advertising in case this was a failed connection
918+
/* Enable advertising in case this was a failed connection
919919
* attempt as a peripheral.
920920
*/
921-
hci_req_reenable_advertising(hdev);
921+
hci_enable_advertising(hdev);
922922
}
923923

924924
static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode)

net/bluetooth/hci_event.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,16 +1514,10 @@ static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
15141514

15151515
/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
15161516
* interrupted scanning due to a connect request. Mark
1517-
* therefore discovery as stopped. If this was not
1518-
* because of a connect request advertising might have
1519-
* been disabled because of active scanning, so
1520-
* re-enable it again if necessary.
1517+
* therefore discovery as stopped.
15211518
*/
15221519
if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED))
15231520
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1524-
else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) &&
1525-
hdev->discovery.state == DISCOVERY_FINDING)
1526-
hci_req_reenable_advertising(hdev);
15271521

15281522
break;
15291523

@@ -2440,7 +2434,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
24402434

24412435
if (conn->type == LE_LINK && conn->role == HCI_ROLE_SLAVE) {
24422436
hdev->cur_adv_instance = conn->adv_instance;
2443-
hci_req_reenable_advertising(hdev);
2437+
hci_enable_advertising(hdev);
24442438
}
24452439

24462440
/* If the disconnection failed for any reason, the upper layer
@@ -3050,7 +3044,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
30503044
*/
30513045
if (conn->type == LE_LINK && conn->role == HCI_ROLE_SLAVE) {
30523046
hdev->cur_adv_instance = conn->adv_instance;
3053-
hci_req_reenable_advertising(hdev);
3047+
hci_enable_advertising(hdev);
30543048
}
30553049

30563050
hci_conn_del(conn);
@@ -5500,9 +5494,6 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
55005494
le16_to_cpu(ev->interval),
55015495
le16_to_cpu(ev->latency),
55025496
le16_to_cpu(ev->supervision_timeout));
5503-
5504-
if (hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION))
5505-
hci_req_disable_address_resolution(hdev);
55065497
}
55075498

55085499
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)

net/bluetooth/hci_sync.c

Lines changed: 226 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,6 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
189189
return ERR_PTR(err);
190190
}
191191

192-
if (!skb)
193-
return ERR_PTR(-ENODATA);
194-
195192
return skb;
196193
}
197194
EXPORT_SYMBOL(__hci_cmd_sync_sk);
@@ -241,12 +238,19 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
241238
u8 status;
242239

243240
skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
244-
if (IS_ERR_OR_NULL(skb)) {
241+
if (IS_ERR(skb)) {
245242
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
246243
PTR_ERR(skb));
247244
return PTR_ERR(skb);
248245
}
249246

247+
/* If command return a status event skb will be set to NULL as there are
248+
* no parameters, in case of failure IS_ERR(skb) would have be set to
249+
* the actual error would be found with PTR_ERR(skb).
250+
*/
251+
if (!skb)
252+
return 0;
253+
250254
status = skb->data[0];
251255

252256
kfree_skb(skb);
@@ -1017,8 +1021,22 @@ int hci_enable_advertising_sync(struct hci_dev *hdev)
10171021
sizeof(enable), &enable, HCI_CMD_TIMEOUT);
10181022
}
10191023

1020-
static int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance,
1021-
struct sock *sk)
1024+
static int enable_advertising_sync(struct hci_dev *hdev, void *data)
1025+
{
1026+
return hci_enable_advertising_sync(hdev);
1027+
}
1028+
1029+
int hci_enable_advertising(struct hci_dev *hdev)
1030+
{
1031+
if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
1032+
list_empty(&hdev->adv_instances))
1033+
return 0;
1034+
1035+
return hci_cmd_sync_queue(hdev, enable_advertising_sync, NULL, NULL);
1036+
}
1037+
1038+
int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance,
1039+
struct sock *sk)
10221040
{
10231041
int err;
10241042

@@ -1622,7 +1640,7 @@ static int hci_pause_advertising_sync(struct hci_dev *hdev)
16221640
return 0;
16231641
}
16241642

1625-
/* This function disables all user advertising instances (excluding 0x00) */
1643+
/* This function enables all user advertising instances (excluding 0x00) */
16261644
static int hci_resume_advertising_sync(struct hci_dev *hdev)
16271645
{
16281646
struct adv_info *adv, *tmp;
@@ -1870,7 +1888,8 @@ static int hci_le_set_scan_param_sync(struct hci_dev *hdev, u8 type,
18701888
}
18711889

18721890
static int hci_start_scan_sync(struct hci_dev *hdev, u8 type, u16 interval,
1873-
u16 window, u8 own_addr_type, u8 filter_policy)
1891+
u16 window, u8 own_addr_type, u8 filter_policy,
1892+
u8 filter_dup)
18741893
{
18751894
int err;
18761895

@@ -1884,8 +1903,7 @@ static int hci_start_scan_sync(struct hci_dev *hdev, u8 type, u16 interval,
18841903
if (err)
18851904
return err;
18861905

1887-
return hci_le_set_scan_enable_sync(hdev, LE_SCAN_ENABLE,
1888-
LE_SCAN_FILTER_DUP_ENABLE);
1906+
return hci_le_set_scan_enable_sync(hdev, LE_SCAN_ENABLE, filter_dup);
18891907
}
18901908

18911909
int hci_passive_scan_sync(struct hci_dev *hdev)
@@ -1960,7 +1978,8 @@ int hci_passive_scan_sync(struct hci_dev *hdev)
19601978
bt_dev_dbg(hdev, "LE passive scan with acceptlist = %d", filter_policy);
19611979

19621980
return hci_start_scan_sync(hdev, LE_SCAN_PASSIVE, interval, window,
1963-
own_addr_type, filter_policy);
1981+
own_addr_type, filter_policy,
1982+
LE_SCAN_FILTER_DUP_ENABLE);
19641983
}
19651984

19661985
/* This function controls the passive scanning based on hdev->pend_le_conns
@@ -2420,7 +2439,7 @@ static int hci_remote_name_cancel_sync(struct hci_dev *hdev, bdaddr_t *addr)
24202439
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
24212440
}
24222441

2423-
static int hci_stop_discovery_sync(struct hci_dev *hdev)
2442+
int hci_stop_discovery_sync(struct hci_dev *hdev)
24242443
{
24252444
struct discovery_state *d = &hdev->discovery;
24262445
struct inquiry_entry *e;
@@ -2451,6 +2470,10 @@ static int hci_stop_discovery_sync(struct hci_dev *hdev)
24512470
return err;
24522471
}
24532472

2473+
/* Resume advertising if it was paused */
2474+
if (use_ll_privacy(hdev))
2475+
hci_resume_advertising_sync(hdev);
2476+
24542477
/* No further actions needed for LE-only discovery */
24552478
if (d->type == DISCOV_TYPE_LE)
24562479
return 0;
@@ -2618,3 +2641,194 @@ int hci_set_powered_sync(struct hci_dev *hdev, u8 val)
26182641

26192642
return hci_power_off_sync(hdev);
26202643
}
2644+
2645+
static int hci_inquiry_sync(struct hci_dev *hdev, u8 length)
2646+
{
2647+
const u8 giac[3] = { 0x33, 0x8b, 0x9e };
2648+
const u8 liac[3] = { 0x00, 0x8b, 0x9e };
2649+
struct hci_cp_inquiry cp;
2650+
2651+
bt_dev_dbg(hdev, "");
2652+
2653+
if (hci_dev_test_flag(hdev, HCI_INQUIRY))
2654+
return 0;
2655+
2656+
hci_dev_lock(hdev);
2657+
hci_inquiry_cache_flush(hdev);
2658+
hci_dev_unlock(hdev);
2659+
2660+
memset(&cp, 0, sizeof(cp));
2661+
2662+
if (hdev->discovery.limited)
2663+
memcpy(&cp.lap, liac, sizeof(cp.lap));
2664+
else
2665+
memcpy(&cp.lap, giac, sizeof(cp.lap));
2666+
2667+
cp.length = length;
2668+
2669+
return __hci_cmd_sync_status(hdev, HCI_OP_INQUIRY,
2670+
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
2671+
}
2672+
2673+
static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
2674+
{
2675+
u8 own_addr_type;
2676+
/* Accept list is not used for discovery */
2677+
u8 filter_policy = 0x00;
2678+
/* Default is to enable duplicates filter */
2679+
u8 filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
2680+
int err;
2681+
2682+
bt_dev_dbg(hdev, "");
2683+
2684+
/* If controller is scanning, it means the passive scanning is
2685+
* running. Thus, we should temporarily stop it in order to set the
2686+
* discovery scanning parameters.
2687+
*/
2688+
err = hci_scan_disable_sync(hdev);
2689+
if (err) {
2690+
bt_dev_err(hdev, "Unable to disable scanning: %d", err);
2691+
return err;
2692+
}
2693+
2694+
cancel_interleave_scan(hdev);
2695+
2696+
/* Pause advertising since active scanning disables address resolution
2697+
* which advertising depend on in order to generate its RPAs.
2698+
*/
2699+
if (use_ll_privacy(hdev)) {
2700+
err = hci_pause_advertising_sync(hdev);
2701+
if (err) {
2702+
bt_dev_err(hdev, "pause advertising failed: %d", err);
2703+
goto failed;
2704+
}
2705+
}
2706+
2707+
/* Disable address resolution while doing active scanning since the
2708+
* accept list shall not be used and all reports shall reach the host
2709+
* anyway.
2710+
*/
2711+
err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
2712+
if (err) {
2713+
bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
2714+
err);
2715+
goto failed;
2716+
}
2717+
2718+
/* All active scans will be done with either a resolvable private
2719+
* address (when privacy feature has been enabled) or non-resolvable
2720+
* private address.
2721+
*/
2722+
err = hci_update_random_address_sync(hdev, true, scan_use_rpa(hdev),
2723+
&own_addr_type);
2724+
if (err < 0)
2725+
own_addr_type = ADDR_LE_DEV_PUBLIC;
2726+
2727+
if (hci_is_adv_monitoring(hdev)) {
2728+
/* Duplicate filter should be disabled when some advertisement
2729+
* monitor is activated, otherwise AdvMon can only receive one
2730+
* advertisement for one peer(*) during active scanning, and
2731+
* might report loss to these peers.
2732+
*
2733+
* Note that different controllers have different meanings of
2734+
* |duplicate|. Some of them consider packets with the same
2735+
* address as duplicate, and others consider packets with the
2736+
* same address and the same RSSI as duplicate. Although in the
2737+
* latter case we don't need to disable duplicate filter, but
2738+
* it is common to have active scanning for a short period of
2739+
* time, the power impact should be neglectable.
2740+
*/
2741+
filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
2742+
}
2743+
2744+
err = hci_start_scan_sync(hdev, LE_SCAN_ACTIVE, interval,
2745+
hdev->le_scan_window_discovery,
2746+
own_addr_type, filter_policy, filter_dup);
2747+
if (!err)
2748+
return err;
2749+
2750+
failed:
2751+
/* Resume advertising if it was paused */
2752+
if (use_ll_privacy(hdev))
2753+
hci_resume_advertising_sync(hdev);
2754+
2755+
/* Resume passive scanning */
2756+
hci_update_passive_scan_sync(hdev);
2757+
return err;
2758+
}
2759+
2760+
static int hci_start_interleaved_discovery_sync(struct hci_dev *hdev)
2761+
{
2762+
int err;
2763+
2764+
bt_dev_dbg(hdev, "");
2765+
2766+
err = hci_active_scan_sync(hdev, hdev->le_scan_int_discovery * 2);
2767+
if (err)
2768+
return err;
2769+
2770+
return hci_inquiry_sync(hdev, DISCOV_BREDR_INQUIRY_LEN);
2771+
}
2772+
2773+
int hci_start_discovery_sync(struct hci_dev *hdev)
2774+
{
2775+
unsigned long timeout;
2776+
int err;
2777+
2778+
bt_dev_dbg(hdev, "type %u", hdev->discovery.type);
2779+
2780+
switch (hdev->discovery.type) {
2781+
case DISCOV_TYPE_BREDR:
2782+
return hci_inquiry_sync(hdev, DISCOV_BREDR_INQUIRY_LEN);
2783+
case DISCOV_TYPE_INTERLEAVED:
2784+
/* When running simultaneous discovery, the LE scanning time
2785+
* should occupy the whole discovery time sine BR/EDR inquiry
2786+
* and LE scanning are scheduled by the controller.
2787+
*
2788+
* For interleaving discovery in comparison, BR/EDR inquiry
2789+
* and LE scanning are done sequentially with separate
2790+
* timeouts.
2791+
*/
2792+
if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
2793+
&hdev->quirks)) {
2794+
timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
2795+
/* During simultaneous discovery, we double LE scan
2796+
* interval. We must leave some time for the controller
2797+
* to do BR/EDR inquiry.
2798+
*/
2799+
err = hci_start_interleaved_discovery_sync(hdev);
2800+
break;
2801+
}
2802+
2803+
timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
2804+
err = hci_active_scan_sync(hdev, hdev->le_scan_int_discovery);
2805+
break;
2806+
case DISCOV_TYPE_LE:
2807+
timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
2808+
err = hci_active_scan_sync(hdev, hdev->le_scan_int_discovery);
2809+
break;
2810+
default:
2811+
return -EINVAL;
2812+
}
2813+
2814+
if (err)
2815+
return err;
2816+
2817+
bt_dev_dbg(hdev, "timeout %u ms", jiffies_to_msecs(timeout));
2818+
2819+
/* When service discovery is used and the controller has a
2820+
* strict duplicate filter, it is important to remember the
2821+
* start and duration of the scan. This is required for
2822+
* restarting scanning during the discovery phase.
2823+
*/
2824+
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) &&
2825+
hdev->discovery.result_filtering) {
2826+
hdev->discovery.scan_start = jiffies;
2827+
hdev->discovery.scan_duration = timeout;
2828+
}
2829+
2830+
queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_disable,
2831+
timeout);
2832+
2833+
return 0;
2834+
}

0 commit comments

Comments
 (0)