* [PATCH] avctp: Fix memory leak
From: Andrei Emeltchenko @ 2014-02-04 9:50 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Unregister pdu hanlders in avctp_disconnected()
---
profiles/audio/avctp.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index a77aa9d..a28cf71 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -496,6 +496,15 @@ static void avctp_disconnected(struct avctp *session)
if (!session)
return;
+ if (session->passthrough_id > 0)
+ avctp_unregister_pdu_handler(session->passthrough_id);
+
+ if (session->unit_id > 0)
+ avctp_unregister_pdu_handler(session->unit_id);
+
+ if (session->subunit_id > 0)
+ avctp_unregister_pdu_handler(session->subunit_id);
+
if (session->browsing)
avctp_channel_destroy(session->browsing);
--
1.8.3.2
^ permalink raw reply related
* [PATCH] android/avctp: Fix memory leak: unregister pdu handler
From: Andrei Emeltchenko @ 2014-02-04 9:28 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Unregister pdu handlers on shutdown.
---
android/avctp.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/android/avctp.c b/android/avctp.c
index 8f35403..8681cb0 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -1462,6 +1462,15 @@ void avctp_shutdown(struct avctp *session)
if (session->browsing)
avctp_channel_destroy(session->browsing);
+ if (session->passthrough_id > 0)
+ avctp_unregister_pdu_handler(session, session->passthrough_id);
+
+ if (session->unit_id > 0)
+ avctp_unregister_pdu_handler(session, session->unit_id);
+
+ if (session->subunit_id > 0)
+ avctp_unregister_pdu_handler(session, session->subunit_id);
+
if (session->control)
avctp_channel_destroy(session->control);
--
1.8.3.2
^ permalink raw reply related
* [PATCH] android/pts: Update PICS and PTS for AVCTP
From: Sebastian Chlad @ 2014-02-04 9:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sebastian Chlad
Since we do not support AVCTP fragmentation for now we shell set PICS
settings for AVCTP accordingly as well as set respective PTS test cases
as N/A
---
android/pics-avctp.txt | 2 +-
android/pts-avctp.txt | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/android/pics-avctp.txt b/android/pics-avctp.txt
index 939ffdb..269bf08 100644
--- a/android/pics-avctp.txt
+++ b/android/pics-avctp.txt
@@ -58,7 +58,7 @@ TSPC_AVCTP_2_14 False Support for multiple AVCTP channel establishment
-------------------------------------------------------------------------------
Parameter Name Selected Description
-------------------------------------------------------------------------------
-TSPC_AVCTP_3_1 True (*) Message fragmentation (O)
+TSPC_AVCTP_3_1 False Message fragmentation (O)
TSPC_AVCTP_3_2 True Transaction label management (M)
TSPC_AVCTP_3_3 True Packet type field management (M)
TSPC_AVCTP_3_4 True Message type field management (M)
diff --git a/android/pts-avctp.txt b/android/pts-avctp.txt
index 4090ec0..72a6373 100644
--- a/android/pts-avctp.txt
+++ b/android/pts-avctp.txt
@@ -37,6 +37,6 @@ TC_TG_CCM_BV_04_C PASS avtest --device hci0 --avctp --send x <bdaddr>
TC_TG_NFR_BV_02_C PASS avtest --device hci0 --avctp --send x <bdaddr>
TC_TG_NFR_BV_03_C PASS avtest --device hci0 --avctp --send x <bdaddr>
TC_TG_NFR_BI_01_C PASS
-TC_TG_FRA_BV_02_C FAIL
-TC_TG_FRA_BV_03_C INC
+TC_TG_FRA_BV_02_C N/A Fragmentation not supported
+TC_TG_FRA_BV_03_C N/A Fragmentation not supported
-------------------------------------------------------------------------------
--
1.8.3.2
---------------------------------------------------------------------
Intel Finland Oy
Registered Address: PL 281, 00181 Helsinki
Business Identity Code: 0357606 - 4
Domiciled in Helsinki
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply related
* Re: How do you install bluez for development?
From: Alejandro Exojo @ 2014-02-04 7:28 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <20140203183606.GA12511@molly>
2014-02-03 Vinicius Costa Gomes <vcgomes@gmail.com>:
>> Feb 03 17:14:38 PC-MW03 systemd[1]: Starting Bluetooth service...
>> Feb 03 17:14:38 PC-MW03 bluetoothd[22571]: Bluetooth daemon 5.14
>> Feb 03 17:14:38 PC-MW03 systemd[1]: Started Bluetooth service.
>> Feb 03 17:14:38 PC-MW03 systemd[1]: Starting Bluetooth.
>> Feb 03 17:14:38 PC-MW03 systemd[1]: Reached target Bluetooth.
>> Feb 03 17:14:38 PC-MW03 bluetoothd[22571]: Failed to access management interface
>
> Two probable causes, your kernel is older than 3.4, or the user that is running
> bluetoothd doesn't have the CAP_NET_ADMIN capability.
True! I was running 3.2. I've installed a more recent one, and I got
it working. Thank you very much, I would not have thought of the
kernel at all.
How come that at least 3.4 is needed?
Thank you again.
Cheers.
--
Alejandro Exojo Piqueras
ModpoW, S.L.
Technova LaSalle | Sant Joan de la Salle 42 | 08022 Barcelona | www.modpow.es
^ permalink raw reply
* Re: [RFC v7 08/11] Bluetooth: Temporarily stop background scanning on discovery
From: Marcel Holtmann @ 2014-02-04 4:25 UTC (permalink / raw)
To: Andre Guedes; +Cc: BlueZ development
In-Reply-To: <1391446588-18729-8-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
> If the user sends a mgmt start discovery command while the background
> scanning is running, we should temporarily stop it. Once the discovery
> finishes, we start the background scanning again.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/hci_core.c | 2 ++
> net/bluetooth/mgmt.c | 12 ++++++++----
> 2 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 388a453..222bd07 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1609,6 +1609,8 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
>
> switch (state) {
> case DISCOVERY_STOPPED:
> + hci_update_background_scan(hdev);
> +
> if (hdev->discovery.state != DISCOVERY_STARTING)
> mgmt_discovering(hdev, 0);
> break;
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index ce7ef33..83af8de 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -3319,11 +3319,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
> goto failed;
> }
>
> + /* If controller is scanning, it means the background scanning
> + * is running. Thus, we should temporarily stop it in order to
> + * set the discovery scanning parameters.
> + */
> 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(&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);
> }
is the start_discovery protected enough by itself so that we do not accidentally stop some discovery that got triggered which is actually not a background scan.
Regards
Marcel
^ permalink raw reply
* Re: [RFC v7 07/11] Bluetooth: Re-enable background scan in case of error
From: Marcel Holtmann @ 2014-02-04 4:10 UTC (permalink / raw)
To: Andre Guedes; +Cc: BlueZ development
In-Reply-To: <1391446588-18729-7-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
> Since we temporarily stop the background scanning in favor of
> connection, we should re-enable it in case something goes wrong
> with connection establishment. So this patch adds a hci_update_
> background_scan() call in fail_conn_attempt() and hci_le_conn_
> complete_evt() error flow.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/hci_conn.c | 2 ++
> net/bluetooth/hci_event.c | 1 +
> 2 files changed, 3 insertions(+)
>
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 127465f..2ef29c7 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -527,6 +527,8 @@ static void le_conn_failed(struct hci_conn *conn, u8 status)
> hci_proto_connect_cfm(conn, status);
>
> hci_conn_del(conn);
> +
> + hci_update_background_scan(hdev);
> }
>
> static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index ef95030..8de51b1 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -3606,6 +3606,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
> hci_proto_connect_cfm(conn, ev->status);
> conn->state = BT_CLOSED;
> hci_conn_del(conn);
> + hci_update_background_scan(hdev);
> goto unlock;
please fold this patch into the one that does the disabling.
Regards
Marcel
^ permalink raw reply
* Re: [RFC v7 03/11] Bluetooth: Stop scanning on LE connection
From: Marcel Holtmann @ 2014-02-04 4:08 UTC (permalink / raw)
To: Andre Guedes; +Cc: BlueZ development
In-Reply-To: <1391446588-18729-3-git-send-email-andre.guedes@openbossa.org>
Hi Andrei,
> Some LE controllers don't support scanning and creating a connection
> at the same time. So we should always stop scanning in order to
> establish the connection.
>
> Since we may prematurely stop the discovery procedure in favor of
> the connection establishment, we should also cancel hdev->le_scan_
> disable delayed work and set the discovery state to DISCOVERY_STOPPED.
>
> This change does a small improvement since it is not mandatory the
> user stops scanning before connecting anymore. Moreover, this change
> is required by upcoming LE auto connection mechanism in order to work
> properly with controllers that don't support background scanning and
> connection establishment at the same time.
>
> In future, we might want to do a small optimization by checking if
> controller is able to scan and connect at the same time. For now,
> we want the simplest approach so we always stop scanning (even if
> the controller is able to carry out both operations).
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> include/net/bluetooth/hci.h | 1 +
> net/bluetooth/hci_conn.c | 84 +++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 83 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 352d3d7..a0d5262 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -352,6 +352,7 @@ enum {
>
> /* ---- HCI Error Codes ---- */
> #define HCI_ERROR_AUTH_FAILURE 0x05
> +#define HCI_ERROR_MEMORY_EXCEEDED 0x07
> #define HCI_ERROR_CONNECTION_TIMEOUT 0x08
> #define HCI_ERROR_REJ_BAD_ADDR 0x0f
> #define HCI_ERROR_REMOTE_USER_TERM 0x13
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 6797292..63c1e4f 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -583,11 +583,71 @@ static int hci_create_le_conn(struct hci_conn *conn)
> return 0;
> }
>
> +static void create_le_conn_req(struct hci_request *req, struct hci_conn *conn)
> +{
> + struct hci_cp_le_create_conn cp;
> + struct hci_dev *hdev = conn->hdev;
> +
> + memset(&cp, 0, sizeof(cp));
> + cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
> + cp.scan_window = cpu_to_le16(hdev->le_scan_window);
> + bacpy(&cp.peer_addr, &conn->dst);
> + cp.peer_addr_type = conn->dst_type;
> + cp.own_address_type = conn->src_type;
> + cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
> + cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
> + cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
> + cp.min_ce_len = __constant_cpu_to_le16(0x0000);
> + cp.max_ce_len = __constant_cpu_to_le16(0x0000);
> +
> + hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
> +}
> +
> +static void stop_scan_complete(struct hci_dev *hdev, u8 status)
> +{
> + struct hci_request req;
> + struct hci_conn *conn;
> + int err;
> +
> + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
> + if (!conn)
> + return;
> +
> + if (status) {
> + BT_DBG("HCI request failed to stop scanning: status 0x%2.2x",
> + status);
> +
> + hci_dev_lock(hdev);
> + le_conn_failed(conn, status);
> + hci_dev_unlock(hdev);
> + return;
> + }
> +
> + /* Since we may have prematurely stopped discovery procedure, we should
> + * update discovery state.
> + */
> + cancel_delayed_work(&hdev->le_scan_disable);
> + hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> +
> + hci_req_init(&req, hdev);
> +
> + create_le_conn_req(&req, conn);
> +
> + err = hci_req_run(&req, create_le_conn_complete);
> + if (err) {
> + hci_dev_lock(hdev);
> + le_conn_failed(conn, HCI_ERROR_MEMORY_EXCEEDED);
> + hci_dev_unlock(hdev);
> + return;
> + }
> +}
> +
> static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
> u8 dst_type, u8 sec_level, u8 auth_type)
> {
> struct hci_conn_params *params;
> struct hci_conn *conn;
> + struct hci_request req;
> int err;
>
> if (test_bit(HCI_ADVERTISING, &hdev->flags))
> @@ -643,9 +703,29 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
> conn->le_conn_max_interval = hdev->le_conn_max_interval;
> }
>
> - err = hci_create_le_conn(conn);
> - if (err)
> + hci_req_init(&req, hdev);
> +
> + /* If controller is scanning, we stop it since some controllers are
> + * not able to scan and connect at the same time.
> + */
> + if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
> + struct hci_cp_le_set_scan_enable cp;
> +
> + memset(&cp, 0, sizeof(cp));
> + cp.enable = LE_SCAN_DISABLE;
> + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> +
> + err = hci_req_run(&req, stop_scan_complete);
> + } else {
> + create_le_conn_req(&req, conn);
> +
> + err = hci_req_run(&req, create_le_conn_complete);
> + }
so I wonder why we not just add the disabling of the scan to the request right here. Our request queue will always fail on the first request and then do not execute the other ones. Especially when you have to send two requests this kind of request queue behavior is pretty nice.
I also think that this is currently a bit racy in error handling path. So you might want to check this in all cases. One other thing to consider is might be introducing helper for adding certain commands like disable LE scan if they are used more than once.
Regards
Marcel
^ permalink raw reply
* Re: [RFC v7 02/11] Bluetooth: Use connection parameters if any
From: Marcel Holtmann @ 2014-02-04 4:02 UTC (permalink / raw)
To: Andre Guedes; +Cc: BlueZ development
In-Reply-To: <1391446588-18729-2-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
> This patch changes hci_connect_le() so it uses the connection
> parameters specified for the certain device. If no parameters
> were configured, we use the default values.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/hci_conn.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
I know applied the first 2 patches in this series since they were nicely self-contained.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH v2 0/6] android/hal-audio: Fixes
From: Szymon Janc @ 2014-02-03 21:16 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1391446549-31455-1-git-send-email-andrzej.kaczmarek@tieto.com>
Hi Andrzej,
On Monday 03 February 2014 17:55:43 Andrzej Kaczmarek wrote:
> v1 -> v2
> fixed build error introduced during rebase
>
>
> Andrzej Kaczmarek (6):
> android/hal-audio: Remove unsupported mono channel mode
> android/hal-audio: Be more verbose on SBC errors
> android/hal-audio: Print calculated SBC parameters
> android/hal-audio: Fix audio with large omtu value
> android/hal-audio: Fix RTP sequence numbers
> android/hal-audio: Add RTP timestamps
>
> android/hal-audio.c | 33 +++++++++++++++++++++++++--------
> 1 file changed, 25 insertions(+), 8 deletions(-)
All patches in this set have been applied, thanks a lot.
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: How do you install bluez for development?
From: Vinicius Costa Gomes @ 2014-02-03 18:36 UTC (permalink / raw)
To: Alejandro Exojo; +Cc: linux-bluetooth
In-Reply-To: <CACMtdhhCecEWiK33A6uNSQr-=iRJSehfbJCqb0Maxpq-8WjkPA@mail.gmail.com>
Hi Alejandro,
On 17:21 Mon 03 Feb, Alejandro Exojo wrote:
> Hi.
>
> I want to build a recent bluez, since I need the DualShock support.
> I'm used to play with PATH, LD_LIBRARY_PATH and other stuff, so I tend
> to install what I've built in /opt/foo or even in a subdirectory in my
> /home, but I'm missing something, maybe obvious, to start bluetoothd.
>
> I've built fine with ./configure --prefix=/ --enable-sixaxis &&
> DESTDIR=/opt/bluez5 make install.
>
> Then I've configured everything I saw that bluez installs:
>
> * /opt/bluez5/etc/dbus-1/system.d/bluetooth.conf (sourced from the
> stuff in /etc)
> * /lib/udev (I've symlinked the two files, just in case)
> * /etc/systemd/system/bluetooth.service (points to the service file
> provided by bluez, with the proper path for bluetoothd).
>
> With that the service starts, but stops immediately. This is what I've
> get in the log when plugging the adapter (or forcing a manual
> startup):
>
> Feb 03 17:14:38 PC-MW03 systemd[1]: Starting Bluetooth service...
> Feb 03 17:14:38 PC-MW03 bluetoothd[22571]: Bluetooth daemon 5.14
> Feb 03 17:14:38 PC-MW03 systemd[1]: Started Bluetooth service.
> Feb 03 17:14:38 PC-MW03 systemd[1]: Starting Bluetooth.
> Feb 03 17:14:38 PC-MW03 systemd[1]: Reached target Bluetooth.
> Feb 03 17:14:38 PC-MW03 bluetoothd[22571]: Failed to access management interface
Two probable causes, your kernel is older than 3.4, or the user that is running
bluetoothd doesn't have the CAP_NET_ADMIN capability.
> Feb 03 17:14:38 PC-MW03 bluetoothd[22571]: Adapter handling
> initialization failed
> Feb 03 17:14:38 PC-MW03 systemd[1]: bluetooth.service: main process
> exited, code=exited, status=1/FAILURE
>
>
> Any hints? Or should I just give up and install everything in /usr,
> possibly clashing files from other installations like packages?
>
> Thank you.
>
> --
> Alejandro Exojo Piqueras
>
> ModpoW, S.L.
> Technova LaSalle | Sant Joan de la Salle 42 | 08022 Barcelona | www.modpow.es
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Cheers,
--
Vinicius
^ permalink raw reply
* Re: Working with the gatt-example.c plugin
From: Sandy Chapman @ 2014-02-03 18:11 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_PCW5DQ3-qbp75F1uMryX7hoJedzE1CD-AT2tNbvwT=NA@mail.gmail.com>
Hi Anderson,
On Mon, Feb 3, 2014 at 11:51 AM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi Sandy,
>
> On Mon, Feb 3, 2014 at 10:38 AM, Sandy Chapman <schapman@lixar.com> wrote:
>> Hi All,
>>
>> I'm having some difficulties getting the gatt-example plugin working.
>> I've checked out the latest tag (5.14) from git and have built it
>> using the --enable-maintainer-mode configure flag so that
>> gatt-example.c is compiled into a static plugin that is loaded at
>> runtime. I've confirmed that the plugin is compiled and is loaded at
>> runtime when I run bluetoothd.
>>
>> My problem is with making modifications to the plugin. I've tried
>> something as simple as changing the UUID for the battery service,
>> however, every time I scan the services (using an iPhone), the same
>> list of UUIDs is returned (0xA002 , 0xA004, and 0xFEEE... for the
>> services, which match up with what's defined in the gatt-example.c
>> file). Any modifications I make to the file don't seem to have any
>> effect on the services advertised. I've even rebuilt it without
>> maintainer mode and have confirmed the plugin isn't loaded, but still,
>> the same set of services and characteristics are loaded. Is there some
>> sort of cache where the advertisement is loaded from that can be
>> cleared? It looks like a bunch of HCI Commands are sent every time I
>> "hciconfig hci0 up" which didn't happen when I initially ran the
>> hciconfig tool prior to compiling and running bluetoothd.
>
> Most likely iPhone is caching the attribute database and thus not
> redoing any discovery. If this is the case, it is because we don't
> provide a Service Changed characteristic on the GATT service,
> therefore the iPhone thinks the database is static.
>
> BTW this is a bug/limitation on the current BlueZ. While working on
> the new GATT API we are also implementing a Service Changed service
> that notifies changes to the entire database on every connection. This
> is suboptimal (may trigger service discovery on every connection) but
> at least will avoid stale cache on the client side. In future we need
> to implement tracking of added / removed services and notify only
> those that change.
>
> Please use "btmon" while iphone connects to bluez and check if there
> is any ATT traffic for GATT service discovery.
>
> If this is the case, you need to find out how to clear the cache on the iPhone.
>
> Best Regards,
> --
> Anderson Lizardo
> http://www.indt.org/?lang=en
> INdT - Manaus - Brazil
This was exactly the problem. Apple doesn't provide any API to reset
the GATT cache and neglects to mention that fact. Turns out, disabling
and re-enabling Bluetooth on iOS clears the cache. After doing this,
my updated UUIDs are shown on the phone correctly. For reference, this
is the stack overflow link that points this out:
http://stackoverflow.com/q/17090949/1270148
Thanks,
Sandy
--
^ permalink raw reply
* [RFC v7 11/11] Bluetooth: Add le_auto_conn file on debugfs
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
This patch adds to debugfs the le_auto_conn file. This file will be
used to test LE auto connection infrastructure.
To add a new auto connection address we write on le_auto_conn file
following the format <address> <address type> <auto_connect>.
The <address type> values are:
* 0 for public address
* 1 for random address
The <auto_connect> values are (for more details see struct hci_
conn_params):
* 0 for disabled
* 1 for always
* 2 for link loss
So for instance, if you want the kernel autonomously establishes
connections with device AA:BB:CC:DD:EE:FF (public address) every
time the device enters in connectable mode (starts advertising),
you should run the command:
$ echo "AA:BB:CC:DD:EE:FF 0 1" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
To get the list of connection parameters configured in kernel, read
the le_auto_conn file:
$ cat /sys/kernel/debug/bluetooth/hci0/le_auto_conn
Finally, to clear the connection parameters list, write an empty
string:
$ echo "" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
This file is created only if LE is enabled.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_core.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 246a2ff..3ae3f7d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -725,6 +725,89 @@ static const struct file_operations lowpan_debugfs_fops = {
.llseek = default_llseek,
};
+static int le_auto_conn_show(struct seq_file *sf, void *ptr)
+{
+ struct hci_dev *hdev = sf->private;
+ struct hci_conn_params *p;
+
+ hci_dev_lock(hdev);
+
+ list_for_each_entry(p, &hdev->le_conn_params, list) {
+ seq_printf(sf, "%pMR %u %u\n", &p->addr, p->addr_type,
+ p->auto_connect);
+ }
+
+ hci_dev_unlock(hdev);
+
+ return 0;
+}
+
+static int le_auto_conn_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, le_auto_conn_show, inode->i_private);
+}
+
+static ssize_t le_auto_conn_write(struct file *file, const char __user *data,
+ size_t count, loff_t *offset)
+{
+ struct seq_file *sf = file->private_data;
+ struct hci_dev *hdev = sf->private;
+ u8 auto_connect;
+ bdaddr_t addr;
+ u8 addr_type;
+ char *buf;
+ int n;
+
+ /* Don't allow partial write */
+ if (*offset != 0)
+ return -EINVAL;
+
+ /* If empty string, clear the connection parameters and pending LE
+ * connection list.
+ */
+ if (count == 1) {
+ hci_dev_lock(hdev);
+ hci_conn_params_clear(hdev);
+ hci_pend_le_conns_clear(hdev);
+ hci_dev_unlock(hdev);
+ return count;
+ }
+
+ buf = kzalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, data, count)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+
+ n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu", &addr.b[5],
+ &addr.b[4], &addr.b[3], &addr.b[2], &addr.b[1], &addr.b[0],
+ &addr_type, &auto_connect);
+ if (n != 8) {
+ kfree(buf);
+ return -EINVAL;
+ }
+
+ hci_dev_lock(hdev);
+ hci_conn_params_add(hdev, &addr, addr_type, auto_connect,
+ hdev->le_conn_min_interval,
+ hdev->le_conn_max_interval);
+ hci_dev_unlock(hdev);
+
+ kfree(buf);
+ return count;
+}
+
+static const struct file_operations le_auto_conn_fops = {
+ .open = le_auto_conn_open,
+ .read = seq_read,
+ .write = le_auto_conn_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
/* ---- HCI requests ---- */
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
@@ -1517,6 +1600,8 @@ static int __hci_init(struct hci_dev *hdev)
hdev, &conn_max_interval_fops);
debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
&lowpan_debugfs_fops);
+ debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev,
+ &le_auto_conn_fops);
}
return 0;
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 10/11] Bluetooth: Auto connection and power on
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
When hdev is closed (e.g. Mgmt power off command, RFKILL or controller
is reset), the ongoing active connections are silently dropped by the
controller (no Disconnection Complete Event is sent to host). For that
reason, the devices that require HCI_AUTO_CONN_ALWAYS are not added to
hdev->pend_le_conns list and they won't auto connect.
So to fix this issue, during hdev closing, we remove all pending LE
connections. After adapter is powered on, we add a pending LE connection
for each HCI_AUTO_CONN_ALWAYS address.
This way, the auto connection mechanism works propely after a power
off and power on sequence as well as RFKILL block/unblock.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_core.c | 1 +
net/bluetooth/mgmt.c | 13 +++++++++++++
2 files changed, 14 insertions(+)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2bdcaa5..246a2ff 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2080,6 +2080,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
+ hci_pend_le_conns_clear(hdev);
hci_dev_unlock(hdev);
hci_notify(hdev, HCI_DEV_DOWN);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 83af8de..c30547b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4406,6 +4406,17 @@ void mgmt_index_removed(struct hci_dev *hdev)
mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
}
+/* This function requires the caller holds hdev->lock */
+static void restart_le_auto_conns(struct hci_dev *hdev)
+{
+ struct hci_conn_params *p;
+
+ list_for_each_entry(p, &hdev->le_conn_params, list) {
+ if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
+ hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
+ }
+}
+
static void powered_complete(struct hci_dev *hdev, u8 status)
{
struct cmd_lookup match = { NULL, hdev };
@@ -4414,6 +4425,8 @@ static void powered_complete(struct hci_dev *hdev, u8 status)
hci_dev_lock(hdev);
+ restart_le_auto_conns(hdev);
+
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
new_settings(hdev, match.sk);
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 09/11] Bluetooth: Introduce LE auto connect options
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
This patch introduces the LE auto connection options: HCI_AUTO_CONN_
ALWAYS and HCI_AUTO_CONN_LINK_LOSS. Their working mechanism are
described as follows:
The HCI_AUTO_CONN_ALWAYS option configures the kernel to always re-
establish the connection, no matter the reason the connection was
terminated. This feature is required by some LE profiles such as
HID over GATT, Health Thermometer and Blood Pressure. These profiles
require the host autonomously connect to the device as soon as it
enters in connectable mode (start advertising) so the device is able
to delivery notifications or indications.
The BT_AUTO_CONN_LINK_LOSS option configures the kernel to re-
establish the connection in case the connection was terminated due
to a link loss. This feature is required by the majority of LE
profiles such as Proximity, Find Me, Cycling Speed and Cadence and
Time.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 9 ++++++++-
net/bluetooth/hci_core.c | 11 +++++++----
net/bluetooth/hci_event.c | 18 ++++++++++++++++++
3 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4591b8f..b6dd650 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -383,6 +383,12 @@ struct hci_conn_params {
u16 conn_min_interval;
u16 conn_max_interval;
+
+ enum {
+ HCI_AUTO_CONN_DISABLED,
+ HCI_AUTO_CONN_ALWAYS,
+ HCI_AUTO_CONN_LINK_LOSS,
+ } auto_connect;
};
extern struct list_head hci_dev_list;
@@ -766,7 +772,8 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type);
void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
- u16 conn_min_interval, u16 conn_max_interval);
+ u8 auto_connect, u16 conn_min_interval,
+ u16 conn_max_interval);
void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_conn_params_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 222bd07..2bdcaa5 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2944,7 +2944,8 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
/* This function requires the caller holds hdev->lock */
void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
- u16 conn_min_interval, u16 conn_max_interval)
+ u8 auto_connect, u16 conn_min_interval,
+ u16 conn_max_interval)
{
struct hci_conn_params *params;
@@ -2952,6 +2953,7 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
if (params) {
params->conn_min_interval = conn_min_interval;
params->conn_max_interval = conn_max_interval;
+ params->auto_connect = auto_connect;
return;
}
@@ -2965,12 +2967,13 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
params->addr_type = addr_type;
params->conn_min_interval = conn_min_interval;
params->conn_max_interval = conn_max_interval;
+ params->auto_connect = auto_connect;
list_add(¶ms->list, &hdev->le_conn_params);
- BT_DBG("addr %pMR (type %u) conn_min_interval 0x%.4x "
- "conn_max_interval 0x%.4x", addr, addr_type, conn_min_interval,
- conn_max_interval);
+ BT_DBG("addr %pMR (type %u) auto_connect %u conn_min_interval 0x%.4x "
+ "conn_max_interval 0x%.4x", addr, addr_type, auto_connect,
+ conn_min_interval, conn_max_interval);
}
/* This function requires the caller holds hdev->lock */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8de51b1..6b2e2e4 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1825,6 +1825,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_disconn_complete *ev = (void *) skb->data;
u8 reason = hci_to_mgmt_reason(ev->reason);
+ struct hci_conn_params *params;
struct hci_conn *conn;
u8 type;
@@ -1851,6 +1852,23 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn->type == ACL_LINK && conn->flush_key)
hci_remove_link_key(hdev, &conn->dst);
+ params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+ if (params) {
+ switch (params->auto_connect) {
+ case HCI_AUTO_CONN_LINK_LOSS:
+ if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
+ break;
+ /* Fall through */
+
+ case HCI_AUTO_CONN_ALWAYS:
+ hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type);
+ break;
+
+ default:
+ break;
+ }
+ }
+
type = conn->type;
hci_proto_disconn_cfm(conn, ev->reason);
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 08/11] Bluetooth: Temporarily stop background scanning on discovery
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
If the user sends a mgmt start discovery command while the background
scanning is running, we should temporarily stop it. Once the discovery
finishes, we start the background scanning again.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_core.c | 2 ++
net/bluetooth/mgmt.c | 12 ++++++++----
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 388a453..222bd07 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1609,6 +1609,8 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
switch (state) {
case DISCOVERY_STOPPED:
+ hci_update_background_scan(hdev);
+
if (hdev->discovery.state != DISCOVERY_STARTING)
mgmt_discovering(hdev, 0);
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ce7ef33..83af8de 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3319,11 +3319,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}
+ /* If controller is scanning, it means the background scanning
+ * is running. Thus, we should temporarily stop it in order to
+ * set the discovery scanning parameters.
+ */
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(&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);
}
memset(¶m_cp, 0, sizeof(param_cp));
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 07/11] Bluetooth: Re-enable background scan in case of error
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
Since we temporarily stop the background scanning in favor of
connection, we should re-enable it in case something goes wrong
with connection establishment. So this patch adds a hci_update_
background_scan() call in fail_conn_attempt() and hci_le_conn_
complete_evt() error flow.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_conn.c | 2 ++
net/bluetooth/hci_event.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 127465f..2ef29c7 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -527,6 +527,8 @@ static void le_conn_failed(struct hci_conn *conn, u8 status)
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
+
+ hci_update_background_scan(hdev);
}
static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ef95030..8de51b1 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3606,6 +3606,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_proto_connect_cfm(conn, ev->status);
conn->state = BT_CLOSED;
hci_conn_del(conn);
+ hci_update_background_scan(hdev);
goto unlock;
}
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 06/11] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
This patch introduces the LE auto connection infrastructure.
This infrastructure will be used to implement the LE auto connection
options which will be introduced in a few patches ahead.
In summary, the auto connection mechanism works as follows: Once the
first pending LE connection is created, the background scanning is
started. When the target device is found in range, the kernel
autonomously starts the connection attempt. If connection is
established successfully, that pending LE connection is deleted and
the background is stopped.
To achieve that, this patch introduces the hci_update_background_scan()
which controls the background scanning state. This function starts or
stops the background scanning based on the hdev->pend_le_conns list. If
there is no pending LE connection, the background scanning is stopped.
Otherwise, we start the background scanning.
Then, every time a pending LE connection is added we call hci_update_
background_scan() so the background scanning is started (in case it is
not already running). Likewise, every time a pending LE connection is
deleted we call hci_update_background_scan() so the background scanning
is stopped (in case this was the last pending LE connection) or it is
started again (in case we have more pending LE connections). This way
the background scanning keeps running until all pending LE connection
are established.
When a device with pending connection is in range, we establish the
connection and delete the pending connection.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 2 +
net/bluetooth/hci_core.c | 86 +++++++++++++++++++++++++++++++++++++++-
net/bluetooth/hci_event.c | 41 +++++++++++++++++++
3 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 97f758a..4591b8f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -776,6 +776,8 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conns_clear(struct hci_dev *hdev);
+void hci_update_background_scan(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f353a71..388a453 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3021,7 +3021,7 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
if (entry)
- return;
+ goto done;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
@@ -3035,6 +3035,9 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
list_add(&entry->list, &hdev->pend_le_conns);
BT_DBG("addr %pMR (type %u)", addr, addr_type);
+
+done:
+ hci_update_background_scan(hdev);
}
/* This function requires the caller holds hdev->lock */
@@ -3044,12 +3047,15 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
if (!entry)
- return;
+ goto done;
list_del(&entry->list);
kfree(entry);
BT_DBG("addr %pMR (type %u)", addr, addr_type);
+
+done:
+ hci_update_background_scan(hdev);
}
/* This function requires the caller holds hdev->lock */
@@ -4591,3 +4597,79 @@ static void hci_cmd_work(struct work_struct *work)
}
}
}
+
+static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+ if (status)
+ BT_DBG("HCI request failed to update background scanning: "
+ "status 0x%2.2x", status);
+}
+
+/* This function controls the background scanning based on hdev->pend_le_conns
+ * list. If there are pending LE connection we start the background scanning,
+ * otherwise we stop it.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+void hci_update_background_scan(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_param param_cp;
+ struct hci_cp_le_set_scan_enable enable_cp;
+ struct hci_request req;
+ struct hci_conn *conn;
+ int err;
+
+ hci_req_init(&req, hdev);
+
+ if (list_empty(&hdev->pend_le_conns)) {
+ /* If there is no pending LE connections, we should stop
+ * the background scanning.
+ */
+
+ /* If controller is not scanning we are done. */
+ if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return;
+
+ 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);
+
+ BT_DBG("%s stopping background scanning", hdev->name);
+ } else {
+ /* If there is at least one pending LE connection, we should
+ * keep the background scan running.
+ */
+
+ /* If controller is already scanning we are done. */
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return;
+
+ /* If controller is connecting, we should not start scanning
+ * since some controllers are not able to scan and connect at
+ * the same time.
+ */
+ conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+ if (conn)
+ return;
+
+ memset(¶m_cp, 0, sizeof(param_cp));
+ param_cp.type = LE_SCAN_PASSIVE;
+ param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
+ param_cp.window = cpu_to_le16(hdev->le_scan_window);
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+ ¶m_cp);
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_ENABLE;
+ enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ &enable_cp);
+
+ BT_DBG("%s starting background scanning", hdev->name);
+ }
+
+ err = hci_req_run(&req, update_background_scan_complete);
+ if (err)
+ BT_ERR("Failed to run HCI request: err %d", err);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d2c6878..ef95030 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3624,25 +3624,66 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_proto_connect_cfm(conn, ev->status);
+ hci_pend_le_conn_del(hdev, &ev->bdaddr, ev->bdaddr_type);
+
unlock:
hci_dev_unlock(hdev);
}
+/* This function requires the caller holds hdev->lock */
+static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ struct hci_conn *conn;
+ u8 bdaddr_type;
+
+ if (!hci_pend_le_conn_lookup(hdev, addr, addr_type))
+ return;
+
+ if (addr_type == ADDR_LE_DEV_PUBLIC)
+ bdaddr_type = BDADDR_LE_PUBLIC;
+ else
+ bdaddr_type = BDADDR_LE_RANDOM;
+
+ conn = hci_connect(hdev, LE_LINK, addr, bdaddr_type, BT_SECURITY_LOW,
+ HCI_AT_NO_BONDING);
+ if (!IS_ERR(conn))
+ return;
+
+ switch (PTR_ERR(conn)) {
+ case -EBUSY:
+ /* If hci_connect() returns -EBUSY it means there is already
+ * an LE connection attempt going on. Since controllers don't
+ * support more than one connection attempt at the time, we
+ * don't consider this an error case.
+ */
+ break;
+ default:
+ BT_ERR("Failed to connect: err %ld", PTR_ERR(conn));
+ }
+}
+
static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
u8 num_reports = skb->data[0];
void *ptr = &skb->data[1];
s8 rssi;
+ hci_dev_lock(hdev);
+
while (num_reports--) {
struct hci_ev_le_advertising_info *ev = ptr;
+ check_pending_le_conn(hdev, &ev->bdaddr, ev->bdaddr_type);
+
rssi = ev->data[ev->length];
mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
NULL, rssi, 0, 1, ev->data, ev->length);
ptr += sizeof(*ev) + ev->length + 1;
}
+
+ hci_dev_unlock(hdev);
}
static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 05/11] Bluetooth: Introduce hdev->pend_le_conn list
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
This patch introduces the hdev->pend_le_conn list which holds the
device addresses the kernel should autonomously connect. It also
introduces some helper functions to manipulate the list.
The list and helper functions will be used by the next patch which
implements the LE auto connection infrastructure.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 7 +++++
net/bluetooth/hci_core.c | 68 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 75 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 92fa75f..97f758a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -270,6 +270,7 @@ struct hci_dev {
struct list_head long_term_keys;
struct list_head remote_oob_data;
struct list_head le_conn_params;
+ struct list_head pend_le_conns;
struct hci_dev_stats stat;
@@ -769,6 +770,12 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_conn_params_clear(struct hci_dev *hdev);
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conns_clear(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e774669..f353a71 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2999,6 +2999,72 @@ void hci_conn_params_clear(struct hci_dev *hdev)
BT_DBG("All LE connection parameters were removed");
}
+/* This function requires the caller holds hdev->lock */
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type)
+{
+ struct bdaddr_list *entry;
+
+ list_for_each_entry(entry, &hdev->pend_le_conns, list) {
+ if (bacmp(&entry->bdaddr, addr) == 0 &&
+ entry->bdaddr_type == addr_type)
+ return entry;
+ }
+
+ return NULL;
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+ struct bdaddr_list *entry;
+
+ entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
+ if (entry)
+ return;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ BT_ERR("Out of memory");
+ return;
+ }
+
+ bacpy(&entry->bdaddr, addr);
+ entry->bdaddr_type = addr_type;
+
+ list_add(&entry->list, &hdev->pend_le_conns);
+
+ BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+ struct bdaddr_list *entry;
+
+ entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
+ if (!entry)
+ return;
+
+ list_del(&entry->list);
+ kfree(entry);
+
+ BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conns_clear(struct hci_dev *hdev)
+{
+ struct bdaddr_list *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &hdev->pend_le_conns, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+
+ BT_DBG("All LE pending connections cleared");
+}
+
static void inquiry_complete(struct hci_dev *hdev, u8 status)
{
if (status) {
@@ -3110,6 +3176,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
INIT_LIST_HEAD(&hdev->le_conn_params);
+ INIT_LIST_HEAD(&hdev->pend_le_conns);
INIT_LIST_HEAD(&hdev->conn_hash.list);
INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3296,6 +3363,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_smp_ltks_clear(hdev);
hci_remote_oob_data_clear(hdev);
hci_conn_params_clear(hdev);
+ hci_pend_le_conns_clear(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 04/11] Bluetooth: Remove unused function
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
This patch removes hci_create_le_conn() since it is not used anymore.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_conn.c | 32 --------------------------------
1 file changed, 32 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 63c1e4f..127465f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -551,38 +551,6 @@ done:
hci_dev_unlock(hdev);
}
-static int hci_create_le_conn(struct hci_conn *conn)
-{
- struct hci_dev *hdev = conn->hdev;
- struct hci_cp_le_create_conn cp;
- struct hci_request req;
- int err;
-
- hci_req_init(&req, hdev);
-
- memset(&cp, 0, sizeof(cp));
- cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
- cp.scan_window = cpu_to_le16(hdev->le_scan_window);
- bacpy(&cp.peer_addr, &conn->dst);
- cp.peer_addr_type = conn->dst_type;
- cp.own_address_type = conn->src_type;
- cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
- cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
- cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
- cp.min_ce_len = __constant_cpu_to_le16(0x0000);
- cp.max_ce_len = __constant_cpu_to_le16(0x0000);
-
- hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
-
- err = hci_req_run(&req, create_le_conn_complete);
- if (err) {
- hci_conn_del(conn);
- return err;
- }
-
- return 0;
-}
-
static void create_le_conn_req(struct hci_request *req, struct hci_conn *conn)
{
struct hci_cp_le_create_conn cp;
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 03/11] Bluetooth: Stop scanning on LE connection
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
Some LE controllers don't support scanning and creating a connection
at the same time. So we should always stop scanning in order to
establish the connection.
Since we may prematurely stop the discovery procedure in favor of
the connection establishment, we should also cancel hdev->le_scan_
disable delayed work and set the discovery state to DISCOVERY_STOPPED.
This change does a small improvement since it is not mandatory the
user stops scanning before connecting anymore. Moreover, this change
is required by upcoming LE auto connection mechanism in order to work
properly with controllers that don't support background scanning and
connection establishment at the same time.
In future, we might want to do a small optimization by checking if
controller is able to scan and connect at the same time. For now,
we want the simplest approach so we always stop scanning (even if
the controller is able to carry out both operations).
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci.h | 1 +
net/bluetooth/hci_conn.c | 84 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 352d3d7..a0d5262 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -352,6 +352,7 @@ enum {
/* ---- HCI Error Codes ---- */
#define HCI_ERROR_AUTH_FAILURE 0x05
+#define HCI_ERROR_MEMORY_EXCEEDED 0x07
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08
#define HCI_ERROR_REJ_BAD_ADDR 0x0f
#define HCI_ERROR_REMOTE_USER_TERM 0x13
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6797292..63c1e4f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -583,11 +583,71 @@ static int hci_create_le_conn(struct hci_conn *conn)
return 0;
}
+static void create_le_conn_req(struct hci_request *req, struct hci_conn *conn)
+{
+ struct hci_cp_le_create_conn cp;
+ struct hci_dev *hdev = conn->hdev;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
+ cp.scan_window = cpu_to_le16(hdev->le_scan_window);
+ bacpy(&cp.peer_addr, &conn->dst);
+ cp.peer_addr_type = conn->dst_type;
+ cp.own_address_type = conn->src_type;
+ cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
+ cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
+ cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
+ cp.min_ce_len = __constant_cpu_to_le16(0x0000);
+ cp.max_ce_len = __constant_cpu_to_le16(0x0000);
+
+ hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+}
+
+static void stop_scan_complete(struct hci_dev *hdev, u8 status)
+{
+ struct hci_request req;
+ struct hci_conn *conn;
+ int err;
+
+ conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+ if (!conn)
+ return;
+
+ if (status) {
+ BT_DBG("HCI request failed to stop scanning: status 0x%2.2x",
+ status);
+
+ hci_dev_lock(hdev);
+ le_conn_failed(conn, status);
+ hci_dev_unlock(hdev);
+ return;
+ }
+
+ /* Since we may have prematurely stopped discovery procedure, we should
+ * update discovery state.
+ */
+ cancel_delayed_work(&hdev->le_scan_disable);
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+ hci_req_init(&req, hdev);
+
+ create_le_conn_req(&req, conn);
+
+ err = hci_req_run(&req, create_le_conn_complete);
+ if (err) {
+ hci_dev_lock(hdev);
+ le_conn_failed(conn, HCI_ERROR_MEMORY_EXCEEDED);
+ hci_dev_unlock(hdev);
+ return;
+ }
+}
+
static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u8 auth_type)
{
struct hci_conn_params *params;
struct hci_conn *conn;
+ struct hci_request req;
int err;
if (test_bit(HCI_ADVERTISING, &hdev->flags))
@@ -643,9 +703,29 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
conn->le_conn_max_interval = hdev->le_conn_max_interval;
}
- err = hci_create_le_conn(conn);
- if (err)
+ hci_req_init(&req, hdev);
+
+ /* If controller is scanning, we stop it since some controllers are
+ * not able to scan and connect at the same time.
+ */
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
+ struct hci_cp_le_set_scan_enable cp;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.enable = LE_SCAN_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+
+ err = hci_req_run(&req, stop_scan_complete);
+ } else {
+ create_le_conn_req(&req, conn);
+
+ err = hci_req_run(&req, create_le_conn_complete);
+ }
+
+ if (err) {
+ hci_conn_del(conn);
return ERR_PTR(err);
+ }
done:
hci_conn_hold(conn);
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 02/11] Bluetooth: Use connection parameters if any
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391446588-18729-1-git-send-email-andre.guedes@openbossa.org>
This patch changes hci_connect_le() so it uses the connection
parameters specified for the certain device. If no parameters
were configured, we use the default values.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_conn.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 801820f..6797292 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -586,6 +586,7 @@ static int hci_create_le_conn(struct hci_conn *conn)
static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u8 auth_type)
{
+ struct hci_conn_params *params;
struct hci_conn *conn;
int err;
@@ -632,8 +633,15 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
conn->sec_level = BT_SECURITY_LOW;
conn->pending_sec_level = sec_level;
conn->auth_type = auth_type;
- conn->le_conn_min_interval = hdev->le_conn_min_interval;
- conn->le_conn_max_interval = hdev->le_conn_max_interval;
+
+ params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+ if (params) {
+ conn->le_conn_min_interval = params->conn_min_interval;
+ conn->le_conn_max_interval = params->conn_max_interval;
+ } else {
+ conn->le_conn_min_interval = hdev->le_conn_min_interval;
+ conn->le_conn_max_interval = hdev->le_conn_max_interval;
+ }
err = hci_create_le_conn(conn);
if (err)
--
1.8.5.3
^ permalink raw reply related
* [RFC v7 01/11] Bluetooth: Introduce connection parameters list
From: Andre Guedes @ 2014-02-03 16:56 UTC (permalink / raw)
To: linux-bluetooth
This patch adds to hdev the connection parameters list (hdev->le_
conn_params). The elements from this list (struct hci_conn_params)
contains the connection parameters (for now, minimum and maximum
connection interval) that should be used during the connection
establishment.
Moreover, this patch adds helper functions to manipulate hdev->le_
conn_params list. Some of these functions are also declared in
hci_core.h since they will be used outside hci_core.c in upcoming
patches.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 18 ++++++++++
net/bluetooth/hci_core.c | 77 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4e87878..92fa75f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -269,6 +269,7 @@ struct hci_dev {
struct list_head link_keys;
struct list_head long_term_keys;
struct list_head remote_oob_data;
+ struct list_head le_conn_params;
struct hci_dev_stats stat;
@@ -373,6 +374,16 @@ struct hci_chan {
__u8 state;
};
+struct hci_conn_params {
+ struct list_head list;
+
+ bdaddr_t addr;
+ u8 addr_type;
+
+ u16 conn_min_interval;
+ u16 conn_max_interval;
+};
+
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock;
@@ -751,6 +762,13 @@ int hci_blacklist_clear(struct hci_dev *hdev);
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type);
+void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+ u16 conn_min_interval, u16 conn_max_interval);
+void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_conn_params_clear(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 7a44c8c..e774669 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2924,6 +2924,81 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return mgmt_device_unblocked(hdev, bdaddr, type);
}
+/* This function requires the caller holds hdev->lock */
+struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type)
+{
+ struct hci_conn_params *params;
+
+ list_for_each_entry(params, &hdev->le_conn_params, list) {
+ if (bacmp(¶ms->addr, addr) == 0 &&
+ params->addr_type == addr_type) {
+ return params;
+ }
+ }
+
+ return NULL;
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+ u16 conn_min_interval, u16 conn_max_interval)
+{
+ struct hci_conn_params *params;
+
+ params = hci_conn_params_lookup(hdev, addr, addr_type);
+ if (params) {
+ params->conn_min_interval = conn_min_interval;
+ params->conn_max_interval = conn_max_interval;
+ return;
+ }
+
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params) {
+ BT_ERR("Out of memory");
+ return;
+ }
+
+ bacpy(¶ms->addr, addr);
+ params->addr_type = addr_type;
+ params->conn_min_interval = conn_min_interval;
+ params->conn_max_interval = conn_max_interval;
+
+ list_add(¶ms->list, &hdev->le_conn_params);
+
+ BT_DBG("addr %pMR (type %u) conn_min_interval 0x%.4x "
+ "conn_max_interval 0x%.4x", addr, addr_type, conn_min_interval,
+ conn_max_interval);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+ struct hci_conn_params *params;
+
+ params = hci_conn_params_lookup(hdev, addr, addr_type);
+ if (!params)
+ return;
+
+ list_del(¶ms->list);
+ kfree(params);
+
+ BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_clear(struct hci_dev *hdev)
+{
+ struct hci_conn_params *params, *tmp;
+
+ list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
+ list_del(¶ms->list);
+ kfree(params);
+ }
+
+ BT_DBG("All LE connection parameters were removed");
+}
+
static void inquiry_complete(struct hci_dev *hdev, u8 status)
{
if (status) {
@@ -3034,6 +3109,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
+ INIT_LIST_HEAD(&hdev->le_conn_params);
INIT_LIST_HEAD(&hdev->conn_hash.list);
INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3219,6 +3295,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_link_keys_clear(hdev);
hci_smp_ltks_clear(hdev);
hci_remote_oob_data_clear(hdev);
+ hci_conn_params_clear(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 6/6] android/hal-audio: Add RTP timestamps
From: Andrzej Kaczmarek @ 2014-02-03 16:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391446549-31455-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
android/hal-audio.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index 6439880..efdf823 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -133,6 +133,7 @@ struct sbc_data {
struct timespec start;
unsigned frames_sent;
+ uint32_t timestamp;
uint16_t seq;
};
@@ -404,6 +405,7 @@ static void sbc_resume(void *codec_data)
clock_gettime(CLOCK_MONOTONIC, &sbc_data->start);
sbc_data->frames_sent = 0;
+ sbc_data->timestamp = 0;
}
static int write_media_packet(int fd, struct sbc_data *sbc_data,
@@ -455,31 +457,38 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
struct media_packet *mp = (struct media_packet *) sbc_data->out_buf;
size_t free_space = sbc_data->out_buf_size - sizeof(*mp);
int ret;
+ ssize_t bytes_read;
mp->hdr.v = 2;
mp->hdr.pt = 1;
mp->hdr.ssrc = htonl(1);
+ mp->hdr.timestamp = htonl(sbc_data->timestamp);
mp->payload.frame_count = 0;
while (bytes - consumed >= sbc_data->in_frame_len) {
ssize_t written = 0;
- ret = sbc_encode(&sbc_data->enc, buffer + consumed,
+ bytes_read = sbc_encode(&sbc_data->enc, buffer + consumed,
sbc_data->in_frame_len,
mp->data + encoded, free_space,
&written);
- if (ret < 0) {
- error("SBC: failed to encode block (%d)", ret);
+ if (bytes_read < 0) {
+ error("SBC: failed to encode block (%zd)", bytes_read);
break;
}
mp->payload.frame_count++;
- consumed += ret;
+ consumed += bytes_read;
encoded += written;
free_space -= written;
+ /* AudioFlinger provides PCM 16bit stereo only, thus sample size
+ * is always 4 bytes
+ */
+ sbc_data->timestamp += (bytes_read / 4);
+
/* write data if we either filled media packed or encoded all
* input data
*/
@@ -495,6 +504,7 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
encoded = 0;
free_space = sbc_data->out_buf_size - sizeof(*mp);
+ mp->hdr.timestamp = htonl(sbc_data->timestamp);
mp->payload.frame_count = 0;
}
}
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 5/6] android/hal-audio: Fix RTP sequence numbers
From: Andrzej Kaczmarek @ 2014-02-03 16:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391446549-31455-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
android/hal-audio.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index be17c76..6439880 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -458,7 +458,6 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
mp->hdr.v = 2;
mp->hdr.pt = 1;
- mp->hdr.sequence_number = htons(sbc_data->seq++);
mp->hdr.ssrc = htonl(1);
mp->payload.frame_count = 0;
@@ -488,6 +487,8 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
bytes == consumed ||
mp->payload.frame_count ==
MAX_FRAMES_IN_PAYLOAD) {
+ mp->hdr.sequence_number = htons(sbc_data->seq++);
+
ret = write_media_packet(fd, sbc_data, mp, encoded);
if (ret < 0)
return ret;
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 4/6] android/hal-audio: Fix audio with large omtu value
From: Andrzej Kaczmarek @ 2014-02-03 16:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391446549-31455-1-git-send-email-andrzej.kaczmarek@tieto.com>
This patch fixes media packet construction with devices which use large
omtu value. In such cases it's possible that we will try to fit more
than 15 SBC frames in single media packet (which is maximum possible
value as it's encoded using 4 bits) which will cause frame counter to
wrap around and provide incorrect data to SBC encoder.
This behaviour was seen on UPF with one of carkit devices which set
omtu=2688.
---
android/hal-audio.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index ff2b6e4..be17c76 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -39,6 +39,8 @@
#define FIXED_A2DP_PLAYBACK_LATENCY_MS 25
+#define MAX_FRAMES_IN_PAYLOAD 15
+
static const uint8_t a2dp_src_uuid[] = {
0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
@@ -483,7 +485,9 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
* input data
*/
if (mp->payload.frame_count == sbc_data->frames_per_packet ||
- bytes == consumed) {
+ bytes == consumed ||
+ mp->payload.frame_count ==
+ MAX_FRAMES_IN_PAYLOAD) {
ret = write_media_packet(fd, sbc_data, mp, encoded);
if (ret < 0)
return ret;
--
1.8.5.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox