* Re: RFC: btusb firmware load help
From: Bala Shanmugam @ 2010-11-10 18:32 UTC (permalink / raw)
To: Marcel Holtmann
Cc: Shanmugamkamatchi Balashanmugam, Luis Rodriguez, Johannes Berg,
linux-bluetooth, linux-kernel@vger.kernel.org,
linux-wireless@vger.kernel.org, Deepak Dhamdhere, Sree Durbha
In-Reply-To: <4CADF6BF.6070305@atheros.com>
Hi Marcel,
On 10/7/2010 10:05 PM, Bala Shanmugam wrote:
> On 10/7/2010 8:54 PM, Marcel Holtmann wrote:
>> Hi Bala,
>>
>>> Thanks Johannes. This would be better option to change PID in firmware
>>> as blacklisting 3002 might create problems for 3011 chipsets.
>>> Will try and let you people know.
>> The misbehaving 3002 needs to be blacklisted in btusb.c anyway. However
>> after loading the firmware to 3002 device, it should change its PID to
>> something else.
>>
>> I am still trying to figure out if this is one stage firmware loading or
>> a two stage firmware loading. This is all pretty unclear and nobody has
>> answered this clearly so far.
>>
>> Regards
>>
>> Marcel
>>
>>
> Marcel,
>
> eeprom based 3011 chips comes up with PID 3000 giving control to DFU
> driver [ath3k]. ath3k downloads the
> firmware changing PID to 3002. Now btusb gets control.
>
> In sflash based devices to reduce windows suspend/resume time we had a
> small firmware in flash which
> enables the device to get detected as Generic Bluetooth USB device with
> PID 3002. So control reaches btusb when device is plugged in, leaving
> no option for us to load the actual firmware.
>
> Solution would be to blacklist 3002 in btusb, enable ath3k to get
> control for both the devices, download the firmware and change PID to
> 3003 so that control with come to btusb.
>
> Thanks for your time.
>
> Regards,
> Bala.
As you suggested we blacklisted PID 3002 in btusb and loaded firmware
using ath3k and it worked.
Thanks.
Many of our customers are using their own PIDs and blacklisting 3002
won't work for them.
Can we blacklist all the PIDs used by different customers?
We have another device similar to above one, it doesn't do a USB reset
after downloading firmware.
This is basically to reduce bring-up and suspend/resume time.
Can we add an infrastructure in btusb to download configuration or
firmware for these devices?
If not can you please suggest a solution for this device.
Thanks in advance.
Regards,
Bala.
^ permalink raw reply
* [PATCH 7/7] Emit "DeviceFound" signal for LE devices
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1289411487-6113-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
The adapter_emit_device_found() function was modified to emit
DeviceFound signal for LE devices as well.
---
src/adapter.c | 30 +++++++++++++++++++++++++-----
1 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index b263096..dab9087 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3102,6 +3102,27 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
if (device)
paired = device_is_paired(device);
+ /* Extract UUIDs from extended inquiry response if any */
+ dev->services = get_eir_uuids(eir_data, eir_length, dev->services);
+ uuid_count = g_slist_length(dev->services);
+
+ if (dev->services)
+ uuids = strlist2array(dev->services);
+
+ if (dev->le) {
+ emit_device_found(adapter->path, paddr,
+ "Address", DBUS_TYPE_STRING, &paddr,
+ "RSSI", DBUS_TYPE_INT16, &rssi,
+ "Name", DBUS_TYPE_STRING, &dev->name,
+ "Paired", DBUS_TYPE_BOOLEAN, &paired,
+ "UUIDs", DBUS_TYPE_ARRAY, &uuids, uuid_count,
+ NULL);
+
+ g_strfreev(uuids);
+
+ return;
+ }
+
icon = class_to_icon(dev->class);
if (!dev->alias) {
@@ -3113,12 +3134,7 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
} else
alias = g_strdup(dev->alias);
- /* Extract UUIDs from extended inquiry response if any */
- dev->services = get_eir_uuids(eir_data, eir_length, dev->services);
- uuid_count = g_slist_length(dev->services);
-
if (dev->services) {
- uuids = strlist2array(dev->services);
g_slist_foreach(dev->services, (GFunc) g_free, NULL);
g_slist_free(dev->services);
dev->services = NULL;
@@ -3196,6 +3212,10 @@ void adapter_update_adv(struct btd_adapter *adapter, le_advertising_info *info)
if (tmp_name)
dev->name = tmp_name;
}
+
+ /* FIXME: check if other information was changed before emitting the
+ * signal */
+ adapter_emit_device_found(adapter, dev, info->data, info->length);
}
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
--
1.7.0.4
^ permalink raw reply related
* [PATCH 6/7] Extract service UUIDs from advertising data
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1289411487-6113-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
Make get_eir_uuids() return a GSList of strings, so it can be reused to
extract UUIDs from LE advertising data. The bt_strlist2array() helper
function was created to convert a GSList into a plain array of strings
(needed to send through D-Bus).
---
src/adapter.c | 64 ++++++++++++++++++++++++++++++++++++++++++--------------
src/adapter.h | 1 +
2 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 95fcbda..b263096 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -202,6 +202,8 @@ static void dev_info_free(struct remote_dev_info *dev)
{
g_free(dev->name);
g_free(dev->alias);
+ g_slist_foreach(dev->services, (GFunc) g_free, NULL);
+ g_slist_free(dev->services);
g_free(dev);
}
@@ -2962,11 +2964,20 @@ static void emit_device_found(const char *path, const char *address,
g_dbus_send_message(connection, signal);
}
-static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
- size_t *uuid_count)
+static char **strlist2array(GSList *list)
+{
+ char *tmp, **array;
+
+ tmp = bt_list2string(list);
+ array = g_strsplit(tmp, " ", 0);
+ g_free(tmp);
+
+ return array;
+}
+
+static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length, GSList *list)
{
uint16_t len = 0;
- char **uuids;
size_t total;
size_t uuid16_count = 0;
size_t uuid32_count = 0;
@@ -2975,10 +2986,11 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
uint8_t *uuid32 = 0;
uint8_t *uuid128 = 0;
uuid_t service;
+ char *uuid_str;
unsigned int i;
if (eir_data == NULL || eir_length == 0)
- return NULL;
+ return list;
while (len < eir_length - 1) {
uint8_t field_len = eir_data[0];
@@ -3011,15 +3023,12 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
/* Bail out if got incorrect length */
if (len > eir_length)
- return NULL;
+ return list;
total = uuid16_count + uuid32_count + uuid128_count;
- *uuid_count = total;
if (!total)
- return NULL;
-
- uuids = g_new0(char *, total + 1);
+ return list;
/* Generate uuids in SDP format (EIR data is Little Endian) */
service.type = SDP_UUID16;
@@ -3028,7 +3037,12 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
val16 = (val16 << 8) + uuid16[0];
service.value.uuid16 = val16;
- uuids[i] = bt_uuid2string(&service);
+ uuid_str = bt_uuid2string(&service);
+ if (g_slist_find_custom(list, uuid_str,
+ (GCompareFunc) strcmp) == NULL)
+ list = g_slist_append(list, uuid_str);
+ else
+ g_free(uuid_str);
uuid16 += 2;
}
@@ -3041,7 +3055,12 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
val32 = (val32 << 8) + uuid32[k];
service.value.uuid32 = val32;
- uuids[i] = bt_uuid2string(&service);
+ uuid_str = bt_uuid2string(&service);
+ if (g_slist_find_custom(list, uuid_str,
+ (GCompareFunc) strcmp) == NULL)
+ list = g_slist_append(list, uuid_str);
+ else
+ g_free(uuid_str);
uuid32 += 4;
}
@@ -3052,11 +3071,16 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
for (k = 0; k < 16; k++)
service.value.uuid128.data[k] = uuid128[16 - k - 1];
- uuids[i] = bt_uuid2string(&service);
+ uuid_str = bt_uuid2string(&service);
+ if (g_slist_find_custom(list, uuid_str,
+ (GCompareFunc) strcmp) == NULL)
+ list = g_slist_append(list, uuid_str);
+ else
+ g_free(uuid_str);
uuid128 += 16;
}
- return uuids;
+ return list;
}
void adapter_emit_device_found(struct btd_adapter *adapter,
@@ -3069,7 +3093,7 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
dbus_int16_t rssi = dev->rssi;
char *alias;
char **uuids = NULL;
- size_t uuid_count = 0;
+ size_t uuid_count;
ba2str(&dev->bdaddr, peer_addr);
ba2str(&adapter->bdaddr, local_addr);
@@ -3089,8 +3113,16 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
} else
alias = g_strdup(dev->alias);
- /* Extract UUIDs from extended inquiry response if any*/
- uuids = get_eir_uuids(eir_data, eir_length, &uuid_count);
+ /* Extract UUIDs from extended inquiry response if any */
+ dev->services = get_eir_uuids(eir_data, eir_length, dev->services);
+ uuid_count = g_slist_length(dev->services);
+
+ if (dev->services) {
+ uuids = strlist2array(dev->services);
+ g_slist_foreach(dev->services, (GFunc) g_free, NULL);
+ g_slist_free(dev->services);
+ dev->services = NULL;
+ }
emit_device_found(adapter->path, paddr,
"Address", DBUS_TYPE_STRING, &paddr,
diff --git a/src/adapter.h b/src/adapter.h
index 766b079..84d691b 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -71,6 +71,7 @@ struct remote_dev_info {
name_status_t name_status;
gboolean le;
/* LE adv data */
+ GSList *services;
uint8_t evt_type;
uint8_t bdaddr_type;
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 5/7] Advertising data: extract local name
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1289411487-6113-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
Move extract_eir_name() to glib-helper.c file and rename function to
bt_extract_eir_name(). The local name is extracted from the advertising
data.
---
src/adapter.c | 7 +++++++
src/event.c | 23 +----------------------
src/glib-helper.c | 22 ++++++++++++++++++++++
src/glib-helper.h | 1 +
4 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 6b94a43..95fcbda 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3142,6 +3142,7 @@ void adapter_update_adv(struct btd_adapter *adapter, le_advertising_info *info)
struct remote_dev_info *dev;
bdaddr_t bdaddr;
int8_t rssi = 0;
+ uint8_t type = 0x00;
rssi = *(info->data + info->length);
bdaddr = info->bdaddr;
@@ -3157,6 +3158,12 @@ void adapter_update_adv(struct btd_adapter *adapter, le_advertising_info *info)
adapter->found_devices = g_slist_sort(adapter->found_devices,
(GCompareFunc) dev_rssi_cmp);
+
+ if (info->length) {
+ char *tmp_name = bt_extract_eir_name(info->data, &type);
+ if (tmp_name)
+ dev->name = tmp_name;
+ }
}
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
diff --git a/src/event.c b/src/event.c
index 8b03bc3..57bdf60 100644
--- a/src/event.c
+++ b/src/event.c
@@ -301,27 +301,6 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}
-static char *extract_eir_name(uint8_t *data, uint8_t *type)
-{
- if (!data || !type)
- return NULL;
-
- if (data[0] == 0)
- return NULL;
-
- *type = data[1];
-
- switch (*type) {
- case 0x08:
- case 0x09:
- if (!g_utf8_validate((char *) (data + 2), data[0] - 1, NULL))
- return strdup("");
- return strndup((char *) (data + 2), data[0] - 1);
- }
-
- return NULL;
-}
-
void btd_event_adv(bdaddr_t *local, le_advertising_info *info)
{
struct btd_adapter *adapter;
@@ -410,7 +389,7 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
} else
legacy = TRUE;
- tmp_name = extract_eir_name(data, &name_type);
+ tmp_name = bt_extract_eir_name(data, &name_type);
if (tmp_name) {
if (name_type == 0x09) {
write_device_name(local, peer, tmp_name);
diff --git a/src/glib-helper.c b/src/glib-helper.c
index 9d76626..33668d7 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -43,6 +43,7 @@
#include <glib.h>
#include "glib-helper.h"
+#include "sdpd.h"
/* Number of seconds to keep a sdp_session_t in the cache */
#define CACHE_TIMEOUT 2
@@ -576,3 +577,24 @@ GSList *bt_string2list(const gchar *str)
return l;
}
+
+char *bt_extract_eir_name(uint8_t *data, uint8_t *type)
+{
+ if (!data || !type)
+ return NULL;
+
+ if (data[0] == 0)
+ return NULL;
+
+ *type = data[1];
+
+ switch (*type) {
+ case EIR_NAME_SHORT:
+ case EIR_NAME_COMPLETE:
+ if (!g_utf8_validate((char *) (data + 2), data[0] - 1, NULL))
+ return strdup("");
+ return strndup((char *) (data + 2), data[0] - 1);
+ }
+
+ return NULL;
+}
diff --git a/src/glib-helper.h b/src/glib-helper.h
index e89c2c6..dfe4123 100644
--- a/src/glib-helper.h
+++ b/src/glib-helper.h
@@ -38,3 +38,4 @@ char *bt_name2string(const char *string);
int bt_string2uuid(uuid_t *uuid, const char *string);
gchar *bt_list2string(GSList *list);
GSList *bt_string2list(const gchar *str);
+char *bt_extract_eir_name(uint8_t *data, uint8_t *type);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 4/7] Initial advertising data parsing implementation
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1289411487-6113-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
Implement adapter_update_adv() function to parse advertising data
received by btd_event_adv() function. Add some fields for advertising
data in remote_device_info struct.
---
plugins/hciops.c | 9 +++------
src/adapter.c | 23 +++++++++++++++++++++++
src/adapter.h | 5 +++++
src/event.c | 13 +++++++++++++
src/event.h | 1 +
5 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/plugins/hciops.c b/plugins/hciops.c
index fc99275..dc7a657 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -1011,7 +1011,7 @@ static inline void le_metaevent(int index, void *ptr)
{
evt_le_meta_event *meta = ptr;
le_advertising_info *info;
- uint8_t *rssi, num, i;
+ uint8_t num, i;
DBG("LE Meta Event");
@@ -1022,11 +1022,8 @@ static inline void le_metaevent(int index, void *ptr)
info = (le_advertising_info *) (meta->data + 1);
for (i = 0; i < num; i++) {
- /* RSSI is last byte of the advertising report event */
- rssi = info->data + info->length;
- btd_event_inquiry_result(&BDADDR(index), &info->bdaddr, 0,
- *rssi, NULL);
- info = (le_advertising_info *) (rssi + 1);
+ btd_event_adv(&BDADDR(index), info);
+ info = (le_advertising_info *) (info->data + info->length + 1);
}
}
diff --git a/src/adapter.c b/src/adapter.c
index c54d035..6b94a43 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3137,6 +3137,28 @@ static gboolean update_found_devices(struct btd_adapter *adapter,
return found;
}
+void adapter_update_adv(struct btd_adapter *adapter, le_advertising_info *info)
+{
+ struct remote_dev_info *dev;
+ bdaddr_t bdaddr;
+ int8_t rssi = 0;
+
+ rssi = *(info->data + info->length);
+ bdaddr = info->bdaddr;
+
+ if (!update_found_devices(adapter, &bdaddr, rssi, &dev)) {
+ dev->le = TRUE;
+ dev->evt_type = info->evt_type;
+ bacpy(&dev->bdaddr, &info->bdaddr);
+ } else if (dev->rssi == rssi)
+ return;
+
+ dev->rssi = rssi;
+
+ adapter->found_devices = g_slist_sort(adapter->found_devices,
+ (GCompareFunc) dev_rssi_cmp);
+}
+
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int8_t rssi, uint32_t class, const char *name,
const char *alias, gboolean legacy,
@@ -3145,6 +3167,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
struct remote_dev_info *dev;
if (!update_found_devices(adapter, bdaddr, rssi, &dev)) {
+ dev->le = FALSE;
dev->class = class;
if (name)
dev->name = g_strdup(name);
diff --git a/src/adapter.h b/src/adapter.h
index 89b07d7..766b079 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -69,6 +69,10 @@ struct remote_dev_info {
char *alias;
dbus_bool_t legacy;
name_status_t name_status;
+ gboolean le;
+ /* LE adv data */
+ uint8_t evt_type;
+ uint8_t bdaddr_type;
};
struct hci_dev {
@@ -118,6 +122,7 @@ int adapter_get_discover_type(struct btd_adapter *adapter);
gboolean adapter_is_ready(struct btd_adapter *adapter);
struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter,
struct remote_dev_info *match);
+void adapter_update_adv(struct btd_adapter *adapter, le_advertising_info *info);
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int8_t rssi, uint32_t class, const char *name,
const char *alias, gboolean legacy,
diff --git a/src/event.c b/src/event.c
index a057306..8b03bc3 100644
--- a/src/event.c
+++ b/src/event.c
@@ -322,6 +322,19 @@ static char *extract_eir_name(uint8_t *data, uint8_t *type)
return NULL;
}
+void btd_event_adv(bdaddr_t *local, le_advertising_info *info)
+{
+ struct btd_adapter *adapter;
+
+ adapter = manager_find_adapter(local);
+ if (adapter == NULL) {
+ error("No matching adapter found");
+ return;
+ }
+
+ adapter_update_adv(adapter, info);
+}
+
void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
int8_t rssi, uint8_t *data)
{
diff --git a/src/event.h b/src/event.h
index 4a7b9c9..44e1462 100644
--- a/src/event.h
+++ b/src/event.h
@@ -23,6 +23,7 @@
*/
int btd_event_request_pin(bdaddr_t *sba, struct hci_conn_info *ci);
+void btd_event_adv(bdaddr_t *local, le_advertising_info *info);
void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, int8_t rssi, uint8_t *data);
void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer, gboolean legacy);
void btd_event_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/7] Refactoring adapter_update_found_devices() function
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1289411487-6113-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
The common code from adapter_update_found_devices() was moved to
update_found_devices().
---
src/adapter.c | 52 +++++++++++++++++++++++++++++++---------------------
1 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 4d23db0..c54d035 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3108,12 +3108,11 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
g_strfreev(uuids);
}
-void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
- int8_t rssi, uint32_t class, const char *name,
- const char *alias, gboolean legacy,
- name_status_t name_status, uint8_t *eir_data)
+static gboolean update_found_devices(struct btd_adapter *adapter,
+ bdaddr_t *bdaddr, int8_t rssi, struct remote_dev_info **dev_info)
{
struct remote_dev_info *dev, match;
+ gboolean found;
memset(&match, 0, sizeof(struct remote_dev_info));
bacpy(&match.bdaddr, bdaddr);
@@ -3121,30 +3120,41 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
dev = adapter_search_found_devices(adapter, &match);
if (dev) {
+ found = TRUE;
/* Out of range list update */
adapter->oor_devices = g_slist_remove(adapter->oor_devices,
- dev);
-
- if (rssi == dev->rssi)
- return;
-
- goto done;
+ dev);
+ } else {
+ found = FALSE;
+ dev = g_new0(struct remote_dev_info, 1);
+ bacpy(&dev->bdaddr, bdaddr);
+ adapter->found_devices = g_slist_prepend(adapter->found_devices,
+ dev);
}
- dev = g_new0(struct remote_dev_info, 1);
+ *dev_info = dev;
- bacpy(&dev->bdaddr, bdaddr);
- dev->class = class;
- if (name)
- dev->name = g_strdup(name);
- if (alias)
- dev->alias = g_strdup(alias);
- dev->legacy = legacy;
- dev->name_status = name_status;
+ return found;
+}
- adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);
+void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
+ int8_t rssi, uint32_t class, const char *name,
+ const char *alias, gboolean legacy,
+ name_status_t name_status, uint8_t *eir_data)
+{
+ struct remote_dev_info *dev;
+
+ if (!update_found_devices(adapter, bdaddr, rssi, &dev)) {
+ dev->class = class;
+ if (name)
+ dev->name = g_strdup(name);
+ if (alias)
+ dev->alias = g_strdup(alias);
+ dev->legacy = legacy;
+ dev->name_status = name_status;
+ } else if (dev->rssi == rssi)
+ return;
-done:
dev->rssi = rssi;
adapter->found_devices = g_slist_sort(adapter->found_devices,
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/7] Refactor get_eir_uuids() to get EIR data length parameter
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1289411487-6113-1-git-send-email-anderson.lizardo@openbossa.org>
get_eir_uuids() will be reused to parse LE advertising data as well, as
they share the same format. But for Advertising, maximum data length is
different (31 bytes vs. 240 bytes for EIR), and the radio is not
required to send the non-significant (zero-filled) bytes.
adapter_emit_device_found() now also accepts a EIR data length
parameter, so it can be reused for LE and can propagate the exact data
length.
---
src/adapter.c | 17 ++++++++++-------
src/adapter.h | 2 +-
src/event.c | 2 +-
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 2f79e1c..4d23db0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2962,7 +2962,8 @@ static void emit_device_found(const char *path, const char *address,
g_dbus_send_message(connection, signal);
}
-static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
+static char **get_eir_uuids(uint8_t *eir_data, size_t eir_length,
+ size_t *uuid_count)
{
uint16_t len = 0;
char **uuids;
@@ -2976,7 +2977,10 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
uuid_t service;
unsigned int i;
- while (len < EIR_DATA_LENGTH - 1) {
+ if (eir_data == NULL || eir_length == 0)
+ return NULL;
+
+ while (len < eir_length - 1) {
uint8_t field_len = eir_data[0];
/* Check for the end of EIR */
@@ -3006,7 +3010,7 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
}
/* Bail out if got incorrect length */
- if (len > EIR_DATA_LENGTH)
+ if (len > eir_length)
return NULL;
total = uuid16_count + uuid32_count + uuid128_count;
@@ -3056,7 +3060,7 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
}
void adapter_emit_device_found(struct btd_adapter *adapter,
- struct remote_dev_info *dev, uint8_t *eir_data)
+ struct remote_dev_info *dev, uint8_t *eir_data, size_t eir_length)
{
struct btd_device *device;
char peer_addr[18], local_addr[18];
@@ -3086,8 +3090,7 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
alias = g_strdup(dev->alias);
/* Extract UUIDs from extended inquiry response if any*/
- if (eir_data != NULL)
- uuids = get_eir_uuids(eir_data, &uuid_count);
+ uuids = get_eir_uuids(eir_data, eir_length, &uuid_count);
emit_device_found(adapter->path, paddr,
"Address", DBUS_TYPE_STRING, &paddr,
@@ -3147,7 +3150,7 @@ done:
adapter->found_devices = g_slist_sort(adapter->found_devices,
(GCompareFunc) dev_rssi_cmp);
- adapter_emit_device_found(adapter, dev, eir_data);
+ adapter_emit_device_found(adapter, dev, eir_data, EIR_DATA_LENGTH);
}
int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
diff --git a/src/adapter.h b/src/adapter.h
index 8019cfc..89b07d7 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -124,7 +124,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
name_status_t name_status, uint8_t *eir_data);
int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr);
void adapter_emit_device_found(struct btd_adapter *adapter,
- struct remote_dev_info *dev, uint8_t *eir_data);
+ struct remote_dev_info *dev, uint8_t *eir_data, size_t eir_length);
void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
void adapter_setname_complete(bdaddr_t *local, uint8_t status);
void adapter_update_tx_power(bdaddr_t *bdaddr, uint8_t status, void *ptr);
diff --git a/src/event.c b/src/event.c
index 971bb35..a057306 100644
--- a/src/event.c
+++ b/src/event.c
@@ -510,7 +510,7 @@ void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status,
if (dev_info) {
g_free(dev_info->name);
dev_info->name = g_strdup(name);
- adapter_emit_device_found(adapter, dev_info, NULL);
+ adapter_emit_device_found(adapter, dev_info, NULL, 0);
}
if (device)
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/7] Fix invalid memory access when EIR field length is zero
From: Anderson Lizardo @ 2010-11-10 17:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
From: Bruna Moreira <bruna.moreira@openbossa.org>
---
src/adapter.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 31014e5..2f79e1c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2970,21 +2970,20 @@ static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
size_t uuid16_count = 0;
size_t uuid32_count = 0;
size_t uuid128_count = 0;
- uint8_t *uuid16;
- uint8_t *uuid32;
- uint8_t *uuid128;
+ uint8_t *uuid16 = 0;
+ uint8_t *uuid32 = 0;
+ uint8_t *uuid128 = 0;
uuid_t service;
unsigned int i;
while (len < EIR_DATA_LENGTH - 1) {
- uint8_t type = eir_data[1];
uint8_t field_len = eir_data[0];
/* Check for the end of EIR */
if (field_len == 0)
break;
- switch (type) {
+ switch (eir_data[1]) {
case EIR_UUID16_SOME:
case EIR_UUID16_ALL:
uuid16_count = field_len / 2;
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 3/6] Bluetooth: Use LE buffers for LE traffic
From: Claudio Takahasi @ 2010-11-10 16:53 UTC (permalink / raw)
To: Ville Tervo; +Cc: linux-bluetooth
In-Reply-To: <1288009280-5149-4-git-send-email-ville.tervo@nokia.com>
SGkgVmlsbGUsCgpPbiBNb24sIE9jdCAyNSwgMjAxMCBhdCAxMDoyMSBBTSwgVmlsbGUgVGVydm8g
PHZpbGxlLnRlcnZvQG5va2lhLmNvbT4gd3JvdGU6Cj4gQkx1ZXRvb3RoIGNoaXBzIG1heSBoYXZl
IHNlcGFyYXRlIGJ1ZmZlcnMgZm9yCj4gTEUgdHJhZmZpYy4gVGhpcyBwYXRjaCBhZGQgc3VwcG9y
dCB0byB1c2UgTEUKPiBidWZmZXJzIHByb3ZpZGVkIGJ5IHRoZSBjaGlwLgo+Cj4gU2lnbmVkLW9m
Zi1ieTogVmlsbGUgVGVydm8gPHZpbGxlLnRlcnZvQG5va2lhLmNvbT4KPiAtLS0KPiDCoGluY2x1
ZGUvbmV0L2JsdWV0b290aC9oY2kuaCDCoCDCoCDCoHwgwqAgwqAxICsKPiDCoGluY2x1ZGUvbmV0
L2JsdWV0b290aC9oY2lfY29yZS5oIHwgwqAgwqA1ICsrKwo+IMKgbmV0L2JsdWV0b290aC9oY2lf
Y29ubi5jIMKgIMKgIMKgIMKgIHwgwqAgwqA1ICsrKwo+IMKgbmV0L2JsdWV0b290aC9oY2lfY29y
ZS5jIMKgIMKgIMKgIMKgIHwgwqAgNzQgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KystLQo+IMKgbmV0L2JsdWV0b290aC9oY2lfZXZlbnQuYyDCoCDCoCDCoCDCoHwgwqAgNDAgKysr
KysrKysrKysrKysrKysrKy0KPiDCoDUgZmlsZXMgY2hhbmdlZCwgMTE5IGluc2VydGlvbnMoKyks
IDYgZGVsZXRpb25zKC0pCj4KPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9uZXQvYmx1ZXRvb3RoL2hj
aS5oIGIvaW5jbHVkZS9uZXQvYmx1ZXRvb3RoL2hjaS5oCj4gaW5kZXggMDIwNTViOS4uMjEwMzcz
MSAxMDA2NDQKPiAtLS0gYS9pbmNsdWRlL25ldC9ibHVldG9vdGgvaGNpLmgKPiArKysgYi9pbmNs
dWRlL25ldC9ibHVldG9vdGgvaGNpLmgKPiBAQCAtMTg5LDYgKzE4OSw3IEBAIGVudW0gewo+Cj4g
wqAjZGVmaW5lIExNUF9FVjQgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAweDAxCj4gwqAjZGVmaW5l
IExNUF9FVjUgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAweDAyCj4gKyNkZWZpbmUgTE1QX0xFIMKg
IMKgIMKgIMKgIDB4NDAKPgo+IMKgI2RlZmluZSBMTVBfU05JRkZfU1VCUiAweDAyCj4gwqAjZGVm
aW5lIExNUF9FRFJfRVNDT18yTSDCoCDCoCDCoCDCoDB4MjAKPiBkaWZmIC0tZ2l0IGEvaW5jbHVk
ZS9uZXQvYmx1ZXRvb3RoL2hjaV9jb3JlLmggYi9pbmNsdWRlL25ldC9ibHVldG9vdGgvaGNpX2Nv
cmUuaAo+IGluZGV4IDJiN2Y5NGEuLmUyZDg1N2EgMTAwNjQ0Cj4gLS0tIGEvaW5jbHVkZS9uZXQv
Ymx1ZXRvb3RoL2hjaV9jb3JlLmgKPiArKysgYi9pbmNsdWRlL25ldC9ibHVldG9vdGgvaGNpX2Nv
cmUuaAo+IEBAIC0xMDMsMTUgKzEwMywxOSBAQCBzdHJ1Y3QgaGNpX2RldiB7Cj4gwqAgwqAgwqAg
wqBhdG9taWNfdCDCoCDCoCDCoCDCoGNtZF9jbnQ7Cj4gwqAgwqAgwqAgwqB1bnNpZ25lZCBpbnQg
wqAgwqBhY2xfY250Owo+IMKgIMKgIMKgIMKgdW5zaWduZWQgaW50IMKgIMKgc2NvX2NudDsKPiAr
IMKgIMKgIMKgIHVuc2lnbmVkIGludCDCoCDCoGxlX2NudDsKPgo+IMKgIMKgIMKgIMKgdW5zaWdu
ZWQgaW50IMKgIMKgYWNsX210dTsKPiDCoCDCoCDCoCDCoHVuc2lnbmVkIGludCDCoCDCoHNjb19t
dHU7Cj4gKyDCoCDCoCDCoCB1bnNpZ25lZCBpbnQgwqAgwqBsZV9tdHU7Cj4gwqAgwqAgwqAgwqB1
bnNpZ25lZCBpbnQgwqAgwqBhY2xfcGt0czsKPiDCoCDCoCDCoCDCoHVuc2lnbmVkIGludCDCoCDC
oHNjb19wa3RzOwo+ICsgwqAgwqAgwqAgdW5zaWduZWQgaW50IMKgIMKgbGVfcGt0czsKPgo+IMKg
IMKgIMKgIMKgdW5zaWduZWQgbG9uZyDCoCBjbWRfbGFzdF90eDsKPiDCoCDCoCDCoCDCoHVuc2ln
bmVkIGxvbmcgwqAgYWNsX2xhc3RfdHg7Cj4gwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25nIMKgIHNj
b19sYXN0X3R4Owo+ICsgwqAgwqAgwqAgdW5zaWduZWQgbG9uZyDCoCBsZV9sYXN0X3R4Owo+Cj4g
wqAgwqAgwqAgwqBzdHJ1Y3Qgd29ya3F1ZXVlX3N0cnVjdCAqd29ya3F1ZXVlOwo+Cj4gQEAgLTQ3
Myw2ICs0NzcsNyBAQCB2b2lkIGhjaV9jb25uX2RlbF9zeXNmcyhzdHJ1Y3QgaGNpX2Nvbm4gKmNv
bm4pOwo+IMKgI2RlZmluZSBsbXBfc25pZmZzdWJyX2NhcGFibGUoZGV2KSAoKGRldiktPmZlYXR1
cmVzWzVdICYgTE1QX1NOSUZGX1NVQlIpCj4gwqAjZGVmaW5lIGxtcF9lc2NvX2NhcGFibGUoZGV2
KSDCoCDCoCDCoCgoZGV2KS0+ZmVhdHVyZXNbM10gJiBMTVBfRVNDTykKPiDCoCNkZWZpbmUgbG1w
X3NzcF9jYXBhYmxlKGRldikgwqAgwqAgwqAgKChkZXYpLT5mZWF0dXJlc1s2XSAmIExNUF9TSU1Q
TEVfUEFJUikKPiArI2RlZmluZSBsbXBfbGVfY2FwYWJsZShkZXYpIMKgIMKgIMKgIMKgKChkZXYp
LT5mZWF0dXJlc1s0XSAmIExNUF9MRSkKPgo+IMKgLyogLS0tLS0gSENJIHByb3RvY29scyAtLS0t
LSAqLwo+IMKgc3RydWN0IGhjaV9wcm90byB7Cj4gZGlmZiAtLWdpdCBhL25ldC9ibHVldG9vdGgv
aGNpX2Nvbm4uYyBiL25ldC9ibHVldG9vdGgvaGNpX2Nvbm4uYwo+IGluZGV4IDA5NDRjMGMuLmRk
YzJlNWUgMTAwNjQ0Cj4gLS0tIGEvbmV0L2JsdWV0b290aC9oY2lfY29ubi5jCj4gKysrIGIvbmV0
L2JsdWV0b290aC9oY2lfY29ubi5jCj4gQEAgLTMyNCw2ICszMjQsMTEgQEAgaW50IGhjaV9jb25u
X2RlbChzdHJ1Y3QgaGNpX2Nvbm4gKmNvbm4pCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8q
IFVuYWNrZWQgZnJhbWVzICovCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBoZGV2LT5hY2xfY250
ICs9IGNvbm4tPnNlbnQ7Cj4gKyDCoCDCoCDCoCB9IGVsc2UgaWYgKGNvbm4tPnR5cGUgPT0gTEVf
TElOSykgewo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGhkZXYtPmxlX3BrdHMpCj4gKyDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBoZGV2LT5sZV9jbnQgKz0gY29ubi0+c2Vu
dDsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGVsc2UKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIGhkZXYtPmFjbF9jbnQgKz0gY29ubi0+c2VudDsKPiDCoCDCoCDCoCDCoH0g
ZWxzZSB7Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3QgaGNpX2Nvbm4gKmFjbCA9IGNv
bm4tPmxpbms7Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoYWNsKSB7Cj4gZGlmZiAtLWdp
dCBhL25ldC9ibHVldG9vdGgvaGNpX2NvcmUuYyBiL25ldC9ibHVldG9vdGgvaGNpX2NvcmUuYwo+
IGluZGV4IGJjMmEwNTIuLjQ1Yzc4YzIgMTAwNjQ0Cj4gLS0tIGEvbmV0L2JsdWV0b290aC9oY2lf
Y29yZS5jCj4gKysrIGIvbmV0L2JsdWV0b290aC9oY2lfY29yZS5jCj4gQEAgLTI1NCw2ICsyNTQs
MTQgQEAgc3RhdGljIHZvaWQgaGNpX2luaXRfcmVxKHN0cnVjdCBoY2lfZGV2ICpoZGV2LCB1bnNp
Z25lZCBsb25nIG9wdCkKPiDCoCDCoCDCoCDCoGhjaV9zZW5kX2NtZChoZGV2LCBIQ0lfT1BfV1JJ
VEVfQ0FfVElNRU9VVCwgMiwgJnBhcmFtKTsKPiDCoH0KPgo+ICtzdGF0aWMgdm9pZCBoY2lfbGVf
aW5pdF9yZXEoc3RydWN0IGhjaV9kZXYgKmhkZXYsIHVuc2lnbmVkIGxvbmcgb3B0KQo+ICt7Cj4g
KyDCoCDCoCDCoCBCVF9EQkcoIiVzIiwgaGRldi0+bmFtZSk7Cj4gKwo+ICsgwqAgwqAgwqAgLyog
UmVhZCBMRSBidWZmZXIgc2l6ZSAqLwo+ICsgwqAgwqAgwqAgaGNpX3NlbmRfY21kKGhkZXYsIEhD
SV9PUF9MRV9SRUFEX0JVRkZFUl9TSVpFLCAwLCBOVUxMKTsKPiArfQo+ICsKPiDCoHN0YXRpYyB2
b2lkIGhjaV9zY2FuX3JlcShzdHJ1Y3QgaGNpX2RldiAqaGRldiwgdW5zaWduZWQgbG9uZyBvcHQp
Cj4gwqB7Cj4gwqAgwqAgwqAgwqBfX3U4IHNjYW4gPSBvcHQ7Cj4gQEAgLTUwOSw2ICs1MTcsMTAg
QEAgaW50IGhjaV9kZXZfb3BlbihfX3UxNiBkZXYpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBy
ZXQgPSBfX2hjaV9yZXF1ZXN0KGhkZXYsIGhjaV9pbml0X3JlcSwgMCwKPiDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG1zZWNzX3RvX2pp
ZmZpZXMoSENJX0lOSVRfVElNRU9VVCkpOwo+Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAo
bG1wX2xlX2NhcGFibGUoaGRldikpCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCByZXQgPSBfX2hjaV9yZXF1ZXN0KGhkZXYsIGhjaV9sZV9pbml0X3JlcSwgMCwKPiArIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIG1zZWNz
X3RvX2ppZmZpZXMoSENJX0lOSVRfVElNRU9VVCkpOwo+ICsKPiDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoGNsZWFyX2JpdChIQ0lfSU5JVCwgJmhkZXYtPmZsYWdzKTsKPiDCoCDCoCDCoCDCoH0KPgo+
IEBAIC02NDUsNyArNjU3LDcgQEAgaW50IGhjaV9kZXZfcmVzZXQoX191MTYgZGV2KQo+IMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgaGRldi0+Zmx1c2goaGRldik7Cj4KPiDCoCDCoCDCoCDCoGF0b21p
Y19zZXQoJmhkZXYtPmNtZF9jbnQsIDEpOwo+IC0gwqAgwqAgwqAgaGRldi0+YWNsX2NudCA9IDA7
IGhkZXYtPnNjb19jbnQgPSAwOwo+ICsgwqAgwqAgwqAgaGRldi0+YWNsX2NudCA9IDA7IGhkZXYt
PnNjb19jbnQgPSAwOyBoZGV2LT5sZV9jbnQgPSAwOwo+Cj4gwqAgwqAgwqAgwqBpZiAoIXRlc3Rf
Yml0KEhDSV9SQVcsICZoZGV2LT5mbGFncykpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXQg
PSBfX2hjaV9yZXF1ZXN0KGhkZXYsIGhjaV9yZXNldF9yZXEsIDAsCj4gQEAgLTE0NTYsOCArMTQ2
OCwyNSBAQCBzdGF0aWMgaW5saW5lIHN0cnVjdCBoY2lfY29ubiAqaGNpX2xvd19zZW50KHN0cnVj
dCBoY2lfZGV2ICpoZGV2LCBfX3U4IHR5cGUsIGludAo+IMKgIMKgIMKgIMKgfQo+Cj4gwqAgwqAg
wqAgwqBpZiAoY29ubikgewo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgaW50IGNudCA9ICh0eXBl
ID09IEFDTF9MSU5LID8gaGRldi0+YWNsX2NudCA6IGhkZXYtPnNjb19jbnQpOwo+IC0gwqAgwqAg
wqAgwqAgwqAgwqAgwqAgaW50IHEgPSBjbnQgLyBudW07Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDC
oCBpbnQgY250LCBxOwo+ICsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN3aXRjaCAoY29ubi0+
dHlwZSkgewo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY2FzZSBBQ0xfTElOSzoKPiArIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNudCA9IGhkZXYtPmFjbF9jbnQ7Cj4gKyDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPiArIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIGNhc2UgU0NPX0xJTks6Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjYXNlIEVTQ09fTElO
SzoKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNudCA9IGhkZXYtPnNjb19j
bnQ7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPiArIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIGNhc2UgTEVfTElOSzoKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIGNudCA9IGhkZXYtPmxlX210dSA/IGhkZXYtPmxlX2NudCA6IGhkZXYtPmFjbF9j
bnQ7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPiArIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIGRlZmF1bHQ6Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCBjbnQgPSAwOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgQlRfRVJS
KCJVbmtub3duIGxpbmsgdHlwZSIpOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfQo+ICsKPiAr
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIHEgPSBjbnQgLyBudW07Cj4gwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAqcXVvdGUgPSBxID8gcSA6IDE7Cj4gwqAgwqAgwqAgwqB9IGVsc2UKPiDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCpxdW90ZSA9IDA7Cj4gQEAgLTE1NTYsNiArMTU4NSw0MCBAQCBzdGF0aWMg
aW5saW5lIHZvaWQgaGNpX3NjaGVkX2VzY28oc3RydWN0IGhjaV9kZXYgKmhkZXYpCj4gwqAgwqAg
wqAgwqB9Cj4gwqB9Cj4KPiArc3RhdGljIGlubGluZSB2b2lkIGhjaV9zY2hlZF9sZShzdHJ1Y3Qg
aGNpX2RldiAqaGRldikKPiArewo+ICsgwqAgwqAgwqAgc3RydWN0IGhjaV9jb25uICpjb25uOwo+
ICsgwqAgwqAgwqAgc3RydWN0IHNrX2J1ZmYgKnNrYjsKPiArIMKgIMKgIMKgIGludCBxdW90ZSwg
Y250Owo+ICsKPiArIMKgIMKgIMKgIEJUX0RCRygiJXMiLCBoZGV2LT5uYW1lKTsKPiArCj4gKyDC
oCDCoCDCoCBpZiAoIXRlc3RfYml0KEhDSV9SQVcsICZoZGV2LT5mbGFncykpIHsKPiArIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIC8qIEFDTCB0eCB0aW1lb3V0IG11c3QgYmUgbG9uZ2VyIHRoYW4gbWF4
aW11bQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAqIGxpbmsgc3VwZXJ2aXNpb24gdGltZW91
dCAoNDAuOSBzZWNvbmRzKSAqLwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKCFoZGV2LT5s
ZV9jbnQgJiYKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHRpbWVfYWZ0ZXIoamlmZmll
cywgaGRldi0+bGVfbGFzdF90eCArIEhaICogNDUpKQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgaGNpX2FjbF90eF90byhoZGV2KTsKPiArIMKgIMKgIMKgIH0KCkl0IHNlZW1z
IHRoYXQgdGhlIEFDTCB0eCB0aW1lb3V0IGlzIGNhdXNpbmcgc29tZSBwcm9ibGVtczogQlIvRURS
IGFuZApMRSBjb25uZWN0aW9ucyBhcmUgbm90IHdvcmtpbmcgcHJvcGVybHkgb24gbWFjYm9va3Mh
IERvbid0IGFzayBtZSB3aHkKb24gbWFjYm9va3Mgb25seSEgQnV0IEkgZG91YmxlIGNoZWNrZWQu
IEkgdGVzdGVkIHlvdXIgYnJhbmNoIGFuZCBhbHNvCmJsdWV0b290aC1uZXh0ICsgTEUgcGF0Y2hl
cyBhbmQgYm90aCBhcmUgbm90IHdvcmtpbmcgYXMgZXhwZWN0ZWQuIEkKZGlkbid0IGhhdmUgdGlt
ZSB0byBpbnZlc3RpZ2F0ZSBpdCwgZG8geW91IGhhdmUgYW55IGNsdWU/CgpGb3IgQlIvRURSIEkg
YW0gcmVjZWl2aW5nICJraWxsaW5nIHN0YWxsZWQgQUNMIGNvbm5lY3Rpb24iIG1lc3NhZ2VzCmZv
ciBhbGwgY29ubmVjdGlvbnMuCgoKUmVnYXJkcywKQ2xhdWRpbwoKCj4gKwo+ICsgwqAgwqAgwqAg
Y250ID0gaGRldi0+bGVfcGt0cyA/IGhkZXYtPmxlX2NudCA6IGhkZXYtPmFjbF9jbnQ7Cj4gKyDC
oCDCoCDCoCB3aGlsZSAoY250ICYmIChjb25uID0gaGNpX2xvd19zZW50KGhkZXYsIExFX0xJTkss
ICZxdW90ZSkpKSB7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCB3aGlsZSAocXVvdGUtLSAmJiAo
c2tiID0gc2tiX2RlcXVldWUoJmNvbm4tPmRhdGFfcSkpKSB7Cj4gKyDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCBCVF9EQkcoInNrYiAlcCBsZW4gJWQiLCBza2IsIHNrYi0+bGVuKTsK
PiArCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBoY2lfc2VuZF9mcmFtZShz
a2IpOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaGRldi0+bGVfbGFzdF90
eCA9IGppZmZpZXM7Cj4gKwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY250
LS07Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjb25uLT5zZW50Kys7Cj4g
KyDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9Cj4gKyDCoCDCoCDCoCB9Cj4gKyDCoCDCoCDCoCBpZiAo
aGRldi0+bGVfcGt0cykKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGhkZXYtPmxlX2NudCA9IGNu
dDsKPiArIMKgIMKgIMKgIGVsc2UKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGhkZXYtPmFjbF9j
bnQgPSBjbnQ7Cj4gK30KPiArCj4gwqBzdGF0aWMgdm9pZCBoY2lfdHhfdGFzayh1bnNpZ25lZCBs
b25nIGFyZykKPiDCoHsKPiDCoCDCoCDCoCDCoHN0cnVjdCBoY2lfZGV2ICpoZGV2ID0gKHN0cnVj
dCBoY2lfZGV2ICopIGFyZzsKPiBAQCAtMTU2Myw3ICsxNjI2LDggQEAgc3RhdGljIHZvaWQgaGNp
X3R4X3Rhc2sodW5zaWduZWQgbG9uZyBhcmcpCj4KPiDCoCDCoCDCoCDCoHJlYWRfbG9jaygmaGNp
X3Rhc2tfbG9jayk7Cj4KPiAtIMKgIMKgIMKgIEJUX0RCRygiJXMgYWNsICVkIHNjbyAlZCIsIGhk
ZXYtPm5hbWUsIGhkZXYtPmFjbF9jbnQsIGhkZXYtPnNjb19jbnQpOwo+ICsgwqAgwqAgwqAgQlRf
REJHKCIlcyBhY2wgJWQgc2NvICVkIGxlICVkIiwgaGRldi0+bmFtZSwgaGRldi0+YWNsX2NudCwK
PiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGhkZXYtPnNjb19jbnQsIGhkZXYtPmxlX2NudCk7Cj4K
PiDCoCDCoCDCoCDCoC8qIFNjaGVkdWxlIHF1ZXVlcyBhbmQgc2VuZCBzdHVmZiB0byBIQ0kgZHJp
dmVyICovCj4KPiBAQCAtMTU3Myw2ICsxNjM3LDggQEAgc3RhdGljIHZvaWQgaGNpX3R4X3Rhc2so
dW5zaWduZWQgbG9uZyBhcmcpCj4KPiDCoCDCoCDCoCDCoGhjaV9zY2hlZF9lc2NvKGhkZXYpOwo+
Cj4gKyDCoCDCoCDCoCBoY2lfc2NoZWRfbGUoaGRldik7Cj4gKwo+IMKgIMKgIMKgIMKgLyogU2Vu
ZCBuZXh0IHF1ZXVlZCByYXcgKHVua25vd24gdHlwZSkgcGFja2V0ICovCj4gwqAgwqAgwqAgwqB3
aGlsZSAoKHNrYiA9IHNrYl9kZXF1ZXVlKCZoZGV2LT5yYXdfcSkpKQo+IMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgaGNpX3NlbmRfZnJhbWUoc2tiKTsKPiBkaWZmIC0tZ2l0IGEvbmV0L2JsdWV0b290
aC9oY2lfZXZlbnQuYyBiL25ldC9ibHVldG9vdGgvaGNpX2V2ZW50LmMKPiBpbmRleCA5MmM4NjIx
Li5kYTIzNTAyIDEwMDY0NAo+IC0tLSBhL25ldC9ibHVldG9vdGgvaGNpX2V2ZW50LmMKPiArKysg
Yi9uZXQvYmx1ZXRvb3RoL2hjaV9ldmVudC5jCj4gQEAgLTUzOSw2ICs1MzksMjYgQEAgc3RhdGlj
IHZvaWQgaGNpX2NjX3JlYWRfYmRfYWRkcihzdHJ1Y3QgaGNpX2RldiAqaGRldiwgc3RydWN0IHNr
X2J1ZmYgKnNrYikKPiDCoCDCoCDCoCDCoGhjaV9yZXFfY29tcGxldGUoaGRldiwgcnAtPnN0YXR1
cyk7Cj4gwqB9Cj4KPiArc3RhdGljIHZvaWQgaGNpX2NjX2xlX3JlYWRfYnVmZmVyX3NpemUoc3Ry
dWN0IGhjaV9kZXYgKmhkZXYsCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHN0cnVjdCBza19idWZmICpza2IpCj4gK3sKPiArIMKgIMKg
IMKgIHN0cnVjdCBoY2lfcnBfbGVfcmVhZF9idWZmZXJfc2l6ZSAqcnAgPSAodm9pZCAqKSBza2It
PmRhdGE7Cj4gKwo+ICsgwqAgwqAgwqAgQlRfREJHKCIlcyBzdGF0dXMgMHgleCIsIGhkZXYtPm5h
bWUsIHJwLT5zdGF0dXMpOwo+ICsKPiArIMKgIMKgIMKgIGlmIChycC0+c3RhdHVzKQo+ICsgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuOwo+ICsKPiArIMKgIMKgIMKgIGhkZXYtPmxlX210dSA9
IF9fbGUxNl90b19jcHUocnAtPmxlX210dSk7Cj4gKyDCoCDCoCDCoCBoZGV2LT5sZV9wa3RzID0g
cnAtPmxlX21heF9wa3Q7Cj4gKwo+ICsgwqAgwqAgwqAgaGRldi0+bGVfY250ID0gaGRldi0+bGVf
cGt0czsKPiArCj4gKyDCoCDCoCDCoCBCVF9EQkcoIiVzIGxlIG10dSAlZDolZCIsIGhkZXYtPm5h
bWUsIGhkZXYtPmxlX210dSwgaGRldi0+bGVfcGt0cyk7Cj4gKwo+ICsgwqAgwqAgwqAgaGNpX3Jl
cV9jb21wbGV0ZShoZGV2LCBycC0+c3RhdHVzKTsKPiArfQo+ICsKPiDCoHN0YXRpYyBpbmxpbmUg
dm9pZCBoY2lfY3NfaW5xdWlyeShzdHJ1Y3QgaGNpX2RldiAqaGRldiwgX191OCBzdGF0dXMpCj4g
wqB7Cj4gwqAgwqAgwqAgwqBCVF9EQkcoIiVzIHN0YXR1cyAweCV4IiwgaGRldi0+bmFtZSwgc3Rh
dHVzKTsKPiBAQCAtMTM1Myw2ICsxMzczLDEwIEBAIHN0YXRpYyBpbmxpbmUgdm9pZCBoY2lfY21k
X2NvbXBsZXRlX2V2dChzdHJ1Y3QgaGNpX2RldiAqaGRldiwgc3RydWN0IHNrX2J1ZmYgKnNrCj4g
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBoY2lfY2NfcmVhZF9iZF9hZGRyKGhkZXYsIHNrYik7Cj4g
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBicmVhazsKPgo+ICsgwqAgwqAgwqAgY2FzZSBIQ0lfT1Bf
TEVfUkVBRF9CVUZGRVJfU0laRToKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGhjaV9jY19sZV9y
ZWFkX2J1ZmZlcl9zaXplKGhkZXYsIHNrYik7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVh
azsKPiArCj4gwqAgwqAgwqAgwqBkZWZhdWx0Ogo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgQlRf
REJHKCIlcyBvcGNvZGUgMHgleCIsIGhkZXYtPm5hbWUsIG9wY29kZSk7Cj4gwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqBicmVhazsKPiBAQCAtMTQ5MCwxMCArMTUxNCwyMiBAQCBzdGF0aWMgaW5saW5l
IHZvaWQgaGNpX251bV9jb21wX3BrdHNfZXZ0KHN0cnVjdCBoY2lfZGV2ICpoZGV2LCBzdHJ1Y3Qg
c2tfYnVmZiAqcwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY29ubi0+c2Vu
dCAtPSBjb3VudDsKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGNv
bm4tPnR5cGUgPT0gQUNMX0xJTkspIHsKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIGlmICgoaGRldi0+YWNsX2NudCArPSBjb3VudCkgPiBoZGV2LT5hY2xf
cGt0cykKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGhk
ZXYtPmFjbF9jbnQgKz0gY291bnQ7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCBpZiAoaGRldi0+YWNsX2NudCA+IGhkZXYtPmFjbF9wa3RzKQo+IMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaGRl
di0+YWNsX2NudCA9IGhkZXYtPmFjbF9wa3RzOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgfSBlbHNlIGlmIChjb25uLT50eXBlID09IExFX0xJTkspIHsKPiArIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChoZGV2LT5sZV9wa3RzKSB7
Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCBoZGV2LT5sZV9jbnQgKz0gY291bnQ7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoaGRldi0+bGVfY250ID4gaGRldi0+
bGVfcGt0cykKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGhkZXYtPmxlX2NudCA9IGhkZXYtPmxlX3BrdHM7Cj4g
KyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9IGVsc2Ugewo+
ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgaGRldi0+YWNsX2NudCArPSBjb3VudDsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChoZGV2LT5hY2xfY250ID4gaGRldi0+
YWNsX3BrdHMpCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBoZGV2LT5hY2xfY250ID0gaGRldi0+YWNsX3BrdHM7
Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9Cj4gwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9IGVsc2Ugewo+IC0gwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKChoZGV2LT5zY29fY250ICs9IGNv
dW50KSA+IGhkZXYtPnNjb19wa3RzKQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgaGRldi0+c2NvX2NudCArPSBjb3VudDsKPiArIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChoZGV2LT5zY29fY250ID4gaGRldi0+
c2NvX3BrdHMpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqBoZGV2LT5zY29fY250ID0gaGRldi0+c2NvX3BrdHM7Cj4gwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9Cj4g
LS0KPiAxLjcuMQo+Cg==
^ permalink raw reply
* Re: [PATCHv4 0/2] Fix kernel crash in rfcomm/l2cap
From: Gustavo F. Padovan @ 2010-11-10 16:32 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <1289402694.23417.2.camel@Nokia-N900>
Hi Andrei,
* Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> [2010-11-10 17:24:=
54 +0200]:
> Hi Marcel,
>=20
> > Hi Andrei,
> >=20
> > > Yet another version of patches fixing kernel crash in RFCOMM / L2CAP.
> > > *v4: taken Gustavo comments about timer HZ -> HZ/5
> > >=20
> > > Do not delete l2cap channel and socket sk when sk is owned by user.
> > > To delete l2cap channel standard timer is used.
> > >=20
> > > lock_sock and release_sock do not hold a normal spinlock directly but=
=20
> > > instead hold the owner field. This means bh_lock_sock can still execu=
te
> > > even if the socket is "locked". More info can be found here:
> > > http://www.linuxfoundation.org/collaborate/workgroups/networking/sock=
etlocks
> > >=20
> > > When sending following sequence:
> > > ...
> > > No.=A0 =A0 =A0 =A0 Time=A0 =A0 =A0 =A0 =A0 =A0 =A0 Source=A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Destination=A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0 =A0 =20
> > > Protocol Info 89 1.951202=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
RFCOMM=A0 =A0 Rcvd DISC DLCI=3D20
> > > 90 1.951324=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 RFCOMM=A0 =A0=
Sent UA DLCI=3D20
> > > 91 1.959381=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 HCI_EVT=A0 =
=A0 Number of Completed Packets
> > > 92 1.966461=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 RFCOMM=A0 =A0=
Rcvd DISC DLCI=3D0
> > > 93 1.966492=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 L2CAP=A0 =A0 =
=A0 Rcvd Disconnect Request
> > > 94 1.972595=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 L2CAP=A0 =A0 =
=A0 Sent Disconnect Response
> > >=20
> > > ...
> > >=20
> > > krfcommd kernel thread is preempted with l2cap tasklet which remove
> > > l2cap_conn (L2CAP connection handler structure). Then rfcomm thread
> > > tries to send RFCOMM UA which is reply to RFCOMM DISC and when
> > > de-referencing l2cap_conn crash happens.
> >=20
> > so I assume you have tested this extensively with various RFCOMM corner
> > cases like incoming RFCOMM. Since a lot of profiles require proper
> > disconnects and we have to ensure that our reference counting is
> > correct.
>=20
> We have the slightly modified patch applied for a several months. No regr=
ession found.
>=20
> Regards,
> Andrei
>=20
> >=20
> > Other then that it seems fine to me.
> >=20
> > Acked-by: Marcel Holtmann <marcel@holtmann.org>
Applied to bluetooth-next-2,6, thanks.
--=20
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH 1/3] Bluetooth: Simplify remote features callback function logic
From: Gustavo F. Padovan @ 2010-11-10 16:24 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth, Johan Hedberg
In-Reply-To: <1289401913-22982-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
* johan.hedberg@gmail.com <johan.hedberg@gmail.com> [2010-11-10 17:11:51 +0200]:
> From: Johan Hedberg <johan.hedberg@nokia.com>
>
> The current remote and remote extended features event callbacks logic
> can be made simpler by using a label and goto statements instead of the
> current multiple levels of nested if statements.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> ---
> net/bluetooth/hci_event.c | 91 +++++++++++++++++++++++----------------------
> 1 files changed, 47 insertions(+), 44 deletions(-)
Applied to bluetooth-next-2.6, thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH 1/4] Sim Access Profile API
From: Gustavo F. Padovan @ 2010-11-10 16:07 UTC (permalink / raw)
To: Waldemar.Rymarkiewicz
Cc: marcel, linux-bluetooth, suraj, johan.hedberg, joakim.xj.ceder
In-Reply-To: <99B09243E1A5DA4898CDD8B7001114480BD700C239@EXMB04.eu.tieto.com>
Hi Waldemar,
* Waldemar.Rymarkiewicz@tieto.com <Waldemar.Rymarkiewicz@tieto.com> [2010-11-10 13:12:53 +0200]:
> Hi Marcel,
>
> >> + void Disable()
> >> +
> >> + Shudown SAP server and remove the SDP record.
> >> +
> >> + Possible errors: org.bluez.Error.Failed
> >
> >I don't like this. If you have properties then just changing
> >the property should be enough. So a SetProperty is more appropriate.
>
> I see another option to get rid of 'Enabled' property and leave the methods. What would you say on that?
It's not a good a idea. We have been moving everything we can to a set
property operation instead of a method call. Do that as method is add
unnecessary code to BlueZ once we already have set property there.
>
> >> +
> >> + void Disconnect(boolean type)
> >> +
> >> + Disconnect SAP client from the server.
> >The 'type'
> >> + parameter indicates disconnection type.
> >> +
> >> + True - gracefull disconnection
> >> + False - immediate disconnection
> >> +
> >> + Possible errors: org.bluez.Error.Failed
> >
> >I don't like this style of method names at all. Using method
> >names like GracefulDisconnect and ImmediateDisconnect would be better.
>
> That's fine.
>
> >However I am not sure we should differentiate here at all. We
> >should always to the graceful disconnect. What will the
> >immediate disconnect bring us?
>
> That's actually intended for testing only. One of PTS test cases expects the tester to trigger immediate disconnect.
> In practce, it is only used when connection to sim card is lost, but this is obviously done internally.
So this shouldn't be in the API, no one is going to use it. You can
create something internally for the immediate disconnection that you go
and set manually inside the code. Make sure to comment in the code why
you are adding this there. That can also be a option in some of the
bluetooth config files. Let's see what others think here.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH 1/7] Bluetooth: Hold the lock inside l2cap_get_sock_by_addr()
From: Gustavo F. Padovan @ 2010-11-10 15:47 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: Ville Tervo, linux-bluetooth@vger.kernel.org
In-Reply-To: <1289367595.9615.240.camel@aeonflux>
Hi Marcel,
* Marcel Holtmann <marcel@holtmann.org> [2010-11-10 14:39:55 +0900]:
> Hi Gustavo,
>
> > > On Tue, Nov 02, 2010 at 04:03:12PM +0100, ext Gustavo F. Padovan wrote:
> > > > It also have to change the name of the function to
> > > > l2cap_get_sock_by_addr() because we do hold the lock inside it now.
> > > >
> > > > Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> > > > ---
> > > > net/bluetooth/l2cap.c | 17 ++++++-----------
> > > > 1 files changed, 6 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> > > > index 6f931cc..3d48867 100644
> > > > --- a/net/bluetooth/l2cap.c
> > > > +++ b/net/bluetooth/l2cap.c
> > > > @@ -728,15 +728,18 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru
> > > > }
> > > >
> > > > /* ---- Socket interface ---- */
> > > > -static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
> > > > +static struct sock *l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
> > > > {
> > > > struct sock *sk;
> > > > struct hlist_node *node;
> > > > +
> > > > + write_lock_bh(&l2cap_sk_list.lock);
> > >
> > > Code is only reading so read_lock_bh would be enough?
> >
> > Sure, I didn't looked to that, I just keept the same code that we were
> > using before. I'll fix it.
>
> we might also not just bother with read/write locks. Since they are not
> always the right thing to do. In a lot of cases a pure spinlock is just
> better. And in case of Bluetooth I think we would be just fine with
> using a pure spinlock. You might run some tests with this.
Better than spinlock is move everything to RCU, than we will just need a
mutex or spinlock in the write operations. Using a RCU is a lot simpler.
These patches are a clean up to add RCU to sk_list, so I propose to
upstream the new version of my patches and do the RCU change on top
of them.
After all these changes we will be ready for the l2cap.c split.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH 0/9] Fixing DBus error system in BlueZ
From: Gustavo F. Padovan @ 2010-11-10 15:38 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1289366622.9615.230.camel@aeonflux>
Hi Marcel,
* Marcel Holtmann <marcel@holtmann.org> [2010-11-10 14:23:42 +0900]:
> Hi Gustavo,
>
> > > On Mon, Nov 08, 2010, Gustavo F. Padovan wrote:
> > > > Here are some patches that try to fix the mess of reporting error to
> > > > DBus inside BlueZ. It follows the oFono and ConnMan error system.
> > > >
> > > > The goal is to get ride of any directly call to g_dbus_create_error()
> > > > inside bluez code, changing that to __btd_error_*. This patch set
> > > > doesn't fix all of them yet, but is a very good start. Please review.
> > > >
> > > >
> > > > Gustavo F. Padovan (9):
> > > > Create __btd_error_invalid_args()
> > > > Add __btd_error_already_exists()
> > > > Add __btd_error_not_supported()
> > > > Add __btd_error_not_connected()
> > > > Add __btd_error_in_progress()
> > > > Add __btd_error_not_available()
> > > > Add __btd_error_busy()
> > > > Add __btd_error_does_not_exist()
> > > > Add __btd_error_not_authorized()
> > >
> > > The patches seem fine to me, but before pushing upstream I'd like to
> > > understand the reason for prefixing these with with __btd instead of
> > > btd. What's the criteria used to decide what to use and when and why is
> > > __btd the correct choice for these new functions? My first guess would
> > > have been that __btd is for things only accessible by the core-daemon
> > > whereas btd is for functions exported to plugins, but that doesn't seem
> > > to be the case with your patches since many of these __btd functions get
> > > called from plugins.
> >
> > I just followed oFono and ConnMan on this. That is the reason and I
> > didn't asked myself why have a __ in this case.. But I see your point.
> > Do you think that change that to btd_error_* will fit better inside
> > BlueZ? I can change that then.
>
> so within ConnMan and oFono we make a difference between public symbols
> that are reachable from within plugins and other which are not.
>
> In general btd_ should be public symbols available to plugins and __btd_
> for internal symbols that are no available to plugins.
>
> For builtin plugins that makes no difference of course, but this is not
> about internal builtin plugins. It is for protecting against external
> plugins to not allow access to internal details.
>
> That said, bluetoothd is not linked with the case to hide certain
> symbols anyway so that right now there is no real difference here.
So to make that more clear, I'll change these functions to btd_
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCHv4 0/2] Fix kernel crash in rfcomm/l2cap
From: Andrei Emeltchenko @ 2010-11-10 15:24 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1289367396.9615.238.camel@aeonflux>
Hi Marcel,
> Hi Andrei,
>
> > Yet another version of patches fixing kernel crash in RFCOMM / L2CAP.
> > *v4: taken Gustavo comments about timer HZ -> HZ/5
> >
> > Do not delete l2cap channel and socket sk when sk is owned by user.
> > To delete l2cap channel standard timer is used.
> >
> > lock_sock and release_sock do not hold a normal spinlock directly but
> > instead hold the owner field. This means bh_lock_sock can still execute
> > even if the socket is "locked". More info can be found here:
> > http://www.linuxfoundation.org/collaborate/workgroups/networking/socketlocks
> >
> > When sending following sequence:
> > ...
> > No. Time Source Destination
> > Protocol Info 89 1.951202 RFCOMM Rcvd DISC DLCI=20
> > 90 1.951324 RFCOMM Sent UA DLCI=20
> > 91 1.959381 HCI_EVT Number of Completed Packets
> > 92 1.966461 RFCOMM Rcvd DISC DLCI=0
> > 93 1.966492 L2CAP Rcvd Disconnect Request
> > 94 1.972595 L2CAP Sent Disconnect Response
> >
> > ...
> >
> > krfcommd kernel thread is preempted with l2cap tasklet which remove
> > l2cap_conn (L2CAP connection handler structure). Then rfcomm thread
> > tries to send RFCOMM UA which is reply to RFCOMM DISC and when
> > de-referencing l2cap_conn crash happens.
>
> so I assume you have tested this extensively with various RFCOMM corner
> cases like incoming RFCOMM. Since a lot of profiles require proper
> disconnects and we have to ensure that our reference counting is
> correct.
We have the slightly modified patch applied for a several months. No regression found.
Regards,
Andrei
>
> Other then that it seems fine to me.
>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>
>
> Regards
>
> Marcel
>
>
^ permalink raw reply
* [PATCH 3/3] Bluetooth: Automate remote name requests
From: johan.hedberg @ 2010-11-10 15:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <1289401913-22982-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
In Bluetooth there are no automatic updates of remote device names when
they get changed on the remote side. Instead, it is a good idea to do a
manual name request when a new connection gets created (for whatever
reason) since at this point it is very cheap (no costly baseband
connection creation needed just for the sake of the name request).
So far userspace has been responsible for this extra name request but
tighter control is needed in order not to flood Bluetooth controllers
with two many commands during connection creation. It has been shown
that some controllers simply fail to function correctly if they get too
many (almost) simultaneous commands during connection creation. The
simplest way to acheive better control of these commands is to move
their sending completely to the kernel side.
This patch inserts name requests into the sequence of events that the
kernel performs during connection creation. It does this after the
remote features have been successfully requested and before any pending
authentication requests are performed. The code will work sub-optimally
with userspace versions that still do the name requesting themselves (it
shouldn't break anything though) so it is recommended to combine this
with a userspace software version that doesn't have automated name
requests.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
net/bluetooth/hci_event.c | 74 ++++++++++++++++++++++++++++++++++----------
1 files changed, 57 insertions(+), 17 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 45569f2..cef970f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -677,9 +677,8 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
-static int request_outgoing_auth(struct hci_dev *hdev, bdaddr_t *bdaddr)
+static int outgoing_auth_needed(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
- struct hci_cp_auth_requested cp;
struct hci_conn *conn;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
@@ -698,15 +697,43 @@ static int request_outgoing_auth(struct hci_dev *hdev, bdaddr_t *bdaddr)
conn->sec_level != BT_SECURITY_HIGH)
return 0;
- cp.handle = __cpu_to_le16(conn->handle);
- hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
-
return 1;
}
+static int request_auth(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct hci_cp_auth_requested cp;
+ struct hci_conn *conn;
+
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
+ if (!conn)
+ return -ENOTCONN;
+
+ cp.handle = __cpu_to_le16(conn->handle);
+ return hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
+}
+
static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{
+ struct hci_cp_remote_name_req *cp;
+
BT_DBG("%s status 0x%x", hdev->name, status);
+
+ /* If successful wait for the name req complete event before
+ * checking for the need to do authentication */
+ if (!status)
+ return;
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
+ if (!cp)
+ return;
+
+ hci_dev_lock(hdev);
+
+ if (outgoing_auth_needed(hdev, &cp->bdaddr))
+ request_auth(hdev, &cp->bdaddr);
+
+ hci_dev_unlock(hdev);
}
static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
@@ -1117,9 +1144,18 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ struct hci_ev_remote_name *ev = (void *) skb->data;
+
BT_DBG("%s", hdev->name);
hci_conn_check_pending(hdev);
+
+ hci_dev_lock(hdev);
+
+ if (outgoing_auth_needed(hdev, &ev->bdaddr))
+ request_auth(hdev, &ev->bdaddr);
+
+ hci_dev_unlock(hdev);
}
static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1183,7 +1219,6 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
{
struct hci_ev_remote_features *ev = (void *) skb->data;
struct hci_conn *conn;
- int auth_requested;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1208,12 +1243,15 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
goto unlock;
}
- if (!ev->status)
- auth_requested = request_outgoing_auth(hdev, &conn->dst);
- else
- auth_requested = 0;
+ if (!ev->status) {
+ struct hci_cp_remote_name_req cp;
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pscan_rep_mode = 0x02;
+ hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
+ }
- if (!auth_requested) {
+ if (!outgoing_auth_needed(hdev, &conn->dst)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
@@ -1671,7 +1709,6 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
{
struct hci_ev_remote_ext_features *ev = (void *) skb->data;
struct hci_conn *conn;
- int auth_requested;
BT_DBG("%s", hdev->name);
@@ -1693,12 +1730,15 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
if (conn->state != BT_CONFIG)
goto unlock;
- if (!ev->status)
- auth_requested = request_outgoing_auth(hdev, &conn->dst);
- else
- auth_requested = 0;
+ if (!ev->status) {
+ struct hci_cp_remote_name_req cp;
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pscan_rep_mode = 0x02;
+ hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
+ }
- if (!auth_requested) {
+ if (!outgoing_auth_needed(hdev, &conn->dst)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
--
1.7.2.3
^ permalink raw reply related
* [PATCH 2/3] Bluetooth: Create a unified authentication request function
From: johan.hedberg @ 2010-11-10 15:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <1289401913-22982-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
This patch adds a single function that's responsible for requesting
authentication for outgoing connections. This is preparation for the
next patch which will add automated name requests and thereby move the
authentication requests to a different location.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
net/bluetooth/hci_event.c | 58 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8430276..45569f2 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -677,6 +677,33 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
+static int request_outgoing_auth(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct hci_cp_auth_requested cp;
+ struct hci_conn *conn;
+
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
+ if (!conn)
+ return 0;
+
+ if (conn->state != BT_CONFIG || !conn->out)
+ return 0;
+
+ if (conn->sec_level == BT_SECURITY_SDP)
+ return 0;
+
+ /* Only request authentication for SSP connections or non-SSP
+ * devices with sec_level HIGH */
+ if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
+ conn->sec_level != BT_SECURITY_HIGH)
+ return 0;
+
+ cp.handle = __cpu_to_le16(conn->handle);
+ hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
+
+ return 1;
+}
+
static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1156,6 +1183,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
{
struct hci_ev_remote_features *ev = (void *) skb->data;
struct hci_conn *conn;
+ int auth_requested;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1177,12 +1205,15 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
cp.page = 0x01;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
sizeof(cp), &cp);
- } else if (!ev->status && conn->out &&
- conn->sec_level == BT_SECURITY_HIGH) {
- struct hci_cp_auth_requested cp;
- cp.handle = ev->handle;
- hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
- } else {
+ goto unlock;
+ }
+
+ if (!ev->status)
+ auth_requested = request_outgoing_auth(hdev, &conn->dst);
+ else
+ auth_requested = 0;
+
+ if (!auth_requested) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
@@ -1640,6 +1671,7 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
{
struct hci_ev_remote_ext_features *ev = (void *) skb->data;
struct hci_conn *conn;
+ int auth_requested;
BT_DBG("%s", hdev->name);
@@ -1661,14 +1693,12 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
if (conn->state != BT_CONFIG)
goto unlock;
- if (!ev->status && hdev->ssp_mode > 0 &&
- conn->ssp_mode > 0 && conn->out &&
- conn->sec_level != BT_SECURITY_SDP) {
- struct hci_cp_auth_requested cp;
- cp.handle = ev->handle;
- hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
- sizeof(cp), &cp);
- } else {
+ if (!ev->status)
+ auth_requested = request_outgoing_auth(hdev, &conn->dst);
+ else
+ auth_requested = 0;
+
+ if (!auth_requested) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
--
1.7.2.3
^ permalink raw reply related
* [PATCH 1/3] Bluetooth: Simplify remote features callback function logic
From: johan.hedberg @ 2010-11-10 15:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg
From: Johan Hedberg <johan.hedberg@nokia.com>
The current remote and remote extended features event callbacks logic
can be made simpler by using a label and goto statements instead of the
current multiple levels of nested if statements.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
net/bluetooth/hci_event.c | 91 +++++++++++++++++++++++----------------------
1 files changed, 47 insertions(+), 44 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 84093b0..8430276 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1162,33 +1162,33 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
- if (conn) {
- if (!ev->status)
- memcpy(conn->features, ev->features, 8);
+ if (!conn)
+ goto unlock;
- if (conn->state == BT_CONFIG) {
- if (!ev->status && lmp_ssp_capable(hdev) &&
- lmp_ssp_capable(conn)) {
- struct hci_cp_read_remote_ext_features cp;
- cp.handle = ev->handle;
- cp.page = 0x01;
- hci_send_cmd(hdev,
- HCI_OP_READ_REMOTE_EXT_FEATURES,
- sizeof(cp), &cp);
- } else if (!ev->status && conn->out &&
- conn->sec_level == BT_SECURITY_HIGH) {
- struct hci_cp_auth_requested cp;
- cp.handle = ev->handle;
- hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
+ if (!ev->status)
+ memcpy(conn->features, ev->features, 8);
+
+ if (conn->state != BT_CONFIG)
+ goto unlock;
+
+ if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
+ struct hci_cp_read_remote_ext_features cp;
+ cp.handle = ev->handle;
+ cp.page = 0x01;
+ hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
sizeof(cp), &cp);
- } else {
- conn->state = BT_CONNECTED;
- hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
- }
- }
+ } else if (!ev->status && conn->out &&
+ conn->sec_level == BT_SECURITY_HIGH) {
+ struct hci_cp_auth_requested cp;
+ cp.handle = ev->handle;
+ hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
+ } else {
+ conn->state = BT_CONNECTED;
+ hci_proto_connect_cfm(conn, ev->status);
+ hci_conn_put(conn);
}
+unlock:
hci_dev_unlock(hdev);
}
@@ -1646,32 +1646,35 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
- if (conn) {
- if (!ev->status && ev->page == 0x01) {
- struct inquiry_entry *ie;
+ if (!conn)
+ goto unlock;
- if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
- ie->data.ssp_mode = (ev->features[0] & 0x01);
+ if (!ev->status && ev->page == 0x01) {
+ struct inquiry_entry *ie;
- conn->ssp_mode = (ev->features[0] & 0x01);
- }
+ if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
+ ie->data.ssp_mode = (ev->features[0] & 0x01);
- if (conn->state == BT_CONFIG) {
- if (!ev->status && hdev->ssp_mode > 0 &&
- conn->ssp_mode > 0 && conn->out &&
- conn->sec_level != BT_SECURITY_SDP) {
- struct hci_cp_auth_requested cp;
- cp.handle = ev->handle;
- hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
- sizeof(cp), &cp);
- } else {
- conn->state = BT_CONNECTED;
- hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
- }
- }
+ conn->ssp_mode = (ev->features[0] & 0x01);
+ }
+
+ if (conn->state != BT_CONFIG)
+ goto unlock;
+
+ if (!ev->status && hdev->ssp_mode > 0 &&
+ conn->ssp_mode > 0 && conn->out &&
+ conn->sec_level != BT_SECURITY_SDP) {
+ struct hci_cp_auth_requested cp;
+ cp.handle = ev->handle;
+ hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
+ sizeof(cp), &cp);
+ } else {
+ conn->state = BT_CONNECTED;
+ hci_proto_connect_cfm(conn, ev->status);
+ hci_conn_put(conn);
}
+unlock:
hci_dev_unlock(hdev);
}
--
1.7.2.3
^ permalink raw reply related
* [PATCHv2 7/7] simple-agent - add RequestApproval method for OOB pairing
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
test/simple-agent | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/test/simple-agent b/test/simple-agent
index f2cc3dd..43f03fe 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -69,6 +69,16 @@ class Agent(dbus.service.Object):
raise Rejected("Mode change by user")
@dbus.service.method("org.bluez.Agent",
+ in_signature="o", out_signature="")
+
+ def RequestApproval(self, device):
+ print "RequestApproval (%s)" % (device)
+ approve = raw_input("Approve pairing (yes/no): ")
+ if (approve == "yes"):
+ return
+ raise Rejected("Not approved")
+
+ @dbus.service.method("org.bluez.Agent",
in_signature="", out_signature="")
def Cancel(self):
print "Cancel"
--
1.7.1
^ permalink raw reply related
* [PATCHv2 6/7] Update DBus OOB API with RequestApproval method.
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
doc/oob-api.txt | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/doc/oob-api.txt b/doc/oob-api.txt
index b0f76db..7b93514 100644
--- a/doc/oob-api.txt
+++ b/doc/oob-api.txt
@@ -59,3 +59,17 @@ Methods void RegisterProvider(object provider)
Possible errors: org.bluez.Error.UpdateFailed
org.bluez.Error.NoProvider
org.bluez.Error.InProgress
+
+--------------------------------------------------------------------------------
+
+Service unique name
+Interface org.bluez.Agent
+Object path freely definable
+
+Methods void RequestApproval(object device)
+
+ This method gets called when the service daemon
+ needs to confirm incoming OOB pairing request.
+
+ Possible errors: org.bluez.Error.Rejected
+ org.bluez.Error.Canceled
--
1.7.1
^ permalink raw reply related
* [PATCHv2 5/7] Add approval request for incoming pairing requests with OOB mechanism
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
plugins/hciops.c | 42 ++++++++++++++++++++++++++++++--------
src/adapter.c | 7 ++++++
src/adapter.h | 3 ++
src/agent.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/agent.h | 3 ++
src/device.c | 22 ++++++++++++++++++++
src/device.h | 1 +
src/event.c | 41 +++++++++++++++++++++++++++++++++++++
src/event.h | 1 +
9 files changed, 169 insertions(+), 10 deletions(-)
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 88bcf15..d66e3d2 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -520,15 +520,8 @@ static void remote_oob_data_request(int index, void *ptr)
adapter = manager_find_adapter(&BDADDR(index));
device = adapter_find_device(adapter, da);
- if (device_has_oob_data(device)) {
- remote_oob_data_reply_cp cp;
-
- bacpy(&cp.bdaddr, dba);
- device_get_oob_data(device,cp.hash,cp.randomizer);
-
- hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY,
- REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
- } else
+ if (!device_has_oob_data(device)
+ || btd_event_user_approve(&BDADDR(index), dba))
hci_send_cmd(SK(index),
OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_NEG_REPLY, 6,
ptr);
@@ -2217,6 +2210,36 @@ static int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey)
return err;
}
+static int hciops_approve_reply(int index, bdaddr_t *bdaddr, gboolean approved)
+{
+ int err;
+ struct btd_adapter *adapter;
+ struct btd_device *device;
+ char da[18];
+
+ ba2str(bdaddr, da);
+ adapter = manager_find_adapter_by_id(index);
+ device = adapter_find_device(adapter, da);
+
+ if (approved) {
+ remote_oob_data_reply_cp cp;
+
+ bacpy(&cp.bdaddr, bdaddr);
+ device_get_oob_data(device,cp.hash,cp.randomizer);
+
+ err = hci_send_cmd(SK(index), OGF_LINK_CTL,
+ OCF_REMOTE_OOB_DATA_REPLY,
+ REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
+ } else
+ err = hci_send_cmd(SK(index), OGF_LINK_CTL,
+ OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, bdaddr);
+
+ if (err < 0)
+ err = -errno;
+
+ return err;
+}
+
static int hciops_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth)
{
struct hci_auth_info_req req;
@@ -2365,6 +2388,7 @@ static struct btd_adapter_ops hci_ops = {
.pincode_reply = hciops_pincode_reply,
.confirm_reply = hciops_confirm_reply,
.passkey_reply = hciops_passkey_reply,
+ .approve_reply = hciops_approve_reply,
.get_auth_info = hciops_get_auth_info,
.read_scan_enable = hciops_read_scan_enable,
.read_ssp_mode = hciops_read_ssp_mode,
diff --git a/src/adapter.c b/src/adapter.c
index 39a6514..ab680f3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3692,6 +3692,13 @@ int btd_adapter_passkey_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
return adapter_ops->passkey_reply(adapter->dev_id, bdaddr, passkey);
}
+int btd_adapter_approve_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
+ gboolean success)
+{
+ DBG("reply %u", success);
+ return adapter_ops->approve_reply(adapter->dev_id, bdaddr, success);
+}
+
int btd_adapter_get_auth_info(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint8_t *auth)
{
diff --git a/src/adapter.h b/src/adapter.h
index cc62865..cf66129 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -221,6 +221,7 @@ struct btd_adapter_ops {
int (*pincode_reply) (int index, bdaddr_t *bdaddr, const char *pin);
int (*confirm_reply) (int index, bdaddr_t *bdaddr, gboolean success);
int (*passkey_reply) (int index, bdaddr_t *bdaddr, uint32_t passkey);
+ int (*approve_reply) (int index, bdaddr_t *bdaddr, gboolean success);
int (*get_auth_info) (int index, bdaddr_t *bdaddr, uint8_t *auth);
int (*read_scan_enable) (int index);
int (*read_ssp_mode) (int index);
@@ -272,6 +273,8 @@ int btd_adapter_confirm_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
gboolean success);
int btd_adapter_passkey_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint32_t passkey);
+int btd_adapter_approve_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
+ gboolean success);
int btd_adapter_get_auth_info(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint8_t *auth);
diff --git a/src/agent.c b/src/agent.c
index 2ddfd6e..a4b26b6 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -55,7 +55,8 @@ typedef enum {
AGENT_REQUEST_CONFIRMATION,
AGENT_REQUEST_PINCODE,
AGENT_REQUEST_AUTHORIZE,
- AGENT_REQUEST_CONFIRM_MODE
+ AGENT_REQUEST_CONFIRM_MODE,
+ AGENT_REQUEST_APPROVAL
} agent_request_type_t;
struct agent {
@@ -693,6 +694,62 @@ failed:
return err;
}
+static int approval_request_new(struct agent_request *req,
+ const char *device_path)
+{
+ struct agent *agent = req->agent;
+
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
+ "org.bluez.Agent", "RequestApproval");
+ if (req->msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return -ENOMEM;
+ }
+
+ dbus_message_append_args(req->msg,
+ DBUS_TYPE_OBJECT_PATH, &device_path,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ return -EIO;
+ }
+
+ dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+
+ return 0;
+}
+
+int agent_request_approval (struct agent *agent, struct btd_device *device,
+ agent_cb cb, void *user_data, GDestroyNotify destroy)
+{
+ struct agent_request *req;
+ const gchar *dev_path = device_get_path(device);
+ int err;
+
+ if (agent->request)
+ return -EBUSY;
+
+ DBG("Calling Agent.RequestApproval: name=%s, path=%s", agent->name,
+ agent->path);
+
+ req = agent_request_new(agent, AGENT_REQUEST_APPROVAL, cb,
+ user_data, destroy);
+
+ err = approval_request_new(req, dev_path);
+ if (err < 0)
+ goto failed;
+
+ agent->request = req;
+
+ return 0;
+
+failed:
+ agent_request_free(req, FALSE);
+ return err;
+}
+
static int request_fallback(struct agent_request *req,
DBusPendingCallNotifyFunction function)
{
diff --git a/src/agent.h b/src/agent.h
index e184250..73dd531 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -64,6 +64,9 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
int agent_display_passkey(struct agent *agent, struct btd_device *device,
uint32_t passkey);
+int agent_request_approval (struct agent *agent, struct btd_device *device,
+ agent_cb cb, void *user_data, GDestroyNotify destroy);
+
int agent_cancel(struct agent *agent);
gboolean agent_is_busy(struct agent *agent, void *user_data);
diff --git a/src/device.c b/src/device.c
index 24fd44d..a507fe8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2245,6 +2245,21 @@ static void passkey_cb(struct agent *agent, DBusError *err,
device->authr->agent = NULL;
}
+static void approve_cb(struct agent *agent, DBusError *err, void *data)
+{
+ struct authentication_req *auth = data;
+ struct btd_device *device = auth->device;
+
+ /* No need to reply anything if the authentication already failed */
+ if (auth->cb == NULL)
+ return;
+
+ ((agent_cb) auth->cb)(agent, err, device);
+
+ device->authr->cb = NULL;
+ device->authr->agent = NULL;
+}
+
int device_request_authentication(struct btd_device *device, auth_type_t type,
uint32_t passkey, void *cb)
{
@@ -2283,6 +2298,10 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
case AUTH_TYPE_NOTIFY:
err = agent_display_passkey(agent, device, passkey);
break;
+ case AUTH_TYPE_APPROVE:
+ err = agent_request_approval (agent, device, approve_cb, auth,
+ NULL);
+ break;
case AUTH_TYPE_AUTO:
err = 0;
break;
@@ -2324,6 +2343,9 @@ static void cancel_authentication(struct authentication_req *auth)
case AUTH_TYPE_PASSKEY:
((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
break;
+ case AUTH_TYPE_APPROVE:
+ ((agent_cb) auth->cb)(agent, &err, device);
+ break;
case AUTH_TYPE_NOTIFY:
case AUTH_TYPE_AUTO:
/* User Notify/Auto doesn't require any reply */
diff --git a/src/device.h b/src/device.h
index b62cdc5..2da3311 100644
--- a/src/device.h
+++ b/src/device.h
@@ -33,6 +33,7 @@ typedef enum {
AUTH_TYPE_CONFIRM,
AUTH_TYPE_NOTIFY,
AUTH_TYPE_AUTO,
+ AUTH_TYPE_APPROVE
} auth_type_t;
struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
diff --git a/src/event.c b/src/event.c
index 5a5a288..957a17d 100644
--- a/src/event.c
+++ b/src/event.c
@@ -175,6 +175,18 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
btd_adapter_passkey_reply(adapter, &bdaddr, passkey);
}
+static void approve_cb(struct agent *agent, DBusError *err, void *user_data)
+{
+ struct btd_device *device = user_data;
+ struct btd_adapter *adapter = device_get_adapter(device);
+ bdaddr_t bdaddr;
+ gboolean approve = (err == NULL) ? TRUE : FALSE;
+
+ device_get_address(device, &bdaddr);
+
+ btd_adapter_approve_reply(adapter, &bdaddr, approve);
+}
+
int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
{
struct btd_adapter *adapter;
@@ -264,6 +276,35 @@ int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
passkey, NULL);
}
+int btd_event_user_approve(bdaddr_t *sba, bdaddr_t *dba)
+{
+ struct btd_adapter *adapter;
+ struct btd_device *device;
+ struct agent *agent;
+ uint8_t cap;
+
+ if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
+ return -ENODEV;
+
+ agent = device_get_agent(device);
+ if (!agent)
+ return -ENODEV;
+
+ cap = agent_get_io_capability(agent);
+
+ /* If initiator or agent has no input capability approve immediately. */
+ if (device_is_bonding(device, NULL) || cap == 0x00 || cap == 0x03) {
+ bdaddr_t bdaddr;
+
+ device_get_address(device, &bdaddr);
+ btd_adapter_approve_reply(adapter, &bdaddr, TRUE);
+ return 0;
+ }
+
+ return device_request_authentication(device, AUTH_TYPE_APPROVE, 0,
+ approve_cb);
+}
+
void btd_event_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
uint8_t status)
{
diff --git a/src/event.h b/src/event.h
index a3e7dda..c1ea2ef 100644
--- a/src/event.h
+++ b/src/event.h
@@ -42,6 +42,7 @@ int btd_event_set_io_cap(bdaddr_t *local, bdaddr_t *remote,
int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
int btd_event_user_passkey(bdaddr_t *sba, bdaddr_t *dba);
int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
+int btd_event_user_approve(bdaddr_t *sba, bdaddr_t *dba);
int btd_event_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
uint8_t *key, uint8_t key_type,
int pin_length, uint8_t old_key_type);
--
1.7.1
^ permalink raw reply related
* [PATCHv2 4/7] Add simple-oobprovider for testing.
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
test/simple-oobprovider | 61 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
create mode 100755 test/simple-oobprovider
diff --git a/test/simple-oobprovider b/test/simple-oobprovider
new file mode 100755
index 0000000..8e89fdb
--- /dev/null
+++ b/test/simple-oobprovider
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+# Copyright (C) 2010 ST-Ericsson SA
+# Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+
+import gobject
+
+import sys
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+
+class NoOobData(dbus.DBusException):
+ _dbus_error_name = "org.bluez.Error.NoData"
+
+
+class Provider(dbus.service.Object):
+
+ remotedata = None
+
+ @dbus.service.method("org.bluez.OOB",
+ in_signature="s", out_signature="ayay")
+
+ def RequestRemoteOobData(self, device):
+ print "RequestRemoteOobData for %s" % (device)
+ if (self.remotedata != None):
+ return self.remotedata
+ raise NoOobData("No OOB data present")
+
+if __name__ == '__main__':
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+ bus = dbus.SystemBus()
+
+ manager = dbus.Interface(bus.get_object("org.bluez", "/"),
+ "org.bluez.Manager")
+
+ adapter_path = manager.DefaultAdapter()
+ adapter = dbus.Interface(bus.get_object("org.bluez",
+ adapter_path), "org.bluez.Adapter")
+
+ oob = dbus.Interface(bus.get_object("org.bluez", "/org/bluez"),
+ "org.bluez.OOB")
+
+ path = "/test/oobprovider"
+ provider = Provider(bus, path)
+
+ mainloop = gobject.MainLoop()
+
+ oob.RegisterProvider(path)
+
+ print "Local data for %s:" % (adapter_path)
+ print oob.UpdateLocalOobData(adapter_path)
+
+ provider.remotedata = input("Provide remote data (in python syntax):\n")
+
+ print "You may try pairing now"
+
+ mainloop.run()
+
+ #adapter.UnregisterProvider(path)
+ #print "Provider unregistered"
--
1.7.1
^ permalink raw reply related
* [PATCHv2 3/7] Add DBus OOB API documentation.
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
Makefile.am | 2 +-
doc/oob-api.txt | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletions(-)
create mode 100644 doc/oob-api.txt
diff --git a/Makefile.am b/Makefile.am
index 1f8f7fb..9098084 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -358,7 +358,7 @@ EXTRA_DIST += doc/manager-api.txt \
doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
doc/serial-api.txt doc/network-api.txt \
doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
- doc/hfp-api.txt doc/assigned-numbers.txt
+ doc/hfp-api.txt doc/assigned-numbers.txt doc/oob-api.txt
AM_YFLAGS = -d
diff --git a/doc/oob-api.txt b/doc/oob-api.txt
new file mode 100644
index 0000000..b0f76db
--- /dev/null
+++ b/doc/oob-api.txt
@@ -0,0 +1,61 @@
+BlueZ D-Bus OOB API description
+*******************************
+
+Copyright (C) 2010 ST-Ericsson SA
+
+Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+
+OOB hierarchy
+=================
+
+Service unique name
+Interface org.bluez.OOB
+Object path freely definable
+
+Methods array{byte} hash, array{byte} randomizer
+ RequestRemoteOobData(object device)
+
+ This method gets called when the service daemon needs to
+ get device's hash and randomizer for an OOB
+ authentication. Each array should be 16 bytes long.
+
+ Possible errors: org.bluez.Error.NoData
+
+ void Deactivate()
+
+ This method gets called when DBus plug-in for OOB was
+ deactivated. There is no need to unregister provider,
+ because when this method gets called it has already been
+ unregistered.
+
+--------------------------------------------------------------------------------
+
+Service org.bluez
+Interface org.bluez.OOB
+Object path /org/bluez
+
+Methods void RegisterProvider(object provider)
+
+ This method registers provider for DBus OOB plug-in.
+ When provider is successfully registered plug-in becomes
+ active. Only one provider can be registered at time.
+
+ Possible errors: org.bluez.Error.AlreadyExists
+
+ void UnregisterProvider(object provider)
+
+ This method unregisters provider for DBus OOB plug-in.
+
+ Possible errors: org.bluez.Error.DoesNotExist
+
+
+ array{byte} hash, array{byte} randomizer
+ UpdateLocalOobData(object adapter)
+
+ This method generates new local OOB data for adapter.
+ Return value is pair of arrays 16 bytes each. Only
+ registered provider should call this method.
+
+ Possible errors: org.bluez.Error.UpdateFailed
+ org.bluez.Error.NoProvider
+ org.bluez.Error.InProgress
--
1.7.1
^ permalink raw reply related
* [PATCHv2 2/7] Add DBus OOB plugin.
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
Makefile.am | 5 +
acinclude.m4 | 6 +
plugins/dbusoob.c | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 364 insertions(+), 0 deletions(-)
create mode 100644 plugins/dbusoob.c
diff --git a/Makefile.am b/Makefile.am
index a61e754..1f8f7fb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -216,6 +216,11 @@ builtin_modules += maemo6
builtin_sources += plugins/maemo6.c
endif
+if DBUSOOBPLUGIN
+builtin_modules += dbusoob
+builtin_sources += plugins/dbusoob.c
+endif
+
sbin_PROGRAMS += src/bluetoothd
src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
diff --git a/acinclude.m4 b/acinclude.m4
index 287f07d..a52d063 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -193,6 +193,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
configfiles_enable=yes
telephony_driver=dummy
maemo6_enable=no
+ dbusoob_enable=no
AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization]), [
optimization_enable=${enableval}
@@ -316,6 +317,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
maemo6_enable=${enableval}
])
+ AC_ARG_ENABLE(dbusoob, AC_HELP_STRING([--enable-dbusoob], [compile with DBUS OOB plugin]), [
+ dbusoob_enable=${enableval}
+ ])
+
AC_ARG_ENABLE(hal, AC_HELP_STRING([--enable-hal], [Use HAL to determine adapter class]), [
hal_enable=${enableval}
])
@@ -372,4 +377,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(UDEVRULES, test "${udevrules_enable}" = "yes")
AM_CONDITIONAL(CONFIGFILES, test "${configfiles_enable}" = "yes")
AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
+ AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
])
diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c
new file mode 100644
index 0000000..7fc0c52
--- /dev/null
+++ b/plugins/dbusoob.c
@@ -0,0 +1,353 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 ST-Ericsson SA
+ *
+ * Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ * 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 <errno.h>
+#include <gdbus.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/sdp.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "manager.h"
+#include "device.h"
+#include "adapter.h"
+#include "dbus-common.h"
+#include "event.h"
+#include "error.h"
+#include "oob.h"
+
+#define REQUEST_TIMEOUT (10 * 1000) /* 10 seconds */
+#define OOB_INTERFACE "org.bluez.OOB"
+#define OOB_PATH "/org/bluez"
+
+struct oob_provider {
+ char *name;
+ char *path;
+
+ struct btd_adapter *adapter;
+ DBusMessage *msg;
+
+ guint listener_id;
+ gboolean exited;
+};
+
+static struct oob_provider *provider = NULL;
+static DBusConnection *connection = NULL;
+static struct oob_plugin dbusoob;
+
+static void destroy_provider(void)
+{
+ if (!provider->exited)
+ g_dbus_remove_watch(connection, provider->listener_id);
+
+ if (provider->msg)
+ dbus_message_unref(provider->msg);
+
+ g_free(provider->name);
+ g_free(provider->path);
+ g_free(provider);
+ provider = NULL;
+
+ oob_deactivate_plugin(&dbusoob);
+}
+
+static void provider_exited(DBusConnection *conn, void *user_data)
+{
+ DBG("Provider exited without calling Unregister");
+
+ provider->exited = TRUE;
+ destroy_provider();
+}
+
+static void create_provider(const char *path, const char *name)
+{
+ provider = g_new(struct oob_provider, 1);
+ provider->path = g_strdup(path);
+ provider->name = g_strdup(name);
+ provider->adapter = NULL;
+ provider->msg = NULL;
+ provider->exited = FALSE;
+ provider->listener_id = g_dbus_add_disconnect_watch(connection, name,
+ provider_exited, NULL, NULL);
+
+ oob_activate_plugin(&dbusoob);
+}
+
+static void request_remote_data_reply(DBusPendingCall *call, void *data)
+{
+ DBusMessage *msg;
+ DBusError err;
+ struct btd_device *device = data;
+ uint8_t *hash = NULL;
+ uint8_t *randomizer = NULL;
+ int32_t hlen, rlen;
+
+ msg = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, msg)) {
+ error("Provider replied with an error: %s, %s", err.name,
+ err.message);
+ dbus_error_free(&err);
+ goto error;
+ }
+
+ dbus_error_init(&err);
+ if (!dbus_message_get_args(msg, &err,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hlen,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &rlen,
+ DBUS_TYPE_INVALID) || hlen != 16 || rlen != 16) {
+ error("RequestRemoteOobData reply signature error: %s, %s",
+ err.name, err.message);
+ dbus_error_free(&err);
+ hash = NULL;
+ randomizer = NULL;
+ }
+
+error:
+ dbus_message_unref(msg);
+ dbus_pending_call_unref(call);
+
+ device_set_oob_data(device, hash, randomizer);
+}
+
+static gboolean request_remote_data(struct btd_device *device)
+{
+ DBusMessage* msg;
+ DBusPendingCall *call = NULL;
+ const gchar *path;
+ gboolean ret = FALSE;
+
+ msg = dbus_message_new_method_call(provider->name, provider->path,
+ OOB_INTERFACE, "RequestRemoteOobData");
+
+ if (!msg) {
+ error("Couldn't allocate D-Bus message");
+ goto error;
+ }
+
+ path = device_get_path(device);
+
+ if (!dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID)) {
+ error ("Couldn't append arguments");
+ goto error;
+ }
+
+ if (!dbus_connection_send_with_reply(connection, msg, &call,
+ REQUEST_TIMEOUT)) {
+ error("D-Bus send failed");
+ goto error;
+ }
+
+ if (!dbus_pending_call_set_notify(call, request_remote_data_reply,
+ device, NULL)) {
+ error("Couldn't set reply notification.");
+ dbus_pending_call_unref(call);
+ goto error;
+ }
+
+ ret = TRUE;
+
+error:
+ if (msg)
+ dbus_message_unref(msg);
+
+ return ret;
+}
+
+static void local_data_updated(bdaddr_t *ba, uint8_t *hash, uint8_t *randomizer)
+{
+ struct DBusMessage *reply;
+ bdaddr_t addr;
+
+ if (!provider)
+ return;
+
+ adapter_get_address(provider->adapter, &addr);
+ if (bacmp(ba, &addr))
+ return;
+
+ if (hash && randomizer)
+ reply = g_dbus_create_reply(provider->msg,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, 16,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, 16,
+ DBUS_TYPE_INVALID);
+ else
+ reply = g_dbus_create_error(provider->msg,
+ ERROR_INTERFACE ".UpdateFailed",
+ "Failed to update local OOB.");
+
+ dbus_message_unref(provider->msg);
+ provider->msg = NULL;
+ provider->adapter = NULL;
+
+ if (!reply) {
+ error("Couldn't allocate D-Bus message");
+ return;
+ }
+
+ if (!g_dbus_send_message(connection, reply))
+ error("D-Bus send failed");
+}
+
+static DBusMessage *update_local_data(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *name;
+ const char *path;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return NULL;
+
+ name = dbus_message_get_sender(msg);
+ if (!provider || strcmp(provider->name, name) != 0)
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".NoProvider",
+ "Not OOB provider or no provider registered");
+
+ if (provider->msg)
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
+ "Another request in progress.");
+
+ provider->adapter = manager_find_adapter_by_path(path);
+ if (!provider->adapter)
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".UpdateFailed",
+ "No adapter with given address found");
+
+ if (btd_adapter_read_local_oob_data(provider->adapter))
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".UpdateFailed",
+ "HCI request failed");
+
+ provider->msg = dbus_message_ref(msg);
+ return NULL;
+}
+
+static void plugin_deactivated(void)
+{
+ DBusMessage *msg;
+
+ msg = dbus_message_new_method_call(provider->name, provider->path,
+ OOB_INTERFACE, "Deactivate");
+
+ if (!msg)
+ error("Couldn't allocate D-Bus message");
+ else if (!g_dbus_send_message(connection, msg))
+ error("D-Bus send failed");
+
+ destroy_provider();
+}
+
+static DBusMessage *register_provider(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *path;
+ const char *name;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return NULL;
+
+ if (provider)
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExists",
+ "OOB provider already registered");
+
+ name = dbus_message_get_sender(msg);
+ create_provider(path, name);
+
+ DBG("OOB provider registered at %s:%s", provider->name, provider->path);
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_provider(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *path;
+ const char *name;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return NULL;
+
+ name = dbus_message_get_sender(msg);
+
+ if (!provider || !g_str_equal(provider->path, path)
+ || !g_str_equal(provider->name, name))
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
+ "No such OOB provider registered");
+
+ DBG("OOB provider (%s:%s) unregistered", provider->name, provider->path);
+
+ destroy_provider();
+
+ return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable oob_methods[] = {
+ { "RegisterProvider", "o", "", register_provider},
+ { "UnregisterProvider", "o", "", unregister_provider},
+ { "UpdateLocalOobData", "o", "ayay", update_local_data,
+ G_DBUS_METHOD_FLAG_ASYNC},
+ { }
+};
+
+static gboolean register_on_dbus(void)
+{
+ connection = get_dbus_connection();
+
+ if (!g_dbus_register_interface(connection, OOB_PATH, OOB_INTERFACE,
+ oob_methods, NULL, NULL, NULL, NULL)) {
+ error("OOB interface init failed on path %s", OOB_PATH);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int dbusoob_init(void)
+{
+ DBG("Setup dbusoob plugin");
+
+ dbusoob.request_remote_data = request_remote_data;
+ dbusoob.local_data_updated = local_data_updated;
+ dbusoob.plugin_deactivated = plugin_deactivated;
+
+ return register_on_dbus();
+}
+
+static void dbusoob_exit(void)
+{
+ DBG("Cleanup dbusoob plugin");
+ oob_deactivate_plugin(&dbusoob);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, dbusoob_init, dbusoob_exit)
--
1.7.1
^ permalink raw reply related
* [PATCHv2 1/7] Add support for Out of Band (OOB) association model.
From: Szymon Janc @ 2010-11-10 13:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1289395877-12384-1-git-send-email-szymon.janc@tieto.com>
---
Makefile.am | 3 +-
lib/hci.h | 3 ++
plugins/hciops.c | 72 +++++++++++++++++++++++++++++++++++++++++---------
src/adapter.c | 7 ++++-
src/adapter.h | 3 ++
src/device.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/device.h | 12 ++++++++
src/event.c | 75 +++++++++++++++++++++++++++++++++++++++-------------
src/event.h | 3 +-
src/oob.c | 61 +++++++++++++++++++++++++++++++++++++++++++
src/oob.h | 47 +++++++++++++++++++++++++++++++++
11 files changed, 326 insertions(+), 36 deletions(-)
create mode 100644 src/oob.c
create mode 100644 src/oob.h
diff --git a/Makefile.am b/Makefile.am
index da308a7..a61e754 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -238,7 +238,8 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/adapter.h src/adapter.c \
src/device.h src/device.c \
src/dbus-common.c src/dbus-common.h \
- src/event.h src/event.c
+ src/event.h src/event.c \
+ src/oob.c
src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
@CAPNG_LIBS@ -ldl -lrt
src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
diff --git a/lib/hci.h b/lib/hci.h
index 0cb120f..409abd9 100644
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -524,6 +524,9 @@ typedef struct {
#define OCF_REMOTE_OOB_DATA_NEG_REPLY 0x0033
+#define OOB_DATA_NOT_PRESENT 0x00
+#define OOB_DATA_PRESENT 0x01
+
#define OCF_IO_CAPABILITY_NEG_REPLY 0x0034
typedef struct {
bdaddr_t bdaddr;
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 829011a..88bcf15 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -3,6 +3,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2010 ST-Ericsson SA
*
* 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
@@ -47,6 +48,7 @@
#include "event.h"
#include "device.h"
#include "manager.h"
+#include "oob.h"
#define HCI_REQ_TIMEOUT 5000
@@ -509,20 +511,41 @@ static void user_passkey_notify(int index, void *ptr)
static void remote_oob_data_request(int index, void *ptr)
{
- hci_send_cmd(SK(index), OGF_LINK_CTL,
- OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, ptr);
+ bdaddr_t *dba = ptr;
+ struct btd_adapter *adapter;
+ struct btd_device *device;
+ char da[18];
+
+ ba2str(dba, da);
+ adapter = manager_find_adapter(&BDADDR(index));
+ device = adapter_find_device(adapter, da);
+
+ if (device_has_oob_data(device)) {
+ remote_oob_data_reply_cp cp;
+
+ bacpy(&cp.bdaddr, dba);
+ device_get_oob_data(device,cp.hash,cp.randomizer);
+
+ hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY,
+ REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
+ } else
+ hci_send_cmd(SK(index),
+ OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_NEG_REPLY, 6,
+ ptr);
}
static void io_capa_request(int index, void *ptr)
{
bdaddr_t *dba = ptr;
char sa[18], da[18];
- uint8_t cap, auth;
ba2str(&BDADDR(index), sa); ba2str(dba, da);
info("io_capa_request (sba=%s, dba=%s)", sa, da);
- if (btd_event_get_io_cap(&BDADDR(index), dba, &cap, &auth) < 0) {
+ /* If failed to establish IO capabilities then send negative reply
+ * immediately. Positive reply will be sent when IO capabilities are
+ * established. */
+ if (btd_event_request_io_cap(&BDADDR(index), dba)) {
io_capability_neg_reply_cp cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, dba);
@@ -530,15 +553,6 @@ static void io_capa_request(int index, void *ptr)
hci_send_cmd(SK(index), OGF_LINK_CTL,
OCF_IO_CAPABILITY_NEG_REPLY,
IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp);
- } else {
- io_capability_reply_cp cp;
- memset(&cp, 0, sizeof(cp));
- bacpy(&cp.bdaddr, dba);
- cp.capability = cap;
- cp.oob_data = 0x00;
- cp.authentication = auth;
- hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY,
- IO_CAPABILITY_REPLY_CP_SIZE, &cp);
}
}
@@ -748,6 +762,15 @@ static void read_scan_complete(int index, uint8_t status, void *ptr)
adapter_mode_changed(adapter, rp->enable);
}
+static void read_local_oob_data_complete(bdaddr_t *local, uint8_t status,
+ read_local_oob_data_rp *rp)
+{
+ if (status)
+ oob_local_data_updated(local, NULL, NULL);
+ else
+ oob_local_data_updated(local, rp->hash, rp->randomizer);
+}
+
static inline void cmd_complete(int index, void *ptr)
{
evt_cmd_complete *evt = ptr;
@@ -808,6 +831,10 @@ static inline void cmd_complete(int index, void *ptr)
ptr += sizeof(evt_cmd_complete);
adapter_update_tx_power(&BDADDR(index), status, ptr);
break;
+ case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA):
+ ptr += sizeof(evt_cmd_complete);
+ read_local_oob_data_complete(&BDADDR(index), status, ptr);
+ break;
};
}
@@ -2280,6 +2307,24 @@ static int hciops_get_remote_version(int index, uint16_t handle,
return 0;
}
+static int hciops_read_local_oob_data(int index)
+{
+ int dd;
+ int err = 0;
+
+ dd = hci_open_dev(index);
+ if (dd < 0)
+ return -EIO;
+
+ err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA, 0, 0);
+ if (err < 0)
+ err = -errno;
+
+ hci_close_dev(dd);
+
+ return err;
+}
+
static struct btd_adapter_ops hci_ops = {
.setup = hciops_setup,
.cleanup = hciops_cleanup,
@@ -2326,6 +2371,7 @@ static struct btd_adapter_ops hci_ops = {
.write_le_host = hciops_write_le_host,
.get_remote_version = hciops_get_remote_version,
.encrypt_link = hciops_encrypt_link,
+ .read_local_oob_data = hciops_read_local_oob_data,
};
static int hciops_init(void)
diff --git a/src/adapter.c b/src/adapter.c
index 31014e5..39a6514 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3265,7 +3265,7 @@ void adapter_remove_connection(struct btd_adapter *adapter,
/* clean pending HCI cmds */
device_get_address(device, &bdaddr);
- if (device_is_authenticating(device))
+ if (device_is_authenticating(device) || device_has_oob_data(device))
device_cancel_authentication(device, TRUE);
if (device_is_temporary(device)) {
@@ -3738,3 +3738,8 @@ int btd_adapter_encrypt_link(struct btd_adapter *adapter, bdaddr_t *bdaddr,
{
return adapter_ops->encrypt_link(adapter->dev_id, bdaddr, cb, user_data);
}
+
+int btd_adapter_read_local_oob_data(struct btd_adapter *adapter)
+{
+ return adapter_ops->read_local_oob_data(adapter->dev_id);
+}
diff --git a/src/adapter.h b/src/adapter.h
index 8019cfc..cc62865 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -229,6 +229,7 @@ struct btd_adapter_ops {
gboolean delayed);
int (*encrypt_link) (int index, bdaddr_t *bdaddr, bt_hci_result_t cb,
gpointer user_data);
+ int (*read_local_oob_data) (int index);
};
int btd_register_adapter_ops(struct btd_adapter_ops *ops, gboolean priority);
@@ -289,3 +290,5 @@ int btd_adapter_get_remote_version(struct btd_adapter *adapter,
int btd_adapter_encrypt_link(struct btd_adapter *adapter, bdaddr_t *bdaddr,
bt_hci_result_t cb, gpointer user_data);
+
+int btd_adapter_read_local_oob_data(struct btd_adapter *adapter);
diff --git a/src/device.c b/src/device.c
index 7c421e3..24fd44d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2006-2010 Nokia Corporation
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2010 ST-Ericsson SA
*
*
* This program is free software; you can redistribute it and/or modify
@@ -59,6 +60,7 @@
#include "sdp-xml.h"
#include "storage.h"
#include "btio.h"
+#include "oob.h"
#define DEFAULT_XML_BUF_SIZE 1024
#define DISCONNECT_TIMER 2
@@ -132,6 +134,9 @@ struct btd_device {
uint8_t cap;
uint8_t auth;
+ uint8_t local_cap;
+ uint8_t local_auth;
+
uint16_t handle; /* Connection handle */
/* Whether were creating a security mode 3 connection */
@@ -149,6 +154,12 @@ struct btd_device {
gboolean has_debug_key;
uint8_t debug_key[16];
+
+ /* For OOB association model */
+ void (*oob_request_cb)(struct btd_device *device);
+ gboolean has_oob_data;
+ uint8_t hash[16];
+ uint8_t randomizer[16];
};
static uint16_t uuid_list[] = {
@@ -829,6 +840,69 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
return NULL;
}
+void device_set_oob_data(struct btd_device *device, uint8_t *hash,
+ uint8_t *randomizer)
+{
+ if (!device)
+ return;
+
+ if (hash && randomizer) {
+ memcpy(device->hash, hash, 16);
+ memcpy(device->randomizer, randomizer, 16);
+ device->has_oob_data = TRUE;
+ }
+
+ if (device->oob_request_cb) {
+ device->oob_request_cb(device);
+ device->oob_request_cb = NULL;
+ }
+}
+
+gboolean device_get_oob_data(struct btd_device *device, uint8_t *hash,
+ uint8_t *randomizer)
+{
+ if (!device || !device->has_oob_data)
+ return FALSE;
+
+ memcpy(hash, device->hash, 16);
+ memcpy(randomizer, device->randomizer, 16);
+
+ return TRUE;
+}
+
+gboolean device_has_oob_data(struct btd_device *device)
+{
+ return device && device->has_oob_data;
+}
+
+gboolean device_request_oob_data(struct btd_device *device, void *cb)
+{
+ if (!device)
+ return FALSE;
+
+ device->oob_request_cb = cb;
+ return oob_request_remote_data(device);
+}
+
+void device_set_local_auth_cap(struct btd_device *device, uint8_t auth,
+ uint8_t cap)
+{
+ if (!device)
+ return;
+
+ device->local_auth = auth;
+ device->local_cap = cap;
+}
+void device_get_local_auth_cap(struct btd_device *device, uint8_t *auth,
+ uint8_t *cap)
+{
+ if (!device)
+ return;
+
+ *auth = device->local_auth;
+ *cap = device->local_cap;
+}
+
static GDBusMethodTable device_methods[] = {
{ "GetProperties", "", "a{sv}", get_properties },
{ "SetProperty", "sv", "", set_property },
@@ -2264,6 +2338,8 @@ void device_cancel_authentication(struct btd_device *device, gboolean aborted)
{
struct authentication_req *auth = device->authr;
+ device->has_oob_data = FALSE;
+
if (!auth)
return;
diff --git a/src/device.h b/src/device.h
index b570bd1..b62cdc5 100644
--- a/src/device.h
+++ b/src/device.h
@@ -4,6 +4,7 @@
*
* Copyright (C) 2006-2010 Nokia Corporation
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2010 ST-Ericsson SA
*
*
* This program is free software; you can redistribute it and/or modify
@@ -89,6 +90,17 @@ void device_remove_connection(struct btd_device *device, DBusConnection *conn,
gboolean device_has_connection(struct btd_device *device, uint16_t handle);
void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
+void device_set_oob_data(struct btd_device *device, uint8_t *hash,
+ uint8_t *randomizer);
+gboolean device_get_oob_data(struct btd_device *device, uint8_t *hash,
+ uint8_t *randomizer);
+gboolean device_has_oob_data(struct btd_device *device);
+gboolean device_request_oob_data(struct btd_device *device, void *cb);
+void device_set_local_auth_cap(struct btd_device *device, uint8_t auth,
+ uint8_t cap);
+void device_get_local_auth_cap(struct btd_device *device, uint8_t *auth,
+ uint8_t *cap);
+
typedef void (*disconnect_watch) (struct btd_device *device, gboolean removal,
void *user_data);
diff --git a/src/event.c b/src/event.c
index e943c63..5a5a288 100644
--- a/src/event.c
+++ b/src/event.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2006-2010 Nokia Corporation
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2010 ST-Ericsson SA
*
*
* This program is free software; you can redistribute it and/or modify
@@ -274,7 +275,7 @@ void btd_event_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return;
- if (!device_is_authenticating(device)) {
+ if (!device_is_authenticating(device) && !device_has_oob_data(device)) {
/* This means that there was no pending PIN or SSP token
* request from the controller, i.e. this is not a new
* pairing */
@@ -756,26 +757,56 @@ void btd_event_returned_link_key(bdaddr_t *local, bdaddr_t *peer)
device_set_paired(device, TRUE);
}
-int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
- uint8_t *cap, uint8_t *auth)
+static void btd_event_io_cap_reply(struct btd_device *device)
+{
+ io_capability_reply_cp cp;
+ int dev;
+ struct btd_adapter *adapter = device_get_adapter(device);
+ uint16_t dev_id = adapter_get_dev_id(adapter);
+
+ dev = hci_open_dev(dev_id);
+ if (dev < 0) {
+ error("hci_open_dev(%d): %s (%d)", dev_id,
+ strerror(errno), errno);
+ return;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+ device_get_address(device, &cp.bdaddr);
+ device_get_local_auth_cap(device, &cp.authentication, &cp.capability);
+ cp.oob_data = device_has_oob_data(device)
+ ? OOB_DATA_PRESENT : OOB_DATA_NOT_PRESENT;
+
+ DBG("final capabilities reply is cap=0x%02x, auth=0x%02x, oob=0x%02x",
+ cp.capability, cp.authentication, cp.oob_data);
+
+ hci_send_cmd(dev, OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY,
+ IO_CAPABILITY_REPLY_CP_SIZE, &cp);
+
+ hci_close_dev(dev);
+}
+
+int btd_event_request_io_cap(bdaddr_t *local, bdaddr_t *remote)
{
struct btd_adapter *adapter;
struct btd_device *device;
struct agent *agent = NULL;
uint8_t agent_cap;
int err;
+ uint8_t cap;
+ uint8_t auth;
if (!get_adapter_and_device(local, remote, &adapter, &device, TRUE))
return -ENODEV;
- err = btd_adapter_get_auth_info(adapter, remote, auth);
+ err = btd_adapter_get_auth_info(adapter, remote, &auth);
if (err < 0)
return err;
- DBG("initial authentication requirement is 0x%02x", *auth);
+ DBG("initial authentication requirement is 0x%02x", auth);
- if (*auth == 0xff)
- *auth = device_get_auth(device);
+ if (auth == 0xff)
+ auth = device_get_auth(device);
/* Check if the adapter is not pairable and if there isn't a bonding
* in progress */
@@ -784,11 +815,11 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
if (device_get_auth(device) < 0x02) {
DBG("Allowing no bonding in non-bondable mode");
/* No input, no output */
- *cap = 0x03;
+ cap = 0x03;
/* Kernel defaults to general bonding and so
* overwrite for this special case. Otherwise
* non-pairable test cases will fail. */
- *auth = 0x00;
+ auth = 0x00;
goto done;
}
return -EPERM;
@@ -804,13 +835,13 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
}
/* No agent available, and no bonding case */
- if (*auth == 0x00 || *auth == 0x04) {
+ if (auth == 0x00 || auth == 0x04) {
DBG("Allowing no bonding without agent");
/* No input, no output */
- *cap = 0x03;
+ cap = 0x03;
/* If kernel defaults to general bonding, set it
* back to no bonding */
- *auth = 0x00;
+ auth = 0x00;
goto done;
}
@@ -820,7 +851,7 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
agent_cap = agent_get_io_capability(agent);
- if (*auth == 0x00 || *auth == 0x04) {
+ if (auth == 0x00 || auth == 0x04) {
/* If remote requests dedicated bonding follow that lead */
if (device_get_auth(device) == 0x02 ||
device_get_auth(device) == 0x03) {
@@ -829,9 +860,9 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
* then require it, otherwise don't */
if (device_get_cap(device) == 0x03 ||
agent_cap == 0x03)
- *auth = 0x02;
+ auth = 0x02;
else
- *auth = 0x03;
+ auth = 0x03;
}
/* If remote indicates no bonding then follow that. This
@@ -839,7 +870,7 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
* as default. */
if (device_get_auth(device) == 0x00 ||
device_get_auth(device) == 0x01)
- *auth = 0x00;
+ auth = 0x00;
/* If remote requires MITM then also require it, unless
* our IO capability is NoInputNoOutput (so some
@@ -847,13 +878,19 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
if (device_get_auth(device) != 0xff &&
(device_get_auth(device) & 0x01) &&
agent_cap != 0x03)
- *auth |= 0x01;
+ auth |= 0x01;
}
- *cap = agent_get_io_capability(agent);
+ cap = agent_get_io_capability(agent);
done:
- DBG("final authentication requirement is 0x%02x", *auth);
+ DBG("final authentication requirement is 0x%02x", auth);
+
+ device_set_local_auth_cap(device, auth, cap);
+
+ /* If failed to request remote OOB data then reply immediately. */
+ if (!device_request_oob_data(device, btd_event_io_cap_reply))
+ btd_event_io_cap_reply(device);
return 0;
}
diff --git a/src/event.h b/src/event.h
index 4a7b9c9..a3e7dda 100644
--- a/src/event.h
+++ b/src/event.h
@@ -36,8 +36,7 @@ void btd_event_le_set_scan_enable_complete(bdaddr_t *local, uint8_t status);
void btd_event_write_simple_pairing_mode_complete(bdaddr_t *local);
void btd_event_read_simple_pairing_mode_complete(bdaddr_t *local, void *ptr);
void btd_event_returned_link_key(bdaddr_t *local, bdaddr_t *peer);
-int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
- uint8_t *cap, uint8_t *auth);
+int btd_event_request_io_cap(bdaddr_t *local, bdaddr_t *remote);
int btd_event_set_io_cap(bdaddr_t *local, bdaddr_t *remote,
uint8_t cap, uint8_t auth);
int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
diff --git a/src/oob.c b/src/oob.c
new file mode 100644
index 0000000..cc20c67
--- /dev/null
+++ b/src/oob.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 ST-Ericsson SA
+ *
+ * Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ * 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
+ *
+ */
+
+#include <glib.h>
+#include "manager.h"
+#include "adapter.h"
+#include "oob.h"
+
+static struct oob_plugin *active_plugin = NULL;
+
+void oob_activate_plugin(struct oob_plugin *plugin)
+{
+ if (!plugin || !plugin->local_data_updated|| !plugin->plugin_deactivated
+ || !plugin->request_remote_data
+ || active_plugin == plugin)
+ return;
+
+ if (active_plugin)
+ active_plugin->plugin_deactivated();
+
+ active_plugin = plugin;
+}
+
+void oob_deactivate_plugin(struct oob_plugin *plugin)
+{
+ if (active_plugin == plugin)
+ active_plugin = NULL;
+}
+
+gboolean oob_request_remote_data(struct btd_device *device)
+{
+ return active_plugin && active_plugin->request_remote_data(device);
+}
+
+void oob_local_data_updated(bdaddr_t *ba, uint8_t *hash, uint8_t *randomizer)
+{
+ if (active_plugin)
+ active_plugin->local_data_updated(ba, hash, randomizer);
+}
diff --git a/src/oob.h b/src/oob.h
new file mode 100644
index 0000000..b3e3623
--- /dev/null
+++ b/src/oob.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 ST-Ericsson SA
+ *
+ * Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ * 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
+ *
+ */
+
+struct oob_plugin
+{
+ /* If request was successfully send this functions should return TRUE.
+ * Function should not block for too long. */
+ gboolean (*request_remote_data)(struct btd_device *device);
+
+ /* Local OOB data updated. If corresponding HCI command failed, hash
+ * and randomizer are NULL */
+ void (*local_data_updated)(bdaddr_t *ba, uint8_t *hash,
+ uint8_t *randomizer);
+
+ /* Plug-in was deactivated (called only for active plug-in). */
+ void (*plugin_deactivated)(void);
+};
+
+/* These functions are called by OOB plug-in. */
+void oob_activate_plugin(struct oob_plugin *plugin);
+void oob_deactivate_plugin(struct oob_plugin *plugin);
+
+/* These functions are called from stack to interact with OOB plug-in. */
+gboolean oob_request_remote_data(struct btd_device *device);
+void oob_local_data_updated(bdaddr_t *ba, uint8_t *hash, uint8_t *randomizer);
--
1.7.1
^ 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