* [PATCH BlueZ 6/6 v2] tools: Emit Seeked signal if Position changes
From: Luiz Augusto von Dentz @ 2013-01-24 9:58 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359021484-6958-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
MPRIS spec says PropertiesChanged is not emitted for Position, which is
probably to make clear that progress is done using the rate, so instead
Seeked should be emitted.
---
tools/mpris-player.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 5903ca1..95ef8ab 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -1650,6 +1650,8 @@ static void player_property_changed(GDBusProxy *proxy, const char *name,
{
struct player *player;
const char *property;
+ uint32_t position;
+ uint64_t value;
player = find_player(proxy);
if (player == NULL)
@@ -1662,6 +1664,18 @@ static void player_property_changed(GDBusProxy *proxy, const char *name,
g_dbus_emit_property_changed(player->conn, MPRIS_PLAYER_PATH,
MPRIS_PLAYER_INTERFACE,
property);
+
+ if (strcasecmp(name, "Position") != 0)
+ return;
+
+ dbus_message_iter_get_basic(iter, &position);
+
+ value = position * 1000;
+
+ g_dbus_emit_signal(player->conn, MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE, "Seeked",
+ DBUS_TYPE_INT64, &value,
+ DBUS_TYPE_INVALID);
}
static void transport_property_changed(GDBusProxy *proxy, const char *name,
--
1.8.1
^ permalink raw reply related
* Query regarding LE encryption failure
From: Jaganath Kanakkassery @ 2013-01-24 13:55 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1358781718-386-3-git-send-email-luiz.dentz@gmail.com>
Hello,
We are using BlueZ-4.101 and the device is paired with an LE proximity
device.
When "DiscoverCharacteristics" is called, after creating LE connection it is
trying to encrypt the link which fails with "Pin or key missing".
< HCI Command: LE Start Encryption (0x08|0x0019) plen 28
0000: 40 00 cb 2e 2a ec a1 c5 3c ad 2d d5 02 dc 91 a5 @...*...<.-.....
0010: d7 7b b0 aa 82 ef cb 32 31 ce 4e 6f .{.....21.No
> HCI Event: Command Status (0x0f) plen 4
LE Start Encryption (0x08|0x0019) status 0x00 ncmd 1
> HCI Event: Encrypt Change (0x08) plen 4
status 0x06 handle 64 encrypt 0x00
Error: PIN or Key Missing
Any idea why it is failing?
One thing I noticed is during pairing also this encryption is being done
and it succeeded.
< HCI Command: LE Start Encryption (0x08|0x0019) plen 28
0000: 40 00 00 00 00 00 00 00 00 00 00 00 f4 33 19 ea @............3..
0010: aa 35 95 5a 51 cf 15 a6 23 8a 05 27 .5.ZQ...#..'
> HCI Event: Command Status (0x0f) plen 4
LE Start Encryption (0x08|0x0019) status 0x00 ncmd 1
> HCI Event: Encrypt Change (0x08) plen 4
status 0x00 handle 64 encrypt 0x01
But both the encryption packets are different. Is it expected?
Thanks,
Jaganath
^ permalink raw reply
* Re: usb device removed from sysfs before input children devices
From: Karl Relton @ 2013-01-24 13:58 UTC (permalink / raw)
To: linux-usb, linux-bluetooth
In-Reply-To: <1358281626.3998.29.camel@dellpc>
On Tue, 2013-01-15 at 20:27 +0000, Karl Relton wrote:
> > The end result (for the user) is that even when the bluetooth
> > mouse/keyboard is re-added, Xorg ignores it - thinking it is some
> hoax
> > duplicate device. The keyboard/mouse is then non-operational.
> >
>
> Instrumenting the code suggests that the issue arises in a race
> between:
>
> hidp_session() in bluetooth/hidp/core.c
>
> and
>
> hci_unregister_dev() in bluetooth/hci_core.c
>
>
> Basically hci_unregister_dev() does a hci_dev_do_close() which in turn
> shuts down the hidp connection. This causes hidp_session() running in
> another thread to go into its cleanup phase, which is where the input
> children devices are unregistered.
>
> HOWEVER:
> 1) For some reason input_unregister_device() seems to stall some 3-5
> seconds on my system before removing the input device
> 2) In parallel hci_unregister_dev() ploughs on, and progresses to
> remove
> its hdev (hci<n> device) regardless, without waiting for
> hidp_session()
> to complete.
>
> I can't figure out why there is such a delay for
> input_unregister_device().
The power_supply system seems to be triggering a lookup of battery
'capacity' in the input device. This calls into the driver, which deep
down invokes more code in the 'hidp' module: hidp_get_raw_report()
This function tries to communicate with the bluetooth device (keyboard
in my case), but because the device is being 'torn down' such
communication fails. Accordingly hidp_get_raw_report has a 5 second
timeout ... so this function stalls for 5 seconds until that timeout
occurs.
I would guess that for some reason, removing the 'hid' or associated
'input' device is leading to the power_supply code wanting to lookup the
battery capacity which introduces a 5 second wait. This would delay
hidp_session by 5 seconds ... in the mean time allowing
hci_unregister_dev() to win the race and hence the hci device is removed
before the input & hid devices.
^ permalink raw reply
* Re: Query regarding LE encryption failure
From: Anderson Lizardo @ 2013-01-24 14:32 UTC (permalink / raw)
To: Jaganath Kanakkassery; +Cc: linux-bluetooth
In-Reply-To: <3C2963DE7FB6424B9BCE227143415153@sisodomain.com>
Hi Jaganath,
On Thu, Jan 24, 2013 at 9:55 AM, Jaganath Kanakkassery
<jaganath.k@samsung.com> wrote:
> Hello,
>
> We are using BlueZ-4.101 and the device is paired with an LE proximity
> device.
> When "DiscoverCharacteristics" is called, after creating LE connection it is
> trying to encrypt the link which fails with "Pin or key missing".
>
> < HCI Command: LE Start Encryption (0x08|0x0019) plen 28
> 0000: 40 00 cb 2e 2a ec a1 c5 3c ad 2d d5 02 dc 91 a5 @...*...<.-.....
> 0010: d7 7b b0 aa 82 ef cb 32 31 ce 4e 6f .{.....21.No
>>
>> HCI Event: Command Status (0x0f) plen 4
>
> LE Start Encryption (0x08|0x0019) status 0x00 ncmd 1
>>
>> HCI Event: Encrypt Change (0x08) plen 4
>
> status 0x06 handle 64 encrypt 0x00
> Error: PIN or Key Missing
>
> Any idea why it is failing?
It looks to me the remote device lose the bonding. Are you sure it was
not power cycled (i.e. the battery removed or device was reset some
way)?
>
> One thing I noticed is during pairing also this encryption is being done
> and it succeeded.
>
> < HCI Command: LE Start Encryption (0x08|0x0019) plen 28
> 0000: 40 00 00 00 00 00 00 00 00 00 00 00 f4 33 19 ea @............3..
> 0010: aa 35 95 5a 51 cf 15 a6 23 8a 05 27 .5.ZQ...#..'
>>
>> HCI Event: Command Status (0x0f) plen 4
>
> LE Start Encryption (0x08|0x0019) status 0x00 ncmd 1
>>
>> HCI Event: Encrypt Change (0x08) plen 4
>
> status 0x00 handle 64 encrypt 0x01
>
>
> But both the encryption packets are different. Is it expected?
IIRC this should be the STK used for encryption right after "just
works" pairing. See Figure 5.5 from page 2005 of Core spec. It will
not match the LTK used for encryption after re-connection.
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: usb device removed from sysfs before input children devices
From: Karl Relton @ 2013-01-24 16:09 UTC (permalink / raw)
To: linux-usb, linux-bluetooth
In-Reply-To: <1359035887.5482.1.camel@dellpc>
On Thu, 2013-01-24 at 13:58 +0000, Karl Relton wrote:
> On Tue, 2013-01-15 at 20:27 +0000, Karl Relton wrote:
> > > The end result (for the user) is that even when the bluetooth
> > > mouse/keyboard is re-added, Xorg ignores it - thinking it is some
> > hoax
> > > duplicate device. The keyboard/mouse is then non-operational.
> > >
> >
> > Instrumenting the code suggests that the issue arises in a race
> > between:
> >
> > hidp_session() in bluetooth/hidp/core.c
> >
> > and
> >
> > hci_unregister_dev() in bluetooth/hci_core.c
> >
> >
...
> >
> > I can't figure out why there is such a delay for
> > input_unregister_device().
>
>
> The power_supply system seems to be triggering a lookup of battery
> 'capacity' in the input device. This calls into the driver, which deep
> down invokes more code in the 'hidp' module: hidp_get_raw_report()
>
> This function tries to communicate with the bluetooth device (keyboard
> in my case), but because the device is being 'torn down' such
> communication fails. Accordingly hidp_get_raw_report has a 5 second
> timeout ... so this function stalls for 5 seconds until that timeout
> occurs.
>
>
> I would guess that for some reason, removing the 'hid' or associated
> 'input' device is leading to the power_supply code wanting to lookup the
> battery capacity which introduces a 5 second wait. This would delay
> hidp_session by 5 seconds ... in the mean time allowing
> hci_unregister_dev() to win the race and hence the hci device is removed
> before the input & hid devices.
>
device_del is done on the battery device, called from
hidinput_cleanup_battery in hid-input.c.
This will generate a uevent which has the power_supply attributes added,
which invokes power_supply_show_property for 'capacity' which invokes
the hidp_get_raw_report (which stalls for 5 seconds).
Back in the days of linux 3.2, hid-input.c did not have any support for
batteries, so this chain of calls was never made, hence the race was won
by hidp_session() because it didn't have the 5 second delay injected.
Now with battery support added, the problem is manifest.
--
I think hidp_get_raw_report should abort if the devices is being 'torn
down' (and so not go into the 5 second wait). But also the race between
the two functions needs sorting, since sooner or later someone else will
get unlucky.
^ permalink raw reply
* RFC: Race between hci_unregister_dev and hidp_session
From: Karl Relton @ 2013-01-24 16:44 UTC (permalink / raw)
To: Gustavo Padovan, Marcel Holtmann; +Cc: linux-bluetooth
Dear Gustavo/Marcel
I believe I have tracked down a race condition between
hci_unregister_dev() and hidp_session() that can lead to userspace
failure of bluetooth input devices (see [1] below).
hci_unregister_dev calls
hci_dev_do_close calls
hci_conn_hash_flush calls
hci_proto_disconn_cfm which triggers (via a wakeup)
hidp_session running in another thread (a kthread)
hci_unregister_dev, after the above calls, will go on to call
hci_del_sysfs to remove the 'hci' device
Meanwhile hidp_session will drop out its main loop, start cleaning up
which includes a call to
hid_destroy_device which removes the input & hid (and hidraw) devices
For correct operation, and what userspace would normally expect, removal
from the sysfs tree should be 'bottom up', i.e. event then input then
hid then hci.
For this operation, one would need to guaruntee that hidp_session
finishes its cleanup before hci_unregister_dev continues with its work.
At the moment this is not done. Any delay in hidp_session will allow
hci_unregister_dev to win the race, causing an out of sequence sysfs
removal, and headaches for userspace.
Currently, the power_supply system is causing hidp_session to stall for
5 seconds (as detailed in [2]). Plenty of time to cause hidp_session to
lose the race! But even without such silliness, a race can't be a good
thing can it?
How to fix? Some synchronisation between hidp_session thread and the hci
code is required. hci_conn devices already use a ref counting system to
delay removing the device from sysfs until the count gets to zero
(hci_conn_put_device), so presumably a similar arrangement can be
implemented for the hci device? Note this would need to be a different
count to that currently in hci_dev_put/hold, because that is based on
the lower level kobj references. Perhaps hci_dev_put/hold can be
augmented to keep its own count in addition to the underlying kobj
count?
Karl
References:
[1] https://bugzilla.kernel.org/show_bug.cgi?id=52471
the udev remove events, being out of sequence, have truncated paths
which disturbs userspace programs like Xorg evdev so they cannot process
the keyboard/mouse removal.
[2] https://bugzilla.kernel.org/show_bug.cgi?id=52471#c2 and
https://bugzilla.kernel.org/show_bug.cgi?id=52471#c3
^ permalink raw reply
* [PATCH 0/6] Bluetooth: Add 32 and 128 bit EIR UUID support
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
Hi,
There was another set of patches from Syam to add the same functionality
but it can be accomplished in a simpler way since we only need to follow
the ordering within each group of UUIDs.
I've added test cases to mgmt-tester to verify both the complete and
partial UUID list cases (more can be added, but there are enough that
I'm confident of the correctness of these patches).
Johan Hedberg (6):
Bluetooth: Split UUIDs to three separate lists
Bluetooth: Simplify UUID16 list generation for EIR
Bluetooth: Remove useless eir_len variable from EIR creation
Bluetooth: Refactor UUID-16 list generation into its own function
Bluetooth: Add support for 32-bit UUIDs in EIR data
Bluetooth: Add support for 128-bit UUIDs in EIR data
include/net/bluetooth/hci_core.h | 4 ++
net/bluetooth/hci_core.c | 14 ++---
net/bluetooth/hci_sysfs.c | 2 +-
net/bluetooth/mgmt.c | 218 +++++++++++++++++++++++++++++++++++++++++-----------------------
4 files changed, 152 insertions(+), 86 deletions(-)
^ permalink raw reply
* [PATCH 1/6] Bluetooth: Split UUIDs to three separate lists
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359054206-19528-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The primary purpose of the UUIDs is to eable generation of EIR and AD
data. In these data formats the UUIDs are split into separate fields
based on whether they're 16, 32 or 128 bit UUIDs. To make the generation
of these data fields simple this patch splits the UUIDs into three
separate lists based on their type.
To keep cases needing access to all UUIDs easy the UUIDs are also kept
in an "all" list. This is particularly useful for exposing the UUIDs
through sysfs as well as removing UUIDs (whether removing a specific one
or all UUIDs).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 4 ++
net/bluetooth/hci_core.c | 14 +++----
net/bluetooth/hci_sysfs.c | 2 +-
net/bluetooth/mgmt.c | 85 +++++++++++++++++++++++---------------
4 files changed, 63 insertions(+), 42 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bcf8ffe..d3b1d1b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -85,6 +85,7 @@ struct bdaddr_list {
struct bt_uuid {
struct list_head list;
+ struct list_head all;
u8 uuid[16];
u8 svc_hint;
};
@@ -256,6 +257,9 @@ struct hci_dev {
struct list_head blacklist;
struct list_head uuids;
+ struct list_head uuid16;
+ struct list_head uuid32;
+ struct list_head uuid128;
struct list_head link_keys;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e061b35..8818521 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1183,14 +1183,11 @@ static void hci_discov_off(struct work_struct *work)
int hci_uuids_clear(struct hci_dev *hdev)
{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &hdev->uuids) {
- struct bt_uuid *uuid;
+ struct bt_uuid *uuid, *tmp;
- uuid = list_entry(p, struct bt_uuid, list);
-
- list_del(p);
+ list_for_each_entry_safe(uuid, tmp, &hdev->uuids, all) {
+ list_del(&uuid->list);
+ list_del(&uuid->all);
kfree(uuid);
}
@@ -1718,6 +1715,9 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->mgmt_pending);
INIT_LIST_HEAD(&hdev->blacklist);
INIT_LIST_HEAD(&hdev->uuids);
+ INIT_LIST_HEAD(&hdev->uuid16);
+ INIT_LIST_HEAD(&hdev->uuid32);
+ INIT_LIST_HEAD(&hdev->uuid128);
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 23b4e24..9a60c74 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -483,7 +483,7 @@ static int uuids_show(struct seq_file *f, void *p)
hci_dev_lock(hdev);
- list_for_each_entry(uuid, &hdev->uuids, list)
+ list_for_each_entry(uuid, &hdev->uuids, all)
print_bt_uuid(f, uuid->uuid);
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e7f944f..878b4a2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -435,28 +435,6 @@ static u32 get_current_settings(struct hci_dev *hdev)
#define PNP_INFO_SVCLASS_ID 0x1200
-static u8 bluetooth_base_uuid[] = {
- 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static u16 get_uuid16(u8 *uuid128)
-{
- u32 val;
- int i;
-
- for (i = 0; i < 12; i++) {
- if (bluetooth_base_uuid[i] != uuid128[i])
- return 0;
- }
-
- val = get_unaligned_le32(&uuid128[12]);
- if (val > 0xffff)
- return 0;
-
- return (u16) val;
-}
-
static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
@@ -510,13 +488,10 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
memset(uuid16_list, 0, sizeof(uuid16_list));
/* Group all UUID16 types */
- list_for_each_entry(uuid, &hdev->uuids, list) {
+ list_for_each_entry(uuid, &hdev->uuid16, list) {
u16 uuid16;
- uuid16 = get_uuid16(uuid->uuid);
- if (uuid16 == 0)
- return;
-
+ uuid16 = get_unaligned_le16(&uuid->uuid[12]);
if (uuid16 < 0x1100)
continue;
@@ -592,7 +567,7 @@ static u8 get_service_classes(struct hci_dev *hdev)
struct bt_uuid *uuid;
u8 val = 0;
- list_for_each_entry(uuid, &hdev->uuids, list)
+ list_for_each_entry(uuid, &hdev->uuids, all)
val |= uuid->svc_hint;
return val;
@@ -1304,6 +1279,34 @@ unlock:
return err;
}
+enum bt_uuid_t {
+ BT_UUID16,
+ BT_UUID32,
+ BT_UUID128,
+};
+
+static u8 bluetooth_base_uuid[] = {
+ 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static enum bt_uuid_t bt_uuid_type(u8 *uuid)
+{
+ u32 val;
+ int i;
+
+ for (i = 0; i < 12; i++) {
+ if (bluetooth_base_uuid[i] != uuid[i])
+ return BT_UUID128;
+ }
+
+ val = get_unaligned_le32(&uuid[12]);
+ if (val > 0xffff)
+ return BT_UUID32;
+
+ return BT_UUID16;
+}
+
static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_cp_add_uuid *cp = data;
@@ -1330,7 +1333,23 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
memcpy(uuid->uuid, cp->uuid, 16);
uuid->svc_hint = cp->svc_hint;
- list_add(&uuid->list, &hdev->uuids);
+ switch (bt_uuid_type(uuid->uuid)) {
+ case BT_UUID16:
+ list_add_tail(&uuid->list, &hdev->uuid16);
+ break;
+ case BT_UUID32:
+ list_add_tail(&uuid->list, &hdev->uuid32);
+ break;
+ case BT_UUID128:
+ list_add_tail(&uuid->list, &hdev->uuid128);
+ break;
+ default:
+ /* Should never be reached */
+ err = -EINVAL;
+ goto failed;
+ }
+
+ list_add_tail(&uuid->all, &hdev->uuids);
err = update_class(hdev);
if (err < 0)
@@ -1374,7 +1393,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
{
struct mgmt_cp_remove_uuid *cp = data;
struct pending_cmd *cmd;
- struct list_head *p, *n;
+ struct bt_uuid *match, *tmp;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int err, found;
@@ -1402,13 +1421,11 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
found = 0;
- list_for_each_safe(p, n, &hdev->uuids) {
- struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
-
+ list_for_each_entry_safe(match, tmp, &hdev->uuids, all) {
if (memcmp(match->uuid, cp->uuid, 16) != 0)
continue;
-
list_del(&match->list);
+ list_del(&match->all);
kfree(match);
found++;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/6] Bluetooth: Simplify UUID16 list generation for EIR
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359054206-19528-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
There's no need to use two separate loops to generate a UUID list for
the EIR data. This patch merges the two loops previously used for the
16-bit UUID list generation into a single loop, thus simplifying the
code a great deal.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 46 +++++++++++++++-------------------------------
1 file changed, 15 insertions(+), 31 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 878b4a2..d4e5313 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -438,9 +438,8 @@ static u32 get_current_settings(struct hci_dev *hdev)
static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
+ u8 *uuids_start;
u16 eir_len = 0;
- u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
- int i, truncated = 0;
struct bt_uuid *uuid;
size_t name_len;
@@ -485,7 +484,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
ptr += 10;
}
- memset(uuid16_list, 0, sizeof(uuid16_list));
+ uuids_start = NULL;
/* Group all UUID16 types */
list_for_each_entry(uuid, &hdev->uuid16, list) {
@@ -498,39 +497,24 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
if (uuid16 == PNP_INFO_SVCLASS_ID)
continue;
+ if (!uuids_start) {
+ uuids_start = ptr;
+ uuids_start[0] = 1;
+ uuids_start[1] = EIR_UUID16_ALL;
+ ptr += 2;
+ eir_len += 2;
+ }
+
/* Stop if not enough space to put next UUID */
if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
- truncated = 1;
+ uuids_start[1] = EIR_UUID16_SOME;
break;
}
- /* Check for duplicates */
- for (i = 0; uuid16_list[i] != 0; i++)
- if (uuid16_list[i] == uuid16)
- break;
-
- if (uuid16_list[i] == 0) {
- uuid16_list[i] = uuid16;
- eir_len += sizeof(u16);
- }
- }
-
- if (uuid16_list[0] != 0) {
- u8 *length = ptr;
-
- /* EIR Data type */
- ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
-
- ptr += 2;
- eir_len += 2;
-
- for (i = 0; uuid16_list[i] != 0; i++) {
- *ptr++ = (uuid16_list[i] & 0x00ff);
- *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
- }
-
- /* EIR Data length */
- *length = (i * sizeof(u16)) + 1;
+ *ptr++ = (uuid16 & 0x00ff);
+ *ptr++ = (uuid16 & 0xff00) >> 8;
+ eir_len += sizeof(uuid16);
+ uuids_start[0] += sizeof(uuid16);
}
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/6] Bluetooth: Remove useless eir_len variable from EIR creation
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359054206-19528-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The amount of data encoded so far in the create_eir() function can be
calculated simply through the difference between the data and ptr
pointer variables. The eir_len variable then becomes essentially
useless.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d4e5313..76ba1fd 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -439,7 +439,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
u8 *uuids_start;
- u16 eir_len = 0;
struct bt_uuid *uuid;
size_t name_len;
@@ -458,7 +457,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
memcpy(ptr + 2, hdev->dev_name, name_len);
- eir_len += (name_len + 2);
ptr += (name_len + 2);
}
@@ -467,7 +465,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->inq_tx_power;
- eir_len += 3;
ptr += 3;
}
@@ -480,7 +477,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
put_unaligned_le16(hdev->devid_product, ptr + 6);
put_unaligned_le16(hdev->devid_version, ptr + 8);
- eir_len += 10;
ptr += 10;
}
@@ -502,18 +498,16 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
uuids_start[0] = 1;
uuids_start[1] = EIR_UUID16_ALL;
ptr += 2;
- eir_len += 2;
}
/* Stop if not enough space to put next UUID */
- if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
+ if ((ptr - data) + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
uuids_start[1] = EIR_UUID16_SOME;
break;
}
*ptr++ = (uuid16 & 0x00ff);
*ptr++ = (uuid16 & 0xff00) >> 8;
- eir_len += sizeof(uuid16);
uuids_start[0] += sizeof(uuid16);
}
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/6] Bluetooth: Refactor UUID-16 list generation into its own function
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359054206-19528-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
We will need to create three separate UUID lists in the EIR data (for
16, 32 and 128 bit UUIDs) so the code is easier to follow if each list
is generated in their own function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 69 +++++++++++++++++++++++++++-----------------------
1 file changed, 37 insertions(+), 32 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 76ba1fd..817d8e8 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -435,11 +435,45 @@ static u32 get_current_settings(struct hci_dev *hdev)
#define PNP_INFO_SVCLASS_ID 0x1200
+static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
+{
+ u8 *ptr = data, *uuids_start = NULL;
+ struct bt_uuid *uuid;
+
+ list_for_each_entry(uuid, &hdev->uuid16, list) {
+ u16 uuid16;
+
+ uuid16 = get_unaligned_le16(&uuid->uuid[12]);
+ if (uuid16 < 0x1100)
+ continue;
+
+ if (uuid16 == PNP_INFO_SVCLASS_ID)
+ continue;
+
+ if (!uuids_start) {
+ uuids_start = ptr;
+ uuids_start[0] = 1;
+ uuids_start[1] = EIR_UUID16_ALL;
+ ptr += 2;
+ }
+
+ /* Stop if not enough space to put next UUID */
+ if ((ptr - data) + sizeof(u16) > len) {
+ uuids_start[1] = EIR_UUID16_SOME;
+ break;
+ }
+
+ *ptr++ = (uuid16 & 0x00ff);
+ *ptr++ = (uuid16 & 0xff00) >> 8;
+ uuids_start[0] += sizeof(uuid16);
+ }
+
+ return ptr;
+}
+
static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
- u8 *uuids_start;
- struct bt_uuid *uuid;
size_t name_len;
name_len = strlen(hdev->dev_name);
@@ -480,36 +514,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
ptr += 10;
}
- uuids_start = NULL;
-
- /* Group all UUID16 types */
- list_for_each_entry(uuid, &hdev->uuid16, list) {
- u16 uuid16;
-
- uuid16 = get_unaligned_le16(&uuid->uuid[12]);
- if (uuid16 < 0x1100)
- continue;
-
- if (uuid16 == PNP_INFO_SVCLASS_ID)
- continue;
-
- if (!uuids_start) {
- uuids_start = ptr;
- uuids_start[0] = 1;
- uuids_start[1] = EIR_UUID16_ALL;
- ptr += 2;
- }
-
- /* Stop if not enough space to put next UUID */
- if ((ptr - data) + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
- uuids_start[1] = EIR_UUID16_SOME;
- break;
- }
-
- *ptr++ = (uuid16 & 0x00ff);
- *ptr++ = (uuid16 & 0xff00) >> 8;
- uuids_start[0] += sizeof(uuid16);
- }
+ ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
}
static int update_eir(struct hci_dev *hdev)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 5/6] Bluetooth: Add support for 32-bit UUIDs in EIR data
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359054206-19528-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds the necessary code for inserting a list of 32-bit UUIDs
into the EIR data.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 817d8e8..b9310d1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -471,6 +471,36 @@ static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
return ptr;
}
+static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
+{
+ u8 *ptr = data, *uuids_start = NULL;
+ struct bt_uuid *uuid;
+
+ if (len < 6)
+ return ptr;
+
+ list_for_each_entry(uuid, &hdev->uuid32, list) {
+ if (!uuids_start) {
+ uuids_start = ptr;
+ uuids_start[0] = 1;
+ uuids_start[1] = EIR_UUID32_ALL;
+ ptr += 2;
+ }
+
+ /* Stop if not enough space to put next UUID */
+ if ((ptr - data) + sizeof(u32) > len) {
+ uuids_start[1] = EIR_UUID32_SOME;
+ break;
+ }
+
+ memcpy(ptr, &uuid->uuid[12], sizeof(u32));
+ ptr += sizeof(u32);
+ uuids_start[0] += sizeof(u32);
+ }
+
+ return ptr;
+}
+
static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
@@ -515,6 +545,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
}
ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
+ ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
}
static int update_eir(struct hci_dev *hdev)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 6/6] Bluetooth: Add support for 128-bit UUIDs in EIR data
From: Johan Hedberg @ 2013-01-24 19:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359054206-19528-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds the necessary code for encoding a list of 128-bit UUIDs
into the EIR data.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b9310d1..6ca2de1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -501,6 +501,36 @@ static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
return ptr;
}
+static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
+{
+ u8 *ptr = data, *uuids_start = NULL;
+ struct bt_uuid *uuid;
+
+ if (len < 18)
+ return ptr;
+
+ list_for_each_entry(uuid, &hdev->uuid128, list) {
+ if (!uuids_start) {
+ uuids_start = ptr;
+ uuids_start[0] = 1;
+ uuids_start[1] = EIR_UUID128_ALL;
+ ptr += 2;
+ }
+
+ /* Stop if not enough space to put next UUID */
+ if ((ptr - data) + 16 > len) {
+ uuids_start[1] = EIR_UUID128_SOME;
+ break;
+ }
+
+ memcpy(ptr, uuid->uuid, 16);
+ ptr += 16;
+ uuids_start[0] += 16;
+ }
+
+ return ptr;
+}
+
static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
@@ -546,6 +576,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
+ ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
}
static int update_eir(struct hci_dev *hdev)
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 4/6] Bluetooth: Refactor UUID-16 list generation into its own function
From: Anderson Lizardo @ 2013-01-24 20:21 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1359054206-19528-5-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
On Thu, Jan 24, 2013 at 3:03 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> +static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> +{
> + u8 *ptr = data, *uuids_start = NULL;
> + struct bt_uuid *uuid;
Maybe you should check for "len < 2" here?
> +
> + list_for_each_entry(uuid, &hdev->uuid16, list) {
> + u16 uuid16;
> +
> + uuid16 = get_unaligned_le16(&uuid->uuid[12]);
> + if (uuid16 < 0x1100)
> + continue;
> +
> + if (uuid16 == PNP_INFO_SVCLASS_ID)
> + continue;
> +
> + if (!uuids_start) {
> + uuids_start = ptr;
> + uuids_start[0] = 1;
> + uuids_start[1] = EIR_UUID16_ALL;
> + ptr += 2;
> + }
> +
> + /* Stop if not enough space to put next UUID */
> + if ((ptr - data) + sizeof(u16) > len) {
> + uuids_start[1] = EIR_UUID16_SOME;
> + break;
> + }
> +
> + *ptr++ = (uuid16 & 0x00ff);
> + *ptr++ = (uuid16 & 0xff00) >> 8;
> + uuids_start[0] += sizeof(uuid16);
> + }
> +
> + return ptr;
> +}
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH 4/6] Bluetooth: Refactor UUID-16 list generation into its own function
From: Anderson Lizardo @ 2013-01-24 20:25 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_OMiH4vcoQSG1x++_G_nnQiTseb-moF8p=9k2utE=gAEg@mail.gmail.com>
On Thu, Jan 24, 2013 at 4:21 PM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi Johan,
>
> On Thu, Jan 24, 2013 at 3:03 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> +static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
>> +{
>> + u8 *ptr = data, *uuids_start = NULL;
>> + struct bt_uuid *uuid;
>
> Maybe you should check for "len < 2" here?
Actually, "len < 4", to be able to fit at least a 16-bit UUID.
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [RFC BlueZ 0/6] LE Connection Establishment fixes
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
Sending this as a RFC because I don't know if this is what you guys
had in mind.
Patches 1/6/ and 2/6 are simple enough fixes and should be considered
for inclusion, perhaps 6/6 as well, but the improvement is
non-functional.
The only problem with this aproach that I found while testing is the
problem exposed on the message of commit 5/6: If the remote device is
out of range during pairing any connection attempt will fail until the
Connection Complete event comes (with an error). This is the reason
that we put the devices in the connect list before pairing.
Is this reason enough to have the device put in the connect list
during pairing?
Cheers,
Vinicius Costa Gomes (6):
device: Fix invalid memory access during Find Included
device: Fix memory leak while storing GATT capable devices
device: Clean up device_att_connect()
device: Rename device_att_connect to device_connect_le
core: Add a way to connect to LE devices
gas: Move all the code to only one file
Makefile.plugins | 4 +-
profiles/gatt/gas.c | 46 +++++++++++++++++++++
profiles/gatt/main.c | 47 ---------------------
profiles/gatt/manager.c | 79 -----------------------------------
profiles/gatt/manager.h | 24 -----------
src/adapter.c | 22 +++++++++-
src/adapter.h | 3 ++
src/device.c | 108 +++++++++++++++++++++---------------------------
src/device.h | 3 +-
9 files changed, 119 insertions(+), 217 deletions(-)
delete mode 100644 profiles/gatt/main.c
delete mode 100644 profiles/gatt/manager.c
delete mode 100644 profiles/gatt/manager.h
--
1.8.1.1
^ permalink raw reply
* [RFC BlueZ 1/6] device: Fix invalid memory access during Find Included
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1359083227-13122-1-git-send-email-vinicius.gomes@openbossa.org>
When doing the Find Included Services GATT procedure, the status of the ATT
procedure was being ignored, and in the case of a timeout it is possible to
crash bluetooth with an invalid memory access.
Valgrind log:
==1755== Invalid read of size 8
==1755== at 0x46971A: find_included_cb (device.c:2964)
==1755== by 0x4465AE: isd_unref (gatt.c:92)
==1755== by 0x446885: find_included_cb (gatt.c:425)
==1755== by 0x448266: disconnect_timeout (gattrib.c:269)
==1755== by 0x4E76BCA: g_timeout_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76044: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76377: g_main_context_iterate.isra.24 (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76771: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x40A2EE: main (main.c:583)
==1755== Address 0x69530a8 is 8 bytes inside a block of size 64 free'd
==1755== at 0x4C2874F: free (vg_replace_malloc.c:446)
==1755== by 0x40BFA6: service_filter (watch.c:486)
==1755== by 0x40BC6A: message_filter (watch.c:554)
==1755== by 0x5160A1D: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.7.2)
==1755== by 0x40AAB7: message_dispatch (mainloop.c:76)
==1755== by 0x4E76BCA: g_timeout_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76044: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76377: g_main_context_iterate.isra.24 (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76771: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x40A2EE: main (main.c:583)
==1755==
==1755== Invalid read of size 8
==1755== at 0x4486D5: g_attrib_get_buffer (gattrib.c:657)
==1755== by 0x4467C5: find_included (gatt.c:363)
==1755== by 0x4465AE: isd_unref (gatt.c:92)
==1755== by 0x446885: find_included_cb (gatt.c:425)
==1755== by 0x448266: disconnect_timeout (gattrib.c:269)
==1755== by 0x4E76BCA: g_timeout_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76044: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76377: g_main_context_iterate.isra.24 (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76771: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x40A2EE: main (main.c:583)
==1755== Address 0x18 is not stack'd, malloc'd or (recently) free'd
==1755==
==1755==
==1755== Process terminating with default action of signal 11 (SIGSEGV)
==1755== Access not within mapped region at address 0x18
==1755== at 0x4486D5: g_attrib_get_buffer (gattrib.c:657)
==1755== by 0x4467C5: find_included (gatt.c:363)
==1755== by 0x4465AE: isd_unref (gatt.c:92)
==1755== by 0x446885: find_included_cb (gatt.c:425)
==1755== by 0x448266: disconnect_timeout (gattrib.c:269)
==1755== by 0x4E76BCA: g_timeout_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76044: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76377: g_main_context_iterate.isra.24 (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x4E76771: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3400.2)
==1755== by 0x40A2EE: main (main.c:583)
---
src/device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/device.c b/src/device.c
index bb79b38..893e4bb 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2963,7 +2963,7 @@ static void find_included_cb(GSList *includes, uint8_t status,
struct gatt_primary *prim;
GSList *l;
- if (includes == NULL)
+ if (includes == NULL || status != 0)
goto done;
for (l = includes; l; l = l->next) {
--
1.8.1.1
^ permalink raw reply related
* [RFC BlueZ 2/6] device: Fix memory leak while storing GATT capable devices
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1359083227-13122-1-git-send-email-vinicius.gomes@openbossa.org>
bt_uuid2string() returns a newly allocated string, and so it should
be free'd.
---
src/device.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/device.c b/src/device.c
index 893e4bb..6c4455b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2814,6 +2814,8 @@ static void store_services(struct btd_device *device)
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
prim_uuid = bt_uuid2string(&uuid);
+ if (prim_uuid == NULL)
+ return;
ba2str(adapter_get_address(adapter), src_addr);
ba2str(&device->bdaddr, dst_addr);
@@ -2862,6 +2864,7 @@ static void store_services(struct btd_device *device)
g_file_set_contents(filename, data, length, NULL);
}
+ g_free(prim_uuid);
g_free(data);
g_key_file_free(key_file);
}
--
1.8.1.1
^ permalink raw reply related
* [RFC BlueZ 3/6] device: Clean up device_att_connect()
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1359083227-13122-1-git-send-email-vinicius.gomes@openbossa.org>
device_att_connect() is used to make an ATT connection to an LE device.
We clean it (and its associated callback) to have better error handling
and to respond the user with an error when it happens.
As it is only used for LE devices, we remove all the handling for non-LE
devices.
---
src/device.c | 93 +++++++++++++++++++++++++-----------------------------------
src/device.h | 3 +-
2 files changed, 41 insertions(+), 55 deletions(-)
diff --git a/src/device.c b/src/device.c
index 6c4455b..89df161 100644
--- a/src/device.c
+++ b/src/device.c
@@ -3045,7 +3045,7 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
struct btd_device *device = attcb->user_data;
uint8_t io_cap;
GAttrib *attrib;
- int err;
+ int err = 0;
g_io_channel_unref(device->att_io);
device->att_io = NULL;
@@ -3056,6 +3056,7 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
if (attcb->error)
attcb->error(gerr, user_data);
+ err = -ECONNABORTED;
goto done;
}
@@ -3079,10 +3080,10 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
else
io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
- /* this is a LE device during pairing */
err = adapter_create_bonding(device->adapter, &device->bdaddr,
device->bdaddr_type, io_cap);
- if (err < 0) {
+done:
+ if (device->bonding && err < 0) {
DBusMessage *reply = btd_error_failed(device->bonding->msg,
strerror(-err));
g_dbus_send_message(dbus_conn, reply);
@@ -3090,7 +3091,6 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
bonding_request_free(device->bonding);
}
-done:
g_free(attcb);
}
@@ -3120,80 +3120,65 @@ static void att_success_cb(gpointer user_data)
g_slist_foreach(device->attios, attio_connected, device->attrib);
}
-GIOChannel *device_att_connect(gpointer user_data)
+GIOChannel *device_att_connect(struct btd_device *dev)
{
- struct btd_device *device = user_data;
- struct btd_adapter *adapter = device->adapter;
+ struct btd_adapter *adapter = dev->adapter;
struct att_callbacks *attcb;
+ BtIOSecLevel sec_level;
GIOChannel *io;
GError *gerr = NULL;
char addr[18];
- ba2str(&device->bdaddr, addr);
+ /* There is one connection attempt going on */
+ if (dev->att_io)
+ return NULL;
+
+ ba2str(&dev->bdaddr, addr);
DBG("Connection attempt to: %s", addr);
attcb = g_new0(struct att_callbacks, 1);
attcb->error = att_error_cb;
attcb->success = att_success_cb;
- attcb->user_data = device;
+ attcb->user_data = dev;
- if (device_is_bredr(device)) {
- io = bt_io_connect(att_connect_cb,
- attcb, NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(adapter),
- BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
- BT_IO_OPT_PSM, ATT_PSM,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_INVALID);
- } else if (device->bonding) {
- /* this is a LE device during pairing, using low sec level */
- io = bt_io_connect(att_connect_cb,
- attcb, NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(adapter),
- BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
- BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
- BT_IO_OPT_CID, ATT_CID,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
- BT_IO_OPT_INVALID);
- if (io == NULL) {
+ if (dev->paired)
+ sec_level = BT_IO_SEC_MEDIUM;
+ else
+ sec_level = BT_IO_SEC_LOW;
+
+ /*
+ * This connection will help us catch any PDUs that comes before
+ * pairing finishes
+ */
+ io = bt_io_connect(att_connect_cb, attcb, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, adapter_get_address(adapter),
+ BT_IO_OPT_DEST_BDADDR, &dev->bdaddr,
+ BT_IO_OPT_DEST_TYPE, dev->bdaddr_type,
+ BT_IO_OPT_CID, ATT_CID,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
+ BT_IO_OPT_INVALID);
+
+ if (io == NULL) {
+ if (dev->bonding) {
DBusMessage *reply = btd_error_failed(
- device->bonding->msg, gerr->message);
+ dev->bonding->msg, gerr->message);
+
g_dbus_send_message(dbus_conn, reply);
- bonding_request_cancel(device->bonding);
- bonding_request_free(device->bonding);
+ bonding_request_cancel(dev->bonding);
+ bonding_request_free(dev->bonding);
}
- } else {
- BtIOSecLevel sec_level;
- if (device->paired)
- sec_level = BT_IO_SEC_MEDIUM;
- else
- sec_level = BT_IO_SEC_LOW;
-
- io = bt_io_connect(att_connect_cb,
- attcb, NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(adapter),
- BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
- BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
- BT_IO_OPT_CID, ATT_CID,
- BT_IO_OPT_SEC_LEVEL, sec_level,
- BT_IO_OPT_INVALID);
- }
-
- if (io == NULL) {
error("ATT bt_io_connect(%s): %s", addr, gerr->message);
g_error_free(gerr);
g_free(attcb);
return NULL;
}
- device->att_io = io;
+ /* Keep this, so we can cancel the connection */
+ dev->att_io = g_io_channel_ref(io);
- return g_io_channel_ref(io);
+ return io;
}
static void att_browse_error_cb(const GError *gerr, gpointer user_data)
diff --git a/src/device.h b/src/device.h
index 6c35ff3..5438b0d 100644
--- a/src/device.h
+++ b/src/device.h
@@ -108,7 +108,8 @@ int device_unblock(struct btd_device *device, gboolean silent,
gboolean update_only);
void btd_device_set_pnpid(struct btd_device *device, uint16_t source,
uint16_t vendor, uint16_t product, uint16_t version);
-GIOChannel *device_att_connect(gpointer user_data);
+
+GIOChannel *device_att_connect(struct btd_device *dev);
struct btd_profile;
--
1.8.1.1
^ permalink raw reply related
* [RFC BlueZ 4/6] device: Rename device_att_connect to device_connect_le
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1359083227-13122-1-git-send-email-vinicius.gomes@openbossa.org>
This makes it clearer that this (currently unused) function should
only be used with LE devices.
---
src/device.c | 2 +-
src/device.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/device.c b/src/device.c
index 89df161..c76fb2b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -3120,7 +3120,7 @@ static void att_success_cb(gpointer user_data)
g_slist_foreach(device->attios, attio_connected, device->attrib);
}
-GIOChannel *device_att_connect(struct btd_device *dev)
+GIOChannel *device_connect_le(struct btd_device *dev)
{
struct btd_adapter *adapter = dev->adapter;
struct att_callbacks *attcb;
diff --git a/src/device.h b/src/device.h
index 5438b0d..a86fd59 100644
--- a/src/device.h
+++ b/src/device.h
@@ -109,7 +109,7 @@ int device_unblock(struct btd_device *device, gboolean silent,
void btd_device_set_pnpid(struct btd_device *device, uint16_t source,
uint16_t vendor, uint16_t product, uint16_t version);
-GIOChannel *device_att_connect(struct btd_device *dev);
+GIOChannel *device_connect_le(struct btd_device *dev);
struct btd_profile;
--
1.8.1.1
^ permalink raw reply related
* [RFC BlueZ 5/6] core: Add a way to connect to LE devices
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1359083227-13122-1-git-send-email-vinicius.gomes@openbossa.org>
adapter_create_le_connection() implements the Direct Connection
Procedure, we will use it when the device is in range, and we want to
re-connect to it and also when we want to pair to devices.
When pairing and the device is out of range, any attempt of connection will
fail until the connection times out (the controller sends the Connection
Complete event with an error).
---
src/adapter.c | 22 ++++++++++++++++++++--
src/adapter.h | 3 +++
src/device.c | 10 ++++------
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 5fd5062..e5bcb15 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4054,8 +4054,8 @@ static void update_found_devices(struct btd_adapter *adapter,
dev);
done:
- if (device_is_le(dev) && g_slist_find(adapter->connect_list, dev)) {
- }
+ if (device_is_le(dev) && g_slist_find(adapter->connect_list, dev))
+ adapter_create_le_connection(adapter, dev);
}
static void device_found_callback(uint16_t index, uint16_t length,
@@ -4710,6 +4710,24 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
}
}
+int adapter_create_le_connection(struct btd_adapter *adapter,
+ struct btd_device *dev)
+{
+ GIOChannel *io;
+
+ DBG("");
+
+ io = device_connect_le(dev);
+ if (io == NULL)
+ return -EBUSY;
+
+ g_io_channel_unref(io);
+
+ adapter_connect_list_remove(adapter, dev);
+
+ return 0;
+}
+
int adapter_cancel_bonding(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
uint8_t addr_type)
{
diff --git a/src/adapter.h b/src/adapter.h
index 6e1ba9d..155e3f0 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -166,6 +166,9 @@ int btd_adapter_passkey_reply(struct btd_adapter *adapter,
const bdaddr_t *bdaddr, uint8_t bdaddr_type,
uint32_t passkey);
+int adapter_create_le_connection(struct btd_adapter *adapter,
+ struct btd_device *dev);
+
int adapter_create_bonding(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
uint8_t addr_type, uint8_t io_cap);
diff --git a/src/device.c b/src/device.c
index c76fb2b..2bf1ad9 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1411,12 +1411,10 @@ static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
device->bonding = bonding;
bonding->device = device;
- if (device_is_le(device) && !device_is_connected(device)) {
- adapter_connect_list_add(adapter, device);
- return NULL;
- }
-
- err = adapter_create_bonding(adapter, &device->bdaddr,
+ if (device_is_le(device) && !device_is_connected(device))
+ err = adapter_create_le_connection(adapter, device);
+ else
+ err = adapter_create_bonding(adapter, &device->bdaddr,
device->bdaddr_type, io_cap);
if (err < 0)
return btd_error_failed(msg, strerror(-err));
--
1.8.1.1
^ permalink raw reply related
* [RFC BlueZ 6/6] gas: Move all the code to only one file
From: Vinicius Costa Gomes @ 2013-01-25 3:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1359083227-13122-1-git-send-email-vinicius.gomes@openbossa.org>
Our Generic Attribute/Access Service plugin is small and simple enough
to be kept in only one file.
---
Makefile.plugins | 4 +--
profiles/gatt/gas.c | 46 ++++++++++++++++++++++++++++
profiles/gatt/main.c | 47 -----------------------------
profiles/gatt/manager.c | 79 -------------------------------------------------
profiles/gatt/manager.h | 24 ---------------
5 files changed, 47 insertions(+), 153 deletions(-)
delete mode 100644 profiles/gatt/main.c
delete mode 100644 profiles/gatt/manager.c
delete mode 100644 profiles/gatt/manager.h
diff --git a/Makefile.plugins b/Makefile.plugins
index faab011..f497782 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -69,9 +69,7 @@ builtin_sources += profiles/health/mcap_lib.h profiles/health/mcap_internal.h \
endif
builtin_modules += gatt
-builtin_sources += profiles/gatt/main.c profiles/gatt/manager.h \
- profiles/gatt/manager.c profiles/gatt/gas.h \
- profiles/gatt/gas.c
+builtin_sources += profiles/gatt/gas.c
builtin_modules += scanparam
builtin_sources += profiles/scanparam/scan.c
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 429850b..31281b7 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -35,8 +35,10 @@
#include <btio/btio.h>
#include "lib/uuid.h"
+#include "plugin.h"
#include "adapter.h"
#include "device.h"
+#include "profile.h"
#include "attrib/att.h"
#include "attrib/gattrib.h"
#include "attio.h"
@@ -405,3 +407,47 @@ void gas_unregister(struct btd_device *device)
devices = g_slist_remove(devices, gas);
gas_free(gas);
}
+
+static int gatt_driver_probe(struct btd_profile *p, struct btd_device *device,
+ GSList *uuids)
+{
+ struct gatt_primary *gap, *gatt;
+
+ gap = btd_device_get_primary(device, GAP_UUID);
+ gatt = btd_device_get_primary(device, GATT_UUID);
+
+ if (gap == NULL || gatt == NULL) {
+ error("GAP and GATT are mandatory");
+ return -EINVAL;
+ }
+
+ return gas_register(device, &gap->range, &gatt->range);
+}
+
+static void gatt_driver_remove(struct btd_profile *p,
+ struct btd_device *device)
+{
+ gas_unregister(device);
+}
+
+static struct btd_profile gatt_profile = {
+ .name = "gap-gatt-profile",
+ .remote_uuids = BTD_UUIDS(GAP_UUID, GATT_UUID),
+ .device_probe = gatt_driver_probe,
+ .device_remove = gatt_driver_remove
+};
+
+static int gatt_init(void)
+{
+ btd_profile_register(&gatt_profile);
+
+ return 0;
+}
+
+static void gatt_exit(void)
+{
+ btd_profile_register(&gatt_profile);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(gatt, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ gatt_init, gatt_exit)
diff --git a/profiles/gatt/main.c b/profiles/gatt/main.c
deleted file mode 100644
index ecd4455..0000000
--- a/profiles/gatt/main.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-
-#include "plugin.h"
-#include "manager.h"
-#include "hcid.h"
-#include "log.h"
-
-static int gatt_init(void)
-{
- return gatt_manager_init();
-}
-
-static void gatt_exit(void)
-{
- gatt_manager_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(gatt, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
- gatt_init, gatt_exit)
diff --git a/profiles/gatt/manager.c b/profiles/gatt/manager.c
deleted file mode 100644
index 2f2bd14..0000000
--- a/profiles/gatt/manager.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include "lib/uuid.h"
-#include "adapter.h"
-#include "device.h"
-#include "profile.h"
-#include "attrib/att.h"
-#include "attrib/gattrib.h"
-#include "attrib/gatt.h"
-#include "gas.h"
-#include "log.h"
-#include "manager.h"
-
-static int gatt_driver_probe(struct btd_profile *p, struct btd_device *device,
- GSList *uuids)
-{
- struct gatt_primary *gap, *gatt;
-
- gap = btd_device_get_primary(device, GAP_UUID);
- gatt = btd_device_get_primary(device, GATT_UUID);
-
- if (gap == NULL || gatt == NULL) {
- error("GAP and GATT are mandatory");
- return -EINVAL;
- }
-
- return gas_register(device, &gap->range, &gatt->range);
-}
-
-static void gatt_driver_remove(struct btd_profile *p,
- struct btd_device *device)
-{
- gas_unregister(device);
-}
-
-static struct btd_profile gatt_profile = {
- .name = "gap-gatt-profile",
- .remote_uuids = BTD_UUIDS(GAP_UUID, GATT_UUID),
- .device_probe = gatt_driver_probe,
- .device_remove = gatt_driver_remove
-};
-
-int gatt_manager_init(void)
-{
- return btd_profile_register(&gatt_profile);
-}
-
-void gatt_manager_exit(void)
-{
- btd_profile_unregister(&gatt_profile);
-}
diff --git a/profiles/gatt/manager.h b/profiles/gatt/manager.h
deleted file mode 100644
index 502fceb..0000000
--- a/profiles/gatt/manager.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int gatt_manager_init(void);
-void gatt_manager_exit(void);
--
1.8.1.1
^ permalink raw reply related
* Re: [PATCH 4/6] Bluetooth: Refactor UUID-16 list generation into its own function
From: Johan Hedberg @ 2013-01-25 6:37 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_OqePCY1yMvJTwaUDnXTMbDJgucbYvEWT99=K9tbvgYQg@mail.gmail.com>
Hi Lizardo,
On Thu, Jan 24, 2013, Anderson Lizardo wrote:
> On Thu, Jan 24, 2013 at 4:21 PM, Anderson Lizardo
> <anderson.lizardo@openbossa.org> wrote:
> > Hi Johan,
> >
> > On Thu, Jan 24, 2013 at 3:03 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> >> +static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> >> +{
> >> + u8 *ptr = data, *uuids_start = NULL;
> >> + struct bt_uuid *uuid;
> >
> > Maybe you should check for "len < 2" here?
>
> Actually, "len < 4", to be able to fit at least a 16-bit UUID.
The way the EIR is constructed right now it's impossible for this
condition to be met (i.e. the only variable length field before the
UUID-16 list is the name which we limit to 48 bytes). Anyway, in case we
add more stuff to the beginning of the EIR in the future I agree that
it's good to have this check in place so we avoid stupid bugs.
I'll be sending a v2 of the set (also including a simplification to the
first patch) soon.
Johan
^ permalink raw reply
* [PATCH 0/6 v2] Bluetooth: Add 32 and 128 bit EIR UUID support
From: Johan Hedberg @ 2013-01-25 6:57 UTC (permalink / raw)
To: linux-bluetooth
Hi,
Here's an update set with a fix suggestion from Lizardo for patch 4/6 as
well as a simplification to patch 1/6.
>From the original cover letter:
"
There was another set of patches from Syam to add the same functionality
but it can be accomplished in a simpler way since we only need to follow
the ordering within each group of UUIDs.
I've added test cases to mgmt-tester to verify both the complete and
partial UUID list cases (more can be added, but there are enough that
I'm confident of the correctness of these patches).
"
Johan Hedberg (6):
Bluetooth: Split UUIDs to three separate lists
Bluetooth: Simplify UUID16 list generation for EIR
Bluetooth: Remove useless eir_len variable from EIR creation
Bluetooth: Refactor UUID-16 list generation into its own function
Bluetooth: Add support for 32-bit UUIDs in EIR data
Bluetooth: Add support for 128-bit UUIDs in EIR data
include/net/bluetooth/hci_core.h | 4 +++
net/bluetooth/hci_core.c | 14 +++++-----
net/bluetooth/hci_sysfs.c | 2 +-
net/bluetooth/mgmt.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------
4 files changed, 137 insertions(+), 86 deletions(-)
^ permalink raw reply
* [PATCH 1/6 v2] Bluetooth: Split UUIDs to three separate lists
From: Johan Hedberg @ 2013-01-25 6:57 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1359097050-17552-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The primary purpose of the UUIDs is to eable generation of EIR and AD
data. In these data formats the UUIDs are split into separate fields
based on whether they're 16, 32 or 128 bit UUIDs. To make the generation
of these data fields simple this patch splits the UUIDs into three
separate lists based on their type.
To keep cases needing access to all UUIDs easy the UUIDs are also kept
in an "all" list. This is particularly useful for exposing the UUIDs
through sysfs as well as removing UUIDs (whether removing a specific one
or all UUIDs).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
v2: Removed enum bt_uuid_t since all it was needed for was selecting
which list to add to.
include/net/bluetooth/hci_core.h | 4 +++
net/bluetooth/hci_core.c | 14 ++++----
net/bluetooth/hci_sysfs.c | 2 +-
net/bluetooth/mgmt.c | 67 +++++++++++++++++++-------------------
4 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bcf8ffe..d3b1d1b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -85,6 +85,7 @@ struct bdaddr_list {
struct bt_uuid {
struct list_head list;
+ struct list_head all;
u8 uuid[16];
u8 svc_hint;
};
@@ -256,6 +257,9 @@ struct hci_dev {
struct list_head blacklist;
struct list_head uuids;
+ struct list_head uuid16;
+ struct list_head uuid32;
+ struct list_head uuid128;
struct list_head link_keys;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e061b35..8818521 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1183,14 +1183,11 @@ static void hci_discov_off(struct work_struct *work)
int hci_uuids_clear(struct hci_dev *hdev)
{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &hdev->uuids) {
- struct bt_uuid *uuid;
+ struct bt_uuid *uuid, *tmp;
- uuid = list_entry(p, struct bt_uuid, list);
-
- list_del(p);
+ list_for_each_entry_safe(uuid, tmp, &hdev->uuids, all) {
+ list_del(&uuid->list);
+ list_del(&uuid->all);
kfree(uuid);
}
@@ -1718,6 +1715,9 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->mgmt_pending);
INIT_LIST_HEAD(&hdev->blacklist);
INIT_LIST_HEAD(&hdev->uuids);
+ INIT_LIST_HEAD(&hdev->uuid16);
+ INIT_LIST_HEAD(&hdev->uuid32);
+ INIT_LIST_HEAD(&hdev->uuid128);
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 23b4e24..9a60c74 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -483,7 +483,7 @@ static int uuids_show(struct seq_file *f, void *p)
hci_dev_lock(hdev);
- list_for_each_entry(uuid, &hdev->uuids, list)
+ list_for_each_entry(uuid, &hdev->uuids, all)
print_bt_uuid(f, uuid->uuid);
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e7f944f..1257ed0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -435,28 +435,6 @@ static u32 get_current_settings(struct hci_dev *hdev)
#define PNP_INFO_SVCLASS_ID 0x1200
-static u8 bluetooth_base_uuid[] = {
- 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static u16 get_uuid16(u8 *uuid128)
-{
- u32 val;
- int i;
-
- for (i = 0; i < 12; i++) {
- if (bluetooth_base_uuid[i] != uuid128[i])
- return 0;
- }
-
- val = get_unaligned_le32(&uuid128[12]);
- if (val > 0xffff)
- return 0;
-
- return (u16) val;
-}
-
static void create_eir(struct hci_dev *hdev, u8 *data)
{
u8 *ptr = data;
@@ -510,13 +488,10 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
memset(uuid16_list, 0, sizeof(uuid16_list));
/* Group all UUID16 types */
- list_for_each_entry(uuid, &hdev->uuids, list) {
+ list_for_each_entry(uuid, &hdev->uuid16, list) {
u16 uuid16;
- uuid16 = get_uuid16(uuid->uuid);
- if (uuid16 == 0)
- return;
-
+ uuid16 = get_unaligned_le16(&uuid->uuid[12]);
if (uuid16 < 0x1100)
continue;
@@ -592,7 +567,7 @@ static u8 get_service_classes(struct hci_dev *hdev)
struct bt_uuid *uuid;
u8 val = 0;
- list_for_each_entry(uuid, &hdev->uuids, list)
+ list_for_each_entry(uuid, &hdev->uuids, all)
val |= uuid->svc_hint;
return val;
@@ -1304,11 +1279,34 @@ unlock:
return err;
}
+static u8 bluetooth_base_uuid[] = {
+ 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static struct list_head *select_uuid_list(struct hci_dev *hdev, u8 *uuid)
+{
+ u32 val;
+ int i;
+
+ for (i = 0; i < 12; i++) {
+ if (bluetooth_base_uuid[i] != uuid[i])
+ return &hdev->uuid128;
+ }
+
+ val = get_unaligned_le32(&uuid[12]);
+ if (val > 0xffff)
+ return &hdev->uuid32;
+
+ return &hdev->uuid16;
+}
+
static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_cp_add_uuid *cp = data;
struct pending_cmd *cmd;
struct bt_uuid *uuid;
+ struct list_head *l;
int err;
BT_DBG("request for %s", hdev->name);
@@ -1330,7 +1328,10 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
memcpy(uuid->uuid, cp->uuid, 16);
uuid->svc_hint = cp->svc_hint;
- list_add(&uuid->list, &hdev->uuids);
+ l = select_uuid_list(hdev, cp->uuid);
+ list_add_tail(&uuid->list, l);
+
+ list_add_tail(&uuid->all, &hdev->uuids);
err = update_class(hdev);
if (err < 0)
@@ -1374,7 +1375,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
{
struct mgmt_cp_remove_uuid *cp = data;
struct pending_cmd *cmd;
- struct list_head *p, *n;
+ struct bt_uuid *match, *tmp;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int err, found;
@@ -1402,13 +1403,11 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
found = 0;
- list_for_each_safe(p, n, &hdev->uuids) {
- struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
-
+ list_for_each_entry_safe(match, tmp, &hdev->uuids, all) {
if (memcmp(match->uuid, cp->uuid, 16) != 0)
continue;
-
list_del(&match->list);
+ list_del(&match->all);
kfree(match);
found++;
}
--
1.7.10.4
^ 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