From: Anderson Lizardo <[email protected]>
Moving get_eir_uuids() to src/event.c removes the need to pass the raw
EIR data to higher layers. Now it is not necessary to pass the original
GSList of service UUIDs, because the list is concatenated (with
verification of duplicate entries) on adapter_update_device_from_info()
(for LE) and adapter_update_found_devices() (for BR/EDR).
---
src/adapter.c | 145 +++++++++++---------------------------------------------
src/adapter.h | 7 +--
src/event.c | 114 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 142 insertions(+), 124 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 5118306..34bf24a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2696,117 +2696,8 @@ static char **strlist2array(GSList *list)
return array;
}
-static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length, GSList *list)
-{
- uint16_t len = 0;
- size_t total;
- size_t uuid16_count = 0;
- size_t uuid32_count = 0;
- size_t uuid128_count = 0;
- uint8_t *uuid16;
- uint8_t *uuid32;
- uint8_t *uuid128;
- uuid_t service;
- char *uuid_str;
- unsigned int i;
-
- if (eir_data == NULL || eir_length == 0)
- return list;
-
- while (len < eir_length - 1) {
- uint8_t field_len = eir_data[0];
-
- /* Check for the end of EIR */
- if (field_len == 0)
- break;
-
- switch (eir_data[1]) {
- case EIR_UUID16_SOME:
- case EIR_UUID16_ALL:
- uuid16_count = field_len / 2;
- uuid16 = &eir_data[2];
- break;
- case EIR_UUID32_SOME:
- case EIR_UUID32_ALL:
- uuid32_count = field_len / 4;
- uuid32 = &eir_data[2];
- break;
- case EIR_UUID128_SOME:
- case EIR_UUID128_ALL:
- uuid128_count = field_len / 16;
- uuid128 = &eir_data[2];
- break;
- }
-
- len += field_len + 1;
- eir_data += field_len + 1;
- }
-
- /* Bail out if got incorrect length */
- if (len > eir_length)
- return list;
-
- total = uuid16_count + uuid32_count + uuid128_count;
-
- if (!total)
- return list;
-
- /* Generate uuids in SDP format (EIR data is Little Endian) */
- service.type = SDP_UUID16;
- for (i = 0; i < uuid16_count; i++) {
- uint16_t val16 = uuid16[1];
-
- val16 = (val16 << 8) + uuid16[0];
- service.value.uuid16 = val16;
- 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;
- }
-
- service.type = SDP_UUID32;
- for (i = uuid16_count; i < uuid32_count + uuid16_count; i++) {
- uint32_t val32 = uuid32[3];
- int k;
-
- for (k = 2; k >= 0; k--)
- val32 = (val32 << 8) + uuid32[k];
-
- service.value.uuid32 = val32;
- 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;
- }
-
- service.type = SDP_UUID128;
- for (i = uuid32_count + uuid16_count; i < total; i++) {
- int k;
-
- for (k = 0; k < 16; k++)
- service.value.uuid128.data[k] = uuid128[16 - k - 1];
-
- 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 list;
-}
-
void adapter_emit_device_found(struct btd_adapter *adapter,
- struct remote_dev_info *dev,
- uint8_t *eir_data, size_t eir_length)
+ struct remote_dev_info *dev)
{
struct btd_device *device;
char peer_addr[18], local_addr[18];
@@ -2823,8 +2714,7 @@ 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);
+ /* The uuids string array is updated only if necessary */
uuid_count = g_slist_length(dev->services);
if (dev->services && dev->uuid_count != uuid_count) {
g_strfreev(dev->uuids);
@@ -2911,8 +2801,25 @@ static gboolean extract_eir_flags(uint8_t *flags, uint8_t *eir_data)
return TRUE;
}
+static void remove_same_uuid(gpointer data, gpointer user_data)
+{
+ struct remote_dev_info *dev = user_data;
+ GSList *l;
+
+ for (l = dev->services; l; l = l->next) {
+ char *current_uuid = l->data;
+ char *new_uuid = data;
+
+ if (strcmp(current_uuid, new_uuid) == 0) {
+ g_free(current_uuid);
+ dev->services = g_slist_delete_link(dev->services, l);
+ break;
+ }
+ }
+}
+
void adapter_update_device_from_info(struct btd_adapter *adapter,
- le_advertising_info *info)
+ le_advertising_info *info, GSList *services)
{
struct remote_dev_info *dev;
bdaddr_t bdaddr;
@@ -2935,6 +2842,9 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
adapter->found_devices = g_slist_sort(adapter->found_devices,
(GCompareFunc) dev_rssi_cmp);
+ g_slist_foreach(services, remove_same_uuid, dev);
+ dev->services = g_slist_concat(dev->services, services);
+
if (info->length) {
char *tmp_name = bt_extract_eir_name(info->data, NULL);
if (tmp_name) {
@@ -2947,13 +2857,13 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
/* FIXME: check if other information was changed before emitting the
* signal */
- adapter_emit_device_found(adapter, dev, info->data, info->length);
+ adapter_emit_device_found(adapter, 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)
+ GSList *services, name_status_t name_status)
{
struct remote_dev_info *dev;
gboolean new_dev;
@@ -2979,7 +2889,10 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
adapter->found_devices = g_slist_sort(adapter->found_devices,
(GCompareFunc) dev_rssi_cmp);
- adapter_emit_device_found(adapter, dev, eir_data, EIR_DATA_LENGTH);
+ g_slist_foreach(services, remove_same_uuid, dev);
+ dev->services = g_slist_concat(dev->services, services);
+
+ adapter_emit_device_found(adapter, dev);
}
int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
diff --git a/src/adapter.h b/src/adapter.h
index a02f61c..efcf5b8 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -124,15 +124,14 @@ 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_device_from_info(struct btd_adapter *adapter,
- le_advertising_info *info);
+ le_advertising_info *info, GSList *services);
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);
+ GSList *services, name_status_t name_status);
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, size_t eir_length);
+ struct remote_dev_info *dev);
void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
void adapter_update_local_name(struct btd_adapter *adapter, const char *name);
void adapter_service_insert(const bdaddr_t *bdaddr, void *rec);
diff --git a/src/event.c b/src/event.c
index 47b50c4..0e6c86f 100644
--- a/src/event.c
+++ b/src/event.c
@@ -56,6 +56,7 @@
#include "agent.h"
#include "storage.h"
#include "event.h"
+#include "sdpd.h"
static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
struct btd_adapter **adapter,
@@ -299,9 +300,107 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}
+static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
+{
+ uint16_t len = 0;
+ size_t total;
+ size_t uuid16_count = 0;
+ size_t uuid32_count = 0;
+ size_t uuid128_count = 0;
+ GSList *list = NULL;
+ uint8_t *uuid16 = NULL;
+ uint8_t *uuid32 = NULL;
+ uint8_t *uuid128 = NULL;
+ uuid_t service;
+ char *uuid_str;
+ unsigned int i;
+
+ if (eir_data == NULL || eir_length == 0)
+ return list;
+
+ while (len < eir_length - 1) {
+ uint8_t field_len = eir_data[0];
+
+ /* Check for the end of EIR */
+ if (field_len == 0)
+ break;
+
+ switch (eir_data[1]) {
+ case EIR_UUID16_SOME:
+ case EIR_UUID16_ALL:
+ uuid16_count = field_len / 2;
+ uuid16 = &eir_data[2];
+ break;
+ case EIR_UUID32_SOME:
+ case EIR_UUID32_ALL:
+ uuid32_count = field_len / 4;
+ uuid32 = &eir_data[2];
+ break;
+ case EIR_UUID128_SOME:
+ case EIR_UUID128_ALL:
+ uuid128_count = field_len / 16;
+ uuid128 = &eir_data[2];
+ break;
+ }
+
+ len += field_len + 1;
+ eir_data += field_len + 1;
+ }
+
+ /* Bail out if got incorrect length */
+ if (len > eir_length)
+ return list;
+
+ total = uuid16_count + uuid32_count + uuid128_count;
+
+ if (!total)
+ return list;
+
+ /* Generate uuids in SDP format (EIR data is Little Endian) */
+ service.type = SDP_UUID16;
+ for (i = 0; i < uuid16_count; i++) {
+ uint16_t val16 = uuid16[1];
+
+ val16 = (val16 << 8) + uuid16[0];
+ service.value.uuid16 = val16;
+ uuid_str = bt_uuid2string(&service);
+ list = g_slist_append(list, uuid_str);
+ uuid16 += 2;
+ }
+
+ service.type = SDP_UUID32;
+ for (i = uuid16_count; i < uuid32_count + uuid16_count; i++) {
+ uint32_t val32 = uuid32[3];
+ int k;
+
+ for (k = 2; k >= 0; k--)
+ val32 = (val32 << 8) + uuid32[k];
+
+ service.value.uuid32 = val32;
+ uuid_str = bt_uuid2string(&service);
+ list = g_slist_append(list, uuid_str);
+ uuid32 += 4;
+ }
+
+ service.type = SDP_UUID128;
+ for (i = uuid32_count + uuid16_count; i < total; i++) {
+ int k;
+
+ for (k = 0; k < 16; k++)
+ service.value.uuid128.data[k] = uuid128[16 - k - 1];
+
+ uuid_str = bt_uuid2string(&service);
+ list = g_slist_append(list, uuid_str);
+ uuid128 += 16;
+ }
+
+ return list;
+}
+
void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
{
struct btd_adapter *adapter;
+ GSList *services = NULL;
adapter = manager_find_adapter(local);
if (adapter == NULL) {
@@ -309,7 +408,10 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
return;
}
- adapter_update_device_from_info(adapter, info);
+ /* Extract UUIDs from advertising data if any */
+ services = get_eir_uuids(info->data, info->length);
+
+ adapter_update_device_from_info(adapter, info, services);
}
void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
@@ -322,6 +424,7 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
struct remote_dev_info *dev, match;
uint8_t name_type = 0x00;
name_status_t name_status;
+ GSList *services = NULL;
int state;
dbus_bool_t legacy;
unsigned char features[8];
@@ -350,6 +453,9 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}
+ /* Extract UUIDs from extended inquiry response if any */
+ services = get_eir_uuids(data, EIR_DATA_LENGTH);
+
memset(&match, 0, sizeof(struct remote_dev_info));
bacpy(&match.bdaddr, peer);
match.name_status = NAME_SENT;
@@ -358,7 +464,7 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
if (dev) {
adapter_update_found_devices(adapter, peer, rssi, class,
NULL, NULL, dev->legacy,
- NAME_NOT_REQUIRED, data);
+ services, NAME_NOT_REQUIRED);
return;
}
@@ -410,7 +516,7 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
/* add in the list to track name sent/pending */
adapter_update_found_devices(adapter, peer, rssi, class, name, alias,
- legacy, name_status, data);
+ legacy, services, name_status);
g_free(name);
g_free(alias);
@@ -500,7 +606,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, 0);
+ adapter_emit_device_found(adapter, dev_info);
}
if (device)
--
1.7.0.4
Hi,
On Fri, Dec 17, 2010, Bruna Moreira wrote:
> Moving get_eir_uuids() to src/event.c removes the need to pass the raw
> EIR data to higher layers. Now it is not necessary to pass the original
> GSList of service UUIDs, because the list is concatenated (with
> verification of duplicate entries) on adapter_update_device_from_info()
> (for LE) and adapter_update_found_devices() (for BR/EDR).
> ---
> src/adapter.c | 145 +++++++++++---------------------------------------------
> src/adapter.h | 7 +--
> src/event.c | 114 +++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 142 insertions(+), 124 deletions(-)
All four patches have been pushed upstream. Thanks.
Johan
From: Anderson Lizardo <[email protected]>
---
src/adapter.c | 12 +++++-------
src/adapter.h | 3 ++-
src/event.c | 34 ++++++++++++++++++++++------------
src/glib-helper.c | 22 ----------------------
src/glib-helper.h | 1 -
5 files changed, 29 insertions(+), 43 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index c74019d..b826d4a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2805,7 +2805,8 @@ static void remove_same_uuid(gpointer data, gpointer user_data)
void adapter_update_device_from_info(struct btd_adapter *adapter,
le_advertising_info *info,
- GSList *services, uint8_t flags)
+ char *name, GSList *services,
+ uint8_t flags)
{
struct remote_dev_info *dev;
bdaddr_t bdaddr;
@@ -2833,12 +2834,9 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
dev->flags = flags;
- if (info->length) {
- char *tmp_name = bt_extract_eir_name(info->data, NULL);
- if (tmp_name) {
- g_free(dev->name);
- dev->name = tmp_name;
- }
+ if (name) {
+ g_free(dev->name);
+ dev->name = name;
}
/* FIXME: check if other information was changed before emitting the
diff --git a/src/adapter.h b/src/adapter.h
index d5dceb9..52417b6 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -125,7 +125,8 @@ struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter
struct remote_dev_info *match);
void adapter_update_device_from_info(struct btd_adapter *adapter,
le_advertising_info *info,
- GSList *services, uint8_t flags);
+ char *name, GSList *services,
+ uint8_t flags);
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 4672106..e138312 100644
--- a/src/event.c
+++ b/src/event.c
@@ -61,6 +61,8 @@
struct eir_data {
GSList *services;
uint8_t flags;
+ char *name;
+ gboolean name_complete;
};
static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
@@ -350,6 +352,16 @@ static int parse_eir_data(struct eir_data *eir, uint8_t *eir_data,
case EIR_FLAGS:
eir->flags = eir_data[2];
break;
+ case EIR_NAME_SHORT:
+ case EIR_NAME_COMPLETE:
+ if (g_utf8_validate((char *) &eir_data[2],
+ field_len - 1, NULL))
+ eir->name = g_strndup((char *) &eir_data[2],
+ field_len - 1);
+ else
+ eir->name = g_strdup("");
+ eir->name_complete = eir_data[1] == EIR_NAME_COMPLETE;
+ break;
}
len += field_len + 1;
@@ -426,8 +438,8 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
error("Error parsing advertising data: %s (%d)",
strerror(-err), -err);
- adapter_update_device_from_info(adapter, info, eir_data.services,
- eir_data.flags);
+ adapter_update_device_from_info(adapter, info, eir_data.name,
+ eir_data.services, eir_data.flags);
}
void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
@@ -436,9 +448,8 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
char filename[PATH_MAX + 1];
struct btd_adapter *adapter;
struct btd_device *device;
- char local_addr[18], peer_addr[18], *alias, *name, *tmp_name;
+ char local_addr[18], peer_addr[18], *alias, *name;
struct remote_dev_info *dev, match;
- uint8_t name_type = 0x00;
name_status_t name_status;
struct eir_data eir_data;
int state, err;
@@ -513,25 +524,24 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
} else
legacy = TRUE;
- tmp_name = bt_extract_eir_name(data, &name_type);
- if (tmp_name) {
- if (name_type == 0x09) {
- write_device_name(local, peer, tmp_name);
+ if (eir_data.name) {
+ if (eir_data.name_complete) {
+ write_device_name(local, peer, eir_data.name);
name_status = NAME_NOT_REQUIRED;
if (name)
g_free(name);
- name = tmp_name;
+ name = eir_data.name;
} else {
if (name)
- free(tmp_name);
+ free(eir_data.name);
else
- name = tmp_name;
+ name = eir_data.name;
}
}
- if (name && name_type != 0x08)
+ if (name && eir_data.name_complete)
name_status = NAME_SENT;
/* add in the list to track name sent/pending */
diff --git a/src/glib-helper.c b/src/glib-helper.c
index 6505249..c440e60 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -780,25 +780,3 @@ 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;
-
- if (type)
- *type = data[1];
-
- switch (data[1]) {
- case EIR_NAME_SHORT:
- case EIR_NAME_COMPLETE:
- if (!g_utf8_validate((char *) (data + 2), data[0] - 1, NULL))
- return g_strdup("");
- return g_strndup((char *) (data + 2), data[0] - 1);
- }
-
- return NULL;
-}
diff --git a/src/glib-helper.h b/src/glib-helper.h
index 5bb20a6..10718bb 100644
--- a/src/glib-helper.h
+++ b/src/glib-helper.h
@@ -42,4 +42,3 @@ 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
From: Anderson Lizardo <[email protected]>
---
src/adapter.c | 22 ++++------------------
src/adapter.h | 3 ++-
src/event.c | 7 ++++++-
3 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 34bf24a..c74019d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2786,21 +2786,6 @@ static struct remote_dev_info *get_found_dev(struct btd_adapter *adapter,
return dev;
}
-static gboolean extract_eir_flags(uint8_t *flags, uint8_t *eir_data)
-{
- if (eir_data[0] == 0)
- return FALSE;
-
- if (eir_data[1] != EIR_FLAGS)
- return FALSE;
-
- /* For now, only one octet is used for flags */
- if (flags)
- *flags = eir_data[2];
-
- return TRUE;
-}
-
static void remove_same_uuid(gpointer data, gpointer user_data)
{
struct remote_dev_info *dev = user_data;
@@ -2819,7 +2804,8 @@ static void remove_same_uuid(gpointer data, gpointer user_data)
}
void adapter_update_device_from_info(struct btd_adapter *adapter,
- le_advertising_info *info, GSList *services)
+ le_advertising_info *info,
+ GSList *services, uint8_t flags)
{
struct remote_dev_info *dev;
bdaddr_t bdaddr;
@@ -2845,14 +2831,14 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
g_slist_foreach(services, remove_same_uuid, dev);
dev->services = g_slist_concat(dev->services, services);
+ dev->flags = flags;
+
if (info->length) {
char *tmp_name = bt_extract_eir_name(info->data, NULL);
if (tmp_name) {
g_free(dev->name);
dev->name = tmp_name;
}
-
- extract_eir_flags(info->data, &dev->flags);
}
/* FIXME: check if other information was changed before emitting the
diff --git a/src/adapter.h b/src/adapter.h
index efcf5b8..d5dceb9 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -124,7 +124,8 @@ 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_device_from_info(struct btd_adapter *adapter,
- le_advertising_info *info, GSList *services);
+ le_advertising_info *info,
+ GSList *services, uint8_t flags);
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 3352717..4672106 100644
--- a/src/event.c
+++ b/src/event.c
@@ -60,6 +60,7 @@
struct eir_data {
GSList *services;
+ uint8_t flags;
};
static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
@@ -346,6 +347,9 @@ static int parse_eir_data(struct eir_data *eir, uint8_t *eir_data,
uuid128_count = field_len / 16;
uuid128 = &eir_data[2];
break;
+ case EIR_FLAGS:
+ eir->flags = eir_data[2];
+ break;
}
len += field_len + 1;
@@ -422,7 +426,8 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
error("Error parsing advertising data: %s (%d)",
strerror(-err), -err);
- adapter_update_device_from_info(adapter, info, eir_data.services);
+ adapter_update_device_from_info(adapter, info, eir_data.services,
+ eir_data.flags);
}
void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
--
1.7.0.4
From: Anderson Lizardo <[email protected]>
Currently, EIR parsing (name, UUIDs, flags etc.) is done in various
places. This leads to duplicated checks and does not support parsing
multiple AD/EIR structures on a single transfer.
These changes modify get_eir_uuids() to parse other EIR data types and
avoid passing raw EIR data to higher layers.
To accomplish this, get_eir_uuids() was renamed to parse_eir_data(), and
a new (internal) "struct eir_data" was introduced to store the parsed
data.
This first commit only handles the services UUIDs, following patches
will move other EIR parsing to it until everything is done inside
parse_eir_data().
---
src/event.c | 49 ++++++++++++++++++++++++++++++++-----------------
1 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/src/event.c b/src/event.c
index 0e6c86f..3352717 100644
--- a/src/event.c
+++ b/src/event.c
@@ -58,6 +58,10 @@
#include "event.h"
#include "sdpd.h"
+struct eir_data {
+ GSList *services;
+};
+
static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
struct btd_adapter **adapter,
struct btd_device **device,
@@ -300,14 +304,14 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}
-static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
+static int parse_eir_data(struct eir_data *eir, uint8_t *eir_data,
+ size_t eir_length)
{
uint16_t len = 0;
size_t total;
size_t uuid16_count = 0;
size_t uuid32_count = 0;
size_t uuid128_count = 0;
- GSList *list = NULL;
uint8_t *uuid16 = NULL;
uint8_t *uuid32 = NULL;
uint8_t *uuid128 = NULL;
@@ -315,8 +319,9 @@ static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
char *uuid_str;
unsigned int i;
+ /* No EIR data to parse */
if (eir_data == NULL || eir_length == 0)
- return list;
+ return 0;
while (len < eir_length - 1) {
uint8_t field_len = eir_data[0];
@@ -349,12 +354,13 @@ static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
/* Bail out if got incorrect length */
if (len > eir_length)
- return list;
+ return -EINVAL;
total = uuid16_count + uuid32_count + uuid128_count;
+ /* No UUIDs were parsed, so skip code below */
if (!total)
- return list;
+ return 0;
/* Generate uuids in SDP format (EIR data is Little Endian) */
service.type = SDP_UUID16;
@@ -364,7 +370,7 @@ static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
val16 = (val16 << 8) + uuid16[0];
service.value.uuid16 = val16;
uuid_str = bt_uuid2string(&service);
- list = g_slist_append(list, uuid_str);
+ eir->services = g_slist_append(eir->services, uuid_str);
uuid16 += 2;
}
@@ -378,7 +384,7 @@ static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
service.value.uuid32 = val32;
uuid_str = bt_uuid2string(&service);
- list = g_slist_append(list, uuid_str);
+ eir->services = g_slist_append(eir->services, uuid_str);
uuid32 += 4;
}
@@ -390,17 +396,18 @@ static GSList *get_eir_uuids(uint8_t *eir_data, size_t eir_length)
service.value.uuid128.data[k] = uuid128[16 - k - 1];
uuid_str = bt_uuid2string(&service);
- list = g_slist_append(list, uuid_str);
+ eir->services = g_slist_append(eir->services, uuid_str);
uuid128 += 16;
}
- return list;
+ return 0;
}
void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
{
struct btd_adapter *adapter;
- GSList *services = NULL;
+ struct eir_data eir_data;
+ int err;
adapter = manager_find_adapter(local);
if (adapter == NULL) {
@@ -409,9 +416,13 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
}
/* Extract UUIDs from advertising data if any */
- services = get_eir_uuids(info->data, info->length);
+ memset(&eir_data, 0, sizeof(eir_data));
+ err = parse_eir_data(&eir_data, info->data, info->length);
+ if (err < 0)
+ error("Error parsing advertising data: %s (%d)",
+ strerror(-err), -err);
- adapter_update_device_from_info(adapter, info, services);
+ adapter_update_device_from_info(adapter, info, eir_data.services);
}
void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
@@ -424,8 +435,8 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
struct remote_dev_info *dev, match;
uint8_t name_type = 0x00;
name_status_t name_status;
- GSList *services = NULL;
- int state;
+ struct eir_data eir_data;
+ int state, err;
dbus_bool_t legacy;
unsigned char features[8];
@@ -454,7 +465,10 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
}
/* Extract UUIDs from extended inquiry response if any */
- services = get_eir_uuids(data, EIR_DATA_LENGTH);
+ memset(&eir_data, 0, sizeof(eir_data));
+ err = parse_eir_data(&eir_data, data, EIR_DATA_LENGTH);
+ if (err < 0)
+ error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
memset(&match, 0, sizeof(struct remote_dev_info));
bacpy(&match.bdaddr, peer);
@@ -464,7 +478,8 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
if (dev) {
adapter_update_found_devices(adapter, peer, rssi, class,
NULL, NULL, dev->legacy,
- services, NAME_NOT_REQUIRED);
+ eir_data.services,
+ NAME_NOT_REQUIRED);
return;
}
@@ -516,7 +531,7 @@ void btd_event_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
/* add in the list to track name sent/pending */
adapter_update_found_devices(adapter, peer, rssi, class, name, alias,
- legacy, services, name_status);
+ legacy, eir_data.services, name_status);
g_free(name);
g_free(alias);
--
1.7.0.4