2011-06-10 19:35:57

by Andre Guedes

[permalink] [raw]
Subject: [RFC 00/16] Full support discovery procedure

Hi All,

This patch series implements the full support to discovery procedure through
management interface. Today, only BR/EDR devices are supported. This work is
part of the effort to have discovery procedures and name resolution supported
in management interface.

Before beginning LE-Only and BR/EDR/LE support, it was needed to fix some
issues in BR/EDR discovery. These issues are discussed in patches 1 to 6.

Thanks,

Andre Guedes.

Andre Guedes (16):
Bluetooth: Periodic Inquiry and mgmt discovering event
Bluetooth: Add failed/complete functions to discovery commands
Bluetooth: Remove pending discovery commands
Bluetooth: Check pending command in start_discovery()
Bluetooth: Check pending commands in stop_discovery()
Bluetooth: Fix stop_discovery()
Bluetooth: Create do_inquiry()
Bluetooth: Create cancel_inquiry()
Bluetooth: Prepare for full support discovery procedures
Bluetooth: Check 'dev_class' in mgmt_device_found()
Bluetooth: Add 'eir_len' param to mgmt_device_found()
Bluetooth: Report LE devices
Bluetooth: Add 'le_scan_timer' to struct hci_dev
Bluetooth: Add LE Scan helper functions
Bluetooth: Support LE-Only discovery procedure
Bluetooth: Support BR/EDR/LE discovery procedure

include/net/bluetooth/hci.h | 12 ++
include/net/bluetooth/hci_core.h | 12 ++-
net/bluetooth/hci_core.c | 19 +++
net/bluetooth/hci_event.c | 145 +++++++++++++++------
net/bluetooth/mgmt.c | 262 ++++++++++++++++++++++++++++++++++++--
5 files changed, 398 insertions(+), 52 deletions(-)

--
1.7.4.1



2011-06-10 19:36:13

by Andre Guedes

[permalink] [raw]
Subject: [RFC 16/16] Bluetooth: Support BR/EDR/LE discovery procedure

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_event.c | 20 +++++++++++++++-----
net/bluetooth/mgmt.c | 34 +++++++++++++++++++++++++++++++++-
3 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4eb365d..128a678 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -834,6 +834,8 @@ int mgmt_start_discovery_failed(u16 index);
int mgmt_stop_discovery_complete(u16 index);
int mgmt_stop_discovery_failed(u16 index);
int mgmt_has_pending_stop_discov(u16 index);
+int mgmt_is_interleaved_discovery(u16 index);
+int mgmt_do_interleaved_discovery(u16 index);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 709c3e1..3ca749b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -881,7 +881,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
goto unlock;
}

- mgmt_discovering(hdev->id, 1);
+ if (!mgmt_is_interleaved_discovery(hdev->id))
+ mgmt_discovering(hdev->id, 1);
} else if (cp->enable == 0x00) {
if (status) {
if (mgmt_has_pending_stop_discov(hdev->id))
@@ -1315,13 +1316,22 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff

hci_dev_lock(hdev);

- mgmt_discovering(hdev->id, 0);
-
- if (mgmt_has_pending_stop_discov(hdev->id))
+ if (mgmt_has_pending_stop_discov(hdev->id)) {
+ mgmt_discovering(hdev->id, 0);
mgmt_stop_discovery_complete(hdev->id);
- else
+ goto unlock;
+ }
+
+ if (mgmt_is_interleaved_discovery(hdev->id)) {
+ int err = mgmt_do_interleaved_discovery(hdev->id);
+ if (err)
+ mgmt_start_discovery_failed(hdev->id);
+ } else {
+ mgmt_discovering(hdev->id, 0);
mgmt_start_discovery_complete(hdev->id);
+ }

+unlock:
hci_dev_unlock(hdev);
}

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c780367..f3483b5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -40,6 +40,8 @@ enum bt_device_type {
};

#define BREDR_ONLY_INQ_LENGTH 0x08 /* TGAP(100) */
+#define BREDR_LE_INQ_LENGTH 0x04 /* TGAP(100)/2 */
+#define BREDR_LE_SCAN_TIMEOUT 5120 /* TGAP(100)/2 */
#define LE_ONLY_SCAN_TIMEOUT 10240 /* TGAP(gen_disc_scan_min) */

struct pending_cmd {
@@ -1717,7 +1719,7 @@ static int start_discovery(struct sock *sk, u16 index)
err = do_le_scan(hdev, LE_ONLY_SCAN_TIMEOUT);
break;
case BREDR_LE:
- err = -ENOSYS;
+ err = do_inquiry(hdev, BREDR_LE_INQ_LENGTH);
break;
default:
err = -EINVAL;
@@ -2394,3 +2396,33 @@ int mgmt_has_pending_stop_discov(u16 index)

return 0;
}
+
+int mgmt_is_interleaved_discovery(u16 index)
+{
+ struct hci_dev *hdev;
+
+ hdev = hci_dev_get(index);
+
+ if (get_device_type(hdev) == BREDR_LE &&
+ mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev->id))
+ return 1;
+
+ hci_dev_put(hdev);
+
+ return 0;
+}
+
+/* hdev must be locked */
+int mgmt_do_interleaved_discovery(u16 index)
+{
+ int err;
+ struct hci_dev *hdev;
+
+ hdev = hci_dev_get(index);
+
+ err = do_le_scan(hdev, BREDR_LE_SCAN_TIMEOUT);
+
+ hci_dev_put(hdev);
+
+ return err;
+}
--
1.7.4.1


2011-06-10 19:36:12

by Andre Guedes

[permalink] [raw]
Subject: [RFC 15/16] Bluetooth: Support LE-Only discovery procedure

This patch adds support for LE-Only discovery procedure through
management interface.

A new flag (HCI_LE_SCAN) was created to inform if the controller is
performing LE scan. The HCI_LE_SCAN flag is set/cleared when the
controller starts/stops scanning.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 2 +
net/bluetooth/hci_event.c | 47 ++++++++++++++++++++++++++++++++++++++++--
net/bluetooth/mgmt.c | 5 ++++
3 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c92a4cc..7e82b2c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -86,6 +86,8 @@ enum {
HCI_DEBUG_KEYS,

HCI_RESET,
+
+ HCI_LE_SCAN,
};

/* HCI ioctl defines */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index fa6e6f7..709c3e1 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -840,6 +840,17 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
rp->randomizer, rp->status);
}

+/* hdev must be locked */
+static inline void disable_le_scan(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_enable cp;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.enable = 0;
+
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+}
+
static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -848,9 +859,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,

BT_DBG("%s status 0x%x", hdev->name, status);

- if (status)
- return;
-
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
if (!cp)
return;
@@ -858,12 +866,45 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
hci_dev_lock(hdev);

if (cp->enable == 0x01) {
+ if (status) {
+ mgmt_start_discovery_failed(hdev->id);
+ goto unlock;
+ }
+
+ set_bit(HCI_LE_SCAN, &hdev->flags);
+
del_timer(&hdev->adv_timer);
hci_adv_entries_clear(hdev);
+
+ if (mgmt_has_pending_stop_discov(hdev->id)) {
+ disable_le_scan(hdev);
+ goto unlock;
+ }
+
+ mgmt_discovering(hdev->id, 1);
} else if (cp->enable == 0x00) {
+ if (status) {
+ if (mgmt_has_pending_stop_discov(hdev->id))
+ mgmt_stop_discovery_failed(hdev->id);
+ else
+ mgmt_start_discovery_failed(hdev->id);
+
+ goto unlock;
+ }
+
+ clear_bit(HCI_LE_SCAN, &hdev->flags);
+
mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
+
+ mgmt_discovering(hdev->id, 0);
+
+ if (mgmt_has_pending_stop_discov(hdev->id))
+ mgmt_stop_discovery_complete(hdev->id);
+ else
+ mgmt_start_discovery_complete(hdev->id);
}

+unlock:
hci_dev_unlock(hdev);
}

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9e60416..c780367 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -40,6 +40,7 @@ enum bt_device_type {
};

#define BREDR_ONLY_INQ_LENGTH 0x08 /* TGAP(100) */
+#define LE_ONLY_SCAN_TIMEOUT 10240 /* TGAP(gen_disc_scan_min) */

struct pending_cmd {
struct list_head list;
@@ -1713,6 +1714,8 @@ static int start_discovery(struct sock *sk, u16 index)
err = do_inquiry(hdev, BREDR_ONLY_INQ_LENGTH);
break;
case LE_ONLY:
+ err = do_le_scan(hdev, LE_ONLY_SCAN_TIMEOUT);
+ break;
case BREDR_LE:
err = -ENOSYS;
break;
@@ -1777,6 +1780,8 @@ static int stop_discovery(struct sock *sk, u16 index)

if (test_bit(HCI_INQUIRY, &hdev->flags))
err = cancel_inquiry(hdev);
+ else if (test_bit(HCI_LE_SCAN, &hdev->flags))
+ err = cancel_le_scan(hdev);

if (err < 0)
mgmt_pending_remove(cmd);
--
1.7.4.1


2011-06-10 19:36:11

by Andre Guedes

[permalink] [raw]
Subject: [RFC 14/16] Bluetooth: Add LE Scan helper functions

This patch adds some helper functions to perform LE scan according
to the general discovery procedure recommendations.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 9 +++++++
net/bluetooth/mgmt.c | 56 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 7a0dd4f..c92a4cc 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -711,6 +711,15 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;

+#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
+struct hci_cp_le_set_scan_param {
+ __u8 type;
+ __le16 interval;
+ __le16 window;
+ __u8 own_address_type;
+ __u8 filter_policy;
+} __packed;
+
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct hci_cp_le_set_scan_enable {
__u8 enable;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9453b1a..9e60416 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1619,6 +1619,54 @@ static int do_inquiry(struct hci_dev *hdev, __u8 inq_length)
return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
}

+/* hdev must be locked */
+static int set_le_scan_param(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_param cp;
+
+ /*
+ * These values are set according to LE General Discovery Procedure
+ * specification.
+ */
+ cp.type = 0x01; /* Active scanning */
+ cp.interval = cpu_to_le16(0x0012); /* TGAP(gen_disc_scan_int) */
+ cp.window = cpu_to_le16(0x0012); /* TGAP(gen_disc_scan_wind) */
+ cp.own_address_type = 0x00; /* Public */
+ cp.filter_policy = 0x00; /* Accept all advertisement packets */
+
+ return hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp);
+}
+
+/* hdev must be locked */
+static int enable_le_scan(struct hci_dev *hdev, __u8 enable)
+{
+ struct hci_cp_le_set_scan_enable cp;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.enable = enable;
+
+ return hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+}
+
+/* hdev must be locked */
+static int do_le_scan(struct hci_dev *hdev, int timeout)
+{
+ int err;
+
+ err = set_le_scan_param(hdev);
+ if (err < 0)
+ return err;
+
+ err = enable_le_scan(hdev, 1);
+ if (err < 0)
+ return err;
+
+ mod_timer(&hdev->le_scan_timer,
+ jiffies + msecs_to_jiffies(timeout));
+
+ return 0;
+}
+
static int get_device_type(struct hci_dev *hdev)
{
if (!lmp_no_bredr_capable(hdev) && lmp_le_capable(hdev))
@@ -1688,6 +1736,14 @@ static inline int cancel_inquiry(struct hci_dev *hdev)
return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
}

+/* hdev must be locked */
+static int cancel_le_scan(struct hci_dev *hdev)
+{
+ del_timer(&hdev->le_scan_timer);
+
+ return enable_le_scan(hdev, 0);
+}
+
static int stop_discovery(struct sock *sk, u16 index)
{
struct hci_dev *hdev;
--
1.7.4.1


2011-06-10 19:36:10

by Andre Guedes

[permalink] [raw]
Subject: [RFC 13/16] Bluetooth: Add 'le_scan_timer' to struct hci_dev

This patch adds a timer to disable LE Scan after some amount of
time. The timer will be controlled by the management interface and
it will be used to carry out discovery procedure in LE capable
devices.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_core.c | 19 +++++++++++++++++++
2 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5610c48..4eb365d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -190,6 +190,8 @@ struct hci_dev {
struct list_head adv_entries;
struct timer_list adv_timer;

+ struct timer_list le_scan_timer;
+
struct hci_dev_stats stat;

struct sk_buff_head driver_init;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e14e8a1..1a6bfb8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1274,6 +1274,21 @@ int hci_add_adv_entry(struct hci_dev *hdev,
return 0;
}

+static void hci_disable_le_scan(unsigned long arg)
+{
+ struct hci_cp_le_set_scan_enable cp;
+ struct hci_dev *hdev = (void *) arg;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.enable = 0;
+
+ hci_dev_lock(hdev);
+
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+
+ hci_dev_unlock(hdev);
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1344,6 +1359,9 @@ int hci_register_dev(struct hci_dev *hdev)
setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
(unsigned long) hdev);

+ setup_timer(&hdev->le_scan_timer, hci_disable_le_scan,
+ (unsigned long) hdev);
+
INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->power_off, hci_power_off);
setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1417,6 +1435,7 @@ int hci_unregister_dev(struct hci_dev *hdev)

hci_del_off_timer(hdev);
del_timer(&hdev->adv_timer);
+ del_timer(&hdev->le_scan_timer);

destroy_workqueue(hdev->workqueue);

--
1.7.4.1


2011-06-10 19:36:09

by Andre Guedes

[permalink] [raw]
Subject: [RFC 12/16] Bluetooth: Report LE devices

Devices found during LE scan should be reported to userspace through
mgmt_device_found events.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_event.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9d6fdbb..fa6e6f7 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2733,6 +2733,7 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
{
struct hci_ev_le_advertising_info *ev;
u8 num_reports;
+ s8 rssi;

num_reports = skb->data[0];
ev = (void *) &skb->data[1];
@@ -2741,9 +2742,18 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev,

hci_add_adv_entry(hdev, ev);

+ rssi = ev->data[ev->length];
+ mgmt_device_found(hdev->id, &ev->bdaddr, NULL, rssi, ev->data,
+ ev->length);
+
while (--num_reports) {
ev = (void *) (ev->data + ev->length + 1);
+
hci_add_adv_entry(hdev, ev);
+
+ rssi = ev->data[ev->length];
+ mgmt_device_found(hdev->id, &ev->bdaddr, NULL, rssi, ev->data,
+ ev->length);
}

hci_dev_unlock(hdev);
--
1.7.4.1


2011-06-10 19:36:08

by Andre Guedes

[permalink] [raw]
Subject: [RFC 11/16] Bluetooth: Add 'eir_len' param to mgmt_device_found()

This patch adds a new parameter to mgmt_device_found() to inform
the length of 'eir' pointer.

EIR data from LE advertising report event doesn't have a fixed length
as EIR data from extended inquiry result event does. We needed to
change mgmt_device_found() so it copies 'eir_len' bytes instead of
HCI_MAX_EIR_LENGTH.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 2 +-
net/bluetooth/hci_event.c | 9 +++++----
net/bluetooth/mgmt.c | 7 +++++--
3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 30550c8..5610c48 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -824,7 +824,7 @@ int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
u8 status);
int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
- u8 *eir);
+ u8 *eir, u8 eir_len);
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
int mgmt_discovering(u16 index, u8 discovering);
int mgmt_start_discovery_complete(u16 index);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 540beb7..9d6fdbb 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1308,7 +1308,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
data.ssp_mode = 0x00;
hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
- NULL);
+ NULL, 0);
}

hci_dev_unlock(hdev);
@@ -2284,7 +2284,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr,
info->dev_class, info->rssi,
- NULL);
+ NULL, 0);
}
} else {
struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
@@ -2301,7 +2301,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr,
info->dev_class, info->rssi,
- NULL);
+ NULL, 0);
}
}

@@ -2443,7 +2443,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
data.ssp_mode = 0x01;
hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
- info->rssi, info->data);
+ info->rssi, info->data,
+ sizeof(info->data));
}

hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7c7ef2c..9453b1a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2219,17 +2219,20 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
}

int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
- u8 *eir)
+ u8 *eir, u8 eir_len)
{
struct mgmt_ev_device_found ev;

+ if (eir_len > sizeof(ev.eir))
+ return -EINVAL;
+
memset(&ev, 0, sizeof(ev));

bacpy(&ev.bdaddr, bdaddr);
ev.rssi = rssi;

if (eir)
- memcpy(ev.eir, eir, sizeof(ev.eir));
+ memcpy(ev.eir, eir, eir_len);

if (dev_class)
memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
--
1.7.4.1


2011-06-10 19:36:07

by Andre Guedes

[permalink] [raw]
Subject: [RFC 10/16] Bluetooth: Check 'dev_class' in mgmt_device_found()

The mgmt_device_found event will be used to report LE devices found
during discovery procedure. Since LE advertising reports events
doesn't have class of device information, we need to check if
'dev_class' is not NULL before copying it.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/mgmt.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index bf08564..7c7ef2c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2226,12 +2226,14 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
memset(&ev, 0, sizeof(ev));

bacpy(&ev.bdaddr, bdaddr);
- memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
ev.rssi = rssi;

if (eir)
memcpy(ev.eir, eir, sizeof(ev.eir));

+ if (dev_class)
+ memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
+
return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
}

--
1.7.4.1


2011-06-10 19:36:06

by Andre Guedes

[permalink] [raw]
Subject: [RFC 09/16] Bluetooth: Prepare for full support discovery procedures

This patch prepares start_discovery() to support LE-Only and BR/EDR/LE
devices discovery procedures (BR/EDR devices are already supported).

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/mgmt.c | 37 ++++++++++++++++++++++++++++++++++++-
3 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index bd285c6..7a0dd4f 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -202,6 +202,7 @@ enum {

#define LMP_EV4 0x01
#define LMP_EV5 0x02
+#define LMP_NO_BREDR 0x20
#define LMP_LE 0x40

#define LMP_SNIFF_SUBR 0x02
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 9bfcbb5..30550c8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -572,6 +572,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
+#define lmp_no_bredr_capable(dev) ((dev)->features[4] & LMP_NO_BREDR)
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)

/* ----- HCI protocols ----- */
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 36f6bc2..bf08564 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -32,6 +32,15 @@
#define MGMT_VERSION 0
#define MGMT_REVISION 1

+enum bt_device_type {
+ BREDR_ONLY,
+ LE_ONLY,
+ BREDR_LE,
+ UNKNOWN,
+};
+
+#define BREDR_ONLY_INQ_LENGTH 0x08 /* TGAP(100) */
+
struct pending_cmd {
struct list_head list;
__u16 opcode;
@@ -1610,10 +1619,23 @@ static int do_inquiry(struct hci_dev *hdev, __u8 inq_length)
return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
}

+static int get_device_type(struct hci_dev *hdev)
+{
+ if (!lmp_no_bredr_capable(hdev) && lmp_le_capable(hdev))
+ return BREDR_LE;
+ else if (lmp_le_capable(hdev))
+ return LE_ONLY;
+ else if (!lmp_no_bredr_capable(hdev))
+ return BREDR_ONLY;
+ else
+ return UNKNOWN;
+}
+
static int start_discovery(struct sock *sk, u16 index)
{
struct pending_cmd *cmd;
struct hci_dev *hdev;
+ int dev_type;
int err;

BT_DBG("hci%u", index);
@@ -1636,7 +1658,20 @@ static int start_discovery(struct sock *sk, u16 index)
goto failed;
}

- err = do_inquiry(hdev, 0x08);
+ dev_type = get_device_type(hdev);
+
+ switch (dev_type) {
+ case BREDR_ONLY:
+ err = do_inquiry(hdev, BREDR_ONLY_INQ_LENGTH);
+ break;
+ case LE_ONLY:
+ case BREDR_LE:
+ err = -ENOSYS;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
if (err < 0)
mgmt_pending_remove(cmd);

--
1.7.4.1


2011-06-10 19:36:05

by Andre Guedes

[permalink] [raw]
Subject: [RFC 08/16] Bluetooth: Create cancel_inquiry()

This patch moves all cancel inquiry code from stop_discovery() to
a new function called cancel_inquiry().

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/mgmt.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 21bbf69..36f6bc2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1647,6 +1647,12 @@ failed:
return err;
}

+/* hdev must be locked */
+static inline int cancel_inquiry(struct hci_dev *hdev)
+{
+ return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+}
+
static int stop_discovery(struct sock *sk, u16 index)
{
struct hci_dev *hdev;
@@ -1679,7 +1685,7 @@ static int stop_discovery(struct sock *sk, u16 index)
}

if (test_bit(HCI_INQUIRY, &hdev->flags))
- err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+ err = cancel_inquiry(hdev);

if (err < 0)
mgmt_pending_remove(cmd);
--
1.7.4.1


2011-06-10 19:36:04

by Andre Guedes

[permalink] [raw]
Subject: [RFC 07/16] Bluetooth: Create do_inquiry()

This patch moves all inquiry code from start_discovery() to a new
function called do_inquiry().

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/mgmt.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 12b7fcb..21bbf69 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1597,10 +1597,21 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
return err;
}

-static int start_discovery(struct sock *sk, u16 index)
+/* hdev must be locked */
+static int do_inquiry(struct hci_dev *hdev, __u8 inq_length)
{
u8 lap[3] = { 0x33, 0x8b, 0x9e };
struct hci_cp_inquiry cp;
+
+ memset(&cp, 0, sizeof(cp));
+ memcpy(&cp.lap, lap, 3);
+ cp.length = inq_length;
+
+ return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+}
+
+static int start_discovery(struct sock *sk, u16 index)
+{
struct pending_cmd *cmd;
struct hci_dev *hdev;
int err;
@@ -1625,12 +1636,7 @@ static int start_discovery(struct sock *sk, u16 index)
goto failed;
}

- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.lap, lap, 3);
- cp.length = 0x08;
- cp.num_rsp = 0x00;
-
- err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+ err = do_inquiry(hdev, 0x08);
if (err < 0)
mgmt_pending_remove(cmd);

--
1.7.4.1


2011-06-10 19:36:03

by Andre Guedes

[permalink] [raw]
Subject: [RFC 06/16] Bluetooth: Fix stop_discovery()

According to the Bluetooth spec, the inquiry cancel command should
only be issued after the inquiry command has been issued, a command
status event has been received for the inquiry command, and before
the inquiry complete event occurs.

As HCI_INQUIRY flag is only set just after an inquiry command status
event occurs and it is cleared just after an inquiry complete event
occurs, the inquiry cancel command should be issued only if HCI_INQUIRY
flag is set.

This spec constraint raises two possible race condition we must handle.

1. A MGMT_OP_STOP_DISCOVERY command is issued just after a
MGMT_OP_START_DISCOVERY. The controller haven't sent the inquiry
command status yet so the HCI_INQUIRY flag is not set.

2. While the MGMT_OP_STOP_DISCOVERY is being processed the controller
sends the inquiry complete event and the HCI_INQUIRY flag is
cleared.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_event.c | 15 +++++++++++++--
net/bluetooth/mgmt.c | 14 ++++++++++++--
3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bfa5f0b..9bfcbb5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -830,6 +830,7 @@ int mgmt_start_discovery_complete(u16 index);
int mgmt_start_discovery_failed(u16 index);
int mgmt_stop_discovery_complete(u16 index);
int mgmt_stop_discovery_failed(u16 index);
+int mgmt_has_pending_stop_discov(u16 index);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0f8126d..540beb7 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -882,7 +882,10 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)

set_bit(HCI_INQUIRY, &hdev->flags);

- mgmt_discovering(hdev->id, 1);
+ if (mgmt_has_pending_stop_discov(hdev->id))
+ hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+ else
+ mgmt_discovering(hdev->id, 1);
}

static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
@@ -1269,8 +1272,16 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff

hci_req_complete(hdev, HCI_OP_INQUIRY, status);

+ hci_dev_lock(hdev);
+
mgmt_discovering(hdev->id, 0);
- mgmt_start_discovery_complete(hdev->id);
+
+ if (mgmt_has_pending_stop_discov(hdev->id))
+ mgmt_stop_discovery_complete(hdev->id);
+ else
+ mgmt_start_discovery_complete(hdev->id);
+
+ hci_dev_unlock(hdev);
}

static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 70c7c77..12b7fcb 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1645,7 +1645,7 @@ static int stop_discovery(struct sock *sk, u16 index)
{
struct hci_dev *hdev;
struct pending_cmd *cmd;
- int err;
+ int err = 0;

BT_DBG("hci%u", index);

@@ -1672,7 +1672,9 @@ static int stop_discovery(struct sock *sk, u16 index)
goto failed;
}

- err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+ if (test_bit(HCI_INQUIRY, &hdev->flags))
+ err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+
if (err < 0)
mgmt_pending_remove(cmd);

@@ -2271,3 +2273,11 @@ int mgmt_stop_discovery_failed(u16 index)

return err;
}
+
+int mgmt_has_pending_stop_discov(u16 index)
+{
+ if (mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index))
+ return 1;
+
+ return 0;
+}
--
1.7.4.1


2011-06-10 19:36:02

by Andre Guedes

[permalink] [raw]
Subject: [RFC 05/16] Bluetooth: Check pending commands in stop_discovery()

This patch adds extra checks in stop_discovery().

The MGMT_OP_STOP_DISCOVERY command should be executed if the device
is running the discovery procedure. So, if there is no discovery
procedure running then EINVAL command status should be returned.

Also, if a MGMT_OP_STOP_DISCOVERY command has been already issued
then EINPROGRESS command status should returned.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/mgmt.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 404ec1a..70c7c77 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1655,6 +1655,17 @@ static int stop_discovery(struct sock *sk, u16 index)

hci_dev_lock_bh(hdev);

+ if (!mgmt_pending_find(MGMT_OP_START_DISCOVERY, index)) {
+ err = cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, EINVAL);
+ goto failed;
+ }
+
+ if (mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index)) {
+ err = cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
+ EINPROGRESS);
+ goto failed;
+ }
+
cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0);
if (!cmd) {
err = -ENOMEM;
--
1.7.4.1


2011-06-10 19:36:01

by Andre Guedes

[permalink] [raw]
Subject: [RFC 04/16] Bluetooth: Check pending command in start_discovery()

If discovery procedure is already running then EINPROGRESS command
status should be returned.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/mgmt.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b9115eb..404ec1a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1613,6 +1613,12 @@ static int start_discovery(struct sock *sk, u16 index)

hci_dev_lock_bh(hdev);

+ if (mgmt_pending_find(MGMT_OP_START_DISCOVERY, index)) {
+ err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
+ EINPROGRESS);
+ goto failed;
+ }
+
cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
if (!cmd) {
err = -ENOMEM;
--
1.7.4.1


2011-06-10 19:36:00

by Andre Guedes

[permalink] [raw]
Subject: [RFC 03/16] Bluetooth: Remove pending discovery commands

Discovery commands are added to the pending list but they aren't
removed.

This patch removes MGMT_OP_START_DISCOVERY and MGMT_OP_STOP_DISCOVERY
commands from pending command list when they terminate.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_event.c | 14 +++++++++++++-
1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 18b9813..0f8126d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -53,8 +53,10 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)

BT_DBG("%s status 0x%x", hdev->name, status);

- if (status)
+ if (status) {
+ mgmt_stop_discovery_failed(hdev->id);
return;
+ }

clear_bit(HCI_INQUIRY, &hdev->flags);

@@ -63,6 +65,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
hci_conn_check_pending(hdev);

mgmt_discovering(hdev->id, 0);
+ mgmt_stop_discovery_complete(hdev->id);
}

static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
@@ -871,6 +874,9 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
if (status) {
hci_req_complete(hdev, HCI_OP_INQUIRY, status);
hci_conn_check_pending(hdev);
+
+ mgmt_start_discovery_failed(hdev->id);
+
return;
}

@@ -1254,11 +1260,17 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
if (!test_bit(HCI_INQUIRY, &hdev->flags))
return;

+ if (status) {
+ mgmt_start_discovery_failed(hdev->id);
+ return;
+ }
+
clear_bit(HCI_INQUIRY, &hdev->flags);

hci_req_complete(hdev, HCI_OP_INQUIRY, status);

mgmt_discovering(hdev->id, 0);
+ mgmt_start_discovery_complete(hdev->id);
}

static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
--
1.7.4.1


2011-06-10 19:35:59

by Andre Guedes

[permalink] [raw]
Subject: [RFC 02/16] Bluetooth: Add failed/complete functions to discovery commands

These functions remove pending commands and send command complete/
status events.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 4 ++
net/bluetooth/mgmt.c | 68 ++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 836d3e8..bfa5f0b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -826,6 +826,10 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
u8 *eir);
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
int mgmt_discovering(u16 index, u8 discovering);
+int mgmt_start_discovery_complete(u16 index);
+int mgmt_start_discovery_failed(u16 index);
+int mgmt_stop_discovery_complete(u16 index);
+int mgmt_stop_discovery_failed(u16 index);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index fcccf10..b9115eb 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2186,3 +2186,71 @@ int mgmt_discovering(u16 index, u8 discovering)
return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering,
sizeof(discovering), NULL);
}
+
+int mgmt_start_discovery_complete(u16 index)
+{
+ struct pending_cmd *cmd;
+ int err;
+
+ cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, index);
+ if (!cmd)
+ return -ENOENT;
+
+ err = cmd_complete(cmd->sk, index, MGMT_OP_START_DISCOVERY, NULL, 0);
+
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
+int mgmt_start_discovery_failed(u16 index)
+{
+ struct pending_cmd *cmd;
+ int err;
+
+ cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, index);
+ if (!cmd)
+ return -ENOENT;
+
+ err = cmd_status(cmd->sk, index, MGMT_OP_START_DISCOVERY, EIO);
+
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
+int mgmt_stop_discovery_complete(u16 index)
+{
+ struct pending_cmd *cmd;
+ int err;
+
+ cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
+ if (!cmd)
+ return -ENOENT;
+
+ err = cmd_complete(cmd->sk, index, MGMT_OP_STOP_DISCOVERY, NULL, 0);
+
+ mgmt_pending_remove(cmd);
+
+ cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, index);
+ if (cmd)
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
+int mgmt_stop_discovery_failed(u16 index)
+{
+ struct pending_cmd *cmd;
+ int err;
+
+ cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
+ if (!cmd)
+ return -ENOENT;
+
+ err = cmd_status(cmd->sk, index, MGMT_OP_STOP_DISCOVERY, EIO);
+
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
--
1.7.4.1


2011-06-10 19:35:58

by Andre Guedes

[permalink] [raw]
Subject: [RFC 01/16] Bluetooth: Periodic Inquiry and mgmt discovering event

By using periodic inquiry command we're not able to detect correctly
when the controller has started inquiry.

Today we have this workaround in inquiry result event handler to set
the HCI_INQUIRY flag when it sees the first inquiry result event.
This workaround isn't enough because the device may be performing
an inquiry but the HCI_INQUIRY flag is not set. For instance, if
there is no device in range, no inquiry result event is generated,
consequently, the HCI_INQUIRY flags isn't set when it should so.

We rely on HCI_INQUIRY flag to implement the discovery procedure
properly. So, as we aren't able to clear/set the HCI_INQUIRY flag in
a reliable manner, periodic inquiry events shouldn't change the
HCI_INQUIRY flag. In future, if needed, we might add a new flag (e.g.
HCI_PINQUIRY) to know if the controller is performing periodic
inquiry.

Thus, due to that issue and in order to keep compatibility with
userspace, periodic inquiry events shouldn't send mgmt discovering
events.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_event.c | 46 ++++++++++++--------------------------------
1 files changed, 13 insertions(+), 33 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0f643f8..18b9813 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -56,13 +56,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
if (status)
return;

- if (test_bit(HCI_MGMT, &hdev->flags) &&
- test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
- mgmt_discovering(hdev->id, 0);
+ clear_bit(HCI_INQUIRY, &hdev->flags);

hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);

hci_conn_check_pending(hdev);
+
+ mgmt_discovering(hdev->id, 0);
}

static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
@@ -74,10 +74,6 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
if (status)
return;

- if (test_bit(HCI_MGMT, &hdev->flags) &&
- test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
- mgmt_discovering(hdev->id, 0);
-
hci_conn_check_pending(hdev);
}

@@ -878,10 +874,9 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
return;
}

- if (test_bit(HCI_MGMT, &hdev->flags) &&
- !test_and_set_bit(HCI_INQUIRY,
- &hdev->flags))
- mgmt_discovering(hdev->id, 1);
+ set_bit(HCI_INQUIRY, &hdev->flags);
+
+ mgmt_discovering(hdev->id, 1);
}

static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
@@ -1254,13 +1249,16 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff

BT_DBG("%s status %d", hdev->name, status);

- if (test_bit(HCI_MGMT, &hdev->flags) &&
- test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
- mgmt_discovering(hdev->id, 0);
+ hci_conn_check_pending(hdev);
+
+ if (!test_bit(HCI_INQUIRY, &hdev->flags))
+ return;
+
+ clear_bit(HCI_INQUIRY, &hdev->flags);

hci_req_complete(hdev, HCI_OP_INQUIRY, status);

- hci_conn_check_pending(hdev);
+ mgmt_discovering(hdev->id, 0);
}

static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1276,12 +1274,6 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *

hci_dev_lock(hdev);

- if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
-
- if (test_bit(HCI_MGMT, &hdev->flags))
- mgmt_discovering(hdev->id, 1);
- }
-
for (; num_rsp; num_rsp--, info++) {
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
@@ -2253,12 +2245,6 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct

hci_dev_lock(hdev);

- if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
-
- if (test_bit(HCI_MGMT, &hdev->flags))
- mgmt_discovering(hdev->id, 1);
- }
-
if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
struct inquiry_info_with_rssi_and_pscan_mode *info;
info = (void *) (skb->data + 1);
@@ -2421,12 +2407,6 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
if (!num_rsp)
return;

- if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
-
- if (test_bit(HCI_MGMT, &hdev->flags))
- mgmt_discovering(hdev->id, 1);
- }
-
hci_dev_lock(hdev);

for (; num_rsp; num_rsp--, info++) {
--
1.7.4.1