2011-04-28 22:36:56

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 00/13] Discovery Cleanup - Step 1

This patch series is the first step to cleanup the device discovery
procedure. The main changes are:
- Unify advertising reports and inquiry results: mgmt sends
one device found event
- Logic improvement/cleanup: device found
- Move EIR functions to a new file

Andre Guedes will send soon a patch series changing the discovery state
control to be make hciops and mgmtops functional.

There is excessive dynamic memory allocations/deallocations for EIR data.
This is not a problem introduced by this patch serie. eir_data_free
will be removed soon.

***** Open Issues *****

* Use BDADDR_TYPE_NON_LE instead of BR?
#define BDADDR_TYPE_LE_PUBLIC 0x00
#define BRADDR_TYPE_LE_RANDOM 0x01
#define BDADDR_TYPE_BR 0xff

Bruna Moreira (3):
Remove btd_event_advertising_report
Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH
Drop variable EIR length

Claudio Takahasi (10):
Move EIR related functions to a new file
Add Bluetooth address type definition
Initial device found cleanup
Move legacy verification to a new function
Cleanup read name and alias from storage
Don't resolve name if the name is in the storage
Unify inquiry results and advertises
Fix memory leak of EIR data
Change the order to write/read the remote's name
Cleanup inserting new device found entry

Makefile.am | 2 +-
lib/bluetooth.h | 4 +
plugins/hciops.c | 202 +++++----------------------------
plugins/mgmtops.c | 3 +-
src/adapter.c | 178 ++++++++++++++++++-----------
src/adapter.h | 9 +-
src/eir.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eir.h | 41 +++++++
src/event.c | 222 +-----------------------------------
src/event.h | 5 +-
src/sdpd.h | 14 ---
11 files changed, 526 insertions(+), 482 deletions(-)
create mode 100644 src/eir.c
create mode 100644 src/eir.h

--
1.7.5.rc3



2011-04-29 21:07:48

by Claudio Takahasi

[permalink] [raw]
Subject: Re: [PATCH 00/13] Discovery Cleanup - Step 1

Hi Johan,

Please ignore this patch series. I will fix the unnecessary
file-system lookup for the remote features.

On Thu, Apr 28, 2011 at 7:36 PM, Claudio Takahasi
<[email protected]> wrote:
> This patch series is the first step to cleanup the device discovery
> procedure. The main changes are:
> =C2=A0- Unify advertising reports and inquiry results: mgmt sends
> =C2=A0 =C2=A0one device found event
> =C2=A0- Logic improvement/cleanup: device found
> =C2=A0- Move EIR functions to a new file
>
> Andre Guedes will send soon a patch series changing the discovery state
> control to be make hciops and mgmtops functional.
>
> There is excessive dynamic memory allocations/deallocations for EIR data.
> This is not a problem introduced by this patch serie. eir_data_free
> will be removed soon.
>
> ***** Open Issues *****
>
> * Use BDADDR_TYPE_NON_LE instead of BR?
> #define BDADDR_TYPE_LE_PUBLIC =C2=A00x00
> #define BRADDR_TYPE_LE_RANDOM =C2=A00x01
> #define BDADDR_TYPE_BR =C2=A0 =C2=A0 =C2=A0 =C2=A0 0xff

Comments here?

BR,
Claudio

>
> Bruna Moreira (3):
> =C2=A0Remove btd_event_advertising_report
> =C2=A0Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH
> =C2=A0Drop variable EIR length
>
> Claudio Takahasi (10):
> =C2=A0Move EIR related functions to a new file
> =C2=A0Add Bluetooth address type definition
> =C2=A0Initial device found cleanup
> =C2=A0Move legacy verification to a new function
> =C2=A0Cleanup read name and alias from storage
> =C2=A0Don't resolve name if the name is in the storage
> =C2=A0Unify inquiry results and advertises
> =C2=A0Fix memory leak of EIR data
> =C2=A0Change the order to write/read the remote's name
> =C2=A0Cleanup inserting new device found entry
>
> =C2=A0Makefile.am =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A02 +-
> =C2=A0lib/bluetooth.h =C2=A0 | =C2=A0 =C2=A04 +
> =C2=A0plugins/hciops.c =C2=A0| =C2=A0202 +++++---------------------------=
-
> =C2=A0plugins/mgmtops.c | =C2=A0 =C2=A03 +-
> =C2=A0src/adapter.c =C2=A0 =C2=A0 | =C2=A0178 ++++++++++++++++++---------=
--
> =C2=A0src/adapter.h =C2=A0 =C2=A0 | =C2=A0 =C2=A09 +-
> =C2=A0src/eir.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0328 +++++++++++++++++=
++++++++++++++++++++++++++++++++++++
> =C2=A0src/eir.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 41 +++++++
> =C2=A0src/event.c =C2=A0 =C2=A0 =C2=A0 | =C2=A0222 +---------------------=
--------------
> =C2=A0src/event.h =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A05 +-
> =C2=A0src/sdpd.h =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 14 ---
> =C2=A011 files changed, 526 insertions(+), 482 deletions(-)
> =C2=A0create mode 100644 src/eir.c
> =C2=A0create mode 100644 src/eir.h
>
> --
> 1.7.5.rc3
>

2011-04-28 22:37:09

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 13/13] Drop variable EIR length

From: Bruna Moreira <[email protected]>

The functions eir_parse() and adapter_update_found_devices() now
assume that the EIR buffer has always 240 octets. For advertising
reports, the advertising data is stored on a buffer with 240 bytes,
padded with zeroes.
---
plugins/hciops.c | 13 +++++++++----
src/adapter.c | 5 ++---
src/adapter.h | 3 +--
src/eir.c | 8 ++++----
src/eir.h | 2 +-
src/event.c | 2 +-
6 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index 91d5778..8b7befa 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -2080,7 +2080,7 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
{
struct dev_info *dev = &devs[index];
le_advertising_info *info;
- uint8_t num_reports, rssi;
+ uint8_t num_reports, rssi, eir[HCI_MAX_EIR_LENGTH];
const uint8_t RSSI_SIZE = 1;

num_reports = meta->data[0];
@@ -2088,8 +2088,11 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
info = (le_advertising_info *) &meta->data[1];
rssi = *(info->data + info->length);

+ memset(eir, 0, sizeof(eir));
+ memcpy(eir, info->data, info->length);
+
btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- info->bdaddr_type, 0, rssi, info->data);
+ info->bdaddr_type, 0, rssi, eir);

num_reports--;

@@ -2098,9 +2101,11 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
RSSI_SIZE);
rssi = *(info->data + info->length);

+ memset(eir, 0, sizeof(eir));
+ memcpy(eir, info->data, info->length);
+
btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- info->bdaddr_type, 0,
- rssi, info->data);
+ info->bdaddr_type, 0, rssi, eir);
}
}

diff --git a/src/adapter.c b/src/adapter.c
index bae7324..cd9df75 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3114,8 +3114,7 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)

void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint8_t bda_type, uint32_t class,
- int8_t rssi, uint8_t *data,
- size_t eir_size)
+ int8_t rssi, uint8_t *data)
{
struct remote_dev_info *dev, match;
struct eir_data eir_data;
@@ -3125,7 +3124,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, data, HCI_MAX_EIR_LENGTH);
+ err = eir_parse(&eir_data, data);
if (err < 0) {
error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
return;
diff --git a/src/adapter.h b/src/adapter.h
index 931be37..f296389 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -120,8 +120,7 @@ struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter
struct remote_dev_info *match);
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint8_t bda_type, uint32_t class,
- int8_t rssi, uint8_t *data,
- size_t eir_size);
+ int8_t rssi, uint8_t *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);
diff --git a/src/eir.c b/src/eir.c
index 7dfc444..01b6ac5 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -52,7 +52,7 @@ void eir_data_free(struct eir_data *eir)
g_free(eir->name);
}

-int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
+int eir_parse(struct eir_data *eir, uint8_t *eir_data)
{
uint16_t len = 0;
size_t total;
@@ -69,10 +69,10 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
eir->flags = -1;

/* No EIR data to parse */
- if (eir_data == NULL || eir_length == 0)
+ if (eir_data == NULL)
return 0;

- while (len < eir_length - 1) {
+ while (len < HCI_MAX_EIR_LENGTH - 1) {
uint8_t field_len = eir_data[0];

/* Check for the end of EIR */
@@ -115,7 +115,7 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
}

/* Bail out if got incorrect length */
- if (len > eir_length)
+ if (len > HCI_MAX_EIR_LENGTH)
return -EINVAL;

total = uuid16_count + uuid32_count + uuid128_count;
diff --git a/src/eir.h b/src/eir.h
index ea38570..d225973 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -35,7 +35,7 @@ struct eir_data {
};

void eir_data_free(struct eir_data *eir);
-int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length);
+int eir_parse(struct eir_data *eir, uint8_t *eir_data);
void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
uint16_t did_product, uint16_t did_version,
GSList *uuids, uint8_t *data);
diff --git a/src/event.c b/src/event.c
index 2b83ea7..4390c54 100644
--- a/src/event.c
+++ b/src/event.c
@@ -302,7 +302,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
}

adapter_update_found_devices(adapter, peer, bda_type, class,
- rssi, data, HCI_MAX_EIR_LENGTH);
+ rssi, data);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-04-28 22:37:08

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 12/13] Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH

From: Bruna Moreira <[email protected]>

Both defines have the same value (240) and meaning.
---
src/adapter.c | 2 +-
src/eir.c | 9 +++++----
src/eir.h | 2 --
src/event.c | 2 +-
4 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 29a018a..bae7324 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3125,7 +3125,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
+ err = eir_parse(&eir_data, data, HCI_MAX_EIR_LENGTH);
if (err < 0) {
error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
return;
diff --git a/src/eir.c b/src/eir.c
index 2fbd919..7dfc444 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -27,6 +27,7 @@
#include <glib.h>

#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
#include <bluetooth/sdp.h>

#include "glib-helper.h"
@@ -184,7 +185,7 @@ static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
continue;

/* Stop if not enough space to put next UUID128 */
- if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
+ if ((len + 2 + SIZEOF_UUID128) > HCI_MAX_EIR_LENGTH) {
truncated = TRUE;
break;
}
@@ -229,7 +230,7 @@ void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
GSList *l;
uint8_t *ptr = data;
uint16_t eir_len = 0;
- uint16_t uuid16[EIR_DATA_LENGTH / 2];
+ uint16_t uuid16[HCI_MAX_EIR_LENGTH / 2];
int i, uuid_count = 0;
gboolean truncated = FALSE;
size_t name_len;
@@ -289,7 +290,7 @@ void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
continue;

/* Stop if not enough space to put next UUID16 */
- if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
+ if ((eir_len + 2 + sizeof(uint16_t)) > HCI_MAX_EIR_LENGTH) {
truncated = TRUE;
break;
}
@@ -322,6 +323,6 @@ void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
}

/* Group all UUID128 types */
- if (eir_len <= EIR_DATA_LENGTH - 2)
+ if (eir_len <= HCI_MAX_EIR_LENGTH - 2)
eir_generate_uuid128(uuids, ptr, &eir_len);
}
diff --git a/src/eir.h b/src/eir.h
index aacd16a..ea38570 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -22,8 +22,6 @@
*
*/

-#define EIR_DATA_LENGTH 240
-
struct uuid_info {
uuid_t uuid;
uint8_t svc_hint;
diff --git a/src/event.c b/src/event.c
index 6dc40c0..2b83ea7 100644
--- a/src/event.c
+++ b/src/event.c
@@ -302,7 +302,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
}

adapter_update_found_devices(adapter, peer, bda_type, class,
- rssi, data, EIR_DATA_LENGTH);
+ rssi, data, HCI_MAX_EIR_LENGTH);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-04-28 22:37:07

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 11/13] Cleanup inserting new device found entry

---
src/adapter.c | 97 +++++++++++++++++++++++++++-----------------------------
1 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 7fb92e3..29a018a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3030,29 +3030,24 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
g_free(alias);
}

-static struct remote_dev_info *get_found_dev(struct btd_adapter *adapter,
- const bdaddr_t *bdaddr,
- gboolean *new_dev)
+static struct remote_dev_info *found_device_new(const bdaddr_t *bdaddr,
+ gboolean le, const char *name,
+ const char *alias, uint32_t class,
+ gboolean legacy, name_status_t status,
+ int flags)
{
- struct remote_dev_info *dev, match;
+ struct remote_dev_info *dev;

- memset(&match, 0, sizeof(struct remote_dev_info));
- bacpy(&match.bdaddr, bdaddr);
- match.name_status = NAME_ANY;
-
- dev = adapter_search_found_devices(adapter, &match);
- if (dev) {
- *new_dev = FALSE;
- /* Out of range list update */
- adapter->oor_devices = g_slist_remove(adapter->oor_devices,
- dev);
- } else {
- *new_dev = TRUE;
- 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);
+ bacpy(&dev->bdaddr, bdaddr);
+ dev->le = le;
+ dev->name = g_strdup(name);
+ dev->alias = g_strdup(alias);
+ dev->class = class;
+ dev->legacy = legacy;
+ dev->name_status = status;
+ if (flags >= 0)
+ dev->flags = flags;

return dev;
}
@@ -3122,11 +3117,11 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int8_t rssi, uint8_t *data,
size_t eir_size)
{
- struct remote_dev_info *dev;
+ struct remote_dev_info *dev, match;
struct eir_data eir_data;
- char *name;
- gboolean new_dev, legacy, le;
- name_status_t name_status = NAME_NOT_REQUIRED;
+ char *alias, *name;
+ gboolean legacy, le;
+ name_status_t name_status;
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
@@ -3139,6 +3134,25 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
if (eir_data.name != NULL && eir_data.name_complete)
write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);

+ /* Device already seen in the discovery session ? */
+ memset(&match, 0, sizeof(struct remote_dev_info));
+ bacpy(&match.bdaddr, bdaddr);
+ match.name_status = NAME_ANY;
+
+ dev = adapter_search_found_devices(adapter, &match);
+ if (dev) {
+ adapter->oor_devices = g_slist_remove(adapter->oor_devices,
+ dev);
+ if (dev->rssi != rssi)
+ goto done;
+
+ eir_data_free(&eir_data);
+
+ return;
+ }
+
+ /* New device in the discovery session */
+
name = read_stored_data(&adapter->bdaddr, bdaddr, "names");

switch (bda_type) {
@@ -3146,6 +3160,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
case BRADDR_TYPE_LE_RANDOM:
le = TRUE;
legacy = FALSE;
+ name_status = NAME_NOT_REQUIRED;
break;
default:
/* BDADDR_TYPE_BR */
@@ -3164,32 +3179,16 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
break;
}

- dev = get_found_dev(adapter, bdaddr, &new_dev);
-
- if (new_dev) {
- const char *dev_name = (name ? name : eir_data.name);
- char *alias;
+ alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");

- if (dev_name)
- dev->name = g_strdup(dev_name);
-
- alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");
- if (alias) {
- dev->alias = g_strdup(alias);
- free(alias);
- }
-
- dev->le = FALSE;
- dev->class = class;
- dev->legacy = legacy;
- dev->name_status = name_status;
+ dev = found_device_new(bdaddr, le, name, alias, class, legacy,
+ name_status, eir_data.flags);
+ free(name);
+ free(alias);

- if (eir_data.flags >= 0)
- dev->flags = eir_data.flags;
-
- } else if (dev->rssi == rssi)
- goto done;
+ adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);

+done:
dev->rssi = rssi;

adapter->found_devices = g_slist_sort(adapter->found_devices,
@@ -3200,8 +3199,6 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,

adapter_emit_device_found(adapter, dev);

-done:
- free(name);
eir_data_free(&eir_data);
}

--
1.7.5.rc3


2011-04-28 22:37:06

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 10/13] Change the order to write/read the remote's name

When discovering, write the EIR "complete" name first before to read
the name. Only names retrieved from EIR "complete" name and HCI Remote
Name Request Complete event are stored. This patch doesn't change the
final result: the value of the name sent in the signal.
---
src/adapter.c | 19 +++++--------------
1 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index f96c115..7fb92e3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3127,7 +3127,6 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
char *name;
gboolean new_dev, legacy, le;
name_status_t name_status = NAME_NOT_REQUIRED;
- const char *dev_name;
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
@@ -3137,6 +3136,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
return;
}

+ if (eir_data.name != NULL && eir_data.name_complete)
+ write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);
+
name = read_stored_data(&adapter->bdaddr, bdaddr, "names");

switch (bda_type) {
@@ -3162,23 +3164,12 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
break;
}

- /* Complete EIR names are always used. Shortened EIR names are only
- * used if there is no name already in storage. */
- dev_name = name;
- if (eir_data.name != NULL) {
- if (eir_data.name_complete) {
- write_device_name(&adapter->bdaddr, bdaddr,
- eir_data.name);
- name_status = NAME_NOT_REQUIRED;
- dev_name = eir_data.name;
- } else if (name == NULL)
- dev_name = eir_data.name;
- }
-
dev = get_found_dev(adapter, bdaddr, &new_dev);

if (new_dev) {
+ const char *dev_name = (name ? name : eir_data.name);
char *alias;
+
if (dev_name)
dev->name = g_strdup(dev_name);

--
1.7.5.rc3


2011-04-28 22:37:05

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 09/13] Remove btd_event_advertising_report

From: Bruna Moreira <[email protected]>

Advertises should be notified using btd_event_device_found function
to keep the compatibility with mgmtops plugin.
---
plugins/hciops.c | 27 +++++++++++++++++++--------
plugins/mgmtops.c | 3 ++-
src/event.c | 24 +++---------------------
src/event.h | 5 ++---
4 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index c2aa614..91d5778 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -1805,8 +1805,8 @@ static inline void inquiry_result(int index, int plen, void *ptr)
(info->dev_class[1] << 8) |
(info->dev_class[2] << 16);

- btd_event_device_found(&dev->bdaddr, &info->bdaddr, class,
- 0, NULL);
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ BDADDR_TYPE_BR, class, 0, NULL);
ptr += INQUIRY_INFO_SIZE;
}
}
@@ -1828,7 +1828,8 @@ static inline void inquiry_result_with_rssi(int index, int plen, void *ptr)
| (info->dev_class[2] << 16);

btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- class, info->rssi, NULL);
+ BDADDR_TYPE_BR, class,
+ info->rssi, NULL);
ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE;
}
} else {
@@ -1839,7 +1840,8 @@ static inline void inquiry_result_with_rssi(int index, int plen, void *ptr)
| (info->dev_class[2] << 16);

btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- class, info->rssi, NULL);
+ BDADDR_TYPE_BR, class,
+ info->rssi, NULL);
ptr += INQUIRY_INFO_WITH_RSSI_SIZE;
}
}
@@ -1857,7 +1859,8 @@ static inline void extended_inquiry_result(int index, int plen, void *ptr)
| (info->dev_class[1] << 8)
| (info->dev_class[2] << 16);

- btd_event_device_found(&dev->bdaddr, &info->bdaddr, class,
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ BDADDR_TYPE_BR, class,
info->rssi, info->data);
ptr += EXTENDED_INQUIRY_INFO_SIZE;
}
@@ -2077,19 +2080,27 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
{
struct dev_info *dev = &devs[index];
le_advertising_info *info;
- uint8_t num_reports;
+ uint8_t num_reports, rssi;
const uint8_t RSSI_SIZE = 1;

num_reports = meta->data[0];

info = (le_advertising_info *) &meta->data[1];
- btd_event_advertising_report(&dev->bdaddr, info);
+ rssi = *(info->data + info->length);
+
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ info->bdaddr_type, 0, rssi, info->data);
+
num_reports--;

while (num_reports--) {
info = (le_advertising_info *) (info->data + info->length +
RSSI_SIZE);
- btd_event_advertising_report(&dev->bdaddr, info);
+ rssi = *(info->data + info->length);
+
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ info->bdaddr_type, 0,
+ rssi, info->data);
}
}

diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index be94267..15f024a 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -1321,7 +1321,8 @@ static void mgmt_device_found(int sk, uint16_t index, void *buf, size_t len)
DBG("hci%u addr %s, class %u rssi %d %s", index, addr, cls,
ev->rssi, eir ? "eir" : "");

- btd_event_device_found(&info->bdaddr, &ev->bdaddr, cls, ev->rssi, eir);
+ btd_event_device_found(&info->bdaddr, &ev->bdaddr, BDADDR_TYPE_BR,
+ cls, ev->rssi, eir);
}

static void mgmt_remote_name(int sk, uint16_t index, void *buf, size_t len)
diff --git a/src/event.c b/src/event.c
index 84a51cf..6dc40c0 100644
--- a/src/event.c
+++ b/src/event.c
@@ -250,23 +250,6 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}

-void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
-{
- struct btd_adapter *adapter;
- int8_t rssi;
-
- adapter = manager_find_adapter(local);
- if (adapter == NULL) {
- error("No matching adapter found");
- return;
- }
-
- rssi = *(info->data + info->length);
-
- adapter_update_found_devices(adapter, &info->bdaddr, info->bdaddr_type,
- 0, rssi, info->data, info->length);
-}
-
static void update_lastseen(bdaddr_t *sba, bdaddr_t *dba)
{
time_t t;
@@ -289,8 +272,8 @@ static void update_lastused(bdaddr_t *sba, bdaddr_t *dba)
write_lastused_info(sba, dba, tm);
}

-void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
- int8_t rssi, uint8_t *data)
+void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
+ uint32_t class, int8_t rssi, uint8_t *data)
{
struct btd_adapter *adapter;
int state;
@@ -318,9 +301,8 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}

- adapter_update_found_devices(adapter, peer, BDADDR_TYPE_BR, class,
+ adapter_update_found_devices(adapter, peer, bda_type, class,
rssi, data, EIR_DATA_LENGTH);
-
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
diff --git a/src/event.h b/src/event.h
index 765390a..16a900c 100644
--- a/src/event.h
+++ b/src/event.h
@@ -23,9 +23,8 @@
*/

int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba);
-void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info);
-void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
- int8_t rssi, uint8_t *data);
+void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
+ 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);
void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name);
--
1.7.5.rc3


2011-04-28 22:37:04

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 08/13] Fix memory leak of EIR data

---
src/adapter.c | 1 +
src/eir.c | 7 +++++++
src/eir.h | 1 +
3 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 7612eb6..f96c115 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3211,6 +3211,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,

done:
free(name);
+ eir_data_free(&eir_data);
}

int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
diff --git a/src/eir.c b/src/eir.c
index d827c7e..2fbd919 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -44,6 +44,13 @@
#define EIR_TX_POWER 0x0A /* transmit power level */
#define EIR_DEVICE_ID 0x10 /* device ID */

+void eir_data_free(struct eir_data *eir)
+{
+ g_slist_foreach(eir->services, (GFunc) g_free, NULL);
+ g_slist_free(eir->services);
+ g_free(eir->name);
+}
+
int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
{
uint16_t len = 0;
diff --git a/src/eir.h b/src/eir.h
index c7699eb..aacd16a 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -36,6 +36,7 @@ struct eir_data {
gboolean name_complete;
};

+void eir_data_free(struct eir_data *eir);
int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length);
void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
uint16_t did_product, uint16_t did_version,
--
1.7.5.rc3


2011-04-28 22:37:03

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 07/13] Unify inquiry results and advertises

Adapter needs to have only one method to allow discovery results
integration for both interfaces: hciops and mgmtops. This patch
moves the code related to advertises parsing to the same function
that handles inquiry results.
---
src/adapter.c | 80 ++++++++++++++++++++++-----------------------------------
src/adapter.h | 8 ++---
src/event.c | 25 +++---------------
3 files changed, 38 insertions(+), 75 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index f2be3ba..7612eb6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3082,43 +3082,6 @@ static void dev_prepend_uuid(gpointer data, gpointer user_data)
dev->services = g_slist_prepend(dev->services, g_strdup(new_uuid));
}

-void adapter_update_device_from_info(struct btd_adapter *adapter,
- bdaddr_t bdaddr, int8_t rssi,
- uint8_t evt_type, const char *name,
- GSList *services, int flags)
-{
- struct remote_dev_info *dev;
- gboolean new_dev;
-
- dev = get_found_dev(adapter, &bdaddr, &new_dev);
-
- if (new_dev) {
- dev->le = TRUE;
- dev->evt_type = evt_type;
- } else if (dev->rssi == rssi)
- return;
-
- dev->rssi = rssi;
-
- adapter->found_devices = g_slist_sort(adapter->found_devices,
- (GCompareFunc) dev_rssi_cmp);
-
- g_slist_foreach(services, remove_same_uuid, dev);
- g_slist_foreach(services, dev_prepend_uuid, dev);
-
- if (flags >= 0)
- dev->flags = flags;
-
- if (name) {
- g_free(dev->name);
- dev->name = g_strdup(name);
- }
-
- /* FIXME: check if other information was changed before emitting the
- * signal */
- adapter_emit_device_found(adapter, dev);
-}
-
static int remote_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
uint8_t *data, gboolean *legacy)
{
@@ -3155,13 +3118,15 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)
}

void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
- uint32_t class, int8_t rssi, uint8_t *data)
+ uint8_t bda_type, uint32_t class,
+ int8_t rssi, uint8_t *data,
+ size_t eir_size)
{
struct remote_dev_info *dev;
struct eir_data eir_data;
char *name;
- gboolean new_dev, legacy;
- name_status_t name_status;
+ gboolean new_dev, legacy, le;
+ name_status_t name_status = NAME_NOT_REQUIRED;
const char *dev_name;
int err, type;

@@ -3172,17 +3137,30 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
return;
}

- if (remote_legacy_pairing(&adapter->bdaddr, bdaddr, data, &legacy) < 0)
- legacy = TRUE;
-
name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
- type = adapter_get_discover_type(adapter);

- if (!name && type & DISC_RESOLVNAME &&
- adapter_has_discov_sessions(adapter))
- name_status = NAME_REQUIRED;
- else
- name_status = NAME_NOT_REQUIRED;
+ switch (bda_type) {
+ case BDADDR_TYPE_LE_PUBLIC:
+ case BRADDR_TYPE_LE_RANDOM:
+ le = TRUE;
+ legacy = FALSE;
+ break;
+ default:
+ /* BDADDR_TYPE_BR */
+ le = FALSE;
+ if (remote_legacy_pairing(&adapter->bdaddr, bdaddr,
+ data, &legacy) < 0)
+ legacy = TRUE;
+
+ type = adapter_get_discover_type(adapter);
+
+ if (!name && type & DISC_RESOLVNAME &&
+ adapter_has_discov_sessions(adapter))
+ name_status = NAME_REQUIRED;
+ else
+ name_status = NAME_NOT_REQUIRED;
+ break;
+ }

/* Complete EIR names are always used. Shortened EIR names are only
* used if there is no name already in storage. */
@@ -3214,6 +3192,10 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
dev->class = class;
dev->legacy = legacy;
dev->name_status = name_status;
+
+ if (eir_data.flags >= 0)
+ dev->flags = eir_data.flags;
+
} else if (dev->rssi == rssi)
goto done;

diff --git a/src/adapter.h b/src/adapter.h
index 94707e5..931be37 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -118,12 +118,10 @@ int adapter_get_state(struct btd_adapter *adapter);
int adapter_get_discover_type(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,
- bdaddr_t bdaddr, int8_t rssi,
- uint8_t evt_type, const char *name,
- GSList *services, int flags);
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
- uint32_t class, int8_t rssi, uint8_t *data);
+ uint8_t bda_type, uint32_t class,
+ int8_t rssi, uint8_t *data,
+ size_t eir_size);
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);
diff --git a/src/event.c b/src/event.c
index 263d428..84a51cf 100644
--- a/src/event.c
+++ b/src/event.c
@@ -250,19 +250,10 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}

-static void free_eir_data(struct eir_data *eir)
-{
- g_slist_foreach(eir->services, (GFunc) g_free, NULL);
- g_slist_free(eir->services);
- g_free(eir->name);
-}
-
void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
{
struct btd_adapter *adapter;
- struct eir_data eir_data;
int8_t rssi;
- int err;

adapter = manager_find_adapter(local);
if (adapter == NULL) {
@@ -270,19 +261,10 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
return;
}

- memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, info->data, info->length);
- if (err < 0)
- error("Error parsing advertising data: %s (%d)",
- strerror(-err), -err);
-
rssi = *(info->data + info->length);

- adapter_update_device_from_info(adapter, info->bdaddr, rssi,
- info->evt_type, eir_data.name,
- eir_data.services, eir_data.flags);
-
- free_eir_data(&eir_data);
+ adapter_update_found_devices(adapter, &info->bdaddr, info->bdaddr_type,
+ 0, rssi, info->data, info->length);
}

static void update_lastseen(bdaddr_t *sba, bdaddr_t *dba)
@@ -336,7 +318,8 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}

- adapter_update_found_devices(adapter, peer, class, rssi, data);
+ adapter_update_found_devices(adapter, peer, BDADDR_TYPE_BR, class,
+ rssi, data, EIR_DATA_LENGTH);

}

--
1.7.5.rc3


2011-04-28 22:37:02

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 06/13] Don't resolve name if the name is in the storage

---
src/adapter.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index dbdee8f..f2be3ba 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3163,7 +3163,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
gboolean new_dev, legacy;
name_status_t name_status;
const char *dev_name;
- int err;
+ int err, type;

memset(&eir_data, 0, sizeof(eir_data));
err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
@@ -3172,17 +3172,17 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
return;
}

- /* the inquiry result can be triggered by NON D-Bus client */
- if (adapter_get_discover_type(adapter) & DISC_RESOLVNAME &&
- adapter_has_discov_sessions(adapter))
- name_status = NAME_REQUIRED;
- else
- name_status = NAME_NOT_REQUIRED;
-
if (remote_legacy_pairing(&adapter->bdaddr, bdaddr, data, &legacy) < 0)
legacy = TRUE;

name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
+ type = adapter_get_discover_type(adapter);
+
+ if (!name && type & DISC_RESOLVNAME &&
+ adapter_has_discov_sessions(adapter))
+ name_status = NAME_REQUIRED;
+ else
+ name_status = NAME_NOT_REQUIRED;

/* Complete EIR names are always used. Shortened EIR names are only
* used if there is no name already in storage. */
--
1.7.5.rc3


2011-04-28 22:37:01

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 05/13] Cleanup read name and alias from storage

---
src/adapter.c | 37 ++++++++++++++++++++++++-------------
1 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c14e6e0..dbdee8f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3142,13 +3142,24 @@ static int remote_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
return 0;
}

+static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)
+{
+ char local_addr[18], peer_addr[18], filename[PATH_MAX + 1];
+
+ ba2str(local, local_addr);
+ ba2str(peer, peer_addr);
+
+ create_name(filename, PATH_MAX, STORAGEDIR, local_addr, file);
+
+ return textfile_get(filename, peer_addr);
+}
+
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint32_t class, int8_t rssi, uint8_t *data)
{
- char local_addr[18], peer_addr[18], filename[PATH_MAX + 1];
struct remote_dev_info *dev;
struct eir_data eir_data;
- char *alias, *name;
+ char *name;
gboolean new_dev, legacy;
name_status_t name_status;
const char *dev_name;
@@ -3168,18 +3179,11 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
else
name_status = NAME_NOT_REQUIRED;

- ba2str(&adapter->bdaddr, local_addr);
- ba2str(bdaddr, peer_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases");
- alias = textfile_get(filename, peer_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
- name = textfile_get(filename, peer_addr);
-
if (remote_legacy_pairing(&adapter->bdaddr, bdaddr, data, &legacy) < 0)
legacy = TRUE;

+ name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
+
/* Complete EIR names are always used. Shortened EIR names are only
* used if there is no name already in storage. */
dev_name = name;
@@ -3196,18 +3200,22 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
dev = get_found_dev(adapter, bdaddr, &new_dev);

if (new_dev) {
+ char *alias;
if (dev_name)
dev->name = g_strdup(dev_name);

- if (alias)
+ alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");
+ if (alias) {
dev->alias = g_strdup(alias);
+ free(alias);
+ }

dev->le = FALSE;
dev->class = class;
dev->legacy = legacy;
dev->name_status = name_status;
} else if (dev->rssi == rssi)
- return;
+ goto done;

dev->rssi = rssi;

@@ -3218,6 +3226,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
g_slist_foreach(eir_data.services, dev_prepend_uuid, dev);

adapter_emit_device_found(adapter, dev);
+
+done:
+ free(name);
}

int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
--
1.7.5.rc3


2011-04-28 22:37:00

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 04/13] Move legacy verification to a new function

---
src/adapter.c | 34 ++++++++++++++++++++++++----------
1 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 3a671e6..c14e6e0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3119,6 +3119,29 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
adapter_emit_device_found(adapter, dev);
}

+static int remote_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
+ uint8_t *data, gboolean *legacy)
+{
+ unsigned char features[8];
+ int err;
+
+ if (data) {
+ *legacy = FALSE;
+ return 0;
+ }
+
+ err = read_remote_features(local, peer, NULL, features);
+ if (err < 0)
+ return err;
+
+ if (features[0] & 0x01)
+ *legacy = FALSE;
+ else
+ *legacy = TRUE;
+
+ return 0;
+}
+
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint32_t class, int8_t rssi, uint8_t *data)
{
@@ -3128,7 +3151,6 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
char *alias, *name;
gboolean new_dev, legacy;
name_status_t name_status;
- unsigned char features[8];
const char *dev_name;
int err;

@@ -3155,15 +3177,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
name = textfile_get(filename, peer_addr);

- if (data)
- legacy = FALSE;
- else if (read_remote_features(&adapter->bdaddr, bdaddr, NULL,
- features) == 0) {
- if (features[0] & 0x01)
- legacy = FALSE;
- else
- legacy = TRUE;
- } else
+ if (remote_legacy_pairing(&adapter->bdaddr, bdaddr, data, &legacy) < 0)
legacy = TRUE;

/* Complete EIR names are always used. Shortened EIR names are only
--
1.7.5.rc3


2011-04-28 22:36:59

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 03/13] Initial device found cleanup

Moves EIR parsing call and stored name loading to adapter. This patch
doesn't change the implemented logic, it is only the initial step to
integrated inquiry results and LE advertises.
---
src/adapter.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++------
src/adapter.h | 4 +--
src/event.c | 59 +-----------------------------------------------
3 files changed, 64 insertions(+), 68 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index f7bbc3e..3a671e6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -58,6 +58,7 @@
#include "storage.h"
#include "attrib-server.h"
#include "att.h"
+#include "eir.h"

/* Interleaved discovery window: 5.12 sec */
#define GAP_INTER_DISCOV_WIN 5120
@@ -3119,18 +3120,70 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
}

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,
- GSList *services, name_status_t name_status)
+ uint32_t class, int8_t rssi, uint8_t *data)
{
+ char local_addr[18], peer_addr[18], filename[PATH_MAX + 1];
struct remote_dev_info *dev;
- gboolean new_dev;
+ struct eir_data eir_data;
+ char *alias, *name;
+ gboolean new_dev, legacy;
+ name_status_t name_status;
+ unsigned char features[8];
+ const char *dev_name;
+ int err;
+
+ memset(&eir_data, 0, sizeof(eir_data));
+ err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
+ if (err < 0) {
+ error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
+ return;
+ }
+
+ /* the inquiry result can be triggered by NON D-Bus client */
+ if (adapter_get_discover_type(adapter) & DISC_RESOLVNAME &&
+ adapter_has_discov_sessions(adapter))
+ name_status = NAME_REQUIRED;
+ else
+ name_status = NAME_NOT_REQUIRED;
+
+ ba2str(&adapter->bdaddr, local_addr);
+ ba2str(bdaddr, peer_addr);
+
+ create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases");
+ alias = textfile_get(filename, peer_addr);
+
+ create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
+ name = textfile_get(filename, peer_addr);
+
+ if (data)
+ legacy = FALSE;
+ else if (read_remote_features(&adapter->bdaddr, bdaddr, NULL,
+ features) == 0) {
+ if (features[0] & 0x01)
+ legacy = FALSE;
+ else
+ legacy = TRUE;
+ } else
+ legacy = TRUE;
+
+ /* Complete EIR names are always used. Shortened EIR names are only
+ * used if there is no name already in storage. */
+ dev_name = name;
+ if (eir_data.name != NULL) {
+ if (eir_data.name_complete) {
+ write_device_name(&adapter->bdaddr, bdaddr,
+ eir_data.name);
+ name_status = NAME_NOT_REQUIRED;
+ dev_name = eir_data.name;
+ } else if (name == NULL)
+ dev_name = eir_data.name;
+ }

dev = get_found_dev(adapter, bdaddr, &new_dev);

if (new_dev) {
- if (name)
- dev->name = g_strdup(name);
+ if (dev_name)
+ dev->name = g_strdup(dev_name);

if (alias)
dev->alias = g_strdup(alias);
@@ -3147,8 +3200,8 @@ 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);

- g_slist_foreach(services, remove_same_uuid, dev);
- g_slist_foreach(services, dev_prepend_uuid, dev);
+ g_slist_foreach(eir_data.services, remove_same_uuid, dev);
+ g_slist_foreach(eir_data.services, dev_prepend_uuid, dev);

adapter_emit_device_found(adapter, dev);
}
diff --git a/src/adapter.h b/src/adapter.h
index 7cc7c02..94707e5 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -123,9 +123,7 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
uint8_t evt_type, const char *name,
GSList *services, int 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,
- GSList *services, name_status_t name_status);
+ uint32_t class, int8_t rssi, uint8_t *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);
diff --git a/src/event.c b/src/event.c
index b69cea7..263d428 100644
--- a/src/event.c
+++ b/src/event.c
@@ -310,18 +310,8 @@ static void update_lastused(bdaddr_t *sba, bdaddr_t *dba)
void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
int8_t rssi, uint8_t *data)
{
- char filename[PATH_MAX + 1];
struct btd_adapter *adapter;
- char local_addr[18], peer_addr[18], *alias, *name;
- name_status_t name_status;
- struct eir_data eir_data;
- int state, err;
- dbus_bool_t legacy;
- unsigned char features[8];
- const char *dev_name;
-
- ba2str(local, local_addr);
- ba2str(peer, peer_addr);
+ int state;

adapter = manager_find_adapter(local);
if (!adapter) {
@@ -346,53 +336,8 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}

- /* the inquiry result can be triggered by NON D-Bus client */
- if (adapter_get_discover_type(adapter) & DISC_RESOLVNAME &&
- adapter_has_discov_sessions(adapter))
- name_status = NAME_REQUIRED;
- else
- name_status = NAME_NOT_REQUIRED;
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases");
- alias = textfile_get(filename, peer_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
- name = textfile_get(filename, peer_addr);
-
- if (data)
- legacy = FALSE;
- else if (read_remote_features(local, peer, NULL, features) == 0) {
- if (features[0] & 0x01)
- legacy = FALSE;
- else
- legacy = TRUE;
- } else
- legacy = TRUE;
-
- memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
- if (err < 0)
- error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
-
- /* Complete EIR names are always used. Shortened EIR names are only
- * used if there is no name already in storage. */
- dev_name = name;
- if (eir_data.name != NULL) {
- if (eir_data.name_complete) {
- write_device_name(local, peer, eir_data.name);
- name_status = NAME_NOT_REQUIRED;
- dev_name = eir_data.name;
- } else if (name == NULL)
- dev_name = eir_data.name;
- }
-
- adapter_update_found_devices(adapter, peer, rssi, class, dev_name,
- alias, legacy, eir_data.services,
- name_status);
+ adapter_update_found_devices(adapter, peer, class, rssi, data);

- free_eir_data(&eir_data);
- free(name);
- free(alias);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-04-28 22:36:57

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 01/13] Move EIR related functions to a new file

---
Makefile.am | 2 +-
plugins/hciops.c | 170 +----------------------------
src/eir.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eir.h | 42 +++++++
src/event.c | 126 +---------------------
src/sdpd.h | 14 ---
6 files changed, 369 insertions(+), 305 deletions(-)
create mode 100644 src/eir.c
create mode 100644 src/eir.h

diff --git a/Makefile.am b/Makefile.am
index 9703bf0..27a1c29 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -251,7 +251,7 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/device.h src/device.c \
src/dbus-common.c src/dbus-common.h \
src/event.h src/event.c \
- src/oob.h src/oob.c
+ src/oob.h src/oob.c src/eir.h src/eir.c
src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
@CAPNG_LIBS@ -ldl -lrt
src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
diff --git a/plugins/hciops.c b/plugins/hciops.c
index d1156e2..c2aa614 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -51,6 +51,7 @@
#include "event.h"
#include "manager.h"
#include "oob.h"
+#include "eir.h"

static int child_pipe[2] = { -1, -1 };

@@ -65,11 +66,6 @@ enum {
PENDING_NAME,
};

-struct uuid_info {
- uuid_t uuid;
- uint8_t svc_hint;
-};
-
struct bt_conn {
struct dev_info *dev;
bdaddr_t bdaddr;
@@ -1396,167 +1392,6 @@ static void read_local_features_complete(int index,
init_adapter(index);
}

-#define SIZEOF_UUID128 16
-
-static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
-{
- int i, k, uuid_count = 0;
- uint16_t len = *eir_len;
- uint8_t *uuid128;
- gboolean truncated = FALSE;
-
- /* Store UUIDs in place, skip 2 bytes to write type and length later */
- uuid128 = ptr + 2;
-
- for (; list; list = list->next) {
- struct uuid_info *uuid = list->data;
- uint8_t *uuid128_data = uuid->uuid.value.uuid128.data;
-
- if (uuid->uuid.type != SDP_UUID128)
- continue;
-
- /* Stop if not enough space to put next UUID128 */
- if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
- truncated = TRUE;
- break;
- }
-
- /* Check for duplicates, EIR data is Little Endian */
- for (i = 0; i < uuid_count; i++) {
- for (k = 0; k < SIZEOF_UUID128; k++) {
- if (uuid128[i * SIZEOF_UUID128 + k] !=
- uuid128_data[SIZEOF_UUID128 - 1 - k])
- break;
- }
- if (k == SIZEOF_UUID128)
- break;
- }
-
- if (i < uuid_count)
- continue;
-
- /* EIR data is Little Endian */
- for (k = 0; k < SIZEOF_UUID128; k++)
- uuid128[uuid_count * SIZEOF_UUID128 + k] =
- uuid128_data[SIZEOF_UUID128 - 1 - k];
-
- len += SIZEOF_UUID128;
- uuid_count++;
- }
-
- if (uuid_count > 0 || truncated) {
- /* EIR Data length */
- ptr[0] = (uuid_count * SIZEOF_UUID128) + 1;
- /* EIR Data type */
- ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
- len += 2;
- *eir_len = len;
- }
-}
-
-static void create_ext_inquiry_response(int index, uint8_t *data)
-{
- struct dev_info *dev = &devs[index];
- GSList *l;
- uint8_t *ptr = data;
- uint16_t eir_len = 0;
- uint16_t uuid16[EIR_DATA_LENGTH / 2];
- int i, uuid_count = 0;
- gboolean truncated = FALSE;
- size_t name_len;
-
- name_len = strlen(dev->name);
-
- if (name_len > 0) {
- /* EIR Data type */
- if (name_len > 48) {
- name_len = 48;
- ptr[1] = EIR_NAME_SHORT;
- } else
- ptr[1] = EIR_NAME_COMPLETE;
-
- /* EIR Data length */
- ptr[0] = name_len + 1;
-
- memcpy(ptr + 2, dev->name, name_len);
-
- eir_len += (name_len + 2);
- ptr += (name_len + 2);
- }
-
- if (dev->tx_power != 0) {
- *ptr++ = 2;
- *ptr++ = EIR_TX_POWER;
- *ptr++ = (uint8_t) dev->tx_power;
- eir_len += 3;
- }
-
- if (dev->did_vendor != 0x0000) {
- uint16_t source = 0x0002;
- *ptr++ = 9;
- *ptr++ = EIR_DEVICE_ID;
- *ptr++ = (source & 0x00ff);
- *ptr++ = (source & 0xff00) >> 8;
- *ptr++ = (dev->did_vendor & 0x00ff);
- *ptr++ = (dev->did_vendor & 0xff00) >> 8;
- *ptr++ = (dev->did_product & 0x00ff);
- *ptr++ = (dev->did_product & 0xff00) >> 8;
- *ptr++ = (dev->did_version & 0x00ff);
- *ptr++ = (dev->did_version & 0xff00) >> 8;
- eir_len += 10;
- }
-
- /* Group all UUID16 types */
- for (l = dev->uuids; l != NULL; l = g_slist_next(l)) {
- struct uuid_info *uuid = l->data;
-
- if (uuid->uuid.type != SDP_UUID16)
- continue;
-
- if (uuid->uuid.value.uuid16 < 0x1100)
- continue;
-
- if (uuid->uuid.value.uuid16 == PNP_INFO_SVCLASS_ID)
- continue;
-
- /* Stop if not enough space to put next UUID16 */
- if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
- truncated = TRUE;
- break;
- }
-
- /* Check for duplicates */
- for (i = 0; i < uuid_count; i++)
- if (uuid16[i] == uuid->uuid.value.uuid16)
- break;
-
- if (i < uuid_count)
- continue;
-
- uuid16[uuid_count++] = uuid->uuid.value.uuid16;
- eir_len += sizeof(uint16_t);
- }
-
- if (uuid_count > 0) {
- /* EIR Data length */
- ptr[0] = (uuid_count * sizeof(uint16_t)) + 1;
- /* EIR Data type */
- ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
-
- ptr += 2;
- eir_len += 2;
-
- for (i = 0; i < uuid_count; i++) {
- *ptr++ = (uuid16[i] & 0x00ff);
- *ptr++ = (uuid16[i] & 0xff00) >> 8;
- }
- }
-
- /* Group all UUID128 types */
- if (eir_len <= EIR_DATA_LENGTH - 2)
- eir_generate_uuid128(dev->uuids, ptr, &eir_len);
-}
-
static void update_ext_inquiry_response(int index)
{
struct dev_info *dev = &devs[index];
@@ -1575,7 +1410,8 @@ static void update_ext_inquiry_response(int index)

memset(&cp, 0, sizeof(cp));

- create_ext_inquiry_response(index, cp.data);
+ eir_create(dev->name, dev->tx_power, dev->did_vendor, dev->did_product,
+ dev->did_version, dev->uuids, cp.data);

if (memcmp(cp.data, dev->eir, sizeof(cp.data)) == 0)
return;
diff --git a/src/eir.c b/src/eir.c
new file mode 100644
index 0000000..d827c7e
--- /dev/null
+++ b/src/eir.c
@@ -0,0 +1,320 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <glib.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+
+#include "glib-helper.h"
+#include "eir.h"
+
+#define EIR_FLAGS 0x01 /* flags */
+#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
+#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
+#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
+#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
+#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
+#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
+#define EIR_NAME_SHORT 0x08 /* shortened local name */
+#define EIR_NAME_COMPLETE 0x09 /* complete local name */
+#define EIR_TX_POWER 0x0A /* transmit power level */
+#define EIR_DEVICE_ID 0x10 /* device ID */
+
+int eir_parse(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;
+ uint8_t *uuid16 = NULL;
+ uint8_t *uuid32 = NULL;
+ uint8_t *uuid128 = NULL;
+ uuid_t service;
+ char *uuid_str;
+ unsigned int i;
+
+ eir->flags = -1;
+
+ /* No EIR data to parse */
+ if (eir_data == NULL || eir_length == 0)
+ return 0;
+
+ 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;
+ 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;
+ eir_data += field_len + 1;
+ }
+
+ /* Bail out if got incorrect length */
+ if (len > eir_length)
+ return -EINVAL;
+
+ total = uuid16_count + uuid32_count + uuid128_count;
+
+ /* No UUIDs were parsed, so skip code below */
+ if (!total)
+ return 0;
+
+ /* 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);
+ eir->services = g_slist_append(eir->services, 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);
+ eir->services = g_slist_append(eir->services, 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);
+ eir->services = g_slist_append(eir->services, uuid_str);
+ uuid128 += 16;
+ }
+
+ return 0;
+}
+
+#define SIZEOF_UUID128 16
+
+static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
+{
+ int i, k, uuid_count = 0;
+ uint16_t len = *eir_len;
+ uint8_t *uuid128;
+ gboolean truncated = FALSE;
+
+ /* Store UUIDs in place, skip 2 bytes to write type and length later */
+ uuid128 = ptr + 2;
+
+ for (; list; list = list->next) {
+ struct uuid_info *uuid = list->data;
+ uint8_t *uuid128_data = uuid->uuid.value.uuid128.data;
+
+ if (uuid->uuid.type != SDP_UUID128)
+ continue;
+
+ /* Stop if not enough space to put next UUID128 */
+ if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
+ truncated = TRUE;
+ break;
+ }
+
+ /* Check for duplicates, EIR data is Little Endian */
+ for (i = 0; i < uuid_count; i++) {
+ for (k = 0; k < SIZEOF_UUID128; k++) {
+ if (uuid128[i * SIZEOF_UUID128 + k] !=
+ uuid128_data[SIZEOF_UUID128 - 1 - k])
+ break;
+ }
+ if (k == SIZEOF_UUID128)
+ break;
+ }
+
+ if (i < uuid_count)
+ continue;
+
+ /* EIR data is Little Endian */
+ for (k = 0; k < SIZEOF_UUID128; k++)
+ uuid128[uuid_count * SIZEOF_UUID128 + k] =
+ uuid128_data[SIZEOF_UUID128 - 1 - k];
+
+ len += SIZEOF_UUID128;
+ uuid_count++;
+ }
+
+ if (uuid_count > 0 || truncated) {
+ /* EIR Data length */
+ ptr[0] = (uuid_count * SIZEOF_UUID128) + 1;
+ /* EIR Data type */
+ ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
+ len += 2;
+ *eir_len = len;
+ }
+}
+
+void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
+ uint16_t did_product, uint16_t did_version,
+ GSList *uuids, uint8_t *data)
+{
+ GSList *l;
+ uint8_t *ptr = data;
+ uint16_t eir_len = 0;
+ uint16_t uuid16[EIR_DATA_LENGTH / 2];
+ int i, uuid_count = 0;
+ gboolean truncated = FALSE;
+ size_t name_len;
+
+ name_len = strlen(name);
+
+ if (name_len > 0) {
+ /* EIR Data type */
+ if (name_len > 48) {
+ name_len = 48;
+ ptr[1] = EIR_NAME_SHORT;
+ } else
+ ptr[1] = EIR_NAME_COMPLETE;
+
+ /* EIR Data length */
+ ptr[0] = name_len + 1;
+
+ memcpy(ptr + 2, name, name_len);
+
+ eir_len += (name_len + 2);
+ ptr += (name_len + 2);
+ }
+
+ if (tx_power != 0) {
+ *ptr++ = 2;
+ *ptr++ = EIR_TX_POWER;
+ *ptr++ = (uint8_t) tx_power;
+ eir_len += 3;
+ }
+
+ if (did_vendor != 0x0000) {
+ uint16_t source = 0x0002;
+ *ptr++ = 9;
+ *ptr++ = EIR_DEVICE_ID;
+ *ptr++ = (source & 0x00ff);
+ *ptr++ = (source & 0xff00) >> 8;
+ *ptr++ = (did_vendor & 0x00ff);
+ *ptr++ = (did_vendor & 0xff00) >> 8;
+ *ptr++ = (did_product & 0x00ff);
+ *ptr++ = (did_product & 0xff00) >> 8;
+ *ptr++ = (did_version & 0x00ff);
+ *ptr++ = (did_version & 0xff00) >> 8;
+ eir_len += 10;
+ }
+
+ /* Group all UUID16 types */
+ for (l = uuids; l != NULL; l = g_slist_next(l)) {
+ struct uuid_info *uuid = l->data;
+
+ if (uuid->uuid.type != SDP_UUID16)
+ continue;
+
+ if (uuid->uuid.value.uuid16 < 0x1100)
+ continue;
+
+ if (uuid->uuid.value.uuid16 == PNP_INFO_SVCLASS_ID)
+ continue;
+
+ /* Stop if not enough space to put next UUID16 */
+ if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
+ truncated = TRUE;
+ break;
+ }
+
+ /* Check for duplicates */
+ for (i = 0; i < uuid_count; i++)
+ if (uuid16[i] == uuid->uuid.value.uuid16)
+ break;
+
+ if (i < uuid_count)
+ continue;
+
+ uuid16[uuid_count++] = uuid->uuid.value.uuid16;
+ eir_len += sizeof(uint16_t);
+ }
+
+ if (uuid_count > 0) {
+ /* EIR Data length */
+ ptr[0] = (uuid_count * sizeof(uint16_t)) + 1;
+ /* EIR Data type */
+ ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
+
+ ptr += 2;
+ eir_len += 2;
+
+ for (i = 0; i < uuid_count; i++) {
+ *ptr++ = (uuid16[i] & 0x00ff);
+ *ptr++ = (uuid16[i] & 0xff00) >> 8;
+ }
+ }
+
+ /* Group all UUID128 types */
+ if (eir_len <= EIR_DATA_LENGTH - 2)
+ eir_generate_uuid128(uuids, ptr, &eir_len);
+}
diff --git a/src/eir.h b/src/eir.h
new file mode 100644
index 0000000..c7699eb
--- /dev/null
+++ b/src/eir.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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
+ *
+ */
+
+#define EIR_DATA_LENGTH 240
+
+struct uuid_info {
+ uuid_t uuid;
+ uint8_t svc_hint;
+};
+
+struct eir_data {
+ GSList *services;
+ int flags;
+ char *name;
+ gboolean name_complete;
+};
+
+int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length);
+void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
+ uint16_t did_product, uint16_t did_version,
+ GSList *uuids, uint8_t *data);
diff --git a/src/event.c b/src/event.c
index b873000..b69cea7 100644
--- a/src/event.c
+++ b/src/event.c
@@ -57,13 +57,7 @@
#include "storage.h"
#include "event.h"
#include "sdpd.h"
-
-struct eir_data {
- GSList *services;
- int flags;
- char *name;
- gboolean name_complete;
-};
+#include "eir.h"

static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
struct btd_adapter **adapter,
@@ -256,120 +250,6 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}

-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;
- uint8_t *uuid16 = NULL;
- uint8_t *uuid32 = NULL;
- uint8_t *uuid128 = NULL;
- uuid_t service;
- char *uuid_str;
- unsigned int i;
-
- eir->flags = -1;
-
- /* No EIR data to parse */
- if (eir_data == NULL || eir_length == 0)
- return 0;
-
- 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;
- 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;
- eir_data += field_len + 1;
- }
-
- /* Bail out if got incorrect length */
- if (len > eir_length)
- return -EINVAL;
-
- total = uuid16_count + uuid32_count + uuid128_count;
-
- /* No UUIDs were parsed, so skip code below */
- if (!total)
- return 0;
-
- /* 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);
- eir->services = g_slist_append(eir->services, 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);
- eir->services = g_slist_append(eir->services, 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);
- eir->services = g_slist_append(eir->services, uuid_str);
- uuid128 += 16;
- }
-
- return 0;
-}
-
static void free_eir_data(struct eir_data *eir)
{
g_slist_foreach(eir->services, (GFunc) g_free, NULL);
@@ -391,7 +271,7 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
}

memset(&eir_data, 0, sizeof(eir_data));
- err = parse_eir_data(&eir_data, info->data, info->length);
+ err = eir_parse(&eir_data, info->data, info->length);
if (err < 0)
error("Error parsing advertising data: %s (%d)",
strerror(-err), -err);
@@ -490,7 +370,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
legacy = TRUE;

memset(&eir_data, 0, sizeof(eir_data));
- err = parse_eir_data(&eir_data, data, EIR_DATA_LENGTH);
+ err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
if (err < 0)
error("Error parsing EIR data: %s (%d)", strerror(-err), -err);

diff --git a/src/sdpd.h b/src/sdpd.h
index dc7a256..653736c 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -34,20 +34,6 @@
#define SDPDBG(fmt...)
#endif

-#define EIR_DATA_LENGTH 240
-
-#define EIR_FLAGS 0x01 /* flags */
-#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
-#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
-#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
-#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
-#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
-#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
-#define EIR_NAME_SHORT 0x08 /* shortened local name */
-#define EIR_NAME_COMPLETE 0x09 /* complete local name */
-#define EIR_TX_POWER 0x0A /* transmit power level */
-#define EIR_DEVICE_ID 0x10 /* device ID */
-
typedef struct request {
bdaddr_t device;
bdaddr_t bdaddr;
--
1.7.5.rc3


2011-04-28 22:36:58

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 02/13] Add Bluetooth address type definition

Values defined to LE(public and random) are defined in the Bluetooth
Core Specification. For basic rate, there isn't address type concept.
The constants introduced by this commit will be used to identify the
remote address type, basically to distinguish LE/BR devices before
to request the L2CAP connection.
---
lib/bluetooth.h | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index 738e07a..98b8f1c 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -130,6 +130,10 @@ typedef struct {
#define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})

+#define BDADDR_TYPE_LE_PUBLIC 0x00
+#define BRADDR_TYPE_LE_RANDOM 0x01
+#define BDADDR_TYPE_BR 0xff
+
/* Copy, swap, convert BD Address */
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
--
1.7.5.rc3


2011-05-16 20:49:39

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v3 00/12] Discovery Cleanup

Main changes are:
- Unify advertising reports and inquiry results: mgmt sends device
found event. Device type(BR/LE) are now discovered based on the
EIR flags.
- Logic improvement/cleanup: device found
- Move EIR functions to a new file

Check AD Flags of the EIR data(in the advertising data) doesn't require
kernel socket API changes, broken LE devices can send advertises without
AD flags set, for this case the fallback is to consider it as BR device
and for the connection page timeout.

Open(old) issues: excessive dynamic memory allocation/free for EIR data.
Check if EIR has changed to send another DeviceFound signal, trust on RSSI
value only is not correct.

Bruna Moreira (3):
Remove btd_event_advertising_report
Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH
Drop variable EIR length

Claudio Takahasi (9):
Move EIR related functions to a new file
Initial device found cleanup
Move legacy verification to a new function
Cleanup read name and alias from storage
Don't resolve name if the name is in the storage
Unify inquiry results and advertises
Fix memory leak of EIR data
Change the order to write/read the remote's name
Cleanup inserting new device found entry

Makefile.am | 2 +-
plugins/hciops.c | 188 +++----------------------------
src/adapter.c | 174 ++++++++++++++++++-----------
src/adapter.h | 9 +-
src/eir.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eir.h | 41 +++++++
src/event.c | 217 +-----------------------------------
src/event.h | 1 -
src/sdpd.h | 14 ---
9 files changed, 502 insertions(+), 472 deletions(-)
create mode 100644 src/eir.c
create mode 100644 src/eir.h

--
1.7.5.rc3


2011-05-12 19:10:55

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v2 02/13] Add Bluetooth address type definition

Hi Claudio,

> >> > Values defined to LE(public and random) are defined in the Bluetooth
> >> > Core Specification. For basic rate, there isn't address type concept.
> >> > The constants introduced by this commit will be used to identify the
> >> > remote address type, basically to distinguish LE/BR devices before
> >> > to request the L2CAP connection.
> >> > ---
> >> > lib/bluetooth.h | 4 ++++
> >> > 1 files changed, 4 insertions(+), 0 deletions(-)
> >> >
> >> > diff --git a/lib/bluetooth.h b/lib/bluetooth.h
> >> > index 738e07a..98b8f1c 100644
> >> > --- a/lib/bluetooth.h
> >> > +++ b/lib/bluetooth.h
> >> > @@ -130,6 +130,10 @@ typedef struct {
> >> > #define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
> >> > #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
> >> >
> >> > +#define BDADDR_TYPE_LE_PUBLIC 0x00
> >> > +#define BRADDR_TYPE_LE_RANDOM 0x01
> >> > +#define BDADDR_TYPE_BR 0xff
> >>
> >> Firstly this still needs Marcel's blessing (though I don't really see
> >> any other solution than an address type with three possible values).
> >> Secondly, if this is ever going to be added to the L2CAP socket address
> >> you'd have to have 0x00 as BDADDR_TYPE_BR for backwards compatibility.
> >
> > I am still not 100% convinced, but yes, the default 0x00 then needs to
> > be BDADDR_TYPE_BREDR. Otherwise we break APIs.
>
> Use the kernel advertising cache(for address type) plus a device
> type(LE or BR) field in the mgmt_ev_device_found is another approach.
> Can we proceed with this approach?

lets go with the advertising cache for now. That way we do not have to
worry about potential kernel API/ABI breakage.

We will see how LE devices will evolve and then we know what needs to be
done once the first once hit the market.

Regards

Marcel



2011-05-12 17:55:24

by Claudio Takahasi

[permalink] [raw]
Subject: Re: [PATCH v2 02/13] Add Bluetooth address type definition

Hi Marcel/Johan,

On Wed, May 11, 2011 at 10:20 PM, Marcel Holtmann <[email protected]> wro=
te:
> Hi Johan,
>
>> > Values defined to LE(public and random) are defined in the Bluetooth
>> > Core Specification. For basic rate, there isn't address type concept.
>> > The constants introduced by this commit will be used to identify the
>> > remote address type, basically to distinguish LE/BR devices before
>> > to request the L2CAP connection.
>> > ---
>> > =C2=A0lib/bluetooth.h | =C2=A0 =C2=A04 ++++
>> > =C2=A01 files changed, 4 insertions(+), 0 deletions(-)
>> >
>> > diff --git a/lib/bluetooth.h b/lib/bluetooth.h
>> > index 738e07a..98b8f1c 100644
>> > --- a/lib/bluetooth.h
>> > +++ b/lib/bluetooth.h
>> > @@ -130,6 +130,10 @@ typedef struct {
>> > =C2=A0#define BDADDR_ALL =C2=A0 (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff,=
0xff, 0xff}})
>> > =C2=A0#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
>> >
>> > +#define BDADDR_TYPE_LE_PUBLIC =C2=A0 =C2=A0 =C2=A00x00
>> > +#define BRADDR_TYPE_LE_RANDOM =C2=A0 =C2=A0 =C2=A00x01
>> > +#define BDADDR_TYPE_BR =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0xff
>>
>> Firstly this still needs Marcel's blessing (though I don't really see
>> any other solution than an address type with three possible values).
>> Secondly, if this is ever going to be added to the L2CAP socket address
>> you'd have to have 0x00 as BDADDR_TYPE_BR for backwards compatibility.
>
> I am still not 100% convinced, but yes, the default 0x00 then needs to
> be BDADDR_TYPE_BREDR. Otherwise we break APIs.
>
> Regards
>
> Marcel

Use the kernel advertising cache(for address type) plus a device
type(LE or BR) field in the mgmt_ev_device_found is another approach.
Can we proceed with this approach?

Claudio.

2011-05-12 01:20:28

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v2 02/13] Add Bluetooth address type definition

Hi Johan,

> > Values defined to LE(public and random) are defined in the Bluetooth
> > Core Specification. For basic rate, there isn't address type concept.
> > The constants introduced by this commit will be used to identify the
> > remote address type, basically to distinguish LE/BR devices before
> > to request the L2CAP connection.
> > ---
> > lib/bluetooth.h | 4 ++++
> > 1 files changed, 4 insertions(+), 0 deletions(-)
> >
> > diff --git a/lib/bluetooth.h b/lib/bluetooth.h
> > index 738e07a..98b8f1c 100644
> > --- a/lib/bluetooth.h
> > +++ b/lib/bluetooth.h
> > @@ -130,6 +130,10 @@ typedef struct {
> > #define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
> > #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
> >
> > +#define BDADDR_TYPE_LE_PUBLIC 0x00
> > +#define BRADDR_TYPE_LE_RANDOM 0x01
> > +#define BDADDR_TYPE_BR 0xff
>
> Firstly this still needs Marcel's blessing (though I don't really see
> any other solution than an address type with three possible values).
> Secondly, if this is ever going to be added to the L2CAP socket address
> you'd have to have 0x00 as BDADDR_TYPE_BR for backwards compatibility.

I am still not 100% convinced, but yes, the default 0x00 then needs to
be BDADDR_TYPE_BREDR. Otherwise we break APIs.

Regards

Marcel



2011-05-05 17:34:53

by Claudio Takahasi

[permalink] [raw]
Subject: Re: [PATCH v2 00/13] Discovery Cleanup - Step 1

Hi Johan,

On Thu, May 5, 2011 at 5:34 AM, Johan Hedberg <[email protected]> wro=
te:
> Hi Claudio,
>
> On Tue, May 03, 2011, Claudio Takahasi wrote:
>> This patch series is the first step to cleanup the device discovery
>> procedure. The main changes are:
>> =C2=A0 - Unify advertising reports and inquiry results: mgmt sends
>> =C2=A0 =C2=A0 one device found event
>> =C2=A0 - Logic improvement/cleanup: device found
>> =C2=A0 - Move EIR functions to a new file
>> =C2=A0 - Add BDADDR type constants: necessary L2CAP connections and bond=
ing
>>
>>
>>
>> Bruna Moreira (3):
>> =C2=A0 Remove btd_event_advertising_report
>> =C2=A0 Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH
>> =C2=A0 Drop variable EIR length
>>
>> Claudio Takahasi (10):
>> =C2=A0 Move EIR related functions to a new file
>> =C2=A0 Add Bluetooth address type definition
>> =C2=A0 Initial device found cleanup
>> =C2=A0 Move legacy verification to a new function
>> =C2=A0 Cleanup read name and alias from storage
>> =C2=A0 Don't resolve name if the name is in the storage
>> =C2=A0 Unify inquiry results and advertises
>> =C2=A0 Fix memory leak of EIR data
>> =C2=A0 Change the order to write/read the remote's name
>> =C2=A0 Cleanup inserting new device found entry
>>
>> =C2=A0Makefile.am =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A02 +-
>> =C2=A0lib/bluetooth.h =C2=A0 | =C2=A0 =C2=A04 +
>> =C2=A0plugins/hciops.c =C2=A0| =C2=A0202 +++++--------------------------=
--
>> =C2=A0plugins/mgmtops.c | =C2=A0 =C2=A03 +-
>> =C2=A0src/adapter.c =C2=A0 =C2=A0 | =C2=A0182 +++++++++++++++++++-------=
----
>> =C2=A0src/adapter.h =C2=A0 =C2=A0 | =C2=A0 =C2=A09 +-
>> =C2=A0src/eir.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0328 ++++++++++++++++=
+++++++++++++++++++++++++++++++++++++
>> =C2=A0src/eir.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 41 +++++++
>> =C2=A0src/event.c =C2=A0 =C2=A0 =C2=A0 | =C2=A0224 +--------------------=
---------------
>> =C2=A0src/event.h =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A05 +-
>> =C2=A0src/sdpd.h =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 14 ---
>> =C2=A011 files changed, 530 insertions(+), 484 deletions(-)
>> =C2=A0create mode 100644 src/eir.c
>> =C2=A0create mode 100644 src/eir.h
>
> These patches don't seem to apply any more after I applied Andr=C3=A9s
> patches. (also, I can't really try applying anything else except 1/13
> since 2/13 is already the address type patch which is still being
> discussed).
>
> Johan
>

I am aware of this conflict. Patches are already rebased, but I will
wait Marcel's blessing(for the address type) before to send again the
patch series.

BR,
Claudio.

2011-05-05 08:34:17

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v2 00/13] Discovery Cleanup - Step 1

Hi Claudio,

On Tue, May 03, 2011, Claudio Takahasi wrote:
> This patch series is the first step to cleanup the device discovery
> procedure. The main changes are:
> - Unify advertising reports and inquiry results: mgmt sends
> one device found event
> - Logic improvement/cleanup: device found
> - Move EIR functions to a new file
> - Add BDADDR type constants: necessary L2CAP connections and bonding
>
>
>
> Bruna Moreira (3):
> Remove btd_event_advertising_report
> Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH
> Drop variable EIR length
>
> Claudio Takahasi (10):
> Move EIR related functions to a new file
> Add Bluetooth address type definition
> Initial device found cleanup
> Move legacy verification to a new function
> Cleanup read name and alias from storage
> Don't resolve name if the name is in the storage
> Unify inquiry results and advertises
> Fix memory leak of EIR data
> Change the order to write/read the remote's name
> Cleanup inserting new device found entry
>
> Makefile.am | 2 +-
> lib/bluetooth.h | 4 +
> plugins/hciops.c | 202 +++++----------------------------
> plugins/mgmtops.c | 3 +-
> src/adapter.c | 182 +++++++++++++++++++-----------
> src/adapter.h | 9 +-
> src/eir.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/eir.h | 41 +++++++
> src/event.c | 224 +-----------------------------------
> src/event.h | 5 +-
> src/sdpd.h | 14 ---
> 11 files changed, 530 insertions(+), 484 deletions(-)
> create mode 100644 src/eir.c
> create mode 100644 src/eir.h

These patches don't seem to apply any more after I applied Andr?s
patches. (also, I can't really try applying anything else except 1/13
since 2/13 is already the address type patch which is still being
discussed).

Johan

2011-05-05 00:31:34

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH v2 02/13] Add Bluetooth address type definition

Hi,

On 09:03 Wed 04 May, Johan Hedberg wrote:
> Hi Claudio,
>
> On Tue, May 03, 2011, Claudio Takahasi wrote:
> > Values defined to LE(public and random) are defined in the Bluetooth
> > Core Specification. For basic rate, there isn't address type concept.
> > The constants introduced by this commit will be used to identify the
> > remote address type, basically to distinguish LE/BR devices before
> > to request the L2CAP connection.
> > ---
> > lib/bluetooth.h | 4 ++++
> > 1 files changed, 4 insertions(+), 0 deletions(-)
> >
> > diff --git a/lib/bluetooth.h b/lib/bluetooth.h
> > index 738e07a..98b8f1c 100644
> > --- a/lib/bluetooth.h
> > +++ b/lib/bluetooth.h
> > @@ -130,6 +130,10 @@ typedef struct {
> > #define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
> > #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
> >
> > +#define BDADDR_TYPE_LE_PUBLIC 0x00
> > +#define BRADDR_TYPE_LE_RANDOM 0x01
> > +#define BDADDR_TYPE_BR 0xff
>
> Firstly this still needs Marcel's blessing (though I don't really see
> any other solution than an address type with three possible values).
> Secondly, if this is ever going to be added to the L2CAP socket address
> you'd have to have 0x00 as BDADDR_TYPE_BR for backwards compatibility.
>

As Claudio explained in an earlier email, we will need a way to get the
device type when the connection with that device starts
(MGMT_EV_DEVICE_CONNECTED), with hciops we can infer the type if we receive
the LE Meta Event.

My question is: should the event have a bdaddr_type field or a type field?

> Johan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

Cheers,
--
Vinicius

2011-05-04 11:14:52

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [PATCH v2 02/13] Add Bluetooth address type definition

Hi Johan,

On Wed, May 4, 2011 at 2:03 AM, Johan Hedberg <[email protected]> wrote:
> Hi Claudio,
>
> On Tue, May 03, 2011, Claudio Takahasi wrote:
>> Values defined to LE(public and random) are defined in the Bluetooth
>> Core Specification. For basic rate, there isn't address type concept.
>> The constants introduced by this commit will be used to identify the
>> remote address type, basically to distinguish LE/BR devices before
>> to request the L2CAP connection.
>> ---
>> ?lib/bluetooth.h | ? ?4 ++++
>> ?1 files changed, 4 insertions(+), 0 deletions(-)
>>
>> diff --git a/lib/bluetooth.h b/lib/bluetooth.h
>> index 738e07a..98b8f1c 100644
>> --- a/lib/bluetooth.h
>> +++ b/lib/bluetooth.h
>> @@ -130,6 +130,10 @@ typedef struct {
>> ?#define BDADDR_ALL ? (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
>> ?#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
>>
>> +#define BDADDR_TYPE_LE_PUBLIC ? ? ? ?0x00
>> +#define BRADDR_TYPE_LE_RANDOM ? ? ? ?0x01
>> +#define BDADDR_TYPE_BR ? ? ? ? ? ? ? 0xff
>
> Firstly this still needs Marcel's blessing (though I don't really see
> any other solution than an address type with three possible values).
> Secondly, if this is ever going to be added to the L2CAP socket address
> you'd have to have 0x00 as BDADDR_TYPE_BR for backwards compatibility.

The values for LE public/random were chosen to match the "address
type" field on HCI LE commands. We can of course use other values and
map to the HCI ones.

Also, as mentioned on the cover letter of the first version, we have
suggested using "BDADDR_TYPE_NON_LE" instead of "BDADDR_TYPE_BR", to
make it clear that value is more a "fallback" for non-LE addresses.

IIRC there is no current plan to put these types on the socket address
struct (the idea is to use, for instance, on device found events), but
if we go that path, I agree using 0x00 for BR/EDR makes more sense.

Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

2011-05-04 06:03:57

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v2 02/13] Add Bluetooth address type definition

Hi Claudio,

On Tue, May 03, 2011, Claudio Takahasi wrote:
> Values defined to LE(public and random) are defined in the Bluetooth
> Core Specification. For basic rate, there isn't address type concept.
> The constants introduced by this commit will be used to identify the
> remote address type, basically to distinguish LE/BR devices before
> to request the L2CAP connection.
> ---
> lib/bluetooth.h | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/lib/bluetooth.h b/lib/bluetooth.h
> index 738e07a..98b8f1c 100644
> --- a/lib/bluetooth.h
> +++ b/lib/bluetooth.h
> @@ -130,6 +130,10 @@ typedef struct {
> #define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
> #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
>
> +#define BDADDR_TYPE_LE_PUBLIC 0x00
> +#define BRADDR_TYPE_LE_RANDOM 0x01
> +#define BDADDR_TYPE_BR 0xff

Firstly this still needs Marcel's blessing (though I don't really see
any other solution than an address type with three possible values).
Secondly, if this is ever going to be added to the L2CAP socket address
you'd have to have 0x00 as BDADDR_TYPE_BR for backwards compatibility.

Johan

2011-05-03 21:34:00

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 13/13] Drop variable EIR length

From: Bruna Moreira <[email protected]>

The functions eir_parse() and adapter_update_found_devices() now
assume that the EIR buffer has always 240 octets. For advertising
reports, the advertising data is stored on a buffer with 240 bytes,
padded with zeroes.
---
plugins/hciops.c | 13 +++++++++----
src/adapter.c | 5 ++---
src/adapter.h | 3 +--
src/eir.c | 8 ++++----
src/eir.h | 2 +-
src/event.c | 2 +-
6 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index 91d5778..8b7befa 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -2080,7 +2080,7 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
{
struct dev_info *dev = &devs[index];
le_advertising_info *info;
- uint8_t num_reports, rssi;
+ uint8_t num_reports, rssi, eir[HCI_MAX_EIR_LENGTH];
const uint8_t RSSI_SIZE = 1;

num_reports = meta->data[0];
@@ -2088,8 +2088,11 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
info = (le_advertising_info *) &meta->data[1];
rssi = *(info->data + info->length);

+ memset(eir, 0, sizeof(eir));
+ memcpy(eir, info->data, info->length);
+
btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- info->bdaddr_type, 0, rssi, info->data);
+ info->bdaddr_type, 0, rssi, eir);

num_reports--;

@@ -2098,9 +2101,11 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
RSSI_SIZE);
rssi = *(info->data + info->length);

+ memset(eir, 0, sizeof(eir));
+ memcpy(eir, info->data, info->length);
+
btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- info->bdaddr_type, 0,
- rssi, info->data);
+ info->bdaddr_type, 0, rssi, eir);
}
}

diff --git a/src/adapter.c b/src/adapter.c
index e6dc735..46145ba 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3116,8 +3116,7 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)

void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint8_t bda_type, uint32_t class,
- int8_t rssi, uint8_t *data,
- size_t eir_size)
+ int8_t rssi, uint8_t *data)
{
struct remote_dev_info *dev, match;
struct eir_data eir_data;
@@ -3127,7 +3126,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, data, HCI_MAX_EIR_LENGTH);
+ err = eir_parse(&eir_data, data);
if (err < 0) {
error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
return;
diff --git a/src/adapter.h b/src/adapter.h
index 931be37..f296389 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -120,8 +120,7 @@ struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter
struct remote_dev_info *match);
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint8_t bda_type, uint32_t class,
- int8_t rssi, uint8_t *data,
- size_t eir_size);
+ int8_t rssi, uint8_t *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);
diff --git a/src/eir.c b/src/eir.c
index 7dfc444..01b6ac5 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -52,7 +52,7 @@ void eir_data_free(struct eir_data *eir)
g_free(eir->name);
}

-int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
+int eir_parse(struct eir_data *eir, uint8_t *eir_data)
{
uint16_t len = 0;
size_t total;
@@ -69,10 +69,10 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
eir->flags = -1;

/* No EIR data to parse */
- if (eir_data == NULL || eir_length == 0)
+ if (eir_data == NULL)
return 0;

- while (len < eir_length - 1) {
+ while (len < HCI_MAX_EIR_LENGTH - 1) {
uint8_t field_len = eir_data[0];

/* Check for the end of EIR */
@@ -115,7 +115,7 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
}

/* Bail out if got incorrect length */
- if (len > eir_length)
+ if (len > HCI_MAX_EIR_LENGTH)
return -EINVAL;

total = uuid16_count + uuid32_count + uuid128_count;
diff --git a/src/eir.h b/src/eir.h
index ea38570..d225973 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -35,7 +35,7 @@ struct eir_data {
};

void eir_data_free(struct eir_data *eir);
-int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length);
+int eir_parse(struct eir_data *eir, uint8_t *eir_data);
void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
uint16_t did_product, uint16_t did_version,
GSList *uuids, uint8_t *data);
diff --git a/src/event.c b/src/event.c
index 2b83ea7..4390c54 100644
--- a/src/event.c
+++ b/src/event.c
@@ -302,7 +302,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
}

adapter_update_found_devices(adapter, peer, bda_type, class,
- rssi, data, HCI_MAX_EIR_LENGTH);
+ rssi, data);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-05-03 21:33:53

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 12/13] Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH

From: Bruna Moreira <[email protected]>

Both defines have the same value (240) and meaning.
---
src/adapter.c | 2 +-
src/eir.c | 9 +++++----
src/eir.h | 2 --
src/event.c | 2 +-
4 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 378e095..e6dc735 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3127,7 +3127,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
+ err = eir_parse(&eir_data, data, HCI_MAX_EIR_LENGTH);
if (err < 0) {
error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
return;
diff --git a/src/eir.c b/src/eir.c
index 2fbd919..7dfc444 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -27,6 +27,7 @@
#include <glib.h>

#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
#include <bluetooth/sdp.h>

#include "glib-helper.h"
@@ -184,7 +185,7 @@ static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
continue;

/* Stop if not enough space to put next UUID128 */
- if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
+ if ((len + 2 + SIZEOF_UUID128) > HCI_MAX_EIR_LENGTH) {
truncated = TRUE;
break;
}
@@ -229,7 +230,7 @@ void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
GSList *l;
uint8_t *ptr = data;
uint16_t eir_len = 0;
- uint16_t uuid16[EIR_DATA_LENGTH / 2];
+ uint16_t uuid16[HCI_MAX_EIR_LENGTH / 2];
int i, uuid_count = 0;
gboolean truncated = FALSE;
size_t name_len;
@@ -289,7 +290,7 @@ void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
continue;

/* Stop if not enough space to put next UUID16 */
- if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
+ if ((eir_len + 2 + sizeof(uint16_t)) > HCI_MAX_EIR_LENGTH) {
truncated = TRUE;
break;
}
@@ -322,6 +323,6 @@ void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
}

/* Group all UUID128 types */
- if (eir_len <= EIR_DATA_LENGTH - 2)
+ if (eir_len <= HCI_MAX_EIR_LENGTH - 2)
eir_generate_uuid128(uuids, ptr, &eir_len);
}
diff --git a/src/eir.h b/src/eir.h
index aacd16a..ea38570 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -22,8 +22,6 @@
*
*/

-#define EIR_DATA_LENGTH 240
-
struct uuid_info {
uuid_t uuid;
uint8_t svc_hint;
diff --git a/src/event.c b/src/event.c
index 6dc40c0..2b83ea7 100644
--- a/src/event.c
+++ b/src/event.c
@@ -302,7 +302,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
}

adapter_update_found_devices(adapter, peer, bda_type, class,
- rssi, data, EIR_DATA_LENGTH);
+ rssi, data, HCI_MAX_EIR_LENGTH);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-05-03 21:33:46

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 11/13] Cleanup inserting new device found entry

---
src/adapter.c | 97 +++++++++++++++++++++++++++-----------------------------
1 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index b8e6e61..378e095 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3030,29 +3030,24 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
g_free(alias);
}

-static struct remote_dev_info *get_found_dev(struct btd_adapter *adapter,
- const bdaddr_t *bdaddr,
- gboolean *new_dev)
+static struct remote_dev_info *found_device_new(const bdaddr_t *bdaddr,
+ gboolean le, const char *name,
+ const char *alias, uint32_t class,
+ gboolean legacy, name_status_t status,
+ int flags)
{
- struct remote_dev_info *dev, match;
+ struct remote_dev_info *dev;

- memset(&match, 0, sizeof(struct remote_dev_info));
- bacpy(&match.bdaddr, bdaddr);
- match.name_status = NAME_ANY;
-
- dev = adapter_search_found_devices(adapter, &match);
- if (dev) {
- *new_dev = FALSE;
- /* Out of range list update */
- adapter->oor_devices = g_slist_remove(adapter->oor_devices,
- dev);
- } else {
- *new_dev = TRUE;
- 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);
+ bacpy(&dev->bdaddr, bdaddr);
+ dev->le = le;
+ dev->name = g_strdup(name);
+ dev->alias = g_strdup(alias);
+ dev->class = class;
+ dev->legacy = legacy;
+ dev->name_status = status;
+ if (flags >= 0)
+ dev->flags = flags;

return dev;
}
@@ -3124,11 +3119,11 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int8_t rssi, uint8_t *data,
size_t eir_size)
{
- struct remote_dev_info *dev;
+ struct remote_dev_info *dev, match;
struct eir_data eir_data;
- char *name;
- gboolean new_dev, legacy, le;
- name_status_t name_status = NAME_NOT_REQUIRED;
+ char *alias, *name;
+ gboolean legacy, le;
+ name_status_t name_status;
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
@@ -3141,6 +3136,25 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
if (eir_data.name != NULL && eir_data.name_complete)
write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);

+ /* Device already seen in the discovery session ? */
+ memset(&match, 0, sizeof(struct remote_dev_info));
+ bacpy(&match.bdaddr, bdaddr);
+ match.name_status = NAME_ANY;
+
+ dev = adapter_search_found_devices(adapter, &match);
+ if (dev) {
+ adapter->oor_devices = g_slist_remove(adapter->oor_devices,
+ dev);
+ if (dev->rssi != rssi)
+ goto done;
+
+ eir_data_free(&eir_data);
+
+ return;
+ }
+
+ /* New device in the discovery session */
+
name = read_stored_data(&adapter->bdaddr, bdaddr, "names");

switch (bda_type) {
@@ -3148,6 +3162,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
case BRADDR_TYPE_LE_RANDOM:
le = TRUE;
legacy = FALSE;
+ name_status = NAME_NOT_REQUIRED;
break;
default:
/* BDADDR_TYPE_BR */
@@ -3168,32 +3183,16 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
break;
}

- dev = get_found_dev(adapter, bdaddr, &new_dev);
-
- if (new_dev) {
- const char *dev_name = (name ? name : eir_data.name);
- char *alias;
+ alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");

- if (dev_name)
- dev->name = g_strdup(dev_name);
-
- alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");
- if (alias) {
- dev->alias = g_strdup(alias);
- free(alias);
- }
-
- dev->le = FALSE;
- dev->class = class;
- dev->legacy = legacy;
- dev->name_status = name_status;
+ dev = found_device_new(bdaddr, le, name, alias, class, legacy,
+ name_status, eir_data.flags);
+ free(name);
+ free(alias);

- if (eir_data.flags >= 0)
- dev->flags = eir_data.flags;
-
- } else if (dev->rssi == rssi)
- goto done;
+ adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);

+done:
dev->rssi = rssi;

adapter->found_devices = g_slist_sort(adapter->found_devices,
@@ -3204,8 +3203,6 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,

adapter_emit_device_found(adapter, dev);

-done:
- free(name);
eir_data_free(&eir_data);
}

--
1.7.5.rc3


2011-05-03 21:33:38

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 10/13] Change the order to write/read the remote's name

When discovering, write the EIR "complete" name first before to read
the name. Only names retrieved from EIR "complete" name and HCI Remote
Name Request Complete event are stored. This patch doesn't change the
final result: the value of the name sent in the signal.
---
src/adapter.c | 19 +++++--------------
1 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c4e2210..b8e6e61 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3129,7 +3129,6 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
char *name;
gboolean new_dev, legacy, le;
name_status_t name_status = NAME_NOT_REQUIRED;
- const char *dev_name;
int err, type;

memset(&eir_data, 0, sizeof(eir_data));
@@ -3139,6 +3138,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
return;
}

+ if (eir_data.name != NULL && eir_data.name_complete)
+ write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);
+
name = read_stored_data(&adapter->bdaddr, bdaddr, "names");

switch (bda_type) {
@@ -3166,23 +3168,12 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
break;
}

- /* Complete EIR names are always used. Shortened EIR names are only
- * used if there is no name already in storage. */
- dev_name = name;
- if (eir_data.name != NULL) {
- if (eir_data.name_complete) {
- write_device_name(&adapter->bdaddr, bdaddr,
- eir_data.name);
- name_status = NAME_NOT_REQUIRED;
- dev_name = eir_data.name;
- } else if (name == NULL)
- dev_name = eir_data.name;
- }
-
dev = get_found_dev(adapter, bdaddr, &new_dev);

if (new_dev) {
+ const char *dev_name = (name ? name : eir_data.name);
char *alias;
+
if (dev_name)
dev->name = g_strdup(dev_name);

--
1.7.5.rc3


2011-05-03 21:33:31

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 09/13] Remove btd_event_advertising_report

From: Bruna Moreira <[email protected]>

Advertises should be notified using btd_event_device_found function
to keep the compatibility with mgmtops plugin.
---
plugins/hciops.c | 27 +++++++++++++++++++--------
plugins/mgmtops.c | 3 ++-
src/event.c | 23 +++--------------------
src/event.h | 5 ++---
4 files changed, 26 insertions(+), 32 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index c2aa614..91d5778 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -1805,8 +1805,8 @@ static inline void inquiry_result(int index, int plen, void *ptr)
(info->dev_class[1] << 8) |
(info->dev_class[2] << 16);

- btd_event_device_found(&dev->bdaddr, &info->bdaddr, class,
- 0, NULL);
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ BDADDR_TYPE_BR, class, 0, NULL);
ptr += INQUIRY_INFO_SIZE;
}
}
@@ -1828,7 +1828,8 @@ static inline void inquiry_result_with_rssi(int index, int plen, void *ptr)
| (info->dev_class[2] << 16);

btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- class, info->rssi, NULL);
+ BDADDR_TYPE_BR, class,
+ info->rssi, NULL);
ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE;
}
} else {
@@ -1839,7 +1840,8 @@ static inline void inquiry_result_with_rssi(int index, int plen, void *ptr)
| (info->dev_class[2] << 16);

btd_event_device_found(&dev->bdaddr, &info->bdaddr,
- class, info->rssi, NULL);
+ BDADDR_TYPE_BR, class,
+ info->rssi, NULL);
ptr += INQUIRY_INFO_WITH_RSSI_SIZE;
}
}
@@ -1857,7 +1859,8 @@ static inline void extended_inquiry_result(int index, int plen, void *ptr)
| (info->dev_class[1] << 8)
| (info->dev_class[2] << 16);

- btd_event_device_found(&dev->bdaddr, &info->bdaddr, class,
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ BDADDR_TYPE_BR, class,
info->rssi, info->data);
ptr += EXTENDED_INQUIRY_INFO_SIZE;
}
@@ -2077,19 +2080,27 @@ static inline void le_advertising_report(int index, evt_le_meta_event *meta)
{
struct dev_info *dev = &devs[index];
le_advertising_info *info;
- uint8_t num_reports;
+ uint8_t num_reports, rssi;
const uint8_t RSSI_SIZE = 1;

num_reports = meta->data[0];

info = (le_advertising_info *) &meta->data[1];
- btd_event_advertising_report(&dev->bdaddr, info);
+ rssi = *(info->data + info->length);
+
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ info->bdaddr_type, 0, rssi, info->data);
+
num_reports--;

while (num_reports--) {
info = (le_advertising_info *) (info->data + info->length +
RSSI_SIZE);
- btd_event_advertising_report(&dev->bdaddr, info);
+ rssi = *(info->data + info->length);
+
+ btd_event_device_found(&dev->bdaddr, &info->bdaddr,
+ info->bdaddr_type, 0,
+ rssi, info->data);
}
}

diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index a8a7ac2..7a810fd 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -1322,7 +1322,8 @@ static void mgmt_device_found(int sk, uint16_t index, void *buf, size_t len)
DBG("hci%u addr %s, class %u rssi %d %s", index, addr, cls,
ev->rssi, eir ? "eir" : "");

- btd_event_device_found(&info->bdaddr, &ev->bdaddr, cls, ev->rssi, eir);
+ btd_event_device_found(&info->bdaddr, &ev->bdaddr, BDADDR_TYPE_BR,
+ cls, ev->rssi, eir);
}

static void mgmt_remote_name(int sk, uint16_t index, void *buf, size_t len)
diff --git a/src/event.c b/src/event.c
index a9ba368..6dc40c0 100644
--- a/src/event.c
+++ b/src/event.c
@@ -250,23 +250,6 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}

-void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
-{
- struct btd_adapter *adapter;
- int8_t rssi;
-
- adapter = manager_find_adapter(local);
- if (adapter == NULL) {
- error("No matching adapter found");
- return;
- }
-
- rssi = *(info->data + info->length);
-
- adapter_update_found_devices(adapter, &info->bdaddr, info->bdaddr_type,
- 0, rssi, info->data, info->length);
-}
-
static void update_lastseen(bdaddr_t *sba, bdaddr_t *dba)
{
time_t t;
@@ -289,8 +272,8 @@ static void update_lastused(bdaddr_t *sba, bdaddr_t *dba)
write_lastused_info(sba, dba, tm);
}

-void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
- int8_t rssi, uint8_t *data)
+void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
+ uint32_t class, int8_t rssi, uint8_t *data)
{
struct btd_adapter *adapter;
int state;
@@ -318,7 +301,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}

- adapter_update_found_devices(adapter, peer, BDADDR_TYPE_BR, class,
+ adapter_update_found_devices(adapter, peer, bda_type, class,
rssi, data, EIR_DATA_LENGTH);
}

diff --git a/src/event.h b/src/event.h
index 765390a..16a900c 100644
--- a/src/event.h
+++ b/src/event.h
@@ -23,9 +23,8 @@
*/

int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba);
-void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info);
-void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
- int8_t rssi, uint8_t *data);
+void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bda_type,
+ 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);
void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name);
--
1.7.5.rc3


2011-05-03 21:33:23

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 08/13] Fix memory leak of EIR data

---
src/adapter.c | 1 +
src/eir.c | 7 +++++++
src/eir.h | 1 +
3 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index ac5f120..c4e2210 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3215,6 +3215,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,

done:
free(name);
+ eir_data_free(&eir_data);
}

int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
diff --git a/src/eir.c b/src/eir.c
index d827c7e..2fbd919 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -44,6 +44,13 @@
#define EIR_TX_POWER 0x0A /* transmit power level */
#define EIR_DEVICE_ID 0x10 /* device ID */

+void eir_data_free(struct eir_data *eir)
+{
+ g_slist_foreach(eir->services, (GFunc) g_free, NULL);
+ g_slist_free(eir->services);
+ g_free(eir->name);
+}
+
int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length)
{
uint16_t len = 0;
diff --git a/src/eir.h b/src/eir.h
index c7699eb..aacd16a 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -36,6 +36,7 @@ struct eir_data {
gboolean name_complete;
};

+void eir_data_free(struct eir_data *eir);
int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length);
void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
uint16_t did_product, uint16_t did_version,
--
1.7.5.rc3


2011-05-03 21:33:15

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 07/13] Unify inquiry results and advertises

Adapter needs to have only one method to allow discovery results
integration for both interfaces: hciops and mgmtops. This patch
moves the code related to advertises parsing to the same function
that handles inquiry results.
---
src/adapter.c | 82 ++++++++++++++++++++++----------------------------------
src/adapter.h | 8 ++---
src/event.c | 25 +++--------------
3 files changed, 39 insertions(+), 76 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 15f6d2e..ac5f120 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3082,43 +3082,6 @@ static void dev_prepend_uuid(gpointer data, gpointer user_data)
dev->services = g_slist_prepend(dev->services, g_strdup(new_uuid));
}

-void adapter_update_device_from_info(struct btd_adapter *adapter,
- bdaddr_t bdaddr, int8_t rssi,
- uint8_t evt_type, const char *name,
- GSList *services, int flags)
-{
- struct remote_dev_info *dev;
- gboolean new_dev;
-
- dev = get_found_dev(adapter, &bdaddr, &new_dev);
-
- if (new_dev) {
- dev->le = TRUE;
- dev->evt_type = evt_type;
- } else if (dev->rssi == rssi)
- return;
-
- dev->rssi = rssi;
-
- adapter->found_devices = g_slist_sort(adapter->found_devices,
- (GCompareFunc) dev_rssi_cmp);
-
- g_slist_foreach(services, remove_same_uuid, dev);
- g_slist_foreach(services, dev_prepend_uuid, dev);
-
- if (flags >= 0)
- dev->flags = flags;
-
- if (name) {
- g_free(dev->name);
- dev->name = g_strdup(name);
- }
-
- /* FIXME: check if other information was changed before emitting the
- * signal */
- adapter_emit_device_found(adapter, dev);
-}
-
static int pairing_is_legacy(bdaddr_t *local, bdaddr_t *peer, gboolean eir,
gboolean name, gboolean *legacy)
{
@@ -3157,13 +3120,15 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)
}

void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
- uint32_t class, int8_t rssi, uint8_t *data)
+ uint8_t bda_type, uint32_t class,
+ int8_t rssi, uint8_t *data,
+ size_t eir_size)
{
struct remote_dev_info *dev;
struct eir_data eir_data;
char *name;
- gboolean new_dev, legacy;
- name_status_t name_status;
+ gboolean new_dev, legacy, le;
+ name_status_t name_status = NAME_NOT_REQUIRED;
const char *dev_name;
int err, type;

@@ -3175,18 +3140,31 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
}

name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
- if (pairing_is_legacy(&adapter->bdaddr, bdaddr,
- data ? TRUE : FALSE, name ? TRUE : FALSE,
- &legacy) < 0)
- legacy = TRUE;

- type = adapter_get_discover_type(adapter);
+ switch (bda_type) {
+ case BDADDR_TYPE_LE_PUBLIC:
+ case BRADDR_TYPE_LE_RANDOM:
+ le = TRUE;
+ legacy = FALSE;
+ break;
+ default:
+ /* BDADDR_TYPE_BR */
+ le = FALSE;

- if (!name && type & DISC_RESOLVNAME &&
- adapter_has_discov_sessions(adapter))
- name_status = NAME_REQUIRED;
- else
- name_status = NAME_NOT_REQUIRED;
+ if (pairing_is_legacy(&adapter->bdaddr, bdaddr,
+ data ? TRUE : FALSE,
+ name ? TRUE : FALSE, &legacy) < 0)
+ legacy = TRUE;
+
+ type = adapter_get_discover_type(adapter);
+
+ if (!name && type & DISC_RESOLVNAME &&
+ adapter_has_discov_sessions(adapter))
+ name_status = NAME_REQUIRED;
+ else
+ name_status = NAME_NOT_REQUIRED;
+ break;
+ }

/* Complete EIR names are always used. Shortened EIR names are only
* used if there is no name already in storage. */
@@ -3218,6 +3196,10 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
dev->class = class;
dev->legacy = legacy;
dev->name_status = name_status;
+
+ if (eir_data.flags >= 0)
+ dev->flags = eir_data.flags;
+
} else if (dev->rssi == rssi)
goto done;

diff --git a/src/adapter.h b/src/adapter.h
index 94707e5..931be37 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -118,12 +118,10 @@ int adapter_get_state(struct btd_adapter *adapter);
int adapter_get_discover_type(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,
- bdaddr_t bdaddr, int8_t rssi,
- uint8_t evt_type, const char *name,
- GSList *services, int flags);
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
- uint32_t class, int8_t rssi, uint8_t *data);
+ uint8_t bda_type, uint32_t class,
+ int8_t rssi, uint8_t *data,
+ size_t eir_size);
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);
diff --git a/src/event.c b/src/event.c
index 50aadea..a9ba368 100644
--- a/src/event.c
+++ b/src/event.c
@@ -250,19 +250,10 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}

-static void free_eir_data(struct eir_data *eir)
-{
- g_slist_foreach(eir->services, (GFunc) g_free, NULL);
- g_slist_free(eir->services);
- g_free(eir->name);
-}
-
void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
{
struct btd_adapter *adapter;
- struct eir_data eir_data;
int8_t rssi;
- int err;

adapter = manager_find_adapter(local);
if (adapter == NULL) {
@@ -270,19 +261,10 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
return;
}

- memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, info->data, info->length);
- if (err < 0)
- error("Error parsing advertising data: %s (%d)",
- strerror(-err), -err);
-
rssi = *(info->data + info->length);

- adapter_update_device_from_info(adapter, info->bdaddr, rssi,
- info->evt_type, eir_data.name,
- eir_data.services, eir_data.flags);
-
- free_eir_data(&eir_data);
+ adapter_update_found_devices(adapter, &info->bdaddr, info->bdaddr_type,
+ 0, rssi, info->data, info->length);
}

static void update_lastseen(bdaddr_t *sba, bdaddr_t *dba)
@@ -336,7 +318,8 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}

- adapter_update_found_devices(adapter, peer, class, rssi, data);
+ adapter_update_found_devices(adapter, peer, BDADDR_TYPE_BR, class,
+ rssi, data, EIR_DATA_LENGTH);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-05-03 21:33:07

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 06/13] Don't resolve name if the name is in the storage

---
src/adapter.c | 17 +++++++++--------
1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8a10607..15f6d2e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3165,7 +3165,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
gboolean new_dev, legacy;
name_status_t name_status;
const char *dev_name;
- int err;
+ int err, type;

memset(&eir_data, 0, sizeof(eir_data));
err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
@@ -3174,19 +3174,20 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
return;
}

- /* the inquiry result can be triggered by NON D-Bus client */
- if (adapter_get_discover_type(adapter) & DISC_RESOLVNAME &&
- adapter_has_discov_sessions(adapter))
- name_status = NAME_REQUIRED;
- else
- name_status = NAME_NOT_REQUIRED;
-
name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
if (pairing_is_legacy(&adapter->bdaddr, bdaddr,
data ? TRUE : FALSE, name ? TRUE : FALSE,
&legacy) < 0)
legacy = TRUE;

+ type = adapter_get_discover_type(adapter);
+
+ if (!name && type & DISC_RESOLVNAME &&
+ adapter_has_discov_sessions(adapter))
+ name_status = NAME_REQUIRED;
+ else
+ name_status = NAME_NOT_REQUIRED;
+
/* Complete EIR names are always used. Shortened EIR names are only
* used if there is no name already in storage. */
dev_name = name;
--
1.7.5.rc3


2011-05-03 21:33:00

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 05/13] Cleanup read name and alias from storage

---
src/adapter.c | 36 +++++++++++++++++++++++-------------
1 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 908704d..8a10607 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3144,13 +3144,24 @@ static int pairing_is_legacy(bdaddr_t *local, bdaddr_t *peer, gboolean eir,
return 0;
}

+static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)
+{
+ char local_addr[18], peer_addr[18], filename[PATH_MAX + 1];
+
+ ba2str(local, local_addr);
+ ba2str(peer, peer_addr);
+
+ create_name(filename, PATH_MAX, STORAGEDIR, local_addr, file);
+
+ return textfile_get(filename, peer_addr);
+}
+
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint32_t class, int8_t rssi, uint8_t *data)
{
- char local_addr[18], peer_addr[18], filename[PATH_MAX + 1];
struct remote_dev_info *dev;
struct eir_data eir_data;
- char *alias, *name;
+ char *name;
gboolean new_dev, legacy;
name_status_t name_status;
const char *dev_name;
@@ -3170,15 +3181,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
else
name_status = NAME_NOT_REQUIRED;

- ba2str(&adapter->bdaddr, local_addr);
- ba2str(bdaddr, peer_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases");
- alias = textfile_get(filename, peer_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
- name = textfile_get(filename, peer_addr);
-
+ name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
if (pairing_is_legacy(&adapter->bdaddr, bdaddr,
data ? TRUE : FALSE, name ? TRUE : FALSE,
&legacy) < 0)
@@ -3200,18 +3203,22 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
dev = get_found_dev(adapter, bdaddr, &new_dev);

if (new_dev) {
+ char *alias;
if (dev_name)
dev->name = g_strdup(dev_name);

- if (alias)
+ alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");
+ if (alias) {
dev->alias = g_strdup(alias);
+ free(alias);
+ }

dev->le = FALSE;
dev->class = class;
dev->legacy = legacy;
dev->name_status = name_status;
} else if (dev->rssi == rssi)
- return;
+ goto done;

dev->rssi = rssi;

@@ -3222,6 +3229,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
g_slist_foreach(eir_data.services, dev_prepend_uuid, dev);

adapter_emit_device_found(adapter, dev);
+
+done:
+ free(name);
}

int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
--
1.7.5.rc3


2011-05-03 21:32:52

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 04/13] Move legacy verification to a new function

---
src/adapter.c | 40 ++++++++++++++++++++++++++++------------
1 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index f6caca5..908704d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3119,6 +3119,31 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
adapter_emit_device_found(adapter, dev);
}

+static int pairing_is_legacy(bdaddr_t *local, bdaddr_t *peer, gboolean eir,
+ gboolean name, gboolean *legacy)
+{
+ unsigned char features[8];
+ int err;
+
+ if (eir) {
+ *legacy = FALSE;
+ return 0;
+ }
+
+ if (name == FALSE) {
+ *legacy = TRUE;
+ return 0;
+ }
+
+ err = read_remote_features(local, peer, NULL, features);
+ if (err < 0)
+ return err;
+
+ *legacy = (features[0] & 0x01 ? FALSE : TRUE);
+
+ return 0;
+}
+
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
uint32_t class, int8_t rssi, uint8_t *data)
{
@@ -3128,7 +3153,6 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
char *alias, *name;
gboolean new_dev, legacy;
name_status_t name_status;
- unsigned char features[8];
const char *dev_name;
int err;

@@ -3155,17 +3179,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
name = textfile_get(filename, peer_addr);

- if (data)
- legacy = FALSE;
- else if (name == NULL)
- legacy = TRUE;
- else if (read_remote_features(&adapter->bdaddr, bdaddr, NULL,
- features) == 0) {
- if (features[0] & 0x01)
- legacy = FALSE;
- else
- legacy = TRUE;
- } else
+ if (pairing_is_legacy(&adapter->bdaddr, bdaddr,
+ data ? TRUE : FALSE, name ? TRUE : FALSE,
+ &legacy) < 0)
legacy = TRUE;

/* Complete EIR names are always used. Shortened EIR names are only
--
1.7.5.rc3


2011-05-03 21:32:44

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 03/13] Initial device found cleanup

Moves EIR parsing call and stored name loading to adapter. This patch
doesn't change the implemented logic, it is only the initial step to
integrated inquiry results and LE advertises.
---
src/adapter.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++------
src/adapter.h | 4 +--
src/event.c | 62 +------------------------------------------------
3 files changed, 66 insertions(+), 71 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8dbd62c..f6caca5 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -58,6 +58,7 @@
#include "storage.h"
#include "attrib-server.h"
#include "att.h"
+#include "eir.h"

/* Interleaved discovery window: 5.12 sec */
#define GAP_INTER_DISCOV_WIN 5120
@@ -3119,18 +3120,72 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
}

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,
- GSList *services, name_status_t name_status)
+ uint32_t class, int8_t rssi, uint8_t *data)
{
+ char local_addr[18], peer_addr[18], filename[PATH_MAX + 1];
struct remote_dev_info *dev;
- gboolean new_dev;
+ struct eir_data eir_data;
+ char *alias, *name;
+ gboolean new_dev, legacy;
+ name_status_t name_status;
+ unsigned char features[8];
+ const char *dev_name;
+ int err;
+
+ memset(&eir_data, 0, sizeof(eir_data));
+ err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
+ if (err < 0) {
+ error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
+ return;
+ }
+
+ /* the inquiry result can be triggered by NON D-Bus client */
+ if (adapter_get_discover_type(adapter) & DISC_RESOLVNAME &&
+ adapter_has_discov_sessions(adapter))
+ name_status = NAME_REQUIRED;
+ else
+ name_status = NAME_NOT_REQUIRED;
+
+ ba2str(&adapter->bdaddr, local_addr);
+ ba2str(bdaddr, peer_addr);
+
+ create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases");
+ alias = textfile_get(filename, peer_addr);
+
+ create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
+ name = textfile_get(filename, peer_addr);
+
+ if (data)
+ legacy = FALSE;
+ else if (name == NULL)
+ legacy = TRUE;
+ else if (read_remote_features(&adapter->bdaddr, bdaddr, NULL,
+ features) == 0) {
+ if (features[0] & 0x01)
+ legacy = FALSE;
+ else
+ legacy = TRUE;
+ } else
+ legacy = TRUE;
+
+ /* Complete EIR names are always used. Shortened EIR names are only
+ * used if there is no name already in storage. */
+ dev_name = name;
+ if (eir_data.name != NULL) {
+ if (eir_data.name_complete) {
+ write_device_name(&adapter->bdaddr, bdaddr,
+ eir_data.name);
+ name_status = NAME_NOT_REQUIRED;
+ dev_name = eir_data.name;
+ } else if (name == NULL)
+ dev_name = eir_data.name;
+ }

dev = get_found_dev(adapter, bdaddr, &new_dev);

if (new_dev) {
- if (name)
- dev->name = g_strdup(name);
+ if (dev_name)
+ dev->name = g_strdup(dev_name);

if (alias)
dev->alias = g_strdup(alias);
@@ -3147,8 +3202,8 @@ 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);

- g_slist_foreach(services, remove_same_uuid, dev);
- g_slist_foreach(services, dev_prepend_uuid, dev);
+ g_slist_foreach(eir_data.services, remove_same_uuid, dev);
+ g_slist_foreach(eir_data.services, dev_prepend_uuid, dev);

adapter_emit_device_found(adapter, dev);
}
diff --git a/src/adapter.h b/src/adapter.h
index 7cc7c02..94707e5 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -123,9 +123,7 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
uint8_t evt_type, const char *name,
GSList *services, int 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,
- GSList *services, name_status_t name_status);
+ uint32_t class, int8_t rssi, uint8_t *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);
diff --git a/src/event.c b/src/event.c
index 8af30cb..50aadea 100644
--- a/src/event.c
+++ b/src/event.c
@@ -310,18 +310,8 @@ static void update_lastused(bdaddr_t *sba, bdaddr_t *dba)
void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
int8_t rssi, uint8_t *data)
{
- char filename[PATH_MAX + 1];
struct btd_adapter *adapter;
- char local_addr[18], peer_addr[18], *alias, *name;
- name_status_t name_status;
- struct eir_data eir_data;
- int state, err;
- dbus_bool_t legacy;
- unsigned char features[8];
- const char *dev_name;
-
- ba2str(local, local_addr);
- ba2str(peer, peer_addr);
+ int state;

adapter = manager_find_adapter(local);
if (!adapter) {
@@ -346,55 +336,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
adapter_set_state(adapter, state);
}

- /* the inquiry result can be triggered by NON D-Bus client */
- if (adapter_get_discover_type(adapter) & DISC_RESOLVNAME &&
- adapter_has_discov_sessions(adapter))
- name_status = NAME_REQUIRED;
- else
- name_status = NAME_NOT_REQUIRED;
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases");
- alias = textfile_get(filename, peer_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names");
- name = textfile_get(filename, peer_addr);
-
- if (data)
- legacy = FALSE;
- else if (name == NULL)
- legacy = TRUE;
- else if (read_remote_features(local, peer, NULL, features) == 0) {
- if (features[0] & 0x01)
- legacy = FALSE;
- else
- legacy = TRUE;
- } else
- legacy = TRUE;
-
- memset(&eir_data, 0, sizeof(eir_data));
- err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
- if (err < 0)
- error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
-
- /* Complete EIR names are always used. Shortened EIR names are only
- * used if there is no name already in storage. */
- dev_name = name;
- if (eir_data.name != NULL) {
- if (eir_data.name_complete) {
- write_device_name(local, peer, eir_data.name);
- name_status = NAME_NOT_REQUIRED;
- dev_name = eir_data.name;
- } else if (name == NULL)
- dev_name = eir_data.name;
- }
-
- adapter_update_found_devices(adapter, peer, rssi, class, dev_name,
- alias, legacy, eir_data.services,
- name_status);
-
- free_eir_data(&eir_data);
- free(name);
- free(alias);
+ adapter_update_found_devices(adapter, peer, class, rssi, data);
}

void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer,
--
1.7.5.rc3


2011-05-03 21:32:37

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 02/13] Add Bluetooth address type definition

Values defined to LE(public and random) are defined in the Bluetooth
Core Specification. For basic rate, there isn't address type concept.
The constants introduced by this commit will be used to identify the
remote address type, basically to distinguish LE/BR devices before
to request the L2CAP connection.
---
lib/bluetooth.h | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index 738e07a..98b8f1c 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -130,6 +130,10 @@ typedef struct {
#define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})

+#define BDADDR_TYPE_LE_PUBLIC 0x00
+#define BRADDR_TYPE_LE_RANDOM 0x01
+#define BDADDR_TYPE_BR 0xff
+
/* Copy, swap, convert BD Address */
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
--
1.7.5.rc3


2011-05-03 21:32:24

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 01/13] Move EIR related functions to a new file

---
Makefile.am | 2 +-
plugins/hciops.c | 170 +----------------------------
src/eir.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eir.h | 42 +++++++
src/event.c | 126 +---------------------
src/sdpd.h | 14 ---
6 files changed, 369 insertions(+), 305 deletions(-)
create mode 100644 src/eir.c
create mode 100644 src/eir.h

diff --git a/Makefile.am b/Makefile.am
index caffbe2..175f8c9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -251,7 +251,7 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/device.h src/device.c \
src/dbus-common.c src/dbus-common.h \
src/event.h src/event.c \
- src/oob.h src/oob.c
+ src/oob.h src/oob.c src/eir.h src/eir.c
src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
@CAPNG_LIBS@ -ldl -lrt
src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
diff --git a/plugins/hciops.c b/plugins/hciops.c
index d1156e2..c2aa614 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -51,6 +51,7 @@
#include "event.h"
#include "manager.h"
#include "oob.h"
+#include "eir.h"

static int child_pipe[2] = { -1, -1 };

@@ -65,11 +66,6 @@ enum {
PENDING_NAME,
};

-struct uuid_info {
- uuid_t uuid;
- uint8_t svc_hint;
-};
-
struct bt_conn {
struct dev_info *dev;
bdaddr_t bdaddr;
@@ -1396,167 +1392,6 @@ static void read_local_features_complete(int index,
init_adapter(index);
}

-#define SIZEOF_UUID128 16
-
-static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
-{
- int i, k, uuid_count = 0;
- uint16_t len = *eir_len;
- uint8_t *uuid128;
- gboolean truncated = FALSE;
-
- /* Store UUIDs in place, skip 2 bytes to write type and length later */
- uuid128 = ptr + 2;
-
- for (; list; list = list->next) {
- struct uuid_info *uuid = list->data;
- uint8_t *uuid128_data = uuid->uuid.value.uuid128.data;
-
- if (uuid->uuid.type != SDP_UUID128)
- continue;
-
- /* Stop if not enough space to put next UUID128 */
- if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
- truncated = TRUE;
- break;
- }
-
- /* Check for duplicates, EIR data is Little Endian */
- for (i = 0; i < uuid_count; i++) {
- for (k = 0; k < SIZEOF_UUID128; k++) {
- if (uuid128[i * SIZEOF_UUID128 + k] !=
- uuid128_data[SIZEOF_UUID128 - 1 - k])
- break;
- }
- if (k == SIZEOF_UUID128)
- break;
- }
-
- if (i < uuid_count)
- continue;
-
- /* EIR data is Little Endian */
- for (k = 0; k < SIZEOF_UUID128; k++)
- uuid128[uuid_count * SIZEOF_UUID128 + k] =
- uuid128_data[SIZEOF_UUID128 - 1 - k];
-
- len += SIZEOF_UUID128;
- uuid_count++;
- }
-
- if (uuid_count > 0 || truncated) {
- /* EIR Data length */
- ptr[0] = (uuid_count * SIZEOF_UUID128) + 1;
- /* EIR Data type */
- ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
- len += 2;
- *eir_len = len;
- }
-}
-
-static void create_ext_inquiry_response(int index, uint8_t *data)
-{
- struct dev_info *dev = &devs[index];
- GSList *l;
- uint8_t *ptr = data;
- uint16_t eir_len = 0;
- uint16_t uuid16[EIR_DATA_LENGTH / 2];
- int i, uuid_count = 0;
- gboolean truncated = FALSE;
- size_t name_len;
-
- name_len = strlen(dev->name);
-
- if (name_len > 0) {
- /* EIR Data type */
- if (name_len > 48) {
- name_len = 48;
- ptr[1] = EIR_NAME_SHORT;
- } else
- ptr[1] = EIR_NAME_COMPLETE;
-
- /* EIR Data length */
- ptr[0] = name_len + 1;
-
- memcpy(ptr + 2, dev->name, name_len);
-
- eir_len += (name_len + 2);
- ptr += (name_len + 2);
- }
-
- if (dev->tx_power != 0) {
- *ptr++ = 2;
- *ptr++ = EIR_TX_POWER;
- *ptr++ = (uint8_t) dev->tx_power;
- eir_len += 3;
- }
-
- if (dev->did_vendor != 0x0000) {
- uint16_t source = 0x0002;
- *ptr++ = 9;
- *ptr++ = EIR_DEVICE_ID;
- *ptr++ = (source & 0x00ff);
- *ptr++ = (source & 0xff00) >> 8;
- *ptr++ = (dev->did_vendor & 0x00ff);
- *ptr++ = (dev->did_vendor & 0xff00) >> 8;
- *ptr++ = (dev->did_product & 0x00ff);
- *ptr++ = (dev->did_product & 0xff00) >> 8;
- *ptr++ = (dev->did_version & 0x00ff);
- *ptr++ = (dev->did_version & 0xff00) >> 8;
- eir_len += 10;
- }
-
- /* Group all UUID16 types */
- for (l = dev->uuids; l != NULL; l = g_slist_next(l)) {
- struct uuid_info *uuid = l->data;
-
- if (uuid->uuid.type != SDP_UUID16)
- continue;
-
- if (uuid->uuid.value.uuid16 < 0x1100)
- continue;
-
- if (uuid->uuid.value.uuid16 == PNP_INFO_SVCLASS_ID)
- continue;
-
- /* Stop if not enough space to put next UUID16 */
- if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
- truncated = TRUE;
- break;
- }
-
- /* Check for duplicates */
- for (i = 0; i < uuid_count; i++)
- if (uuid16[i] == uuid->uuid.value.uuid16)
- break;
-
- if (i < uuid_count)
- continue;
-
- uuid16[uuid_count++] = uuid->uuid.value.uuid16;
- eir_len += sizeof(uint16_t);
- }
-
- if (uuid_count > 0) {
- /* EIR Data length */
- ptr[0] = (uuid_count * sizeof(uint16_t)) + 1;
- /* EIR Data type */
- ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
-
- ptr += 2;
- eir_len += 2;
-
- for (i = 0; i < uuid_count; i++) {
- *ptr++ = (uuid16[i] & 0x00ff);
- *ptr++ = (uuid16[i] & 0xff00) >> 8;
- }
- }
-
- /* Group all UUID128 types */
- if (eir_len <= EIR_DATA_LENGTH - 2)
- eir_generate_uuid128(dev->uuids, ptr, &eir_len);
-}
-
static void update_ext_inquiry_response(int index)
{
struct dev_info *dev = &devs[index];
@@ -1575,7 +1410,8 @@ static void update_ext_inquiry_response(int index)

memset(&cp, 0, sizeof(cp));

- create_ext_inquiry_response(index, cp.data);
+ eir_create(dev->name, dev->tx_power, dev->did_vendor, dev->did_product,
+ dev->did_version, dev->uuids, cp.data);

if (memcmp(cp.data, dev->eir, sizeof(cp.data)) == 0)
return;
diff --git a/src/eir.c b/src/eir.c
new file mode 100644
index 0000000..d827c7e
--- /dev/null
+++ b/src/eir.c
@@ -0,0 +1,320 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <glib.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+
+#include "glib-helper.h"
+#include "eir.h"
+
+#define EIR_FLAGS 0x01 /* flags */
+#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
+#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
+#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
+#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
+#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
+#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
+#define EIR_NAME_SHORT 0x08 /* shortened local name */
+#define EIR_NAME_COMPLETE 0x09 /* complete local name */
+#define EIR_TX_POWER 0x0A /* transmit power level */
+#define EIR_DEVICE_ID 0x10 /* device ID */
+
+int eir_parse(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;
+ uint8_t *uuid16 = NULL;
+ uint8_t *uuid32 = NULL;
+ uint8_t *uuid128 = NULL;
+ uuid_t service;
+ char *uuid_str;
+ unsigned int i;
+
+ eir->flags = -1;
+
+ /* No EIR data to parse */
+ if (eir_data == NULL || eir_length == 0)
+ return 0;
+
+ 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;
+ 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;
+ eir_data += field_len + 1;
+ }
+
+ /* Bail out if got incorrect length */
+ if (len > eir_length)
+ return -EINVAL;
+
+ total = uuid16_count + uuid32_count + uuid128_count;
+
+ /* No UUIDs were parsed, so skip code below */
+ if (!total)
+ return 0;
+
+ /* 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);
+ eir->services = g_slist_append(eir->services, 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);
+ eir->services = g_slist_append(eir->services, 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);
+ eir->services = g_slist_append(eir->services, uuid_str);
+ uuid128 += 16;
+ }
+
+ return 0;
+}
+
+#define SIZEOF_UUID128 16
+
+static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
+{
+ int i, k, uuid_count = 0;
+ uint16_t len = *eir_len;
+ uint8_t *uuid128;
+ gboolean truncated = FALSE;
+
+ /* Store UUIDs in place, skip 2 bytes to write type and length later */
+ uuid128 = ptr + 2;
+
+ for (; list; list = list->next) {
+ struct uuid_info *uuid = list->data;
+ uint8_t *uuid128_data = uuid->uuid.value.uuid128.data;
+
+ if (uuid->uuid.type != SDP_UUID128)
+ continue;
+
+ /* Stop if not enough space to put next UUID128 */
+ if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
+ truncated = TRUE;
+ break;
+ }
+
+ /* Check for duplicates, EIR data is Little Endian */
+ for (i = 0; i < uuid_count; i++) {
+ for (k = 0; k < SIZEOF_UUID128; k++) {
+ if (uuid128[i * SIZEOF_UUID128 + k] !=
+ uuid128_data[SIZEOF_UUID128 - 1 - k])
+ break;
+ }
+ if (k == SIZEOF_UUID128)
+ break;
+ }
+
+ if (i < uuid_count)
+ continue;
+
+ /* EIR data is Little Endian */
+ for (k = 0; k < SIZEOF_UUID128; k++)
+ uuid128[uuid_count * SIZEOF_UUID128 + k] =
+ uuid128_data[SIZEOF_UUID128 - 1 - k];
+
+ len += SIZEOF_UUID128;
+ uuid_count++;
+ }
+
+ if (uuid_count > 0 || truncated) {
+ /* EIR Data length */
+ ptr[0] = (uuid_count * SIZEOF_UUID128) + 1;
+ /* EIR Data type */
+ ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
+ len += 2;
+ *eir_len = len;
+ }
+}
+
+void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
+ uint16_t did_product, uint16_t did_version,
+ GSList *uuids, uint8_t *data)
+{
+ GSList *l;
+ uint8_t *ptr = data;
+ uint16_t eir_len = 0;
+ uint16_t uuid16[EIR_DATA_LENGTH / 2];
+ int i, uuid_count = 0;
+ gboolean truncated = FALSE;
+ size_t name_len;
+
+ name_len = strlen(name);
+
+ if (name_len > 0) {
+ /* EIR Data type */
+ if (name_len > 48) {
+ name_len = 48;
+ ptr[1] = EIR_NAME_SHORT;
+ } else
+ ptr[1] = EIR_NAME_COMPLETE;
+
+ /* EIR Data length */
+ ptr[0] = name_len + 1;
+
+ memcpy(ptr + 2, name, name_len);
+
+ eir_len += (name_len + 2);
+ ptr += (name_len + 2);
+ }
+
+ if (tx_power != 0) {
+ *ptr++ = 2;
+ *ptr++ = EIR_TX_POWER;
+ *ptr++ = (uint8_t) tx_power;
+ eir_len += 3;
+ }
+
+ if (did_vendor != 0x0000) {
+ uint16_t source = 0x0002;
+ *ptr++ = 9;
+ *ptr++ = EIR_DEVICE_ID;
+ *ptr++ = (source & 0x00ff);
+ *ptr++ = (source & 0xff00) >> 8;
+ *ptr++ = (did_vendor & 0x00ff);
+ *ptr++ = (did_vendor & 0xff00) >> 8;
+ *ptr++ = (did_product & 0x00ff);
+ *ptr++ = (did_product & 0xff00) >> 8;
+ *ptr++ = (did_version & 0x00ff);
+ *ptr++ = (did_version & 0xff00) >> 8;
+ eir_len += 10;
+ }
+
+ /* Group all UUID16 types */
+ for (l = uuids; l != NULL; l = g_slist_next(l)) {
+ struct uuid_info *uuid = l->data;
+
+ if (uuid->uuid.type != SDP_UUID16)
+ continue;
+
+ if (uuid->uuid.value.uuid16 < 0x1100)
+ continue;
+
+ if (uuid->uuid.value.uuid16 == PNP_INFO_SVCLASS_ID)
+ continue;
+
+ /* Stop if not enough space to put next UUID16 */
+ if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
+ truncated = TRUE;
+ break;
+ }
+
+ /* Check for duplicates */
+ for (i = 0; i < uuid_count; i++)
+ if (uuid16[i] == uuid->uuid.value.uuid16)
+ break;
+
+ if (i < uuid_count)
+ continue;
+
+ uuid16[uuid_count++] = uuid->uuid.value.uuid16;
+ eir_len += sizeof(uint16_t);
+ }
+
+ if (uuid_count > 0) {
+ /* EIR Data length */
+ ptr[0] = (uuid_count * sizeof(uint16_t)) + 1;
+ /* EIR Data type */
+ ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
+
+ ptr += 2;
+ eir_len += 2;
+
+ for (i = 0; i < uuid_count; i++) {
+ *ptr++ = (uuid16[i] & 0x00ff);
+ *ptr++ = (uuid16[i] & 0xff00) >> 8;
+ }
+ }
+
+ /* Group all UUID128 types */
+ if (eir_len <= EIR_DATA_LENGTH - 2)
+ eir_generate_uuid128(uuids, ptr, &eir_len);
+}
diff --git a/src/eir.h b/src/eir.h
new file mode 100644
index 0000000..c7699eb
--- /dev/null
+++ b/src/eir.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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
+ *
+ */
+
+#define EIR_DATA_LENGTH 240
+
+struct uuid_info {
+ uuid_t uuid;
+ uint8_t svc_hint;
+};
+
+struct eir_data {
+ GSList *services;
+ int flags;
+ char *name;
+ gboolean name_complete;
+};
+
+int eir_parse(struct eir_data *eir, uint8_t *eir_data, size_t eir_length);
+void eir_create(const char *name, int8_t tx_power, uint16_t did_vendor,
+ uint16_t did_product, uint16_t did_version,
+ GSList *uuids, uint8_t *data);
diff --git a/src/event.c b/src/event.c
index 5373e33..8af30cb 100644
--- a/src/event.c
+++ b/src/event.c
@@ -57,13 +57,7 @@
#include "storage.h"
#include "event.h"
#include "sdpd.h"
-
-struct eir_data {
- GSList *services;
- int flags;
- char *name;
- gboolean name_complete;
-};
+#include "eir.h"

static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
struct btd_adapter **adapter,
@@ -256,120 +250,6 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
device_simple_pairing_complete(device, status);
}

-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;
- uint8_t *uuid16 = NULL;
- uint8_t *uuid32 = NULL;
- uint8_t *uuid128 = NULL;
- uuid_t service;
- char *uuid_str;
- unsigned int i;
-
- eir->flags = -1;
-
- /* No EIR data to parse */
- if (eir_data == NULL || eir_length == 0)
- return 0;
-
- 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;
- 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;
- eir_data += field_len + 1;
- }
-
- /* Bail out if got incorrect length */
- if (len > eir_length)
- return -EINVAL;
-
- total = uuid16_count + uuid32_count + uuid128_count;
-
- /* No UUIDs were parsed, so skip code below */
- if (!total)
- return 0;
-
- /* 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);
- eir->services = g_slist_append(eir->services, 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);
- eir->services = g_slist_append(eir->services, 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);
- eir->services = g_slist_append(eir->services, uuid_str);
- uuid128 += 16;
- }
-
- return 0;
-}
-
static void free_eir_data(struct eir_data *eir)
{
g_slist_foreach(eir->services, (GFunc) g_free, NULL);
@@ -391,7 +271,7 @@ void btd_event_advertising_report(bdaddr_t *local, le_advertising_info *info)
}

memset(&eir_data, 0, sizeof(eir_data));
- err = parse_eir_data(&eir_data, info->data, info->length);
+ err = eir_parse(&eir_data, info->data, info->length);
if (err < 0)
error("Error parsing advertising data: %s (%d)",
strerror(-err), -err);
@@ -492,7 +372,7 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
legacy = TRUE;

memset(&eir_data, 0, sizeof(eir_data));
- err = parse_eir_data(&eir_data, data, EIR_DATA_LENGTH);
+ err = eir_parse(&eir_data, data, EIR_DATA_LENGTH);
if (err < 0)
error("Error parsing EIR data: %s (%d)", strerror(-err), -err);

diff --git a/src/sdpd.h b/src/sdpd.h
index dc7a256..653736c 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -34,20 +34,6 @@
#define SDPDBG(fmt...)
#endif

-#define EIR_DATA_LENGTH 240
-
-#define EIR_FLAGS 0x01 /* flags */
-#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
-#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
-#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
-#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
-#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
-#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
-#define EIR_NAME_SHORT 0x08 /* shortened local name */
-#define EIR_NAME_COMPLETE 0x09 /* complete local name */
-#define EIR_TX_POWER 0x0A /* transmit power level */
-#define EIR_DEVICE_ID 0x10 /* device ID */
-
typedef struct request {
bdaddr_t device;
bdaddr_t bdaddr;
--
1.7.5.rc3


2011-05-03 21:32:10

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 00/13] Discovery Cleanup - Step 1

This patch series is the first step to cleanup the device discovery
procedure. The main changes are:
- Unify advertising reports and inquiry results: mgmt sends
one device found event
- Logic improvement/cleanup: device found
- Move EIR functions to a new file
- Add BDADDR type constants: necessary L2CAP connections and bonding



Bruna Moreira (3):
Remove btd_event_advertising_report
Replace EIR_DATA_LENGTH with HCI_MAX_EIR_LENGTH
Drop variable EIR length

Claudio Takahasi (10):
Move EIR related functions to a new file
Add Bluetooth address type definition
Initial device found cleanup
Move legacy verification to a new function
Cleanup read name and alias from storage
Don't resolve name if the name is in the storage
Unify inquiry results and advertises
Fix memory leak of EIR data
Change the order to write/read the remote's name
Cleanup inserting new device found entry

Makefile.am | 2 +-
lib/bluetooth.h | 4 +
plugins/hciops.c | 202 +++++----------------------------
plugins/mgmtops.c | 3 +-
src/adapter.c | 182 +++++++++++++++++++-----------
src/adapter.h | 9 +-
src/eir.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eir.h | 41 +++++++
src/event.c | 224 +-----------------------------------
src/event.h | 5 +-
src/sdpd.h | 14 ---
11 files changed, 530 insertions(+), 484 deletions(-)
create mode 100644 src/eir.c
create mode 100644 src/eir.h

--
1.7.5.rc3