2011-04-07 17:30:06

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 1/9] Register primary services exported over basic rate

This patch registers the object paths for primary services exported
through SDP. PSM, start and end handle information are available in
the Protocol Descriptor List.
---
src/device.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 129 insertions(+), 1 deletions(-)

diff --git a/src/device.c b/src/device.c
index d567952..32eb643 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1367,6 +1367,127 @@ static void create_device_reply(struct btd_device *device, struct browse_req *re
g_dbus_send_message(req->conn, reply);
}

+static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
+{
+ sdp_list_t *list;
+ uuid_t proto;
+
+ sdp_uuid16_create(&proto, ATT_UUID);
+
+ for (;list = proto_list, list; list = list->next) {
+ sdp_list_t *p;
+ for (p = list->data; p; p = p->next) {
+ sdp_data_t *seq = p->data;
+ if (seq && seq->dtd == SDP_UUID16 &&
+ sdp_uuid16_cmp(&proto, &seq->val.uuid) == 0)
+ return seq->next;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean parse_proto_params(sdp_list_t *proto_list, uint16_t *psm,
+ uint16_t *start, uint16_t *end)
+{
+ sdp_data_t *seq1, *seq2;
+
+ if (psm)
+ *psm = sdp_get_proto_port(proto_list, L2CAP_UUID);
+
+ /* Getting start and end handle */
+ seq1 = proto_seq_find(proto_list);
+ if (!seq1 || seq1->dtd != SDP_UINT16)
+ return FALSE;
+
+ seq2 = seq1->next;
+ if (!seq2 || seq2->dtd != SDP_UINT16)
+ return FALSE;
+
+ if (start)
+ *start = seq1->val.uint16;
+
+ if (end)
+ *end = seq2->val.uint16;
+
+ return TRUE;
+}
+
+static gboolean parse_primary_record(const sdp_record_t *rec,
+ uuid_t *prim_uuid, uint16_t *psm,
+ uint16_t *start, uint16_t *end)
+{
+ sdp_list_t *list;
+ uuid_t uuid;
+ gboolean ret;
+
+ if (sdp_get_service_classes(rec, &list) < 0)
+ return FALSE;
+
+ memcpy(&uuid, list->data, sizeof(uuid));
+ sdp_list_free(list, free);
+
+ if (sdp_get_access_protos(rec, &list) < 0)
+ return FALSE;
+
+ ret = parse_proto_params(list, psm, start, end);
+
+ sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(list, NULL);
+
+ if (ret && prim_uuid)
+ memcpy(prim_uuid, &uuid, sizeof(uuid_t));
+
+ return ret;
+}
+
+static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
+{
+ GSList *l, *prim_list = NULL;
+ char *att_uuid;
+ uuid_t proto_uuid;
+
+ sdp_uuid16_create(&proto_uuid, ATT_UUID);
+ att_uuid = bt_uuid2string(&proto_uuid);
+
+ for (l = profiles; l; l = l->next) {
+ const char *profile_uuid = l->data;
+ const sdp_record_t *rec;
+ struct att_primary *prim;
+ uint16_t start = 0, end = 0, psm = 0;
+ uuid_t prim_uuid;
+
+ rec = btd_device_get_record(device, profile_uuid);
+ if (!rec)
+ continue;
+
+ if (!record_has_uuid(rec, att_uuid))
+ continue;
+
+ if (!parse_primary_record(rec, &prim_uuid, &psm, &start, &end))
+ continue;
+
+ prim = g_new0(struct att_primary, 1);
+ prim->start = start;
+ prim->end = end;
+ sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
+
+ prim_list = g_slist_append(prim_list, prim);
+ }
+
+ g_free(att_uuid);
+
+ return prim_list;
+}
+
+static void register_primary_services(DBusConnection *conn,
+ struct btd_device *device, GSList *prim_list)
+{
+ /* TODO: PSM is hardcoded */
+ attrib_client_register(conn, device, 31, NULL, prim_list);
+ device->primaries = g_slist_concat(device->primaries, prim_list);
+}
+
static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
{
struct browse_req *req = user_data;
@@ -1396,9 +1517,16 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
}

/* Probe matching drivers for services added */
- if (req->profiles_added)
+ if (req->profiles_added) {
+ GSList *list;
+
device_probe_drivers(device, req->profiles_added);

+ list = primary_from_record(device, req->profiles_added);
+ if (list)
+ register_primary_services(req->conn, device, list);
+ }
+
/* Remove drivers for services removed */
if (req->profiles_removed)
device_remove_drivers(device, req->profiles_removed);
--
1.7.4.1



2011-04-14 17:13:07

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v2 1/9] Register primary services exported over basic rate

Hi Claudio,

On Mon, Apr 11, 2011, Claudio Takahasi wrote:
> This patch registers the object paths for primary services exported
> through SDP. PSM, start and end handle information are available in
> the Protocol Descriptor List.
> ---
> attrib/gatt.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> attrib/gatt.h | 6 ++++
> src/device.c | 56 ++++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 139 insertions(+), 1 deletions(-)

All patches in this set have been pushed upstream. Thanks.

Johan

2011-04-11 18:26:34

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 9/9] TODO: Add hard-coded PSM for GATT over basic rate

---
TODO | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/TODO b/TODO
index 461b179..fab3ec0 100644
--- a/TODO
+++ b/TODO
@@ -136,6 +136,11 @@ ATT/GATT
Priority: Medium
Complexity: C1

+- Fix hard-coded PSM for GATT services over basic rate.
+
+ Priority: Low
+ Complexity: C1
+
- Refactor read_by_group() and read_by_type() in src/attrib-server.c
(they've grown simply too big). First step could be to move out the
long for-loops to new functions called e.g. get_groups() and get_types().
--
1.7.4.1


2011-04-11 18:26:16

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 8/9] TODO: Remove item related to GATT service over basic rate

---
TODO | 10 ----------
1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/TODO b/TODO
index d52808b..461b179 100644
--- a/TODO
+++ b/TODO
@@ -114,16 +114,6 @@ Low Energy
ATT/GATT
========

-- For BR/EDR, primary services can be registered based on the information
- extracted from the service records. UUIDs, start and end handles information
- are available in the record, Discover All Primary Services procedure is not
- necessary. If a GATT service doesn't export a service record means that
- it should not be used over BR/EDR. Don't start this task before to move the
- attribute client code to the bluetoothd core.
-
- Priority: Medium
- Complexity: C1
-
- At the moment authentication and authorization is not supported at the
same time, read/write requirements in the attribute server needs to
be extended. According to Bluetooth Specification a server shall check
--
1.7.4.1


2011-04-11 18:26:00

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 7/9] Fix primary services registration from storage for basic rate

---
src/adapter.c | 5 ++++-
src/device.c | 4 ++--
src/device.h | 2 ++
3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 9a0f688..7049ba6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2004,7 +2004,7 @@ static void create_stored_device_from_profiles(char *key, char *value,
void *user_data)
{
struct btd_adapter *adapter = user_data;
- GSList *uuids = bt_string2list(value);
+ GSList *list, *uuids = bt_string2list(value);
struct btd_device *device;

if (g_slist_find_custom(adapter->devices,
@@ -2019,6 +2019,9 @@ static void create_stored_device_from_profiles(char *key, char *value,
adapter->devices = g_slist_append(adapter->devices, device);

device_probe_drivers(device, uuids);
+ list = device_services_from_record(device, uuids);
+ if (list)
+ device_register_services(connection, device, list, 31);

g_slist_foreach(uuids, (GFunc) g_free, NULL);
g_slist_free(uuids);
diff --git a/src/device.c b/src/device.c
index 86f605a..44bf76f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1367,7 +1367,7 @@ static void create_device_reply(struct btd_device *device, struct browse_req *re
g_dbus_send_message(req->conn, reply);
}

-static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
+GSList *device_services_from_record(struct btd_device *device, GSList *profiles)
{
GSList *l, *prim_list = NULL;
char *att_uuid;
@@ -1440,7 +1440,7 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)

device_probe_drivers(device, req->profiles_added);

- list = primary_from_record(device, req->profiles_added);
+ list = device_services_from_record(device, req->profiles_added);
if (list)
device_register_services(req->conn, device, list, 31);
}
diff --git a/src/device.h b/src/device.h
index 2432884..370382d 100644
--- a/src/device.h
+++ b/src/device.h
@@ -58,6 +58,8 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
GSList *btd_device_get_primaries(struct btd_device *device);
void device_register_services(DBusConnection *conn, struct btd_device *device,
GSList *prim_list, int psm);
+GSList *device_services_from_record(struct btd_device *device,
+ GSList *profiles);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
struct btd_adapter *device_get_adapter(struct btd_device *device);
void device_get_address(struct btd_device *device, bdaddr_t *bdaddr);
--
1.7.4.1


2011-04-11 18:25:41

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 6/9] Fix LE device creation from storage

Ignore the device if it already created. This patch adds a consistency
check to avoid registering the same service over basic rate and LE.
---
src/adapter.c | 20 +++++++++-----------
1 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8380a58..9a0f688 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2171,18 +2171,16 @@ static void create_stored_device_from_primary(char *key, char *value,
struct btd_device *device;
GSList *services, *uuids, *l;

- l = g_slist_find_custom(adapter->devices,
- key, (GCompareFunc) device_address_cmp);
- if (l)
- device = l->data;
- else {
- device = device_create(connection, adapter, key, DEVICE_TYPE_LE);
- if (!device)
- return;
+ if (g_slist_find_custom(adapter->devices,
+ key, (GCompareFunc) device_address_cmp))
+ return;

- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
- }
+ device = device_create(connection, adapter, key, DEVICE_TYPE_LE);
+ if (!device)
+ return;
+
+ device_set_temporary(device, FALSE);
+ adapter->devices = g_slist_append(adapter->devices, device);

services = string_to_primary_list(value);
if (services == NULL)
--
1.7.4.1


2011-04-11 18:25:23

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 5/9] Fix device type when creating from primary services storage

GATT services exported through basic rate need to be created based
on the "profiles" file. For GATT over LE, "primary" file entries need
to be used to create the devices and primary services objects.
---
src/adapter.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 6caff9a..8380a58 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2176,7 +2176,7 @@ static void create_stored_device_from_primary(char *key, char *value,
if (l)
device = l->data;
else {
- device = device_create(connection, adapter, key, DEVICE_TYPE_BREDR);
+ device = device_create(connection, adapter, key, DEVICE_TYPE_LE);
if (!device)
return;

--
1.7.4.1


2011-04-11 18:25:06

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 4/9] Move the primary service storage code to a local function

---
src/device.c | 27 ++++++++++++++++-----------
1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/device.c b/src/device.c
index efe9938..86f605a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1562,14 +1562,26 @@ static char *primary_list_to_string(GSList *primary_list)
return g_string_free(services, FALSE);
}

+static void store_services(struct btd_device *device)
+{
+ struct btd_adapter *adapter = device->adapter;
+ bdaddr_t dba, sba;
+ char *str = primary_list_to_string(device->services);
+
+ adapter_get_address(adapter, &sba);
+ device_get_address(device, &dba);
+
+ write_device_type(&sba, &dba, device->type);
+ write_device_services(&sba, &dba, str);
+
+ g_free(str);
+}
+
static void primary_cb(GSList *services, guint8 status, gpointer user_data)
{
struct browse_req *req = user_data;
struct btd_device *device = req->device;
- struct btd_adapter *adapter = device->adapter;
GSList *l, *uuids = NULL;
- bdaddr_t dba, sba;
- char *str;

if (status) {
DBusMessage *reply;
@@ -1594,14 +1606,7 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)

create_device_reply(device, req);

- str = primary_list_to_string(services);
-
- adapter_get_address(adapter, &sba);
- device_get_address(device, &dba);
-
- write_device_type(&sba, &dba, device->type);
- write_device_services(&sba, &dba, str);
- g_free(str);
+ store_services(device);

done:
device->browse = NULL;
--
1.7.4.1


2011-04-11 18:24:48

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 3/9] Remove btd_device_add_service function

btd_device_add_service is no longer necessary if the object paths for
the primary services can be returned during the registration.
---
attrib/client.c | 16 ++++++++--------
attrib/client.h | 2 +-
src/device.c | 11 ++---------
src/device.h | 1 -
4 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 28e5704..2dd70c9 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -1020,11 +1020,11 @@ static GDBusMethodTable prim_methods[] = {
{ }
};

-static void register_primaries(struct gatt_service *gatt, GSList *primaries)
+static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries)
{
- GSList *l;
+ GSList *l, *paths;

- for (l = primaries; l; l = l->next) {
+ for (paths = NULL, l = primaries; l; l = l->next) {
struct att_primary *att = l->data;
struct primary *prim;

@@ -1040,12 +1040,14 @@ static void register_primaries(struct gatt_service *gatt, GSList *primaries)
DBG("Registered: %s", prim->path);

gatt->primary = g_slist_append(gatt->primary, prim);
- btd_device_add_service(gatt->dev, prim->path);
+ paths = g_slist_append(paths, g_strdup(prim->path));
load_characteristics(prim, gatt);
}
+
+ return paths;
}

-int attrib_client_register(DBusConnection *connection,
+GSList *attrib_client_register(DBusConnection *connection,
struct btd_device *device, int psm,
GAttrib *attrib, GSList *primaries)
{
@@ -1069,11 +1071,9 @@ int attrib_client_register(DBusConnection *connection,
if (attrib)
gatt->attrib = g_attrib_ref(attrib);

- register_primaries(gatt, primaries);
-
gatt_services = g_slist_append(gatt_services, gatt);

- return 0;
+ return register_primaries(gatt, primaries);
}

void attrib_client_unregister(struct btd_device *device)
diff --git a/attrib/client.h b/attrib/client.h
index b4a4ecc..b29797c 100644
--- a/attrib/client.h
+++ b/attrib/client.h
@@ -22,7 +22,7 @@
*
*/

-int attrib_client_register(DBusConnection *connection,
+GSList *attrib_client_register(DBusConnection *connection,
struct btd_device *device, int psm,
GAttrib *attrib, GSList *primaries);
void attrib_client_unregister(struct btd_device *device);
diff --git a/src/device.c b/src/device.c
index f9b7a73..efe9938 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2336,18 +2336,11 @@ void device_set_authorizing(struct btd_device *device, gboolean auth)
device->authorizing = auth;
}

-void btd_device_add_service(struct btd_device *device, const char *path)
-{
- if (g_slist_find_custom(device->services, path, (GCompareFunc) strcmp))
- return;
-
- device->services = g_slist_append(device->services, g_strdup(path));
-}
-
void device_register_services(DBusConnection *conn, struct btd_device *device,
GSList *prim_list, int psm)
{
- attrib_client_register(conn, device, psm, NULL, prim_list);
+ device->services = attrib_client_register(conn, device, psm, NULL,
+ prim_list);
device->primaries = g_slist_concat(device->primaries, prim_list);
}

diff --git a/src/device.h b/src/device.h
index 285364f..2432884 100644
--- a/src/device.h
+++ b/src/device.h
@@ -56,7 +56,6 @@ void device_probe_drivers(struct btd_device *device, GSList *profiles);
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
GSList *btd_device_get_primaries(struct btd_device *device);
-void btd_device_add_service(struct btd_device *device, const char *path);
void device_register_services(DBusConnection *conn, struct btd_device *device,
GSList *prim_list, int psm);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
--
1.7.4.1


2011-04-11 18:24:27

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 2/9] Cleanup primary service registration from storage

---
src/adapter.c | 9 +--------
src/device.c | 20 ++++++--------------
src/device.h | 4 ++--
3 files changed, 9 insertions(+), 24 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c400bfd..6caff9a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -58,8 +58,6 @@
#include "storage.h"
#include "attrib-server.h"
#include "att.h"
-#include "gattrib.h"
-#include "attrib/client.h"

/* Interleaved discovery window: 5.12 sec */
#define GAP_INTER_DISCOV_WIN 5120
@@ -2193,16 +2191,11 @@ static void create_stored_device_from_primary(char *key, char *value,
for (l = services, uuids = NULL; l; l = l->next) {
struct att_primary *prim = l->data;
uuids = g_slist_append(uuids, prim->uuid);
-
- device_add_primary(device, prim);
}

- /* FIXME: Need the correct psm */
- attrib_client_register(connection, device, -1, NULL, services);
-
device_probe_drivers(device, uuids);
+ device_register_services(connection, device, services, -1);

- g_slist_free(services);
g_slist_free(uuids);
}

diff --git a/src/device.c b/src/device.c
index ecd1861..f9b7a73 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1406,14 +1406,6 @@ static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
return prim_list;
}

-static void register_primary_services(DBusConnection *conn,
- struct btd_device *device, GSList *prim_list)
-{
- /* TODO: PSM is hardcoded */
- attrib_client_register(conn, device, 31, NULL, prim_list);
- device->primaries = g_slist_concat(device->primaries, prim_list);
-}
-
static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
{
struct browse_req *req = user_data;
@@ -1450,7 +1442,7 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)

list = primary_from_record(device, req->profiles_added);
if (list)
- register_primary_services(req->conn, device, list);
+ device_register_services(req->conn, device, list, 31);
}

/* Remove drivers for services removed */
@@ -1592,13 +1584,11 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
for (l = services; l; l = l->next) {
struct att_primary *prim = l->data;
uuids = g_slist_append(uuids, prim->uuid);
- device_add_primary(device, prim);
}

device_probe_drivers(device, uuids);

- /* FIXME: Need the correct psm */
- attrib_client_register(req->conn, device, -1, req->attrib, services);
+ device_register_services(req->conn, device, services, -1);

g_slist_free(uuids);

@@ -2354,9 +2344,11 @@ void btd_device_add_service(struct btd_device *device, const char *path)
device->services = g_slist_append(device->services, g_strdup(path));
}

-void device_add_primary(struct btd_device *device, struct att_primary *prim)
+void device_register_services(DBusConnection *conn, struct btd_device *device,
+ GSList *prim_list, int psm)
{
- device->primaries = g_slist_append(device->primaries, prim);
+ attrib_client_register(conn, device, psm, NULL, prim_list);
+ device->primaries = g_slist_concat(device->primaries, prim_list);
}

GSList *btd_device_get_primaries(struct btd_device *device)
diff --git a/src/device.h b/src/device.h
index 3ce212b..285364f 100644
--- a/src/device.h
+++ b/src/device.h
@@ -25,7 +25,6 @@
#define DEVICE_INTERFACE "org.bluez.Device"

struct btd_device;
-struct att_primary;

typedef enum {
AUTH_TYPE_PINCODE,
@@ -58,7 +57,8 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
GSList *btd_device_get_primaries(struct btd_device *device);
void btd_device_add_service(struct btd_device *device, const char *path);
-void device_add_primary(struct btd_device *device, struct att_primary *prim);
+void device_register_services(DBusConnection *conn, struct btd_device *device,
+ GSList *prim_list, int psm);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
struct btd_adapter *device_get_adapter(struct btd_device *device);
void device_get_address(struct btd_device *device, bdaddr_t *bdaddr);
--
1.7.4.1


2011-04-11 18:24:03

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH v2 1/9] Register primary services exported over basic rate

This patch registers the object paths for primary services exported
through SDP. PSM, start and end handle information are available in
the Protocol Descriptor List.
---
attrib/gatt.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/gatt.h | 6 ++++
src/device.c | 56 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 139 insertions(+), 1 deletions(-)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index 0b69daf..360218b 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -23,8 +23,11 @@
*/

#include <stdint.h>
+#include <stdlib.h>
#include <glib.h>
#include <bluetooth/uuid.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>

#include "att.h"
#include "gattrib.h"
@@ -575,3 +578,78 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, buf, plen, NULL,
user_data, notify);
}
+
+static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
+{
+ sdp_list_t *list;
+ uuid_t proto;
+
+ sdp_uuid16_create(&proto, ATT_UUID);
+
+ for (list = proto_list; list; list = list->next) {
+ sdp_list_t *p;
+ for (p = list->data; p; p = p->next) {
+ sdp_data_t *seq = p->data;
+ if (seq && seq->dtd == SDP_UUID16 &&
+ sdp_uuid16_cmp(&proto, &seq->val.uuid) == 0)
+ return seq->next;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean parse_proto_params(sdp_list_t *proto_list, uint16_t *psm,
+ uint16_t *start, uint16_t *end)
+{
+ sdp_data_t *seq1, *seq2;
+
+ if (psm)
+ *psm = sdp_get_proto_port(proto_list, L2CAP_UUID);
+
+ /* Getting start and end handle */
+ seq1 = proto_seq_find(proto_list);
+ if (!seq1 || seq1->dtd != SDP_UINT16)
+ return FALSE;
+
+ seq2 = seq1->next;
+ if (!seq2 || seq2->dtd != SDP_UINT16)
+ return FALSE;
+
+ if (start)
+ *start = seq1->val.uint16;
+
+ if (end)
+ *end = seq2->val.uint16;
+
+ return TRUE;
+}
+
+gboolean gatt_parse_record(const sdp_record_t *rec,
+ uuid_t *prim_uuid, uint16_t *psm,
+ uint16_t *start, uint16_t *end)
+{
+ sdp_list_t *list;
+ uuid_t uuid;
+ gboolean ret;
+
+ if (sdp_get_service_classes(rec, &list) < 0)
+ return FALSE;
+
+ memcpy(&uuid, list->data, sizeof(uuid));
+ sdp_list_free(list, free);
+
+ if (sdp_get_access_protos(rec, &list) < 0)
+ return FALSE;
+
+ ret = parse_proto_params(list, psm, start, end);
+
+ sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(list, NULL);
+
+ /* FIXME: replace by bt_uuid_t after uuid_t/sdp code cleanup */
+ if (ret && prim_uuid)
+ memcpy(prim_uuid, &uuid, sizeof(uuid_t));
+
+ return ret;
+}
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 221d94d..2c2f38c 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,6 +24,8 @@

#define GATT_CID 4

+#include <bluetooth/sdp.h>
+
typedef void (*gatt_cb_t) (GSList *l, guint8 status, gpointer user_data);

guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
@@ -51,3 +53,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,

guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
gpointer user_data);
+
+gboolean gatt_parse_record(const sdp_record_t *rec,
+ uuid_t *prim_uuid, uint16_t *psm,
+ uint16_t *start, uint16_t *end);
diff --git a/src/device.c b/src/device.c
index d567952..ecd1861 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1367,6 +1367,53 @@ static void create_device_reply(struct btd_device *device, struct browse_req *re
g_dbus_send_message(req->conn, reply);
}

+static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
+{
+ GSList *l, *prim_list = NULL;
+ char *att_uuid;
+ uuid_t proto_uuid;
+
+ sdp_uuid16_create(&proto_uuid, ATT_UUID);
+ att_uuid = bt_uuid2string(&proto_uuid);
+
+ for (l = profiles; l; l = l->next) {
+ const char *profile_uuid = l->data;
+ const sdp_record_t *rec;
+ struct att_primary *prim;
+ uint16_t start = 0, end = 0, psm = 0;
+ uuid_t prim_uuid;
+
+ rec = btd_device_get_record(device, profile_uuid);
+ if (!rec)
+ continue;
+
+ if (!record_has_uuid(rec, att_uuid))
+ continue;
+
+ if (!gatt_parse_record(rec, &prim_uuid, &psm, &start, &end))
+ continue;
+
+ prim = g_new0(struct att_primary, 1);
+ prim->start = start;
+ prim->end = end;
+ sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
+
+ prim_list = g_slist_append(prim_list, prim);
+ }
+
+ g_free(att_uuid);
+
+ return prim_list;
+}
+
+static void register_primary_services(DBusConnection *conn,
+ struct btd_device *device, GSList *prim_list)
+{
+ /* TODO: PSM is hardcoded */
+ attrib_client_register(conn, device, 31, NULL, prim_list);
+ device->primaries = g_slist_concat(device->primaries, prim_list);
+}
+
static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
{
struct browse_req *req = user_data;
@@ -1396,9 +1443,16 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
}

/* Probe matching drivers for services added */
- if (req->profiles_added)
+ if (req->profiles_added) {
+ GSList *list;
+
device_probe_drivers(device, req->profiles_added);

+ list = primary_from_record(device, req->profiles_added);
+ if (list)
+ register_primary_services(req->conn, device, list);
+ }
+
/* Remove drivers for services removed */
if (req->profiles_removed)
device_remove_drivers(device, req->profiles_removed);
--
1.7.4.1


2011-04-07 18:15:57

by Claudio Takahasi

[permalink] [raw]
Subject: Re: [PATCH 1/9] Register primary services exported over basic rate

Hi Vinicius & Johan,

I will fix this error and move the GATT SDP record functions to gatt.c

BR,
Claudio

On Thu, Apr 7, 2011 at 5:58 PM, Vinicius Costa Gomes
<[email protected]> wrote:
> Hi Claudio,
>
> On 14:30 Thu 07 Apr, Claudio Takahasi wrote:
>> This patch registers the object paths for primary services exported
>> through SDP. PSM, start and end handle information are available in
>> the Protocol Descriptor List.
>> ---
>>  src/device.c |  130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>  1 files changed, 129 insertions(+), 1 deletions(-)
>>
>> diff --git a/src/device.c b/src/device.c
>> index d567952..32eb643 100644
>> --- a/src/device.c
>> +++ b/src/device.c
>> @@ -1367,6 +1367,127 @@ static void create_device_reply(struct btd_device *device, struct browse_req *re
>>       g_dbus_send_message(req->conn, reply);
>>  }
>>
>> +static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
>> +{
>> +     sdp_list_t *list;
>> +     uuid_t proto;
>> +
>> +     sdp_uuid16_create(&proto, ATT_UUID);
>> +
>> +     for (;list = proto_list, list; list = list->next) {
>
> The first ";" doesn't look right.
>
>> +             sdp_list_t *p;
>> +             for (p = list->data; p; p = p->next) {
>> +                     sdp_data_t *seq = p->data;
>> +                     if (seq && seq->dtd == SDP_UUID16 &&
>> +                             sdp_uuid16_cmp(&proto, &seq->val.uuid) == 0)
>> +                             return seq->next;
>> +             }
>> +     }
>> +
>> +     return NULL;
>> +}
>> +
>> +static gboolean parse_proto_params(sdp_list_t *proto_list, uint16_t *psm,
>> +                                             uint16_t *start, uint16_t *end)
>> +{
>> +     sdp_data_t *seq1, *seq2;
>> +
>> +     if (psm)
>> +             *psm = sdp_get_proto_port(proto_list, L2CAP_UUID);
>> +
>> +     /* Getting start and end handle */
>> +     seq1 = proto_seq_find(proto_list);
>> +     if (!seq1 || seq1->dtd != SDP_UINT16)
>> +             return FALSE;
>> +
>> +     seq2 = seq1->next;
>> +     if (!seq2 || seq2->dtd != SDP_UINT16)
>> +             return FALSE;
>> +
>> +     if (start)
>> +             *start = seq1->val.uint16;
>> +
>> +     if (end)
>> +             *end = seq2->val.uint16;
>> +
>> +     return TRUE;
>> +}
>> +
>> +static gboolean parse_primary_record(const sdp_record_t *rec,
>> +                                     uuid_t *prim_uuid, uint16_t *psm,
>> +                                     uint16_t *start, uint16_t *end)
>> +{
>> +     sdp_list_t *list;
>> +     uuid_t uuid;
>> +     gboolean ret;
>> +
>> +     if (sdp_get_service_classes(rec, &list) < 0)
>> +             return FALSE;
>> +
>> +     memcpy(&uuid, list->data, sizeof(uuid));
>> +     sdp_list_free(list, free);
>> +
>> +     if (sdp_get_access_protos(rec, &list) < 0)
>> +             return FALSE;
>> +
>> +     ret = parse_proto_params(list, psm, start, end);
>> +
>> +     sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
>> +     sdp_list_free(list, NULL);
>> +
>> +     if (ret && prim_uuid)
>> +             memcpy(prim_uuid, &uuid, sizeof(uuid_t));
>> +
>> +     return ret;
>> +}
>> +
>> +static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
>> +{
>> +     GSList *l, *prim_list = NULL;
>> +     char *att_uuid;
>> +     uuid_t proto_uuid;
>> +
>> +     sdp_uuid16_create(&proto_uuid, ATT_UUID);
>> +     att_uuid = bt_uuid2string(&proto_uuid);
>> +
>> +     for (l = profiles; l; l = l->next) {
>> +             const char *profile_uuid = l->data;
>> +             const sdp_record_t *rec;
>> +             struct att_primary *prim;
>> +             uint16_t start = 0, end = 0, psm = 0;
>> +             uuid_t prim_uuid;
>> +
>> +             rec = btd_device_get_record(device, profile_uuid);
>> +             if (!rec)
>> +                     continue;
>> +
>> +             if (!record_has_uuid(rec, att_uuid))
>> +                     continue;
>> +
>> +             if (!parse_primary_record(rec, &prim_uuid, &psm, &start, &end))
>> +                     continue;
>> +
>> +             prim = g_new0(struct att_primary, 1);
>> +             prim->start = start;
>> +             prim->end = end;
>> +             sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
>> +
>> +             prim_list = g_slist_append(prim_list, prim);
>> +     }
>> +
>> +     g_free(att_uuid);
>> +
>> +     return prim_list;
>> +}
>> +
>> +static void register_primary_services(DBusConnection *conn,
>> +                             struct btd_device *device, GSList *prim_list)
>> +{
>> +     /* TODO: PSM is hardcoded */
>> +     attrib_client_register(conn, device, 31, NULL, prim_list);
>> +     device->primaries = g_slist_concat(device->primaries, prim_list);
>> +}
>> +
>>  static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
>>  {
>>       struct browse_req *req = user_data;
>> @@ -1396,9 +1517,16 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
>>       }
>>
>>       /* Probe matching drivers for services added */
>> -     if (req->profiles_added)
>> +     if (req->profiles_added) {
>> +             GSList *list;
>> +
>>               device_probe_drivers(device, req->profiles_added);
>>
>> +             list = primary_from_record(device, req->profiles_added);
>> +             if (list)
>> +                     register_primary_services(req->conn, device, list);
>> +     }
>> +
>>       /* Remove drivers for services removed */
>>       if (req->profiles_removed)
>>               device_remove_drivers(device, req->profiles_removed);
>> --
>> 1.7.4.1
>>
>> --
>> 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
>



--
--
Claudio Takahasi
Instituto Nokia de Tecnologia
Recife - Pernambuco - Brasil
+55 81 30879999

2011-04-07 17:58:18

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 1/9] Register primary services exported over basic rate

Hi Claudio,

On 14:30 Thu 07 Apr, Claudio Takahasi wrote:
> This patch registers the object paths for primary services exported
> through SDP. PSM, start and end handle information are available in
> the Protocol Descriptor List.
> ---
> src/device.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 129 insertions(+), 1 deletions(-)
>
> diff --git a/src/device.c b/src/device.c
> index d567952..32eb643 100644
> --- a/src/device.c
> +++ b/src/device.c
> @@ -1367,6 +1367,127 @@ static void create_device_reply(struct btd_device *device, struct browse_req *re
> g_dbus_send_message(req->conn, reply);
> }
>
> +static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
> +{
> + sdp_list_t *list;
> + uuid_t proto;
> +
> + sdp_uuid16_create(&proto, ATT_UUID);
> +
> + for (;list = proto_list, list; list = list->next) {

The first ";" doesn't look right.

> + sdp_list_t *p;
> + for (p = list->data; p; p = p->next) {
> + sdp_data_t *seq = p->data;
> + if (seq && seq->dtd == SDP_UUID16 &&
> + sdp_uuid16_cmp(&proto, &seq->val.uuid) == 0)
> + return seq->next;
> + }
> + }
> +
> + return NULL;
> +}
> +
> +static gboolean parse_proto_params(sdp_list_t *proto_list, uint16_t *psm,
> + uint16_t *start, uint16_t *end)
> +{
> + sdp_data_t *seq1, *seq2;
> +
> + if (psm)
> + *psm = sdp_get_proto_port(proto_list, L2CAP_UUID);
> +
> + /* Getting start and end handle */
> + seq1 = proto_seq_find(proto_list);
> + if (!seq1 || seq1->dtd != SDP_UINT16)
> + return FALSE;
> +
> + seq2 = seq1->next;
> + if (!seq2 || seq2->dtd != SDP_UINT16)
> + return FALSE;
> +
> + if (start)
> + *start = seq1->val.uint16;
> +
> + if (end)
> + *end = seq2->val.uint16;
> +
> + return TRUE;
> +}
> +
> +static gboolean parse_primary_record(const sdp_record_t *rec,
> + uuid_t *prim_uuid, uint16_t *psm,
> + uint16_t *start, uint16_t *end)
> +{
> + sdp_list_t *list;
> + uuid_t uuid;
> + gboolean ret;
> +
> + if (sdp_get_service_classes(rec, &list) < 0)
> + return FALSE;
> +
> + memcpy(&uuid, list->data, sizeof(uuid));
> + sdp_list_free(list, free);
> +
> + if (sdp_get_access_protos(rec, &list) < 0)
> + return FALSE;
> +
> + ret = parse_proto_params(list, psm, start, end);
> +
> + sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
> + sdp_list_free(list, NULL);
> +
> + if (ret && prim_uuid)
> + memcpy(prim_uuid, &uuid, sizeof(uuid_t));
> +
> + return ret;
> +}
> +
> +static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
> +{
> + GSList *l, *prim_list = NULL;
> + char *att_uuid;
> + uuid_t proto_uuid;
> +
> + sdp_uuid16_create(&proto_uuid, ATT_UUID);
> + att_uuid = bt_uuid2string(&proto_uuid);
> +
> + for (l = profiles; l; l = l->next) {
> + const char *profile_uuid = l->data;
> + const sdp_record_t *rec;
> + struct att_primary *prim;
> + uint16_t start = 0, end = 0, psm = 0;
> + uuid_t prim_uuid;
> +
> + rec = btd_device_get_record(device, profile_uuid);
> + if (!rec)
> + continue;
> +
> + if (!record_has_uuid(rec, att_uuid))
> + continue;
> +
> + if (!parse_primary_record(rec, &prim_uuid, &psm, &start, &end))
> + continue;
> +
> + prim = g_new0(struct att_primary, 1);
> + prim->start = start;
> + prim->end = end;
> + sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
> +
> + prim_list = g_slist_append(prim_list, prim);
> + }
> +
> + g_free(att_uuid);
> +
> + return prim_list;
> +}
> +
> +static void register_primary_services(DBusConnection *conn,
> + struct btd_device *device, GSList *prim_list)
> +{
> + /* TODO: PSM is hardcoded */
> + attrib_client_register(conn, device, 31, NULL, prim_list);
> + device->primaries = g_slist_concat(device->primaries, prim_list);
> +}
> +
> static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
> {
> struct browse_req *req = user_data;
> @@ -1396,9 +1517,16 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
> }
>
> /* Probe matching drivers for services added */
> - if (req->profiles_added)
> + if (req->profiles_added) {
> + GSList *list;
> +
> device_probe_drivers(device, req->profiles_added);
>
> + list = primary_from_record(device, req->profiles_added);
> + if (list)
> + register_primary_services(req->conn, device, list);
> + }
> +
> /* Remove drivers for services removed */
> if (req->profiles_removed)
> device_remove_drivers(device, req->profiles_removed);
> --
> 1.7.4.1
>
> --
> 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-04-07 17:30:14

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 9/9] TODO: Add hard-coded PSM for GATT over basic rate

---
TODO | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/TODO b/TODO
index 461b179..fab3ec0 100644
--- a/TODO
+++ b/TODO
@@ -136,6 +136,11 @@ ATT/GATT
Priority: Medium
Complexity: C1

+- Fix hard-coded PSM for GATT services over basic rate.
+
+ Priority: Low
+ Complexity: C1
+
- Refactor read_by_group() and read_by_type() in src/attrib-server.c
(they've grown simply too big). First step could be to move out the
long for-loops to new functions called e.g. get_groups() and get_types().
--
1.7.4.1


2011-04-07 17:30:13

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 8/9] TODO: Remove item related to GATT service over basic rate

---
TODO | 10 ----------
1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/TODO b/TODO
index d52808b..461b179 100644
--- a/TODO
+++ b/TODO
@@ -114,16 +114,6 @@ Low Energy
ATT/GATT
========

-- For BR/EDR, primary services can be registered based on the information
- extracted from the service records. UUIDs, start and end handles information
- are available in the record, Discover All Primary Services procedure is not
- necessary. If a GATT service doesn't export a service record means that
- it should not be used over BR/EDR. Don't start this task before to move the
- attribute client code to the bluetoothd core.
-
- Priority: Medium
- Complexity: C1
-
- At the moment authentication and authorization is not supported at the
same time, read/write requirements in the attribute server needs to
be extended. According to Bluetooth Specification a server shall check
--
1.7.4.1


2011-04-07 17:30:12

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 7/9] Fix primary services registration from storage for basic rate

---
src/adapter.c | 5 ++++-
src/device.c | 4 ++--
src/device.h | 2 ++
3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 9a0f688..7049ba6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2004,7 +2004,7 @@ static void create_stored_device_from_profiles(char *key, char *value,
void *user_data)
{
struct btd_adapter *adapter = user_data;
- GSList *uuids = bt_string2list(value);
+ GSList *list, *uuids = bt_string2list(value);
struct btd_device *device;

if (g_slist_find_custom(adapter->devices,
@@ -2019,6 +2019,9 @@ static void create_stored_device_from_profiles(char *key, char *value,
adapter->devices = g_slist_append(adapter->devices, device);

device_probe_drivers(device, uuids);
+ list = device_services_from_record(device, uuids);
+ if (list)
+ device_register_services(connection, device, list, 31);

g_slist_foreach(uuids, (GFunc) g_free, NULL);
g_slist_free(uuids);
diff --git a/src/device.c b/src/device.c
index eecaee0..4da6579 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1441,7 +1441,7 @@ static gboolean parse_primary_record(const sdp_record_t *rec,
return ret;
}

-static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
+GSList *device_services_from_record(struct btd_device *device, GSList *profiles)
{
GSList *l, *prim_list = NULL;
char *att_uuid;
@@ -1514,7 +1514,7 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)

device_probe_drivers(device, req->profiles_added);

- list = primary_from_record(device, req->profiles_added);
+ list = device_services_from_record(device, req->profiles_added);
if (list)
device_register_services(req->conn, device, list, 31);
}
diff --git a/src/device.h b/src/device.h
index 2432884..370382d 100644
--- a/src/device.h
+++ b/src/device.h
@@ -58,6 +58,8 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
GSList *btd_device_get_primaries(struct btd_device *device);
void device_register_services(DBusConnection *conn, struct btd_device *device,
GSList *prim_list, int psm);
+GSList *device_services_from_record(struct btd_device *device,
+ GSList *profiles);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
struct btd_adapter *device_get_adapter(struct btd_device *device);
void device_get_address(struct btd_device *device, bdaddr_t *bdaddr);
--
1.7.4.1


2011-04-07 17:30:11

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 6/9] Fix LE device creation from storage

Ignore the device if it already created. This patch adds a consistency
check to avoid registering the same service over basic rate and LE.
---
src/adapter.c | 20 +++++++++-----------
1 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8380a58..9a0f688 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2171,18 +2171,16 @@ static void create_stored_device_from_primary(char *key, char *value,
struct btd_device *device;
GSList *services, *uuids, *l;

- l = g_slist_find_custom(adapter->devices,
- key, (GCompareFunc) device_address_cmp);
- if (l)
- device = l->data;
- else {
- device = device_create(connection, adapter, key, DEVICE_TYPE_LE);
- if (!device)
- return;
+ if (g_slist_find_custom(adapter->devices,
+ key, (GCompareFunc) device_address_cmp))
+ return;

- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
- }
+ device = device_create(connection, adapter, key, DEVICE_TYPE_LE);
+ if (!device)
+ return;
+
+ device_set_temporary(device, FALSE);
+ adapter->devices = g_slist_append(adapter->devices, device);

services = string_to_primary_list(value);
if (services == NULL)
--
1.7.4.1


2011-04-07 17:30:10

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 5/9] Fix device type when creating from primary services storage

GATT services exported through basic rate need to be created based
on the "profiles" file. For GATT over LE, "primary" file entries need
to be used to create the devices and primary services objects.
---
src/adapter.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 6caff9a..8380a58 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2176,7 +2176,7 @@ static void create_stored_device_from_primary(char *key, char *value,
if (l)
device = l->data;
else {
- device = device_create(connection, adapter, key, DEVICE_TYPE_BREDR);
+ device = device_create(connection, adapter, key, DEVICE_TYPE_LE);
if (!device)
return;

--
1.7.4.1


2011-04-07 17:30:09

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 4/9] Move the primary service storage code to a local function

---
src/device.c | 27 ++++++++++++++++-----------
1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/device.c b/src/device.c
index d1ed05a..eecaee0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1636,14 +1636,26 @@ static char *primary_list_to_string(GSList *primary_list)
return g_string_free(services, FALSE);
}

+static void store_services(struct btd_device *device)
+{
+ struct btd_adapter *adapter = device->adapter;
+ bdaddr_t dba, sba;
+ char *str = primary_list_to_string(device->services);
+
+ adapter_get_address(adapter, &sba);
+ device_get_address(device, &dba);
+
+ write_device_type(&sba, &dba, device->type);
+ write_device_services(&sba, &dba, str);
+
+ g_free(str);
+}
+
static void primary_cb(GSList *services, guint8 status, gpointer user_data)
{
struct browse_req *req = user_data;
struct btd_device *device = req->device;
- struct btd_adapter *adapter = device->adapter;
GSList *l, *uuids = NULL;
- bdaddr_t dba, sba;
- char *str;

if (status) {
DBusMessage *reply;
@@ -1668,14 +1680,7 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)

create_device_reply(device, req);

- str = primary_list_to_string(services);
-
- adapter_get_address(adapter, &sba);
- device_get_address(device, &dba);
-
- write_device_type(&sba, &dba, device->type);
- write_device_services(&sba, &dba, str);
- g_free(str);
+ store_services(device);

done:
device->browse = NULL;
--
1.7.4.1


2011-04-07 17:30:08

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 3/9] Remove btd_device_add_service function

btd_device_add_service is no longer necessary if the object paths for
the primary services can be returned during the registration.
---
attrib/client.c | 16 ++++++++--------
attrib/client.h | 2 +-
src/device.c | 11 ++---------
src/device.h | 1 -
4 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 28e5704..2dd70c9 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -1020,11 +1020,11 @@ static GDBusMethodTable prim_methods[] = {
{ }
};

-static void register_primaries(struct gatt_service *gatt, GSList *primaries)
+static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries)
{
- GSList *l;
+ GSList *l, *paths;

- for (l = primaries; l; l = l->next) {
+ for (paths = NULL, l = primaries; l; l = l->next) {
struct att_primary *att = l->data;
struct primary *prim;

@@ -1040,12 +1040,14 @@ static void register_primaries(struct gatt_service *gatt, GSList *primaries)
DBG("Registered: %s", prim->path);

gatt->primary = g_slist_append(gatt->primary, prim);
- btd_device_add_service(gatt->dev, prim->path);
+ paths = g_slist_append(paths, g_strdup(prim->path));
load_characteristics(prim, gatt);
}
+
+ return paths;
}

-int attrib_client_register(DBusConnection *connection,
+GSList *attrib_client_register(DBusConnection *connection,
struct btd_device *device, int psm,
GAttrib *attrib, GSList *primaries)
{
@@ -1069,11 +1071,9 @@ int attrib_client_register(DBusConnection *connection,
if (attrib)
gatt->attrib = g_attrib_ref(attrib);

- register_primaries(gatt, primaries);
-
gatt_services = g_slist_append(gatt_services, gatt);

- return 0;
+ return register_primaries(gatt, primaries);
}

void attrib_client_unregister(struct btd_device *device)
diff --git a/attrib/client.h b/attrib/client.h
index b4a4ecc..b29797c 100644
--- a/attrib/client.h
+++ b/attrib/client.h
@@ -22,7 +22,7 @@
*
*/

-int attrib_client_register(DBusConnection *connection,
+GSList *attrib_client_register(DBusConnection *connection,
struct btd_device *device, int psm,
GAttrib *attrib, GSList *primaries);
void attrib_client_unregister(struct btd_device *device);
diff --git a/src/device.c b/src/device.c
index b6750b6..d1ed05a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2410,18 +2410,11 @@ void device_set_authorizing(struct btd_device *device, gboolean auth)
device->authorizing = auth;
}

-void btd_device_add_service(struct btd_device *device, const char *path)
-{
- if (g_slist_find_custom(device->services, path, (GCompareFunc) strcmp))
- return;
-
- device->services = g_slist_append(device->services, g_strdup(path));
-}
-
void device_register_services(DBusConnection *conn, struct btd_device *device,
GSList *prim_list, int psm)
{
- attrib_client_register(conn, device, psm, NULL, prim_list);
+ device->services = attrib_client_register(conn, device, psm, NULL,
+ prim_list);
device->primaries = g_slist_concat(device->primaries, prim_list);
}

diff --git a/src/device.h b/src/device.h
index 285364f..2432884 100644
--- a/src/device.h
+++ b/src/device.h
@@ -56,7 +56,6 @@ void device_probe_drivers(struct btd_device *device, GSList *profiles);
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
GSList *btd_device_get_primaries(struct btd_device *device);
-void btd_device_add_service(struct btd_device *device, const char *path);
void device_register_services(DBusConnection *conn, struct btd_device *device,
GSList *prim_list, int psm);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
--
1.7.4.1


2011-04-07 17:30:07

by Claudio Takahasi

[permalink] [raw]
Subject: [PATCH 2/9] Cleanup primary service registration from storage

---
src/adapter.c | 9 +--------
src/device.c | 20 ++++++--------------
src/device.h | 4 ++--
3 files changed, 9 insertions(+), 24 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c400bfd..6caff9a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -58,8 +58,6 @@
#include "storage.h"
#include "attrib-server.h"
#include "att.h"
-#include "gattrib.h"
-#include "attrib/client.h"

/* Interleaved discovery window: 5.12 sec */
#define GAP_INTER_DISCOV_WIN 5120
@@ -2193,16 +2191,11 @@ static void create_stored_device_from_primary(char *key, char *value,
for (l = services, uuids = NULL; l; l = l->next) {
struct att_primary *prim = l->data;
uuids = g_slist_append(uuids, prim->uuid);
-
- device_add_primary(device, prim);
}

- /* FIXME: Need the correct psm */
- attrib_client_register(connection, device, -1, NULL, services);
-
device_probe_drivers(device, uuids);
+ device_register_services(connection, device, services, -1);

- g_slist_free(services);
g_slist_free(uuids);
}

diff --git a/src/device.c b/src/device.c
index 32eb643..b6750b6 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1480,14 +1480,6 @@ static GSList *primary_from_record(struct btd_device *device, GSList *profiles)
return prim_list;
}

-static void register_primary_services(DBusConnection *conn,
- struct btd_device *device, GSList *prim_list)
-{
- /* TODO: PSM is hardcoded */
- attrib_client_register(conn, device, 31, NULL, prim_list);
- device->primaries = g_slist_concat(device->primaries, prim_list);
-}
-
static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
{
struct browse_req *req = user_data;
@@ -1524,7 +1516,7 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)

list = primary_from_record(device, req->profiles_added);
if (list)
- register_primary_services(req->conn, device, list);
+ device_register_services(req->conn, device, list, 31);
}

/* Remove drivers for services removed */
@@ -1666,13 +1658,11 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
for (l = services; l; l = l->next) {
struct att_primary *prim = l->data;
uuids = g_slist_append(uuids, prim->uuid);
- device_add_primary(device, prim);
}

device_probe_drivers(device, uuids);

- /* FIXME: Need the correct psm */
- attrib_client_register(req->conn, device, -1, req->attrib, services);
+ device_register_services(req->conn, device, services, -1);

g_slist_free(uuids);

@@ -2428,9 +2418,11 @@ void btd_device_add_service(struct btd_device *device, const char *path)
device->services = g_slist_append(device->services, g_strdup(path));
}

-void device_add_primary(struct btd_device *device, struct att_primary *prim)
+void device_register_services(DBusConnection *conn, struct btd_device *device,
+ GSList *prim_list, int psm)
{
- device->primaries = g_slist_append(device->primaries, prim);
+ attrib_client_register(conn, device, psm, NULL, prim_list);
+ device->primaries = g_slist_concat(device->primaries, prim_list);
}

GSList *btd_device_get_primaries(struct btd_device *device)
diff --git a/src/device.h b/src/device.h
index 3ce212b..285364f 100644
--- a/src/device.h
+++ b/src/device.h
@@ -25,7 +25,6 @@
#define DEVICE_INTERFACE "org.bluez.Device"

struct btd_device;
-struct att_primary;

typedef enum {
AUTH_TYPE_PINCODE,
@@ -58,7 +57,8 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
GSList *btd_device_get_primaries(struct btd_device *device);
void btd_device_add_service(struct btd_device *device, const char *path);
-void device_add_primary(struct btd_device *device, struct att_primary *prim);
+void device_register_services(DBusConnection *conn, struct btd_device *device,
+ GSList *prim_list, int psm);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
struct btd_adapter *device_get_adapter(struct btd_device *device);
void device_get_address(struct btd_device *device, bdaddr_t *bdaddr);
--
1.7.4.1