* [PATCH v5 2/6] Bluetooth: Minor code refactoring
2012-02-03 20:47 [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Andre Guedes
@ 2012-02-03 20:47 ` Andre Guedes
2012-02-03 20:47 ` [PATCH v5 3/6] Bluetooth: Add hci_do_le_scan() Andre Guedes
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Andre Guedes @ 2012-02-03 20:47 UTC (permalink / raw)
To: linux-bluetooth
This patch does a trivial code refacting in hci_discovery_active.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_core.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 1705d93..1175f27 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -360,12 +360,15 @@ bool hci_discovery_active(struct hci_dev *hdev)
{
struct discovery_state *discov = &hdev->discovery;
- if (discov->state == DISCOVERY_INQUIRY ||
- discov->state == DISCOVERY_LE_SCAN ||
- discov->state == DISCOVERY_RESOLVING)
+ switch (discov->state) {
+ case DISCOVERY_INQUIRY:
+ case DISCOVERY_LE_SCAN:
+ case DISCOVERY_RESOLVING:
return true;
- return false;
+ default:
+ return false;
+ }
}
void hci_discovery_set_state(struct hci_dev *hdev, int state)
--
1.7.9
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v5 3/6] Bluetooth: Add hci_do_le_scan()
2012-02-03 20:47 [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Andre Guedes
2012-02-03 20:47 ` [PATCH v5 2/6] Bluetooth: Minor code refactoring Andre Guedes
@ 2012-02-03 20:47 ` Andre Guedes
2012-02-03 21:15 ` Marcel Holtmann
2012-02-03 20:48 ` [PATCH v5 4/6] Bluetooth: Add hci_le_scan() Andre Guedes
` (3 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Andre Guedes @ 2012-02-03 20:47 UTC (permalink / raw)
To: linux-bluetooth
This patch adds to hci_core the hci_do_le_scan function which
should be used to scan LE devices.
In order to enable LE scan, hci_do_le_scan() sends commands (Set
LE Scan Parameters and Set LE Scan Enable) to the controller and
waits for its results. If commands were executed successfully a
delayed work is scheduled to disable the ongoing scanning after
some amount of time. This function blocks.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 8 ++++
net/bluetooth/hci_core.c | 74 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 13 +++++--
3 files changed, 92 insertions(+), 3 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bf2ef56..3e70872 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -122,6 +122,12 @@ struct adv_entry {
u8 bdaddr_type;
};
+struct le_scan_params {
+ u8 type;
+ u16 interval;
+ u16 window;
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -261,6 +267,8 @@ struct hci_dev {
unsigned long dev_flags;
+ struct delayed_work le_scan_disable;
+
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 1175f27..ae86cdd 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -759,6 +759,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
cancel_delayed_work(&hdev->service_cache);
+ cancel_delayed_work_sync(&hdev->le_scan_disable);
+
hci_dev_lock(hdev);
inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
@@ -1596,6 +1598,76 @@ int hci_add_adv_entry(struct hci_dev *hdev,
return 0;
}
+static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt)
+{
+ struct le_scan_params *param = (struct le_scan_params *) opt;
+ struct hci_cp_le_set_scan_param cp;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.type = param->type;
+ cp.interval = cpu_to_le16(param->interval);
+ cp.window = cpu_to_le16(param->window);
+
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp);
+}
+
+static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
+{
+ struct hci_cp_le_set_scan_enable cp;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.enable = 1;
+
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+}
+
+static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
+ u16 window, int timeout)
+{
+ long timeo = msecs_to_jiffies(3000);
+ struct le_scan_params param;
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return -EINPROGRESS;
+
+ param.type = type;
+ param.interval = interval;
+ param.window = window;
+
+ hci_req_lock(hdev);
+
+ err = __hci_request(hdev, le_scan_param_req, (unsigned long) ¶m,
+ timeo);
+ if (!err)
+ err = __hci_request(hdev, le_scan_enable_req, 0, timeo);
+
+ hci_req_unlock(hdev);
+
+ if (err < 0)
+ return err;
+
+ schedule_delayed_work(&hdev->le_scan_disable,
+ msecs_to_jiffies(timeout));
+
+ return 0;
+}
+
+static void le_scan_disable_work(struct work_struct *work)
+{
+ struct hci_dev *hdev = container_of(work, struct hci_dev,
+ le_scan_disable.work);
+ struct hci_cp_le_set_scan_enable cp;
+
+ BT_DBG("%s", hdev->name);
+
+ memset(&cp, 0, sizeof(cp));
+
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1682,6 +1754,8 @@ int hci_register_dev(struct hci_dev *hdev)
atomic_set(&hdev->promisc, 0);
+ INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
+
write_unlock(&hci_dev_list_lock);
hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8971c18..97152d9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1031,6 +1031,8 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
__u8 status = *((__u8 *) skb->data);
BT_DBG("%s status 0x%x", hdev->name, status);
+
+ hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
}
static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
@@ -1041,15 +1043,17 @@ 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;
switch (cp->enable) {
case LE_SCANNING_ENABLED:
+ hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
+
+ if (status)
+ return;
+
set_bit(HCI_LE_SCAN, &hdev->dev_flags);
cancel_delayed_work_sync(&hdev->adv_work);
@@ -1061,6 +1065,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
break;
case LE_SCANNING_DISABLED:
+ if (status)
+ return;
+
clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
hci_dev_lock(hdev);
--
1.7.9
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v5 3/6] Bluetooth: Add hci_do_le_scan()
2012-02-03 20:47 ` [PATCH v5 3/6] Bluetooth: Add hci_do_le_scan() Andre Guedes
@ 2012-02-03 21:15 ` Marcel Holtmann
0 siblings, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2012-02-03 21:15 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
Hi Andre,
> This patch adds to hci_core the hci_do_le_scan function which
> should be used to scan LE devices.
>
> In order to enable LE scan, hci_do_le_scan() sends commands (Set
> LE Scan Parameters and Set LE Scan Enable) to the controller and
> waits for its results. If commands were executed successfully a
> delayed work is scheduled to disable the ongoing scanning after
> some amount of time. This function blocks.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> include/net/bluetooth/hci_core.h | 8 ++++
> net/bluetooth/hci_core.c | 74 ++++++++++++++++++++++++++++++++++++++
> net/bluetooth/hci_event.c | 13 +++++--
> 3 files changed, 92 insertions(+), 3 deletions(-)
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Regards
Marcel
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 4/6] Bluetooth: Add hci_le_scan()
2012-02-03 20:47 [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Andre Guedes
2012-02-03 20:47 ` [PATCH v5 2/6] Bluetooth: Minor code refactoring Andre Guedes
2012-02-03 20:47 ` [PATCH v5 3/6] Bluetooth: Add hci_do_le_scan() Andre Guedes
@ 2012-02-03 20:48 ` Andre Guedes
2012-02-03 20:48 ` [PATCH v5 5/6] Bluetooth: MGMT start discovery LE-Only support Andre Guedes
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Andre Guedes @ 2012-02-03 20:48 UTC (permalink / raw)
To: linux-bluetooth
We are not supposed to block in start_discovery() because
start_discovery code is running in write() syscall context
and this would block the write operation on the mgmt socket.
This way, we cannot directly call hci_do_le_scan() to scan
LE devices in start_discovery(). To overcome this issue a
derefered work (hdev->le_scan) was created so we can properly
call hci_do_le_scan().
The helper function hci_le_scan() simply set LE scan parameters
and queue hdev->le_scan work. The work is queued on system_long_wq
since it can sleep for a few seconds in the worst case (timeout).
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci_core.h | 6 ++++++
net/bluetooth/hci_core.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3e70872..7107790 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -126,6 +126,7 @@ struct le_scan_params {
u8 type;
u16 interval;
u16 window;
+ int timeout;
};
#define NUM_REASSEMBLY 4
@@ -269,6 +270,9 @@ struct hci_dev {
struct delayed_work le_scan_disable;
+ struct work_struct le_scan;
+ struct le_scan_params le_scan_params;
+
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
@@ -1033,5 +1037,7 @@ void hci_le_ltk_neg_reply(struct hci_conn *conn);
int hci_do_inquiry(struct hci_dev *hdev, u8 length);
int hci_cancel_inquiry(struct hci_dev *hdev);
+int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
+ int timeout);
#endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index ae86cdd..3d09f4b4 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -735,6 +735,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
+ cancel_work_sync(&hdev->le_scan);
+
hci_req_cancel(hdev, ENODEV);
hci_req_lock(hdev);
@@ -1668,6 +1670,37 @@ static void le_scan_disable_work(struct work_struct *work)
hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
+static void le_scan_work(struct work_struct *work)
+{
+ struct hci_dev *hdev = container_of(work, struct hci_dev, le_scan);
+ struct le_scan_params *param = &hdev->le_scan_params;
+
+ BT_DBG("%s", hdev->name);
+
+ hci_do_le_scan(hdev, param->type, param->interval,
+ param->window, param->timeout);
+}
+
+int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
+ int timeout)
+{
+ struct le_scan_params *param = &hdev->le_scan_params;
+
+ BT_DBG("%s", hdev->name);
+
+ if (work_busy(&hdev->le_scan))
+ return -EINPROGRESS;
+
+ param->type = type;
+ param->interval = interval;
+ param->window = window;
+ param->timeout = timeout;
+
+ queue_work(system_long_wq, &hdev->le_scan);
+
+ return 0;
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1754,6 +1787,8 @@ int hci_register_dev(struct hci_dev *hdev)
atomic_set(&hdev->promisc, 0);
+ INIT_WORK(&hdev->le_scan, le_scan_work);
+
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
write_unlock(&hci_dev_list_lock);
--
1.7.9
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v5 5/6] Bluetooth: MGMT start discovery LE-Only support
2012-02-03 20:47 [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Andre Guedes
` (2 preceding siblings ...)
2012-02-03 20:48 ` [PATCH v5 4/6] Bluetooth: Add hci_le_scan() Andre Guedes
@ 2012-02-03 20:48 ` Andre Guedes
2012-02-03 20:48 ` [PATCH v5 6/6] Bluetooth: Fix indentation Andre Guedes
2012-02-03 21:45 ` [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Johan Hedberg
5 siblings, 0 replies; 8+ messages in thread
From: Andre Guedes @ 2012-02-03 20:48 UTC (permalink / raw)
To: linux-bluetooth
This patch adds LE-Only discovery procedure support to MGMT Start
Discovery command.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_event.c | 13 ++++++++++++-
net/bluetooth/mgmt.c | 20 +++++++++++++++++++-
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 97152d9..ad5f37b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1033,6 +1033,13 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%x", hdev->name, status);
hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
+
+ if (status) {
+ hci_dev_lock(hdev);
+ mgmt_start_discovery_failed(hdev, status);
+ hci_dev_unlock(hdev);
+ return;
+ }
}
static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
@@ -1051,8 +1058,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
case LE_SCANNING_ENABLED:
hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
- if (status)
+ if (status) {
+ hci_dev_lock(hdev);
+ mgmt_start_discovery_failed(hdev, status);
+ hci_dev_unlock(hdev);
return;
+ }
set_bit(HCI_LE_SCAN, &hdev->dev_flags);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9e5dead..8c9de58 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -35,6 +35,15 @@
#define MGMT_VERSION 0
#define MGMT_REVISION 1
+/*
+ * These LE scan and inquiry parameters were chosen according to LE General
+ * Discovery Procedure specification.
+ */
+#define LE_SCAN_TYPE 0x01
+#define LE_SCAN_WIN 0x12
+#define LE_SCAN_INT 0x12
+#define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */
+
#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
#define SERVICE_CACHE_TIMEOUT (5 * 1000)
@@ -1916,6 +1925,7 @@ static int start_discovery(struct sock *sk, u16 index,
void *data, u16 len)
{
struct mgmt_cp_start_discovery *cp = data;
+ unsigned long discov_type = cp->type;
struct pending_cmd *cmd;
struct hci_dev *hdev;
int err;
@@ -1951,7 +1961,15 @@ static int start_discovery(struct sock *sk, u16 index,
goto failed;
}
- err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
+ if (test_bit(MGMT_ADDR_BREDR, &discov_type))
+ err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
+ else if (test_bit(MGMT_ADDR_LE_PUBLIC, &discov_type) &&
+ test_bit(MGMT_ADDR_LE_RANDOM, &discov_type))
+ err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
+ LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
+ else
+ err = -EINVAL;
+
if (err < 0)
mgmt_pending_remove(cmd);
else
--
1.7.9
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v5 6/6] Bluetooth: Fix indentation
2012-02-03 20:47 [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Andre Guedes
` (3 preceding siblings ...)
2012-02-03 20:48 ` [PATCH v5 5/6] Bluetooth: MGMT start discovery LE-Only support Andre Guedes
@ 2012-02-03 20:48 ` Andre Guedes
2012-02-03 21:45 ` [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Johan Hedberg
5 siblings, 0 replies; 8+ messages in thread
From: Andre Guedes @ 2012-02-03 20:48 UTC (permalink / raw)
To: linux-bluetooth
This patch fixes a #define indentation in mgmt.c.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/mgmt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8c9de58..de7326b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -44,7 +44,7 @@
#define LE_SCAN_INT 0x12
#define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */
-#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
+#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
#define SERVICE_CACHE_TIMEOUT (5 * 1000)
--
1.7.9
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events
2012-02-03 20:47 [PATCH v5 1/6] Bluetooth: LE scan should send Discovering events Andre Guedes
` (4 preceding siblings ...)
2012-02-03 20:48 ` [PATCH v5 6/6] Bluetooth: Fix indentation Andre Guedes
@ 2012-02-03 21:45 ` Johan Hedberg
5 siblings, 0 replies; 8+ messages in thread
From: Johan Hedberg @ 2012-02-03 21:45 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
Hi Andre,
On Fri, Feb 03, 2012, Andre Guedes wrote:
> Send MGMT Discovering events once LE scan starts/stops so the
> userspace can track when local adapters are discovering LE devices.
>
> This way, we also keep the same behavior of inquiry which sends MGMT
> Discovering events once inquiry starts/stops even if it is triggered
> by an external tool (e.g. hcitool).
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>
> ---
> include/net/bluetooth/hci_core.h | 1 +
> net/bluetooth/hci_core.c | 2 ++
> net/bluetooth/hci_event.c | 5 +++++
> 3 files changed, 8 insertions(+), 0 deletions(-)
All six patches have been applied to my bluetooth-next tree. Thanks.
Johan
^ permalink raw reply [flat|nested] 8+ messages in thread