2013-04-04 23:20:58

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 00/17] Update Discovery to use HCI request framework

Hi all,

This patch set updates discovery code in order to make use of the HCI request
framework. This way, we can move all Start/Stop Discovery command complete
handling, spread in hci_event.c, to a single place in mgmt.c, reducing the
spaghetti factor from discovery code.

Since this patch set follows a different approach from the previous one, I
reset the version counter on the subject. However, some comments from Marcel
about the previous patch set are still applicable and all of them were covered
in this patch set. The main comments were:
* Move cleanup and trivial refactoring patches to the beginning of the patch
set.
* When build a HCI request, put hci_req_init, hci_req_add and hci_req_run in
the same function;

Since this is a long patch set, below follows a summary of the patches in
order to make the review process a bit easier:

* Patches 1 to 4 are a very trivial patches which add or rename some macros in
order to improve code's readability and remove some magic numbers. These macros
are related to LE scanning parameters such as scanning type, filter duplicates
and scanning timeout.

* Patch 5 makes inquiry_cache_flush function non-static since it will be used
in mgmt.c by the upcoming patch (patch 6).

* Patch 6 updates start_discovery function to use HCI request to send HCI
inquiry/LE scanning commands to the controller. It also defines the start_
discovery_complete function where all command complete events are handled.

* Patch 7 simply removes Start Discovery command complete handling from hci_
event.c since it is now handled by start_discovery_complete function in mgmt.c.

* Patch 8 moves discovery macros from mgmt.c to a common place (hci_core.h)
because some of these macros will be used in hci_core.c in the upcoming patch
(patch 9).

* Patch 9 updates le_scan_disable_work function to use HCI request.

* Patch 10 updates stop_discovery function to use HCI request. This patch does
a similar job as Patch 6, but for Stop Discovery command instead.

* Patch 11 simply removes Stop Discovery command complete handling from hci_
event.c. This patch does a similar job as Patch 7, but for Stop Discovery
command instead.

* Patch 12 does a very trivial refactoring in hci_cc_le_set_scan_enable
function.

* Patches 13 and 14 removes LE scanning helpers and inquiry helpers since they
are no longer used.

* Patch 15 removes the hci_cc_le_set_scan_param function since it became an
empty event handler.

* Patch 16 renames le_scan_disable work to a more suitable name.

* Patch 17 is not really related to this patch set, but it is related to the
whole Device Discovery functionality. As discussed on IRC with Marcel, we
don't want the kernel sending Mgmt Device Found events to user-space when we
are not running the Device Discovery. Therefore, Inquiry or LE scanning
triggered by HCI raw interface (e.g. hcitool) won't generate Mgmt Device Found
events anymore.

Regards,

Andre


Andre Guedes (17):
Bluetooth: Change LE scanning timeout macros
Bluetooth: Add LE scan type macros
Bluetooth: Add macros for filter duplicates values
Bluetooth: Rename LE_SCANNING_* macros
Bluetooth: Make inquiry_cache_flush non-static
Bluetooth: Update start_discovery to use HCI request
Bluetooth: Remove start discovery handling from hci_event.c
Bluetooth: Move discovery macros to hci_core.h
Bluetooth: Update le_scan_disable_work to use HCI request
Bluetooth: Update stop_discovery to use HCI request
Bluetooth: Remove stop discovery handling from hci_event.c
Bluetooth: Refactor hci_cc_le_set_scan_enable
Bluetooth: Remove LE scan helpers
Bluetooth: Remove inquiry helpers
Bluetooth: Remove empty event handler
Bluetooth: Rename le_scan_disable delayed work
Bluetooth: Mgmt Device Found Event

include/net/bluetooth/hci.h | 9 +-
include/net/bluetooth/hci_core.h | 29 +++---
net/bluetooth/hci_core.c | 192 ++++++++++++---------------------------
net/bluetooth/hci_event.c | 71 ++-------------
net/bluetooth/mgmt.c | 156 +++++++++++++++++++++++--------
5 files changed, 201 insertions(+), 256 deletions(-)

--
1.8.1.2



2013-04-18 04:20:13

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 04/17] Bluetooth: Rename LE_SCANNING_* macros

Hi Andre,

* Andre Guedes <[email protected]> [2013-04-04 20:21:02 -0300]:

> This patch renames LE_SCANNING_ENABLED and LE_SCANNING_DISABLED
> macros to LE_SCAN_ENABLE and LE_SCAN_DISABLE in order to keep
> the same prefix others LE scan macros have.
>
> It also fixes le_scan_enable_req function so it uses the LE_SCAN_
> ENABLE macro instead of a magic number.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 4 ++--
> net/bluetooth/hci_core.c | 2 +-
> net/bluetooth/hci_event.c | 4 ++--
> 3 files changed, 5 insertions(+), 5 deletions(-)

Patches 1, 2, 3 and 4 have been applied to bluetooth-next. Thanks.

Gustavo

2013-04-17 22:18:05

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH 09/17] Bluetooth: Update le_scan_disable_work to use HCI request

Hi Johan,

On Wed, Apr 17, 2013 at 6:18 AM, Johan Hedberg <[email protected]> wrote:
>
> Hi Andre,
>
> On Thu, Apr 04, 2013, Andre Guedes wrote:
> > +static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
> > +{
> > + struct hci_command_hdr *last_cmd;
> > + u16 opcode;
> > +
> > + BT_DBG("status %d", status);
> > +
> > + /* Get opcode from the last command sent */
> > + last_cmd = (void *) hdev->sent_cmd->data;
> > + opcode = __le16_to_cpu(last_cmd->opcode);
> > +
> > + switch (opcode) {
> > + case HCI_OP_LE_SET_SCAN_ENABLE:
> > + if (status) {
> > + BT_ERR("Failed to disable LE scanning: status %d",
> > + status);
> > + return;
> > + }
> > +
> > + hci_dev_lock(hdev);
> > + hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> > + hci_dev_unlock(hdev);
> > + break;
> > +
> > + case HCI_OP_INQUIRY:
> > + if (status) {
> > + hci_dev_lock(hdev);
> > + hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> > + hci_dev_unlock(hdev);
> > + return;
> > + }
> > +
> > + break;
> > + }
> > +}
> > +
> > 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;
> > + struct hci_request req;
> > + int err;
> >
> > BT_DBG("%s", hdev->name);
> >
> > + if (hdev->discovery.state != DISCOVERY_FINDING)
> > + return;
> > +
> > + hci_req_init(&req, hdev);
> > +
> > memset(&cp, 0, sizeof(cp));
> > + cp.enable = LE_SCAN_DISABLE;
> > + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> > +
> > + /* If we are running the interleaved discovery, also add the inquiry
> > + * HCI command to the HCI request.
> > + */
> > + if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
> > + struct hci_cp_inquiry inq_cp;
> > + /* General inquiry access code (GIAC) */
> > + u8 lap[3] = { 0x33, 0x8b, 0x9e };
> > +
> > + hci_dev_lock(hdev);
> > + inquiry_cache_flush(hdev);
> > + hci_dev_unlock(hdev);
> > +
> > + memset(&inq_cp, 0, sizeof(inq_cp));
> > + memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
> > + inq_cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN;
> > + hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
> > + }
> >
> > - hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> > + err = hci_req_run(&req, le_scan_disable_work_complete);
> > + if (err)
> > + BT_ERR("Failed to disable LE scanning: err %d", err);
> > }
>
> I don't really like the complexity of the logic here with having to peek
> at hdev->sent_cmd to figure out what's going on in the callback. Maybe
> instead do this in two separate steps, i.e. send the HCI_OP_INQUIRY only
> in the callback for the HCI_OP_LE_SET_SCAN_ENABLE. Alternatively look
> into the possibility of using our recently introduced _sync API, though
> you'll first need to have a patch to add a hci_cmd_sync() which
> internally acquires the request lock.

I took a look at the possibility of using __hci_cmd_sync here, but
this approach isn't going to work. le_scan_disable_work and cmd_work
are both queued on hdev->workqueue. This means, if we call
__hci_cmd_sync here, the worker thread goes to sleep and the HCI
command is not sent until le_scan_disable_work finishes.

About the idea of doing this in two steps, as you suggested, I can
implement it. However, IMO, things can get more complex. IIRC, one of
the motivations of the HCI Request API is we be able to send several
command and handle them all in a single place (the request complete
callback) instead of spreading the handling in hci_event.c. If we
follow this chaining approach, we'll spread interleaved discovery
logic and command complete handling in several functions in
hci_core.c, making this code even more "spaghetty".

Regards,

Andre

2013-04-17 22:17:52

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH 05/17] Bluetooth: Make inquiry_cache_flush non-static

Hi Johan,

On Wed, Apr 17, 2013 at 5:30 AM, Johan Hedberg <[email protected]> wrote:
> Hi Andre,
>
> On Thu, Apr 04, 2013, Andre Guedes wrote:
>> In order to use HCI request framework in start_discovery, we'll need
>> to call inquiry_cache_flush in mgmt.c. Therefore, this patch makes
>> inquiry_cache_flush non-static
>>
>> Signed-off-by: Andre Guedes <[email protected]>
>> ---
>> include/net/bluetooth/hci_core.h | 1 +
>> net/bluetooth/hci_core.c | 2 +-
>> 2 files changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> index 0e7ee89..4713514 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -431,6 +431,7 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
>> struct inquiry_entry *ie);
>> bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
>> bool name_known, bool *ssp);
>> +void inquiry_cache_flush(struct hci_dev *hdev);
>>
>> /* ----- HCI Connections ----- */
>> enum {
>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> index 43ea7e3..eecab8e 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -630,7 +630,7 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
>> hdev->discovery.state = state;
>> }
>>
>> -static void inquiry_cache_flush(struct hci_dev *hdev)
>> +void inquiry_cache_flush(struct hci_dev *hdev)
>> {
>> struct discovery_state *cache = &hdev->discovery;
>> struct inquiry_entry *p, *n;
>
> Making this public means that you also have to prefix it with hci_.

Sure, I'll fix this.

Thanks,

Andre

2013-04-17 09:18:35

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 09/17] Bluetooth: Update le_scan_disable_work to use HCI request

Hi Andre,

On Thu, Apr 04, 2013, Andre Guedes wrote:
> +static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
> +{
> + struct hci_command_hdr *last_cmd;
> + u16 opcode;
> +
> + BT_DBG("status %d", status);
> +
> + /* Get opcode from the last command sent */
> + last_cmd = (void *) hdev->sent_cmd->data;
> + opcode = __le16_to_cpu(last_cmd->opcode);
> +
> + switch (opcode) {
> + case HCI_OP_LE_SET_SCAN_ENABLE:
> + if (status) {
> + BT_ERR("Failed to disable LE scanning: status %d",
> + status);
> + return;
> + }
> +
> + hci_dev_lock(hdev);
> + hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> + hci_dev_unlock(hdev);
> + break;
> +
> + case HCI_OP_INQUIRY:
> + if (status) {
> + hci_dev_lock(hdev);
> + hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> + hci_dev_unlock(hdev);
> + return;
> + }
> +
> + break;
> + }
> +}
> +
> 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;
> + struct hci_request req;
> + int err;
>
> BT_DBG("%s", hdev->name);
>
> + if (hdev->discovery.state != DISCOVERY_FINDING)
> + return;
> +
> + hci_req_init(&req, hdev);
> +
> memset(&cp, 0, sizeof(cp));
> + cp.enable = LE_SCAN_DISABLE;
> + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> +
> + /* If we are running the interleaved discovery, also add the inquiry
> + * HCI command to the HCI request.
> + */
> + if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
> + struct hci_cp_inquiry inq_cp;
> + /* General inquiry access code (GIAC) */
> + u8 lap[3] = { 0x33, 0x8b, 0x9e };
> +
> + hci_dev_lock(hdev);
> + inquiry_cache_flush(hdev);
> + hci_dev_unlock(hdev);
> +
> + memset(&inq_cp, 0, sizeof(inq_cp));
> + memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
> + inq_cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN;
> + hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
> + }
>
> - hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> + err = hci_req_run(&req, le_scan_disable_work_complete);
> + if (err)
> + BT_ERR("Failed to disable LE scanning: err %d", err);
> }

I don't really like the complexity of the logic here with having to peek
at hdev->sent_cmd to figure out what's going on in the callback. Maybe
instead do this in two separate steps, i.e. send the HCI_OP_INQUIRY only
in the callback for the HCI_OP_LE_SET_SCAN_ENABLE. Alternatively look
into the possibility of using our recently introduced _sync API, though
you'll first need to have a patch to add a hci_cmd_sync() which
internally acquires the request lock.

Johan

2013-04-17 08:30:05

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 05/17] Bluetooth: Make inquiry_cache_flush non-static

Hi Andre,

On Thu, Apr 04, 2013, Andre Guedes wrote:
> In order to use HCI request framework in start_discovery, we'll need
> to call inquiry_cache_flush in mgmt.c. Therefore, this patch makes
> inquiry_cache_flush non-static
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 1 +
> net/bluetooth/hci_core.c | 2 +-
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 0e7ee89..4713514 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -431,6 +431,7 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
> struct inquiry_entry *ie);
> bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
> bool name_known, bool *ssp);
> +void inquiry_cache_flush(struct hci_dev *hdev);
>
> /* ----- HCI Connections ----- */
> enum {
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 43ea7e3..eecab8e 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -630,7 +630,7 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
> hdev->discovery.state = state;
> }
>
> -static void inquiry_cache_flush(struct hci_dev *hdev)
> +void inquiry_cache_flush(struct hci_dev *hdev)
> {
> struct discovery_state *cache = &hdev->discovery;
> struct inquiry_entry *p, *n;

Making this public means that you also have to prefix it with hci_.

Johan

2013-04-17 08:29:27

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 04/17] Bluetooth: Rename LE_SCANNING_* macros

Hi Andre,

On Thu, Apr 04, 2013, Andre Guedes wrote:
> This patch renames LE_SCANNING_ENABLED and LE_SCANNING_DISABLED
> macros to LE_SCAN_ENABLE and LE_SCAN_DISABLE in order to keep
> the same prefix others LE scan macros have.
>
> It also fixes le_scan_enable_req function so it uses the LE_SCAN_
> ENABLE macro instead of a magic number.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 4 ++--
> net/bluetooth/hci_core.c | 2 +-
> net/bluetooth/hci_event.c | 4 ++--
> 3 files changed, 5 insertions(+), 5 deletions(-)

Acked-by: Johan Hedberg <[email protected]>

Johan

2013-04-17 08:29:12

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 03/17] Bluetooth: Add macros for filter duplicates values

Hi Andre,

On Thu, Apr 04, 2013, Andre Guedes wrote:
> This patch adds macros for filter_duplicates parameter values from
> HCI LE Set Scan Enable command. It also fixes le_scan_enable_req
> function so it uses the LE_SCAN_FILTER_DUP_ENABLE macro instead of
> a magic number.
>
> The LE_SCAN_FILTER_DUP_DISABLE was also defined since it will be
> required to properly support the GAP Observer Role.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 2 ++
> net/bluetooth/hci_core.c | 2 +-
> 2 files changed, 3 insertions(+), 1 deletion(-)

Acked-by: Johan Hedberg <[email protected]>

Johan

2013-04-17 08:28:58

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 02/17] Bluetooth: Add LE scan type macros

Hi Andre,

On Thu, Apr 04, 2013, Andre Guedes wrote:
> This patch adds macros for active and passive LE scan type values.
> The LE_SCAN_PASSIVE was also defined since it will be used in future
> by LE connection routine and GAP Observer Role support.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 3 +++
> net/bluetooth/mgmt.c | 7 +++----
> 2 files changed, 6 insertions(+), 4 deletions(-)

Acked-by: Johan Hedberg <[email protected]>

Johan

2013-04-17 08:28:44

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 01/17] Bluetooth: Change LE scanning timeout macros

Hi Andre,

On Thu, Apr 04, 2013, Andre Guedes wrote:
> Define LE scanning timeout macros in jiffies just like we do for
> others timeout macros.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> net/bluetooth/hci_core.c | 2 +-
> net/bluetooth/mgmt.c | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)

Acked-by: Johan Hedberg <[email protected]>

Johan

2013-04-15 16:50:46

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH 00/17] Update Discovery to use HCI request framework

Ping.

On Thu, Apr 4, 2013 at 8:20 PM, Andre Guedes <[email protected]> wrote:
> Hi all,
>
> This patch set updates discovery code in order to make use of the HCI request
> framework. This way, we can move all Start/Stop Discovery command complete
> handling, spread in hci_event.c, to a single place in mgmt.c, reducing the
> spaghetti factor from discovery code.
>
> Since this patch set follows a different approach from the previous one, I
> reset the version counter on the subject. However, some comments from Marcel
> about the previous patch set are still applicable and all of them were covered
> in this patch set. The main comments were:
> * Move cleanup and trivial refactoring patches to the beginning of the patch
> set.
> * When build a HCI request, put hci_req_init, hci_req_add and hci_req_run in
> the same function;
>
> Since this is a long patch set, below follows a summary of the patches in
> order to make the review process a bit easier:
>
> * Patches 1 to 4 are a very trivial patches which add or rename some macros in
> order to improve code's readability and remove some magic numbers. These macros
> are related to LE scanning parameters such as scanning type, filter duplicates
> and scanning timeout.
>
> * Patch 5 makes inquiry_cache_flush function non-static since it will be used
> in mgmt.c by the upcoming patch (patch 6).
>
> * Patch 6 updates start_discovery function to use HCI request to send HCI
> inquiry/LE scanning commands to the controller. It also defines the start_
> discovery_complete function where all command complete events are handled.
>
> * Patch 7 simply removes Start Discovery command complete handling from hci_
> event.c since it is now handled by start_discovery_complete function in mgmt.c.
>
> * Patch 8 moves discovery macros from mgmt.c to a common place (hci_core.h)
> because some of these macros will be used in hci_core.c in the upcoming patch
> (patch 9).
>
> * Patch 9 updates le_scan_disable_work function to use HCI request.
>
> * Patch 10 updates stop_discovery function to use HCI request. This patch does
> a similar job as Patch 6, but for Stop Discovery command instead.
>
> * Patch 11 simply removes Stop Discovery command complete handling from hci_
> event.c. This patch does a similar job as Patch 7, but for Stop Discovery
> command instead.
>
> * Patch 12 does a very trivial refactoring in hci_cc_le_set_scan_enable
> function.
>
> * Patches 13 and 14 removes LE scanning helpers and inquiry helpers since they
> are no longer used.
>
> * Patch 15 removes the hci_cc_le_set_scan_param function since it became an
> empty event handler.
>
> * Patch 16 renames le_scan_disable work to a more suitable name.
>
> * Patch 17 is not really related to this patch set, but it is related to the
> whole Device Discovery functionality. As discussed on IRC with Marcel, we
> don't want the kernel sending Mgmt Device Found events to user-space when we
> are not running the Device Discovery. Therefore, Inquiry or LE scanning
> triggered by HCI raw interface (e.g. hcitool) won't generate Mgmt Device Found
> events anymore.
>
> Regards,
>
> Andre
>
>
> Andre Guedes (17):
> Bluetooth: Change LE scanning timeout macros
> Bluetooth: Add LE scan type macros
> Bluetooth: Add macros for filter duplicates values
> Bluetooth: Rename LE_SCANNING_* macros
> Bluetooth: Make inquiry_cache_flush non-static
> Bluetooth: Update start_discovery to use HCI request
> Bluetooth: Remove start discovery handling from hci_event.c
> Bluetooth: Move discovery macros to hci_core.h
> Bluetooth: Update le_scan_disable_work to use HCI request
> Bluetooth: Update stop_discovery to use HCI request
> Bluetooth: Remove stop discovery handling from hci_event.c
> Bluetooth: Refactor hci_cc_le_set_scan_enable
> Bluetooth: Remove LE scan helpers
> Bluetooth: Remove inquiry helpers
> Bluetooth: Remove empty event handler
> Bluetooth: Rename le_scan_disable delayed work
> Bluetooth: Mgmt Device Found Event
>
> include/net/bluetooth/hci.h | 9 +-
> include/net/bluetooth/hci_core.h | 29 +++---
> net/bluetooth/hci_core.c | 192 ++++++++++++---------------------------
> net/bluetooth/hci_event.c | 71 ++-------------
> net/bluetooth/mgmt.c | 156 +++++++++++++++++++++++--------
> 5 files changed, 201 insertions(+), 256 deletions(-)
>
> --
> 1.8.1.2
>

2013-04-04 23:21:14

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 16/17] Bluetooth: Rename le_scan_disable delayed work

The le_scan_disable work basically implements a timer, but now it
does more than simply disabling the LE scanning (it may also start
the inquiry in case we are running an interleaved discovery). So,
renaming it to discovery_timeout seems suitable.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6aa6a30..0c05eae 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -273,7 +273,7 @@ struct hci_dev {

unsigned long dev_flags;

- struct delayed_work le_scan_disable;
+ struct delayed_work discovery_timeout;

__s8 adv_tx_power;
__u8 adv_data[HCI_MAX_AD_LENGTH];
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a38bf9e..ea81630 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1097,7 +1097,7 @@ 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);
+ cancel_delayed_work_sync(&hdev->discovery_timeout);

hci_dev_lock(hdev);
inquiry_cache_flush(hdev);
@@ -1854,7 +1854,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return mgmt_device_unblocked(hdev, bdaddr, type);
}

-static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
+static void discovery_timeout_complete(struct hci_dev *hdev, u8 status)
{
struct hci_command_hdr *last_cmd;
u16 opcode;
@@ -1890,10 +1890,10 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
}
}

-static void le_scan_disable_work(struct work_struct *work)
+static void hci_discovery_timeout(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
- le_scan_disable.work);
+ discovery_timeout.work);
struct hci_cp_le_set_scan_enable cp;
struct hci_request req;
int err;
@@ -1927,7 +1927,7 @@ static void le_scan_disable_work(struct work_struct *work)
hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
}

- err = hci_req_run(&req, le_scan_disable_work_complete);
+ err = hci_req_run(&req, discovery_timeout_complete);
if (err)
BT_ERR("Failed to disable LE scanning: err %d", err);
}
@@ -1969,7 +1969,7 @@ struct hci_dev *hci_alloc_dev(void)

INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
- INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
+ INIT_DELAYED_WORK(&hdev->discovery_timeout, hci_discovery_timeout);

skb_queue_head_init(&hdev->driver_init);
skb_queue_head_init(&hdev->rx_q);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 20958ba..1fa726e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2633,12 +2633,12 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status)

switch (hdev->discovery.type) {
case DISCOV_TYPE_LE:
- queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
+ queue_delayed_work(hdev->workqueue, &hdev->discovery_timeout,
DISCOV_LE_TIMEOUT);
break;

case DISCOV_TYPE_INTERLEAVED:
- queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
+ queue_delayed_work(hdev->workqueue, &hdev->discovery_timeout,
DISCOV_INTERLEAVED_TIMEOUT);
break;

@@ -2841,7 +2841,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
if (test_bit(HCI_INQUIRY, &hdev->flags)) {
hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
} else {
- cancel_delayed_work(&hdev->le_scan_disable);
+ cancel_delayed_work(&hdev->discovery_timeout);

memset(&enable_cp, 0, sizeof(enable_cp));
enable_cp.enable = LE_SCAN_DISABLE;
--
1.8.1.2


2013-04-04 23:21:15

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 17/17] Bluetooth: Mgmt Device Found Event

We only want to send Mgmt Device Found Events if we are running the
Device Discovery procedure (started by the MGMT Start Discovery
Command). Inquiry or LE scanning triggered by HCI raw interface (e.g.
hcitool) or kernel internals should not send Mgmt Device Found Events.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1fa726e..d322ca1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4116,6 +4116,9 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
struct mgmt_ev_device_found *ev = (void *) buf;
size_t ev_size;

+ if (!hci_discovery_active(hdev))
+ return -EPERM;
+
/* Leave 5 bytes for a potential CoD field */
if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
return -EINVAL;
--
1.8.1.2


2013-04-04 23:21:13

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 15/17] Bluetooth: Remove empty event handler

This patch removes the hci_cc_le_set_scan_param event handler. This
handler became empty because failures of this event are now handled
by start_discovery_complete function in mgmt.c.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_event.c | 12 ------------
1 file changed, 12 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bb28ea9..93c26cf 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -933,14 +933,6 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock(hdev);
}

-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%2.2x", hdev->name, status);
-
-}
-
static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -2293,10 +2285,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_user_passkey_neg_reply(hdev, skb);
break;

- case HCI_OP_LE_SET_SCAN_PARAM:
- hci_cc_le_set_scan_param(hdev, skb);
- break;
-
case HCI_OP_LE_SET_ADV_ENABLE:
hci_cc_le_set_adv_enable(hdev, skb);
break;
--
1.8.1.2


2013-04-04 23:21:12

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 14/17] Bluetooth: Remove inquiry helpers

This patch removes hci_do_inquiry and hci_cancel_inquiry helpers. We
now use the HCI request framework in device discovery functionality
and these helpers are no longer needed.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 9760d91..6aa6a30 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1174,8 +1174,6 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier);
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
__u8 ltk[16]);
-int hci_do_inquiry(struct hci_dev *hdev, u8 length);
-int hci_cancel_inquiry(struct hci_dev *hdev);

u8 bdaddr_to_le(u8 bdaddr_type);

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 7f954e2..a38bf9e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3361,36 +3361,6 @@ static void hci_cmd_work(struct work_struct *work)
}
}

-int hci_do_inquiry(struct hci_dev *hdev, u8 length)
-{
- /* General inquiry access code (GIAC) */
- u8 lap[3] = { 0x33, 0x8b, 0x9e };
- struct hci_cp_inquiry cp;
-
- BT_DBG("%s", hdev->name);
-
- if (test_bit(HCI_INQUIRY, &hdev->flags))
- return -EINPROGRESS;
-
- inquiry_cache_flush(hdev);
-
- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.lap, lap, sizeof(cp.lap));
- cp.length = length;
-
- return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
-}
-
-int hci_cancel_inquiry(struct hci_dev *hdev)
-{
- BT_DBG("%s", hdev->name);
-
- if (!test_bit(HCI_INQUIRY, &hdev->flags))
- return -EALREADY;
-
- return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
-}
-
u8 bdaddr_to_le(u8 bdaddr_type)
{
switch (bdaddr_type) {
--
1.8.1.2


2013-04-04 23:21:11

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 13/17] Bluetooth: Remove LE scan helpers

This patch removes the LE scan helpers hci_le_scan and hci_cancel_
le_scan and all code related to it. We now use the HCI request
framework in device discovery functionality and these helpers are
no longer needed.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 13 -----
net/bluetooth/hci_core.c | 113 ---------------------------------------
2 files changed, 126 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8a4c865..9760d91 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -117,13 +117,6 @@ struct oob_data {
u8 randomizer[16];
};

-struct le_scan_params {
- u8 type;
- u16 interval;
- u16 window;
- int timeout;
-};
-
#define HCI_MAX_SHORT_NAME_LENGTH 10

struct amp_assoc {
@@ -282,9 +275,6 @@ struct hci_dev {

struct delayed_work le_scan_disable;

- struct work_struct le_scan;
- struct le_scan_params le_scan_params;
-
__s8 adv_tx_power;
__u8 adv_data[HCI_MAX_AD_LENGTH];
__u8 adv_data_len;
@@ -1186,9 +1176,6 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
__u8 ltk[16]);
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);
-int hci_cancel_le_scan(struct hci_dev *hdev);

u8 bdaddr_to_le(u8 bdaddr_type);

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index dcc602e..7f954e2 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1073,8 +1073,6 @@ static int hci_dev_do_close(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);

- cancel_work_sync(&hdev->le_scan);
-
cancel_delayed_work(&hdev->power_off);

hci_req_cancel(hdev, ENODEV);
@@ -1856,82 +1854,6 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return mgmt_device_unblocked(hdev, bdaddr, type);
}

-static void le_scan_param_req(struct hci_request *req, 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_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp);
-}
-
-static void le_scan_enable_req(struct hci_request *req, unsigned long opt)
-{
- struct hci_cp_le_set_scan_enable cp;
-
- memset(&cp, 0, sizeof(cp));
- cp.enable = LE_SCAN_ENABLE;
- cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
-
- hci_req_add(req, 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_req_sync(hdev, le_scan_param_req, (unsigned long) &param,
- timeo);
- if (!err)
- err = __hci_req_sync(hdev, le_scan_enable_req, 0, timeo);
-
- hci_req_unlock(hdev);
-
- if (err < 0)
- return err;
-
- queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
- timeout);
-
- return 0;
-}
-
-int hci_cancel_le_scan(struct hci_dev *hdev)
-{
- BT_DBG("%s", hdev->name);
-
- if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
- return -EALREADY;
-
- if (cancel_delayed_work(&hdev->le_scan_disable)) {
- struct hci_cp_le_set_scan_enable cp;
-
- /* Send HCI command to disable LE Scan */
- memset(&cp, 0, sizeof(cp));
- hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
- }
-
- return 0;
-}
-
static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
{
struct hci_command_hdr *last_cmd;
@@ -2010,40 +1932,6 @@ static void le_scan_disable_work(struct work_struct *work)
BT_ERR("Failed to disable LE scanning: err %d", err);
}

-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 (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
- return -ENOTSUPP;
-
- 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;
-}
-
/* Alloc HCI device */
struct hci_dev *hci_alloc_dev(void)
{
@@ -2078,7 +1966,6 @@ struct hci_dev *hci_alloc_dev(void)
INIT_WORK(&hdev->cmd_work, hci_cmd_work);
INIT_WORK(&hdev->tx_work, hci_tx_work);
INIT_WORK(&hdev->power_on, hci_power_on);
- INIT_WORK(&hdev->le_scan, le_scan_work);

INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
--
1.8.1.2


2013-04-04 23:21:10

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 12/17] Bluetooth: Refactor hci_cc_le_set_scan_enable

This patch does a trivial refactoring in hci_cc_le_set_scan_enable.
Since start and stop discovery command failures are now handled in
mgmt layer, the status check became empty. So, we can move it to
outside the switch statement.

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

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6f5fb41..bb28ea9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -953,18 +953,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
if (!cp)
return;

+ if (status)
+ return;
+
switch (cp->enable) {
case LE_SCAN_ENABLE:
- if (status)
- return;
-
set_bit(HCI_LE_SCAN, &hdev->dev_flags);
break;

case LE_SCAN_DISABLE:
- if (status)
- return;
-
clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
break;

--
1.8.1.2


2013-04-04 23:21:09

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 11/17] Bluetooth: Remove stop discovery handling from hci_event.c

Since all mgmt stop discovery command complete events are now handled
in stop_discovery_complete callback in mgmt.c, we can remove this
handling from hci_event.c.

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

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index dc42acb..6f5fb41 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -40,21 +40,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)

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

- if (status) {
- hci_dev_lock(hdev);
- mgmt_stop_discovery_failed(hdev, status);
- hci_dev_unlock(hdev);
+ if (status)
return;
- }

clear_bit(HCI_INQUIRY, &hdev->flags);
smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
wake_up_bit(&hdev->flags, HCI_INQUIRY);

- hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
- hci_dev_unlock(hdev);
-
hci_conn_check_pending(hdev);
}

@@ -970,12 +962,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
break;

case LE_SCAN_DISABLE:
- if (status) {
- hci_dev_lock(hdev);
- mgmt_stop_discovery_failed(hdev, status);
- hci_dev_unlock(hdev);
+ if (status)
return;
- }

clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
break;
--
1.8.1.2


2013-04-04 23:21:08

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 10/17] Bluetooth: Update stop_discovery to use HCI request

This patch modifies the stop_discovery function so it uses the HCI
request framework.

The HCI request is built according to the current discovery state
(inquiry, LE scanning or name resolving) and a complete callback is
register to handle the command complete event for the stop discovery
command. This way, we move all stop_discovery mgmt handling code
spread in hci_event.c to a single place in mgmt.c.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index cfae494..20958ba 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2782,6 +2782,23 @@ failed:
return err;
}

+static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("status %d", status);
+
+ hci_dev_lock(hdev);
+
+ if (status) {
+ mgmt_stop_discovery_failed(hdev, status);
+ goto unlock;
+ }
+
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
@@ -2789,6 +2806,8 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
struct pending_cmd *cmd;
struct hci_cp_remote_name_req_cancel cp;
struct inquiry_entry *e;
+ struct hci_request req;
+ struct hci_cp_le_set_scan_enable enable_cp;
int err;

BT_DBG("%s", hdev->name);
@@ -2815,12 +2834,20 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
goto unlock;
}

+ hci_req_init(&req, hdev);
+
switch (hdev->discovery.state) {
case DISCOVERY_FINDING:
- if (test_bit(HCI_INQUIRY, &hdev->flags))
- err = hci_cancel_inquiry(hdev);
- else
- err = hci_cancel_le_scan(hdev);
+ if (test_bit(HCI_INQUIRY, &hdev->flags)) {
+ hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+ } else {
+ cancel_delayed_work(&hdev->le_scan_disable);
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
+ sizeof(enable_cp), &enable_cp);
+ }

break;

@@ -2838,16 +2865,22 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
}

bacpy(&cp.bdaddr, &e->data.bdaddr);
- err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ_CANCEL,
- sizeof(cp), &cp);
+ hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
+ &cp);

break;

default:
BT_DBG("unknown discovery state %u", hdev->discovery.state);
- err = -EFAULT;
+
+ mgmt_pending_remove(cmd);
+ err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
+ MGMT_STATUS_FAILED, &mgmt_cp->type,
+ sizeof(mgmt_cp->type));
+ goto unlock;
}

+ err = hci_req_run(&req, stop_discovery_complete);
if (err < 0)
mgmt_pending_remove(cmd);
else
--
1.8.1.2


2013-04-04 23:21:07

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 09/17] Bluetooth: Update le_scan_disable_work to use HCI request

This patch updates the le_scan_disable_work function so it uses the
HCI request framework. All discovery state handling are done in the
in le_scan_disable_work_complete callback.

This patch also changes the le_scan_disable_work behavior by adding
the HCI Inquiry command to the request in case we are running the
interleaved discovery. This way we don't need the extra logic in
hci_cc_le_set_scan_enable to trigger the inquiry procedure and the
mgmt_interleaved_discovery function becomes useless.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 1 -
net/bluetooth/hci_core.c | 67 +++++++++++++++++++++++++++++++++++++++-
net/bluetooth/hci_event.c | 10 ------
net/bluetooth/mgmt.c | 17 ----------
4 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b2c0207..8a4c865 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1145,7 +1145,6 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
-int mgmt_interleaved_discovery(struct hci_dev *hdev);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
bool mgmt_valid_hdev(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index eecab8e..dcc602e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1932,17 +1932,82 @@ int hci_cancel_le_scan(struct hci_dev *hdev)
return 0;
}

+static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
+{
+ struct hci_command_hdr *last_cmd;
+ u16 opcode;
+
+ BT_DBG("status %d", status);
+
+ /* Get opcode from the last command sent */
+ last_cmd = (void *) hdev->sent_cmd->data;
+ opcode = __le16_to_cpu(last_cmd->opcode);
+
+ switch (opcode) {
+ case HCI_OP_LE_SET_SCAN_ENABLE:
+ if (status) {
+ BT_ERR("Failed to disable LE scanning: status %d",
+ status);
+ return;
+ }
+
+ hci_dev_lock(hdev);
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ hci_dev_unlock(hdev);
+ break;
+
+ case HCI_OP_INQUIRY:
+ if (status) {
+ hci_dev_lock(hdev);
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ hci_dev_unlock(hdev);
+ return;
+ }
+
+ break;
+ }
+}
+
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;
+ struct hci_request req;
+ int err;

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

+ if (hdev->discovery.state != DISCOVERY_FINDING)
+ return;
+
+ hci_req_init(&req, hdev);
+
memset(&cp, 0, sizeof(cp));
+ cp.enable = LE_SCAN_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+
+ /* If we are running the interleaved discovery, also add the inquiry
+ * HCI command to the HCI request.
+ */
+ if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
+ struct hci_cp_inquiry inq_cp;
+ /* General inquiry access code (GIAC) */
+ u8 lap[3] = { 0x33, 0x8b, 0x9e };
+
+ hci_dev_lock(hdev);
+ inquiry_cache_flush(hdev);
+ hci_dev_unlock(hdev);
+
+ memset(&inq_cp, 0, sizeof(inq_cp));
+ memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
+ inq_cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN;
+ hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
+ }

- hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+ err = hci_req_run(&req, le_scan_disable_work_complete);
+ if (err)
+ BT_ERR("Failed to disable LE scanning: err %d", err);
}

static void le_scan_work(struct work_struct *work)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6f78a8c..dc42acb 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -978,16 +978,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
}

clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
-
- if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
- hdev->discovery.state == DISCOVERY_FINDING) {
- mgmt_interleaved_discovery(hdev);
- } else {
- hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
- hci_dev_unlock(hdev);
- }
-
break;

default:
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 06c96f1d..cfae494 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2616,23 +2616,6 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
return err;
}

-int mgmt_interleaved_discovery(struct hci_dev *hdev)
-{
- int err;
-
- BT_DBG("%s", hdev->name);
-
- hci_dev_lock(hdev);
-
- err = hci_do_inquiry(hdev, DISCOV_INTERLEAVED_INQUIRY_LEN);
- if (err < 0)
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
-
- hci_dev_unlock(hdev);
-
- return err;
-}
-
static void start_discovery_complete(struct hci_dev *hdev, u8 status)
{
BT_DBG("status %d", status);
--
1.8.1.2


2013-04-04 23:21:06

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 08/17] Bluetooth: Move discovery macros to hci_core.h

Some of discovery macros will be used in hci_core so we need to
define them in common place such as hci_core.h. Thus, this patch
moves discovery macros to hci_core.h and also adds the DISCOV_
prefix to them.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4713514..b2c0207 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1078,6 +1078,16 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
BIT(BDADDR_LE_PUBLIC) | \
BIT(BDADDR_LE_RANDOM))

+/* These LE scan and inquiry parameters were chosen according to LE General
+ * Discovery Procedure specification.
+ */
+#define DISCOV_LE_SCAN_WIN 0x12
+#define DISCOV_LE_SCAN_INT 0x12
+#define DISCOV_LE_TIMEOUT msecs_to_jiffies(10240)
+#define DISCOV_INTERLEAVED_TIMEOUT msecs_to_jiffies(5120)
+#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04
+#define DISCOV_BREDR_INQUIRY_LEN 0x08
+
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
int mgmt_index_added(struct hci_dev *hdev);
int mgmt_index_removed(struct hci_dev *hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ad3d9b3..06c96f1d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -102,18 +102,6 @@ static const u16 mgmt_events[] = {
MGMT_EV_PASSKEY_NOTIFY,
};

-/*
- * These LE scan and inquiry parameters were chosen according to LE General
- * Discovery Procedure specification.
- */
-#define LE_SCAN_WIN 0x12
-#define LE_SCAN_INT 0x12
-#define LE_SCAN_TIMEOUT_LE_ONLY msecs_to_jiffies(10240)
-#define LE_SCAN_TIMEOUT_BREDR_LE msecs_to_jiffies(5120)
-
-#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
-#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */
-
#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)

#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
@@ -2636,7 +2624,7 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev)

hci_dev_lock(hdev);

- err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
+ err = hci_do_inquiry(hdev, DISCOV_INTERLEAVED_INQUIRY_LEN);
if (err < 0)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);

@@ -2663,12 +2651,12 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status)
switch (hdev->discovery.type) {
case DISCOV_TYPE_LE:
queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
- LE_SCAN_TIMEOUT_LE_ONLY);
+ DISCOV_LE_TIMEOUT);
break;

case DISCOV_TYPE_INTERLEAVED:
queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
- LE_SCAN_TIMEOUT_BREDR_LE);
+ DISCOV_INTERLEAVED_TIMEOUT);
break;

case DISCOV_TYPE_BREDR:
@@ -2744,7 +2732,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,

memset(&inq_cp, 0, sizeof(inq_cp));
memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
- inq_cp.length = INQUIRY_LEN_BREDR;
+ inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
break;

@@ -2781,8 +2769,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,

memset(&param_cp, 0, sizeof(param_cp));
param_cp.type = LE_SCAN_ACTIVE;
- param_cp.interval = cpu_to_le16(LE_SCAN_INT);
- param_cp.window = cpu_to_le16(LE_SCAN_WIN);
+ param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
+ param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
&param_cp);

--
1.8.1.2


2013-04-04 23:21:05

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 07/17] Bluetooth: Remove start discovery handling from hci_event.c

Since all mgmt start discovery command complete events are now handled
in start_discovery_complete callback in mgmt.c, we can remove this
handling from hci_event.c.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_event.c | 24 +-----------------------
1 file changed, 1 insertion(+), 23 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 5daf37f..6f78a8c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -947,12 +947,6 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)

BT_DBG("%s status 0x%2.2x", hdev->name, 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,
@@ -969,18 +963,10 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,

switch (cp->enable) {
case LE_SCAN_ENABLE:
- if (status) {
- hci_dev_lock(hdev);
- mgmt_start_discovery_failed(hdev, status);
- hci_dev_unlock(hdev);
+ if (status)
return;
- }

set_bit(HCI_LE_SCAN, &hdev->dev_flags);
-
- hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_FINDING);
- hci_dev_unlock(hdev);
break;

case LE_SCAN_DISABLE:
@@ -1081,18 +1067,10 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)

if (status) {
hci_conn_check_pending(hdev);
- hci_dev_lock(hdev);
- if (test_bit(HCI_MGMT, &hdev->dev_flags))
- mgmt_start_discovery_failed(hdev, status);
- hci_dev_unlock(hdev);
return;
}

set_bit(HCI_INQUIRY, &hdev->flags);
-
- hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_FINDING);
- hci_dev_unlock(hdev);
}

static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
--
1.8.1.2


2013-04-04 23:21:04

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 06/17] Bluetooth: Update start_discovery to use HCI request

This patch modifies the start_discovery function so it uses the HCI
request framework.

We build the HCI request according to the discovery type (add inquiry
or LE scan HCI commands) and run the HCI request. We also register
the start_discovery_complete callback which handles mgmt command
complete events for this command. This way, we move all start_
discovery mgmt handling code spread in hci_event.c to a single place
in mgmt.c.

This patch also merges the LE-only and interleaved discovery type
cases since these cases are pretty much the same now.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 411117b..ad3d9b3 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2645,11 +2645,51 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev)
return err;
}

+static void start_discovery_complete(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("status %d", status);
+
+ if (status) {
+ hci_dev_lock(hdev);
+ mgmt_start_discovery_failed(hdev, status);
+ hci_dev_unlock(hdev);
+ return;
+ }
+
+ hci_dev_lock(hdev);
+ hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+ hci_dev_unlock(hdev);
+
+ switch (hdev->discovery.type) {
+ case DISCOV_TYPE_LE:
+ queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
+ LE_SCAN_TIMEOUT_LE_ONLY);
+ break;
+
+ case DISCOV_TYPE_INTERLEAVED:
+ queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
+ LE_SCAN_TIMEOUT_BREDR_LE);
+ break;
+
+ case DISCOV_TYPE_BREDR:
+ break;
+
+ default:
+ BT_ERR("Invalid discovery type %d", hdev->discovery.type);
+ }
+}
+
static int start_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_start_discovery *cp = data;
struct pending_cmd *cmd;
+ struct hci_cp_le_set_scan_param param_cp;
+ struct hci_cp_le_set_scan_enable enable_cp;
+ struct hci_cp_inquiry inq_cp;
+ struct hci_request req;
+ /* General inquiry access code (GIAC) */
+ u8 lap[3] = { 0x33, 0x8b, 0x9e };
int err;

BT_DBG("%s", hdev->name);
@@ -2682,6 +2722,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,

hdev->discovery.type = cp->type;

+ hci_req_init(&req, hdev);
+
switch (hdev->discovery.type) {
case DISCOV_TYPE_BREDR:
if (!lmp_bredr_capable(hdev)) {
@@ -2691,10 +2733,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}

- err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
+ if (test_bit(HCI_INQUIRY, &hdev->flags)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_BUSY);
+ mgmt_pending_remove(cmd);
+ goto failed;
+ }
+
+ inquiry_cache_flush(hdev);
+
+ memset(&inq_cp, 0, sizeof(inq_cp));
+ memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
+ inq_cp.length = INQUIRY_LEN_BREDR;
+ hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
break;

case DISCOV_TYPE_LE:
+ case DISCOV_TYPE_INTERLEAVED:
if (!lmp_host_le_capable(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED);
@@ -2702,20 +2757,40 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}

- err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
- LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
- break;
-
- case DISCOV_TYPE_INTERLEAVED:
- if (!lmp_host_le_capable(hdev) || !lmp_bredr_capable(hdev)) {
+ if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
+ !lmp_bredr_capable(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED);
mgmt_pending_remove(cmd);
goto failed;
}

- err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
- LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE);
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_REJECTED);
+ mgmt_pending_remove(cmd);
+ goto failed;
+ }
+
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_BUSY);
+ mgmt_pending_remove(cmd);
+ goto failed;
+ }
+
+ memset(&param_cp, 0, sizeof(param_cp));
+ param_cp.type = LE_SCAN_ACTIVE;
+ param_cp.interval = cpu_to_le16(LE_SCAN_INT);
+ param_cp.window = cpu_to_le16(LE_SCAN_WIN);
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+ &param_cp);
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_ENABLE;
+ enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ &enable_cp);
break;

default:
@@ -2725,6 +2800,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}

+ err = hci_req_run(&req, start_discovery_complete);
if (err < 0)
mgmt_pending_remove(cmd);
else
--
1.8.1.2


2013-04-04 23:21:03

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 05/17] Bluetooth: Make inquiry_cache_flush non-static

In order to use HCI request framework in start_discovery, we'll need
to call inquiry_cache_flush in mgmt.c. Therefore, this patch makes
inquiry_cache_flush non-static

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 0e7ee89..4713514 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -431,6 +431,7 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
struct inquiry_entry *ie);
bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
bool name_known, bool *ssp);
+void inquiry_cache_flush(struct hci_dev *hdev);

/* ----- HCI Connections ----- */
enum {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 43ea7e3..eecab8e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -630,7 +630,7 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
hdev->discovery.state = state;
}

-static void inquiry_cache_flush(struct hci_dev *hdev)
+void inquiry_cache_flush(struct hci_dev *hdev)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *p, *n;
--
1.8.1.2


2013-04-04 23:21:02

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 04/17] Bluetooth: Rename LE_SCANNING_* macros

This patch renames LE_SCANNING_ENABLED and LE_SCANNING_DISABLED
macros to LE_SCAN_ENABLE and LE_SCAN_DISABLE in order to keep
the same prefix others LE scan macros have.

It also fixes le_scan_enable_req function so it uses the LE_SCAN_
ENABLE macro instead of a magic number.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 84c37ab..e0512aa 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -996,8 +996,8 @@ struct hci_cp_le_set_scan_param {
__u8 filter_policy;
} __packed;

-#define LE_SCANNING_DISABLED 0x00
-#define LE_SCANNING_ENABLED 0x01
+#define LE_SCAN_DISABLE 0x00
+#define LE_SCAN_ENABLE 0x01
#define LE_SCAN_FILTER_DUP_DISABLE 0x00
#define LE_SCAN_FILTER_DUP_ENABLE 0x01

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9519ce0..43ea7e3 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1874,7 +1874,7 @@ static void le_scan_enable_req(struct hci_request *req, unsigned long opt)
struct hci_cp_le_set_scan_enable cp;

memset(&cp, 0, sizeof(cp));
- cp.enable = 1;
+ cp.enable = LE_SCAN_ENABLE;
cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;

hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 7e7fbca..5daf37f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -968,7 +968,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
return;

switch (cp->enable) {
- case LE_SCANNING_ENABLED:
+ case LE_SCAN_ENABLE:
if (status) {
hci_dev_lock(hdev);
mgmt_start_discovery_failed(hdev, status);
@@ -983,7 +983,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
hci_dev_unlock(hdev);
break;

- case LE_SCANNING_DISABLED:
+ case LE_SCAN_DISABLE:
if (status) {
hci_dev_lock(hdev);
mgmt_stop_discovery_failed(hdev, status);
--
1.8.1.2


2013-04-04 23:21:01

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 03/17] Bluetooth: Add macros for filter duplicates values

This patch adds macros for filter_duplicates parameter values from
HCI LE Set Scan Enable command. It also fixes le_scan_enable_req
function so it uses the LE_SCAN_FILTER_DUP_ENABLE macro instead of
a magic number.

The LE_SCAN_FILTER_DUP_DISABLE was also defined since it will be
required to properly support the GAP Observer Role.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3f4266b..84c37ab 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -998,6 +998,8 @@ struct hci_cp_le_set_scan_param {

#define LE_SCANNING_DISABLED 0x00
#define LE_SCANNING_ENABLED 0x01
+#define LE_SCAN_FILTER_DUP_DISABLE 0x00
+#define LE_SCAN_FILTER_DUP_ENABLE 0x01

#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct hci_cp_le_set_scan_enable {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0686e42..9519ce0 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1875,7 +1875,7 @@ static void le_scan_enable_req(struct hci_request *req, unsigned long opt)

memset(&cp, 0, sizeof(cp));
cp.enable = 1;
- cp.filter_dup = 1;
+ cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;

hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
--
1.8.1.2


2013-04-04 23:21:00

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 02/17] Bluetooth: Add LE scan type macros

This patch adds macros for active and passive LE scan type values.
The LE_SCAN_PASSIVE was also defined since it will be used in future
by LE connection routine and GAP Observer Role support.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b330892..3f4266b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -984,6 +984,9 @@ struct hci_cp_le_set_adv_data {

#define HCI_OP_LE_SET_ADV_ENABLE 0x200a

+#define LE_SCAN_PASSIVE 0x00
+#define LE_SCAN_ACTIVE 0x01
+
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c00e8ea..411117b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -106,7 +106,6 @@ static const u16 mgmt_events[] = {
* 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 msecs_to_jiffies(10240)
@@ -2703,7 +2702,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}

- err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
+ err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
break;

@@ -2715,8 +2714,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}

- err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, LE_SCAN_WIN,
- LE_SCAN_TIMEOUT_BREDR_LE);
+ err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
+ LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE);
break;

default:
--
1.8.1.2


2013-04-04 23:20:59

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 01/17] Bluetooth: Change LE scanning timeout macros

Define LE scanning timeout macros in jiffies just like we do for
others timeout macros.

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

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a199d63..0686e42 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1909,7 +1909,7 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
return err;

queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
- msecs_to_jiffies(timeout));
+ timeout);

return 0;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 03e7e73..c00e8ea 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -109,8 +109,8 @@ static const u16 mgmt_events[] = {
#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 LE_SCAN_TIMEOUT_BREDR_LE 5120 /* TGAP(100)/2 */
+#define LE_SCAN_TIMEOUT_LE_ONLY msecs_to_jiffies(10240)
+#define LE_SCAN_TIMEOUT_BREDR_LE msecs_to_jiffies(5120)

#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */
--
1.8.1.2