2012-12-13 20:39:16

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 01/15] device: Retrieve device technology from storage

---
src/device.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)

diff --git a/src/device.c b/src/device.c
index e7aa44d..515ee61 100644
--- a/src/device.c
+++ b/src/device.c
@@ -244,6 +244,35 @@ static gboolean store_device_info_cb(gpointer user_data)
g_key_file_remove_key(key_file, "General", "Class", NULL);
}

+ switch (device->bdaddr_type) {
+ case BDADDR_BREDR:
+ g_key_file_set_string(key_file, "General",
+ "SupportedTechnologies", "BR/EDR");
+ g_key_file_remove_key(key_file, "General",
+ "AddressType", NULL);
+ break;
+
+ case BDADDR_LE_PUBLIC:
+ g_key_file_set_string(key_file, "General",
+ "SupportedTechnologies", "LE");
+ g_key_file_set_string(key_file, "General",
+ "AddressType", "public");
+ break;
+
+ case BDADDR_LE_RANDOM:
+ g_key_file_set_string(key_file, "General",
+ "SupportedTechnologies", "LE");
+ g_key_file_set_string(key_file, "General",
+ "AddressType", "static");
+ break;
+
+ default:
+ g_key_file_remove_key(key_file, "General",
+ "SupportedTechnologies", NULL);
+ g_key_file_remove_key(key_file, "General",
+ "AddressType", NULL);
+ }
+
g_key_file_set_boolean(key_file, "General", "Trusted",
device->trusted);

@@ -1714,6 +1743,9 @@ static void load_info(struct btd_device *device, const gchar *local,
gboolean store_needed = FALSE;
gboolean blocked;
int source, vendor, product, version;
+ char **techno, **t;
+ gboolean bredr = FALSE;
+ gboolean le = FALSE;

snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
filename[PATH_MAX] = '\0';
@@ -1750,6 +1782,42 @@ static void load_info(struct btd_device *device, const gchar *local,
g_free(str);
}

+ /* Load device technology */
+ techno = g_key_file_get_string_list(key_file, "General",
+ "SupportedTechnologies", NULL, NULL);
+ if (!techno)
+ goto next;
+
+ for (t = techno; *t; t++) {
+ if (g_str_equal(*t, "BR/EDR"))
+ bredr = TRUE;
+ else if (g_str_equal(*t, "LE"))
+ le = TRUE;
+ else
+ error("Unknown device technology");
+ }
+
+ if (bredr && le) {
+ /* TODO: Add correct type for dual mode device */
+ } else if (bredr) {
+ device->bdaddr_type = BDADDR_BREDR;
+ } else if (le) {
+ str = g_key_file_get_string(key_file, "General",
+ "AddressType", NULL);
+
+ if (str && g_str_equal(str, "public"))
+ device->bdaddr_type = BDADDR_LE_PUBLIC;
+ else if (str && g_str_equal(str, "static"))
+ device->bdaddr_type = BDADDR_LE_RANDOM;
+ else
+ error("Unknown LE device technology");
+
+ g_free(str);
+ }
+
+ g_strfreev(techno);
+
+next:
/* Load trust */
device->trusted = g_key_file_get_boolean(key_file, "General",
"Trusted", NULL);
--
1.7.9.5



2012-12-14 08:31:13

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v2 01/15] device: Retrieve device technology from storage

Hi Fr?d?ric,

On Thu, Dec 13, 2012, Fr?d?ric Danis wrote:
> ---
> src/device.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 68 insertions(+)

All patches in this set have been applied. I also applied one extra
patch to convert "Profiles" to "Services" since the value consists of
service UUIDs and not profile UUIDs.

Johan

2012-12-13 20:39:30

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 15/15] input: Use new storage architecture

Retrieve HID record from device file located in cache directory.

Remove no more used fetch_record().
---
profiles/input/device.c | 20 ++++++++++++++++----
src/storage.c | 27 ---------------------------
src/storage.h | 2 --
3 files changed, 16 insertions(+), 33 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 2d8077a..9cea028 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -316,9 +316,11 @@ static gboolean encrypt_notify(GIOChannel *io, GIOCondition condition,
static int hidp_add_connection(struct input_device *idev)
{
struct hidp_connadd_req *req;
- uint8_t dst_type;
sdp_record_t *rec;
char src_addr[18], dst_addr[18];
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ char handle[11], *str;
GError *gerr = NULL;
int err;

@@ -331,15 +333,25 @@ static int hidp_add_connection(struct input_device *idev)
ba2str(&idev->src, src_addr);
ba2str(&idev->dst, dst_addr);

- dst_type = device_get_addr_type(idev->device);
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr,
+ dst_addr);
+ filename[PATH_MAX] = '\0';
+ sprintf(handle, "0x%8.8X", idev->handle);

- rec = fetch_record(src_addr, dst_addr, dst_type, idev->handle);
- if (!rec) {
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ str = g_key_file_get_string(key_file, "ServiceRecords", handle, NULL);
+ g_key_file_free(key_file);
+
+ if (!str) {
error("Rejected connection from unknown device %s", dst_addr);
err = -EPERM;
goto cleanup;
}

+ rec = record_from_string(str);
+ g_free(str);
+
extract_hid_record(rec, req);
sdp_record_free(rec);

diff --git a/src/storage.c b/src/storage.c
index d3cbc8f..33da2cb 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -268,33 +268,6 @@ sdp_record_t *record_from_string(const gchar *str)
}


-sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
- uint8_t dst_type, const uint32_t handle)
-{
- char filename[PATH_MAX + 1], old_key[28], key[30], *str;
- sdp_record_t *rec;
-
- create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
-
- snprintf(key, sizeof(key), "%17s#%hhu#%08X", dst, dst_type, handle);
- snprintf(old_key, sizeof(old_key), "%17s#%08X", dst, handle);
-
- str = textfile_get(filename, key);
- if (str != NULL)
- goto done;
-
- /* Try old format (address#handle) */
- str = textfile_get(filename, old_key);
- if (str == NULL)
- return NULL;
-
-done:
- rec = record_from_string(str);
- free(str);
-
- return rec;
-}
-
int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
const uint32_t handle)
{
diff --git a/src/storage.h b/src/storage.h
index 4c99693..b125818 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -36,8 +36,6 @@ int write_lastused_info(const bdaddr_t *local, const bdaddr_t *peer,
uint8_t peer_type, struct tm *tm);
ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin);
sdp_record_t *record_from_string(const gchar *str);
-sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
- uint8_t dst_type, const uint32_t handle);
int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
const uint32_t handle);
sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid);
--
1.7.9.5


2012-12-13 20:39:29

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 14/15] device: Update btd_device_get_record to use new storage

Remove no more used functions from storage.[ch].
---
src/device.c | 40 ++++++++++++++++++++++++++++++++++++++--
src/storage.c | 38 --------------------------------------
src/storage.h | 1 -
3 files changed, 38 insertions(+), 41 deletions(-)

diff --git a/src/device.c b/src/device.c
index fc37e51..96b226f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4051,6 +4051,43 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid)
uuids_changed(device);
}

+static sdp_list_t *read_device_records(struct btd_device *device)
+{
+ char local[18], peer[18];
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ char **keys, **handle;
+ char *str;
+ sdp_list_t *recs = NULL;
+ sdp_record_t *rec;
+
+ ba2str(adapter_get_address(device->adapter), local);
+ ba2str(&device->bdaddr, peer);
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ keys = g_key_file_get_keys(key_file, "ServiceRecords", NULL, NULL);
+
+ for (handle = keys; *handle; handle++) {
+ str = g_key_file_get_string(key_file, "ServiceRecords",
+ *handle, NULL);
+ if (!str)
+ continue;
+
+ rec = record_from_string(str);
+ recs = sdp_list_append(recs, rec);
+ g_free(str);
+ }
+
+ g_strfreev(keys);
+ g_key_file_free(key_file);
+
+ return recs;
+}
+
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid)
{
@@ -4066,8 +4103,7 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
device->tmp_records = NULL;
}

- device->tmp_records = read_records(adapter_get_address(device->adapter),
- &device->bdaddr);
+ device->tmp_records = read_device_records(device);
if (!device->tmp_records)
return NULL;

diff --git a/src/storage.c b/src/storage.c
index 180946f..d3cbc8f 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -319,44 +319,6 @@ int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
return err;
}

-struct record_list {
- sdp_list_t *recs;
- const gchar *addr;
-};
-
-static void create_stored_records_from_keys(char *key, char *value,
- void *user_data)
-{
- struct record_list *rec_list = user_data;
- const gchar *addr = rec_list->addr;
- sdp_record_t *rec;
-
- if (strncmp(key, addr, 17))
- return;
-
- rec = record_from_string(value);
-
- rec_list->recs = sdp_list_append(rec_list->recs, rec);
-}
-
-sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst)
-{
- char filename[PATH_MAX + 1];
- struct record_list rec_list;
- char srcaddr[18], dstaddr[18];
-
- ba2str(src, srcaddr);
- ba2str(dst, dstaddr);
-
- rec_list.addr = dstaddr;
- rec_list.recs = NULL;
-
- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "sdp");
- textfile_foreach(filename, create_stored_records_from_keys, &rec_list);
-
- return rec_list.recs;
-}
-
sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid)
{
sdp_list_t *seq;
diff --git a/src/storage.h b/src/storage.h
index 262a594..4c99693 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -40,7 +40,6 @@ sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
uint8_t dst_type, const uint32_t handle);
int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
const uint32_t handle);
-sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst);
sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid);
int read_device_pairable(const bdaddr_t *local, gboolean *mode);
int write_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
--
1.7.9.5


2012-12-13 20:39:28

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 13/15] adapter: Remove create_stored_device_from_primaries

Loading of primaries list is done by device_create_from_storage().

As all device load during start-up has been converted, we can remove
temporary hack in device_create().
---
src/adapter.c | 80 ++-------------------------------------------------------
src/device.c | 22 +++++-----------
2 files changed, 8 insertions(+), 94 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 64d8ed3..80dbc77 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1725,80 +1725,6 @@ failed:
return ltk;
}

-static GSList *string_to_primary_list(char *str)
-{
- GSList *l = NULL;
- char **services;
- int i;
-
- if (str == NULL)
- return NULL;
-
- services = g_strsplit(str, " ", 0);
- if (services == NULL)
- return NULL;
-
- for (i = 0; services[i]; i++) {
- struct gatt_primary *prim;
- int ret;
-
- prim = g_new0(struct gatt_primary, 1);
-
- ret = sscanf(services[i], "%04hX#%04hX#%s", &prim->range.start,
- &prim->range.end, prim->uuid);
-
- if (ret < 3) {
- g_free(prim);
- continue;
- }
-
- l = g_slist_append(l, prim);
- }
-
- g_strfreev(services);
-
- return l;
-}
-
-static void create_stored_device_from_primaries(char *key, char *value,
- void *user_data)
-{
- struct btd_adapter *adapter = user_data;
- struct btd_device *device;
- GSList *services, *uuids, *l;
- char address[18];
- uint8_t bdaddr_type;
-
- if (sscanf(key, "%17s#%hhu", address, &bdaddr_type) < 2)
- return;
-
- if (g_slist_find_custom(adapter->devices,
- address, (GCompareFunc) device_address_cmp))
- return;
-
- device = device_create(adapter, address, bdaddr_type);
- 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)
- return;
-
- for (l = services, uuids = NULL; l; l = l->next) {
- struct gatt_primary *prim = l->data;
- uuids = g_slist_append(uuids, prim->uuid);
- }
-
- device_register_primaries(device, services, -1);
-
- device_probe_profiles(device, uuids);
-
- g_slist_free(uuids);
-}
-
static void load_devices(struct btd_adapter *adapter)
{
char filename[PATH_MAX + 1];
@@ -1811,10 +1737,6 @@ static void load_devices(struct btd_adapter *adapter)

ba2str(&adapter->bdaddr, srcaddr);

- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "primaries");
- textfile_foreach(filename, create_stored_device_from_primaries,
- adapter);
-
snprintf(filename, PATH_MAX, STORAGEDIR "/%s", srcaddr);
filename[PATH_MAX] = '\0';

@@ -1864,6 +1786,8 @@ static void load_devices(struct btd_adapter *adapter)
device_set_temporary(device, FALSE);
adapter->devices = g_slist_append(adapter->devices, device);

+ /* TODO: register services from pre-loaded list of primaries */
+
l = device_get_uuids(device);
if (l)
device_probe_profiles(device, l);
diff --git a/src/device.c b/src/device.c
index d49b397..fc37e51 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2013,8 +2013,7 @@ struct btd_device *device_create(struct btd_adapter *adapter,
struct btd_device *device;
const bdaddr_t *src;
char srcaddr[18];
- char filename[PATH_MAX + 1];
- GKeyFile *key_file;
+ char *str;

device = device_new(adapter, address);
if (device == NULL)
@@ -2024,20 +2023,11 @@ struct btd_device *device_create(struct btd_adapter *adapter,
src = adapter_get_address(adapter);
ba2str(src, srcaddr);

- /*TODO: after all device load during start-up has been converted to
- * new key file structure, this should be replaced by :
- * str = load_cached_name(device, srcaddr, address);
- * if (str) {
- * strcpy(device->name, str);
- * g_free(str);
- * }
- */
- snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", srcaddr,
- address);
- key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, filename, 0, NULL);
- load_info(device, srcaddr, address, key_file);
- g_key_file_free(key_file);
+ str = load_cached_name(device, srcaddr, address);
+ if (str) {
+ strcpy(device->name, str);
+ g_free(str);
+ }

return btd_device_ref(device);
}
--
1.7.9.5


2012-12-13 20:39:27

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 12/15] adapter: Convert device primaries list

---
src/adapter.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 02d54a3..64d8ed3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2762,6 +2762,88 @@ failed:
g_free(att_uuid);
}

+static void convert_primaries_entry(char *key, char *value, void *user_data)
+{
+ char *address = user_data;
+ char device_type = -1;
+ uuid_t uuid;
+ char **services, **service, *prim_uuid;
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ int ret;
+ uint16_t start, end;
+ char uuid_str[MAX_LEN_UUID_STR + 1];
+ char *data;
+ gsize length = 0;
+
+ if (key[17] == '#') {
+ key[17] = '\0';
+ device_type = key[18] - '0';
+ }
+
+ if (bachk(key) != 0)
+ return;
+
+ services = g_strsplit(value, " ", 0);
+ if (services == NULL)
+ return;
+
+ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ prim_uuid = bt_uuid2string(&uuid);
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes", address,
+ key);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+ for (service = services; *service; service++) {
+ ret = sscanf(*service, "%04hX#%04hX#%s", &start, &end,
+ uuid_str);
+ if (ret < 3)
+ continue;
+
+ bt_string2uuid(&uuid, uuid_str);
+ sdp_uuid128_to_uuid(&uuid);
+
+ store_attribute_uuid(key_file, start, prim_uuid, uuid);
+ }
+
+ g_strfreev(services);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ if (length == 0)
+ goto end;
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ g_file_set_contents(filename, data, length, NULL);
+
+ if (device_type < 0)
+ goto end;
+
+ g_free(data);
+ g_key_file_free(key_file);
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", address, key);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ set_device_type(key_file, device_type);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ if (length > 0) {
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ g_file_set_contents(filename, data, length, NULL);
+ }
+
+end:
+ g_free(data);
+ g_free(prim_uuid);
+ g_key_file_free(key_file);
+}
+
static void convert_device_storage(struct btd_adapter *adapter)
{
char filename[PATH_MAX + 1];
@@ -2795,6 +2877,19 @@ static void convert_device_storage(struct btd_adapter *adapter)
/* Convert profiles */
convert_file("profiles", address, convert_profiles_entry, TRUE);

+ /* Convert primaries */
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/primaries", address);
+ filename[PATH_MAX] = '\0';
+
+ str = textfile_get(filename, "converted");
+ if (str && strcmp(str, "yes") == 0) {
+ DBG("Legacy %s file already converted", filename);
+ } else {
+ textfile_foreach(filename, convert_primaries_entry, address);
+ textfile_put(filename, "converted", "yes");
+ }
+ free(str);
+
/* Convert linkkeys */
convert_file("linkkeys", address, convert_linkkey_entry, TRUE);

--
1.7.9.5


2012-12-13 20:39:26

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 11/15] device: Store SDP records in new storage

Store SDP records in device file located in cache directory.

Update attributes file with primary services retrieved from attributes
entry in SDP records.

Remove store_record() from storage.[ch].
---
src/device.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/storage.c | 33 ----------------
src/storage.h | 2 -
3 files changed, 122 insertions(+), 36 deletions(-)

diff --git a/src/device.c b/src/device.c
index 36840a6..d49b397 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2461,6 +2461,77 @@ static void uuids_changed(struct btd_device *device)
g_free(uuids);
}

+static void store_sdp_record(GKeyFile *key_file, sdp_record_t *rec)
+{
+ char handle_str[11];
+ sdp_buf_t buf;
+ int size, i;
+ char *str;
+
+ sprintf(handle_str, "0x%8.8X", rec->handle);
+
+ if (sdp_gen_record_pdu(rec, &buf) < 0)
+ return;
+
+ size = buf.data_size;
+
+ str = g_malloc0(size*2+1);
+
+ for (i = 0; i < size; i++)
+ sprintf(str + (i * 2), "%02X", buf.data[i]);
+
+ g_key_file_set_string(key_file, "ServiceRecords", handle_str, str);
+
+ free(buf.data);
+ g_free(str);
+}
+
+static void store_primaries_from_sdp_record(GKeyFile *key_file,
+ sdp_record_t *rec)
+{
+ uuid_t uuid;
+ char *att_uuid, *prim_uuid;
+ uint16_t start = 0, end = 0, psm = 0;
+ char handle[6], uuid_str[33];
+ int i;
+
+ sdp_uuid16_create(&uuid, ATT_UUID);
+ att_uuid = bt_uuid2string(&uuid);
+
+ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ prim_uuid = bt_uuid2string(&uuid);
+
+ if (!record_has_uuid(rec, att_uuid))
+ goto done;
+
+ if (!gatt_parse_record(rec, &uuid, &psm, &start, &end))
+ goto done;
+
+ sprintf(handle, "%hu", start);
+ switch (uuid.type) {
+ case SDP_UUID16:
+ sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
+ break;
+ case SDP_UUID32:
+ sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
+ break;
+ case SDP_UUID128:
+ for (i = 0; i < 16; i++)
+ sprintf(uuid_str + (i * 2), "%2.2X",
+ uuid.value.uuid128.data[i]);
+ break;
+ default:
+ uuid_str[0] = '\0';
+ }
+
+ g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
+ g_key_file_set_string(key_file, handle, "Value", uuid_str);
+
+done:
+ g_free(prim_uuid);
+ g_free(att_uuid);
+}
+
static int rec_cmp(const void *a, const void *b)
{
const sdp_record_t *r1 = a;
@@ -2474,10 +2545,32 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
struct btd_device *device = req->device;
sdp_list_t *seq;
char srcaddr[18], dstaddr[18];
+ char sdp_file[PATH_MAX + 1];
+ char att_file[PATH_MAX + 1];
+ GKeyFile *sdp_key_file = NULL;
+ GKeyFile *att_key_file = NULL;
+ char *data;
+ gsize length = 0;

ba2str(adapter_get_address(device->adapter), srcaddr);
ba2str(&device->bdaddr, dstaddr);

+ if (!device->temporary) {
+ snprintf(sdp_file, PATH_MAX, STORAGEDIR "/%s/cache/%s",
+ srcaddr, dstaddr);
+ sdp_file[PATH_MAX] = '\0';
+
+ sdp_key_file = g_key_file_new();
+ g_key_file_load_from_file(sdp_key_file, sdp_file, 0, NULL);
+
+ snprintf(att_file, PATH_MAX, STORAGEDIR "/%s/%s/attributes",
+ srcaddr, dstaddr);
+ att_file[PATH_MAX] = '\0';
+
+ att_key_file = g_key_file_new();
+ g_key_file_load_from_file(att_key_file, att_file, 0, NULL);
+ }
+
for (seq = recs; seq; seq = seq->next) {
sdp_record_t *rec = (sdp_record_t *) seq->data;
sdp_list_t *svcclass = NULL;
@@ -2531,7 +2624,11 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
continue;
}

- store_record(srcaddr, dstaddr, device->bdaddr_type, rec);
+ if (sdp_key_file)
+ store_sdp_record(sdp_key_file, rec);
+
+ if (att_key_file)
+ store_primaries_from_sdp_record(att_key_file, rec);

/* Copy record */
req->records = sdp_list_append(req->records,
@@ -2552,6 +2649,30 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)

sdp_list_free(svcclass, free);
}
+
+ if (sdp_key_file) {
+ data = g_key_file_to_data(sdp_key_file, &length, NULL);
+ if (length > 0) {
+ create_file(sdp_file, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IROTH);
+ g_file_set_contents(sdp_file, data, length, NULL);
+ }
+
+ g_free(data);
+ g_key_file_free(sdp_key_file);
+ }
+
+ if (att_key_file) {
+ data = g_key_file_to_data(att_key_file, &length, NULL);
+ if (length > 0) {
+ create_file(att_file, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IROTH);
+ g_file_set_contents(att_file, data, length, NULL);
+ }
+
+ g_free(data);
+ g_key_file_free(att_key_file);
+ }
}

static gint primary_cmp(gconstpointer a, gconstpointer b)
diff --git a/src/storage.c b/src/storage.c
index d4516ed..180946f 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -245,39 +245,6 @@ ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin)
return len;
}

-int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
- sdp_record_t *rec)
-{
- char filename[PATH_MAX + 1], key[30];
- sdp_buf_t buf;
- int err, size, i;
- char *str;
-
- create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
-
- create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- snprintf(key, sizeof(key), "%17s#%hhu#%08X", dst, dst_type,
- rec->handle);
-
- if (sdp_gen_record_pdu(rec, &buf) < 0)
- return -1;
-
- size = buf.data_size;
-
- str = g_malloc0(size*2+1);
-
- for (i = 0; i < size; i++)
- sprintf(str + (i * 2), "%02X", buf.data[i]);
-
- err = textfile_put(filename, key, str);
-
- free(buf.data);
- g_free(str);
-
- return err;
-}
-
sdp_record_t *record_from_string(const gchar *str)
{
sdp_record_t *rec;
diff --git a/src/storage.h b/src/storage.h
index ffc6deb..262a594 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -35,8 +35,6 @@ int read_remote_appearance(const bdaddr_t *local, const bdaddr_t *peer,
int write_lastused_info(const bdaddr_t *local, const bdaddr_t *peer,
uint8_t peer_type, struct tm *tm);
ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin);
-int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
- sdp_record_t *rec);
sdp_record_t *record_from_string(const gchar *str);
sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
uint8_t dst_type, const uint32_t handle);
--
1.7.9.5


2012-12-13 20:39:25

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 10/15] device: Load primary attributes from storage

Parse device attributes file for primary services, then add UUID service
to device primaries list.
---
src/device.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)

diff --git a/src/device.c b/src/device.c
index 24e97e6..36840a6 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1879,6 +1879,81 @@ next:
store_device_info(device);
}

+static void load_att_info(struct btd_device *device, const gchar *local,
+ const gchar *peer)
+{
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ char *prim_uuid, *str;
+ char **groups, **handle, *service_uuid;
+ struct gatt_primary *prim;
+ uuid_t uuid;
+ char tmp[3];
+ int i;
+
+ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ prim_uuid = bt_uuid2string(&uuid);
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes", local,
+ peer);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ groups = g_key_file_get_groups(key_file, NULL);
+
+ for (handle = groups; *handle; handle++) {
+ str = g_key_file_get_string(key_file, *handle, "UUID", NULL);
+ if (!str)
+ continue;
+
+ if (!g_str_equal(str, prim_uuid))
+ continue;
+
+ g_free(str);
+
+ str = g_key_file_get_string(key_file, *handle, "Value", NULL);
+ if (!str)
+ continue;
+
+ prim = g_new0(struct gatt_primary, 1);
+ prim->range.start = atoi(*handle);
+
+ switch (strlen(str)) {
+ case 4:
+ uuid.type = SDP_UUID16;
+ sscanf(str, "%04hx", &uuid.value.uuid16);
+ break;
+ case 8:
+ uuid.type = SDP_UUID32;
+ sscanf(str, "%08x", &uuid.value.uuid32);
+ break;
+ case 32:
+ uuid.type = SDP_UUID128;
+ memset(tmp, 0, sizeof(tmp));
+ for (i = 0; i < 16; i++) {
+ memcpy(tmp, str + (i * 2), 2);
+ uuid.value.uuid128.data[i] =
+ (uint8_t) strtol(tmp, NULL, 16);
+ }
+ break;
+ default:
+ continue;
+ }
+
+ service_uuid = bt_uuid2string(&uuid);
+ memcpy(prim->uuid, service_uuid, MAX_LEN_UUID_STR);
+ g_free(service_uuid);
+ g_free(str);
+
+ device->primaries = g_slist_append(device->primaries, prim);
+ }
+
+ g_strfreev(groups);
+ g_key_file_free(key_file);
+ g_free(prim_uuid);
+}
+
static struct btd_device *device_new(struct btd_adapter *adapter,
const gchar *address)
{
@@ -1927,6 +2002,7 @@ struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
ba2str(src, srcaddr);

load_info(device, srcaddr, address, key_file);
+ load_att_info(device, srcaddr, address);

return device;
}
--
1.7.9.5


2012-12-13 20:39:19

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 04/15] device: Load profiles from storage

Add device_get_uuids() to retrieve UUIDs list.
It will allow to call device_probe_profiles() from
load_devices() of adapter.c after device creation.

Remove write_device_profiles from storage.[ch].
---
src/device.c | 89 ++++++++++++++++++++++++++++++---------------------------
src/device.h | 1 +
src/storage.c | 18 ------------
src/storage.h | 2 --
4 files changed, 48 insertions(+), 62 deletions(-)

diff --git a/src/device.c b/src/device.c
index e07e7b8..42a7c65 100644
--- a/src/device.c
+++ b/src/device.c
@@ -216,6 +216,7 @@ static gboolean store_device_info_cb(gpointer user_data)
char device_addr[18];
char *str;
char class[9];
+ gchar **uuids = NULL;
gsize length = 0;

device->store_id = 0;
@@ -279,6 +280,19 @@ static gboolean store_device_info_cb(gpointer user_data)
g_key_file_set_boolean(key_file, "General", "Blocked",
device->blocked);

+ if (device->uuids) {
+ GSList *l;
+ int i;
+
+ uuids = g_new0(gchar *, g_slist_length(device->uuids) + 1);
+ for (i = 0, l = device->uuids; l; l = g_slist_next(l), i++)
+ uuids[i] = l->data;
+ g_key_file_set_string_list(key_file, "General", "Profiles",
+ (const gchar **)uuids, i);
+ } else {
+ g_key_file_remove_key(key_file, "General", "Profiles", NULL);
+ }
+
if (device->vendor_src) {
g_key_file_set_integer(key_file, "DeviceID", "Source",
device->vendor_src);
@@ -299,6 +313,7 @@ static gboolean store_device_info_cb(gpointer user_data)
g_free(str);

g_key_file_free(key_file);
+ g_free(uuids);

return FALSE;
}
@@ -1740,6 +1755,7 @@ static void load_info(struct btd_device *device, const gchar *local,
char *str;
gboolean store_needed = FALSE;
gboolean blocked;
+ gchar **uuids;
int source, vendor, product, version;
char **techno, **t;
gboolean bredr = FALSE;
@@ -1819,6 +1835,27 @@ next:
if (blocked)
device_block(device, FALSE);

+ /* Load device profile list */
+ uuids = g_key_file_get_string_list(key_file, "General", "Profiles",
+ NULL, NULL);
+ if (uuids) {
+ gchar **uuid;
+
+ for (uuid = uuids; *uuid; uuid++) {
+ GSList *match;
+
+ match = g_slist_find_custom(device->uuids, *uuid,
+ bt_uuid_strcmp);
+ if (match)
+ continue;
+
+ device->uuids = g_slist_insert_sorted(device->uuids,
+ g_strdup(*uuid),
+ bt_uuid_strcmp);
+ }
+ g_strfreev(uuids);
+ }
+
/* Load device id */
source = g_key_file_get_integer(key_file, "DeviceID", "Source", NULL);
if (source) {
@@ -2124,6 +2161,11 @@ static gboolean record_has_uuid(const sdp_record_t *rec,
return FALSE;
}

+GSList *device_get_uuids(struct btd_device *device)
+{
+ return device->uuids;
+}
+
static GSList *device_match_profile(struct btd_device *device,
struct btd_profile *profile,
GSList *uuids)
@@ -2263,35 +2305,16 @@ add_uuids:
static void device_remove_profiles(struct btd_device *device, GSList *uuids)
{
char srcaddr[18], dstaddr[18];
- sdp_list_t *records;
GSList *l, *next;

ba2str(adapter_get_address(device->adapter), srcaddr);
ba2str(&device->bdaddr, dstaddr);

- records = read_records(adapter_get_address(device->adapter),
- &device->bdaddr);
-
DBG("Removing profiles for %s", dstaddr);

- for (l = uuids; l != NULL; l = g_slist_next(l)) {
- sdp_record_t *rec;
-
- device->uuids = g_slist_remove(device->uuids, l->data);
-
- rec = find_record_in_list(records, l->data);
- if (!rec)
- continue;
-
- delete_record(srcaddr, dstaddr, device->bdaddr_type,
- rec->handle);
-
- records = sdp_list_remove(records, rec);
- sdp_record_free(rec);
- }
-
- if (records)
- sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
+ g_slist_free(device->uuids);
+ device->uuids = NULL;
+ store_device_info(device);

for (l = device->profiles; l != NULL; l = next) {
struct btd_profile *profile = l->data;
@@ -2460,24 +2483,6 @@ static void update_gatt_services(struct browse_req *req, GSList *current,
g_slist_free(left);
}

-static void store_profiles(struct btd_device *device)
-{
- struct btd_adapter *adapter = device->adapter;
- char *str;
-
- if (!device->uuids) {
- write_device_profiles(adapter_get_address(adapter),
- &device->bdaddr, device->bdaddr_type,
- "");
- return;
- }
-
- str = bt_list2string(device->uuids);
- write_device_profiles(adapter_get_address(adapter), &device->bdaddr,
- device->bdaddr_type, str);
- g_free(str);
-}
-
GSList *device_services_from_record(struct btd_device *device, GSList *profiles)
{
GSList *l, *prim_list = NULL;
@@ -2567,7 +2572,7 @@ send_reply:
device_svc_resolved(device, err);

if (!device->temporary)
- store_profiles(device);
+ store_device_info(device);

browse_request_free(req);
}
@@ -3820,7 +3825,7 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid)
g_free(new_uuid);
g_slist_free(uuid_list);

- store_profiles(device);
+ store_device_info(device);
uuids_changed(device);
}

diff --git a/src/device.h b/src/device.h
index a207a4f..9102e60 100644
--- a/src/device.h
+++ b/src/device.h
@@ -42,6 +42,7 @@ uint16_t btd_device_get_version(struct btd_device *device);
void device_remove(struct btd_device *device, gboolean remove_stored);
gint device_address_cmp(struct btd_device *device, const gchar *address);
gint device_bdaddr_cmp(struct btd_device *device, bdaddr_t *bdaddr);
+GSList *device_get_uuids(struct btd_device *device);
void device_probe_profiles(struct btd_device *device, GSList *profiles);
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
diff --git a/src/storage.c b/src/storage.c
index 0b9ed2d..74b19c0 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -245,24 +245,6 @@ ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin)
return len;
}

-int write_device_profiles(const bdaddr_t *src, const bdaddr_t *dst,
- uint8_t dst_type, const char *profiles)
-{
- char filename[PATH_MAX + 1], key[20];
-
- if (!profiles)
- return -EINVAL;
-
- create_filename(filename, PATH_MAX, src, "profiles");
-
- create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- ba2str(dst, key);
- sprintf(&key[17], "#%hhu", dst_type);
-
- return textfile_put(filename, key, profiles);
-}
-
int delete_entry(const bdaddr_t *src, const char *storage, const bdaddr_t *dst,
uint8_t dst_type)
{
diff --git a/src/storage.h b/src/storage.h
index cb9d836..2e2889d 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -35,8 +35,6 @@ int read_remote_appearance(const bdaddr_t *local, const bdaddr_t *peer,
int write_lastused_info(const bdaddr_t *local, const bdaddr_t *peer,
uint8_t peer_type, struct tm *tm);
ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin);
-int write_device_profiles(const bdaddr_t *src, const bdaddr_t *dst,
- uint8_t dst_type, const char *profiles);
int delete_entry(const bdaddr_t *src, const char *storage, const bdaddr_t *dst,
uint8_t dst_type);
int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
--
1.7.9.5


2012-12-13 20:39:24

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 09/15] device: Remove stored SDP records on device removal

Also remove management of legacy storage file in device_remove_stored().
Remove no more used storage functions.
---
src/device.c | 31 +++++++++++++++++--------
src/storage.c | 72 ---------------------------------------------------------
src/storage.h | 6 -----
3 files changed, 21 insertions(+), 88 deletions(-)

diff --git a/src/device.c b/src/device.c
index 36bf9bc..24e97e6 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2067,24 +2067,17 @@ static void device_remove_stored(struct btd_device *device)
char adapter_addr[18];
char device_addr[18];
char filename[PATH_MAX + 1];
-
- delete_entry(src, "profiles", &device->bdaddr, dst_type);
- delete_entry(src, "trusts", &device->bdaddr, dst_type);
+ GKeyFile *key_file;
+ char *data;
+ gsize length = 0;

if (device_is_bonded(device)) {
- delete_entry(src, "linkkeys", &device->bdaddr, dst_type);
- delete_entry(src, "aliases", &device->bdaddr, dst_type);
- delete_entry(src, "longtermkeys", &device->bdaddr, dst_type);
-
device_set_bonded(device, FALSE);
device->paired = FALSE;
btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
dst_type);
}

- delete_all_records(src, &device->bdaddr, dst_type);
- delete_device_service(src, &device->bdaddr, dst_type);
-
if (device->blocked)
device_unblock(device, TRUE, FALSE);

@@ -2095,6 +2088,24 @@ static void device_remove_stored(struct btd_device *device)
device_addr);
filename[PATH_MAX] = '\0';
delete_folder_tree(filename);
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", adapter_addr,
+ device_addr);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ g_key_file_remove_group(key_file, "ServiceRecords", NULL);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ if (length > 0) {
+ create_file(filename, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IROTH);
+ g_file_set_contents(filename, data, length, NULL);
+ }
+
+ g_free(data);
+ g_key_file_free(key_file);
}

void device_remove(struct btd_device *device, gboolean remove_stored)
diff --git a/src/storage.c b/src/storage.c
index 74b19c0..d4516ed 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -245,31 +245,6 @@ ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin)
return len;
}

-int delete_entry(const bdaddr_t *src, const char *storage, const bdaddr_t *dst,
- uint8_t dst_type)
-{
- char filename[PATH_MAX + 1], key[20];
- int err, ret;
-
- ba2str(dst, key);
- sprintf(&key[17], "#%hhu", dst_type);
-
- create_filename(filename, PATH_MAX, src, storage);
-
- err = 0;
- ret = textfile_del(filename, key);
- if (ret)
- err = ret;
-
- /* Trying without address type */
- key[17] = '\0';
- ret = textfile_del(filename, key);
- if (ret)
- err = ret;
-
- return err;
-}
-
int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
sdp_record_t *rec)
{
@@ -397,26 +372,6 @@ static void create_stored_records_from_keys(char *key, char *value,
rec_list->recs = sdp_list_append(rec_list->recs, rec);
}

-void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst,
- uint8_t dst_type)
-{
- sdp_list_t *records, *seq;
- char srcaddr[18], dstaddr[18];
-
- ba2str(src, srcaddr);
- ba2str(dst, dstaddr);
-
- records = read_records(src, dst);
-
- for (seq = records; seq; seq = seq->next) {
- sdp_record_t *rec = seq->data;
- delete_record(srcaddr, dstaddr, dst_type, rec->handle);
- }
-
- if (records)
- sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
-}
-
sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst)
{
char filename[PATH_MAX + 1];
@@ -526,33 +481,6 @@ done:
g_slist_free_full(match.keys, g_free);
}

-int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba,
- uint8_t bdaddr_type)
-{
- char filename[PATH_MAX + 1], key[20];
-
- memset(key, 0, sizeof(key));
-
- ba2str(dba, key);
- sprintf(&key[17], "#%hhu", bdaddr_type);
-
- /* Deleting all characteristics of a given key */
- create_filename(filename, PATH_MAX, sba, "characteristics");
- delete_by_pattern(filename, key);
-
- /* Deleting all attributes values of a given key */
- create_filename(filename, PATH_MAX, sba, "attributes");
- delete_by_pattern(filename, key);
-
- /* Deleting all CCC values of a given key */
- create_filename(filename, PATH_MAX, sba, "ccc");
- delete_by_pattern(filename, key);
-
- create_filename(filename, PATH_MAX, sba, "primaries");
-
- return textfile_del(filename, key);
-}
-
char *read_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
uint8_t bdaddr_type)
{
diff --git a/src/storage.h b/src/storage.h
index 2e2889d..ffc6deb 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -35,8 +35,6 @@ int read_remote_appearance(const bdaddr_t *local, const bdaddr_t *peer,
int write_lastused_info(const bdaddr_t *local, const bdaddr_t *peer,
uint8_t peer_type, struct tm *tm);
ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin);
-int delete_entry(const bdaddr_t *src, const char *storage, const bdaddr_t *dst,
- uint8_t dst_type);
int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
sdp_record_t *rec);
sdp_record_t *record_from_string(const gchar *str);
@@ -44,15 +42,11 @@ sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
uint8_t dst_type, const uint32_t handle);
int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
const uint32_t handle);
-void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst,
- uint8_t dst_type);
sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst);
sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid);
int read_device_pairable(const bdaddr_t *local, gboolean *mode);
int write_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
uint8_t bdaddr_type, const char *services);
-int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba,
- uint8_t bdaddr_type);
char *read_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
uint8_t bdaddr_type);
int write_device_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
--
1.7.9.5


2012-12-13 20:39:22

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 07/15] doc: Update Settings-storage for SDP records

SDP records shouls be saved in device file located in cache
directory, as we cannot guarantee that this info is available
always and profiles should work even if the info is not there.
---
doc/settings-storage.txt | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index a43b7af..792c899 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -115,13 +115,23 @@ Sample:
Cache directory file format
============================

-Each file, named by remote device address, contains one [General] group.
-This general group contains:
+Each file, named by remote device address, may includes multiple groups
+(General and ServiceRecords).
+
+In ServiceRecords, SDP records are stored using their handle as key
+(hexadecimal format).
+
+[General] group contains:

Name String Remote device friendly name

ShortName String Remote device shortened name

+[ServiceRecords] group contains
+
+ <0x...> String SDP record as hexadecimal encoded
+ string
+
Info file format
================

--
1.7.9.5


2012-12-13 20:39:23

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 08/15] adapter: Convert device sdp file

Save SDP records in device device file located in SDP directory.

Parse "sdp" file to retrieve services, i.e. sdp records with
attribute uuid.
Create device attributes file based on this.
---
src/adapter.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 171 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 241c6c8..02d54a3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2604,6 +2604,164 @@ static void convert_file(char *file, char *address,
free(str);
}

+static gboolean record_has_uuid(const sdp_record_t *rec,
+ const char *profile_uuid)
+{
+ sdp_list_t *pat;
+
+ for (pat = rec->pattern; pat != NULL; pat = pat->next) {
+ char *uuid;
+ int ret;
+
+ uuid = bt_uuid2string(pat->data);
+ if (!uuid)
+ continue;
+
+ ret = strcasecmp(uuid, profile_uuid);
+
+ g_free(uuid);
+
+ if (ret == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void store_attribute_uuid(GKeyFile *key_file, uint16_t start,
+ char *att_uuid, uuid_t uuid)
+{
+ char handle[6], uuid_str[33];
+ int i;
+
+ switch (uuid.type) {
+ case SDP_UUID16:
+ sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
+ break;
+ case SDP_UUID32:
+ sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
+ break;
+ case SDP_UUID128:
+ for (i = 0; i < 16; i++)
+ sprintf(uuid_str + (i * 2), "%2.2X",
+ uuid.value.uuid128.data[i]);
+ break;
+ default:
+ uuid_str[0] = '\0';
+ }
+
+ sprintf(handle, "%hu", start);
+ g_key_file_set_string(key_file, handle, "UUID", att_uuid);
+ g_key_file_set_string(key_file, handle, "Value", uuid_str);
+}
+
+static void store_sdp_record(char *local, char *peer, int handle, char *value)
+{
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ char handle_str[11];
+ char *data;
+ gsize length = 0;
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+ sprintf(handle_str, "0x%8.8X", handle);
+ g_key_file_set_string(key_file, "ServiceRecords", handle_str, value);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ if (length > 0) {
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ g_file_set_contents(filename, data, length, NULL);
+ }
+
+ g_free(data);
+
+ g_key_file_free(key_file);
+}
+
+static void convert_sdp_entry(char *key, char *value, void *user_data)
+{
+ char *src_addr = user_data;
+ char dst_addr[18];
+ char type = BDADDR_BREDR;
+ int handle, ret;
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ struct stat st;
+ sdp_record_t *rec;
+ uuid_t uuid;
+ char *att_uuid, *prim_uuid;
+ uint16_t start = 0, end = 0, psm = 0;
+ int err;
+ char *data;
+ gsize length = 0;
+
+ ret = sscanf(key, "%17s#%hhu#%08X", dst_addr, &type, &handle);
+ if (ret < 3) {
+ ret = sscanf(key, "%17s#%08X", dst_addr, &handle);
+ if (ret < 2)
+ return;
+ }
+
+ if (bachk(dst_addr) != 0)
+ return;
+
+ /* Check if the device directory has been created as records should
+ * only be converted for known devices */
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s", src_addr, dst_addr);
+ filename[PATH_MAX] = '\0';
+
+ err = stat(filename, &st);
+ if (err || !S_ISDIR(st.st_mode))
+ return;
+
+ /* store device records in cache */
+ store_sdp_record(src_addr, dst_addr, handle, value);
+
+ /* Retrieve device record and check if there is an
+ * attribute entry in it */
+ sdp_uuid16_create(&uuid, ATT_UUID);
+ att_uuid = bt_uuid2string(&uuid);
+
+ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ prim_uuid = bt_uuid2string(&uuid);
+
+ rec = record_from_string(value);
+
+ if (record_has_uuid(rec, att_uuid))
+ goto failed;
+
+ if (!gatt_parse_record(rec, &uuid, &psm, &start, &end))
+ goto failed;
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes", src_addr,
+ dst_addr);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+ store_attribute_uuid(key_file, start, prim_uuid, uuid);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ if (length > 0) {
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ g_file_set_contents(filename, data, length, NULL);
+ }
+
+ g_free(data);
+ g_key_file_free(key_file);
+
+failed:
+ sdp_record_free(rec);
+ g_free(prim_uuid);
+ g_free(att_uuid);
+}
+
static void convert_device_storage(struct btd_adapter *adapter)
{
char filename[PATH_MAX + 1];
@@ -2648,6 +2806,19 @@ static void convert_device_storage(struct btd_adapter *adapter)

/* Convert device ids */
convert_file("did", address, convert_did_entry, FALSE);
+
+ /* Convert sdp */
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/sdp", address);
+ filename[PATH_MAX] = '\0';
+
+ str = textfile_get(filename, "converted");
+ if (str && strcmp(str, "yes") == 0) {
+ DBG("Legacy %s file already converted", filename);
+ } else {
+ textfile_foreach(filename, convert_sdp_entry, address);
+ textfile_put(filename, "converted", "yes");
+ }
+ free(str);
}

static void convert_config(struct btd_adapter *adapter, const char *filename,
--
1.7.9.5


2012-12-13 20:39:20

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 05/15] adapter: Probe profiles after device creation

---
src/adapter.c | 40 ++++------------------------------------
1 file changed, 4 insertions(+), 36 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 3bb1ea6..241c6c8 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1628,38 +1628,6 @@ static const GDBusPropertyTable adapter_properties[] = {
{ }
};

-static void create_stored_device_from_profiles(char *key, char *value,
- void *user_data)
-{
- char address[18];
- uint8_t bdaddr_type;
- struct btd_adapter *adapter = user_data;
- GSList *list, *uuids = bt_string2list(value);
- struct btd_device *device;
-
- if (sscanf(key, "%17s#%hhu", address, &bdaddr_type) < 2)
- bdaddr_type = BDADDR_BREDR;
-
- if (g_slist_find_custom(adapter->devices,
- address, (GCompareFunc) device_address_cmp))
- return;
-
- device = device_create(adapter, address, bdaddr_type);
- if (!device)
- return;
-
- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
-
- list = device_services_from_record(device, uuids);
- if (list)
- device_register_primaries(device, list, ATT_PSM);
-
- device_probe_profiles(device, uuids);
-
- g_slist_free_full(uuids, g_free);
-}
-
struct adapter_keys {
struct btd_adapter *adapter;
GSList *keys;
@@ -1843,10 +1811,6 @@ static void load_devices(struct btd_adapter *adapter)

ba2str(&adapter->bdaddr, srcaddr);

- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "profiles");
- textfile_foreach(filename, create_stored_device_from_profiles,
- adapter);
-
create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "primaries");
textfile_foreach(filename, create_stored_device_from_primaries,
adapter);
@@ -1900,6 +1864,10 @@ static void load_devices(struct btd_adapter *adapter)
device_set_temporary(device, FALSE);
adapter->devices = g_slist_append(adapter->devices, device);

+ l = device_get_uuids(device);
+ if (l)
+ device_probe_profiles(device, l);
+
device_exist:
if (key_info || ltk_info) {
device_set_paired(device, TRUE);
--
1.7.9.5


2012-12-13 20:39:21

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 06/15] device: Delete storage device recursively

Device storage directory may contain multiple files like info or
attributes but also files stored by plug-ins or profiles,
so completely delete directory.
---
src/device.c | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/src/device.c b/src/device.c
index 42a7c65..36bf9bc 100644
--- a/src/device.c
+++ b/src/device.c
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
+#include <dirent.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
@@ -2031,6 +2032,34 @@ uint16_t btd_device_get_version(struct btd_device *device)
return device->version;
}

+static void delete_folder_tree(const char *dirname)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char filename[PATH_MAX + 1];
+
+ dir = opendir(dirname);
+ if (dir == NULL)
+ return;
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (g_str_equal(entry->d_name, ".") ||
+ g_str_equal(entry->d_name, ".."))
+ continue;
+
+ snprintf(filename, PATH_MAX, "%s/%s", dirname, entry->d_name);
+ filename[PATH_MAX] = '\0';
+
+ if (entry->d_type == DT_DIR)
+ delete_folder_tree(filename);
+ else
+ unlink(filename);
+ }
+ closedir(dir);
+
+ rmdir(dirname);
+}
+
static void device_remove_stored(struct btd_device *device)
{
const bdaddr_t *src = adapter_get_address(device->adapter);
@@ -2062,15 +2091,10 @@ static void device_remove_stored(struct btd_device *device)
ba2str(src, adapter_addr);
ba2str(&device->bdaddr, device_addr);

- snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
- device_addr);
- filename[PATH_MAX] = '\0';
- remove(filename);
-
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s", adapter_addr,
device_addr);
filename[PATH_MAX] = '\0';
- remove(filename);
+ delete_folder_tree(filename);
}

void device_remove(struct btd_device *device, gboolean remove_stored)
--
1.7.9.5


2012-12-13 20:39:17

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 02/15] device: Add device_create_from_storage() function

This function is used from load_devices() of adapter.c
during bluetoothd start-up to re-load known devices from
storage key file.

device_create() is used to create new devices for which
no storage exists, but until all device load during start-up
has been converted we should continue to call load_info().
---
src/adapter.c | 10 +++++----
src/device.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-------------
src/device.h | 2 ++
3 files changed, 61 insertions(+), 20 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 15db015..940cc0a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1885,8 +1885,6 @@ static void load_devices(struct btd_adapter *adapter)
if (ltk_info)
ltks.keys = g_slist_append(ltks.keys, ltk_info);

- g_key_file_free(key_file);
-
l = g_slist_find_custom(adapter->devices, entry->d_name,
(GCompareFunc) device_address_cmp);
if (l) {
@@ -1894,9 +1892,10 @@ static void load_devices(struct btd_adapter *adapter)
goto device_exist;
}

- device = device_create(adapter, entry->d_name, BDADDR_BREDR);
+ device = device_create_from_storage(adapter, entry->d_name,
+ key_file);
if (!device)
- continue;
+ goto free;

device_set_temporary(device, FALSE);
adapter->devices = g_slist_append(adapter->devices, device);
@@ -1906,6 +1905,9 @@ device_exist:
device_set_paired(device, TRUE);
device_set_bonded(device, TRUE);
}
+
+free:
+ g_key_file_free(key_file);
}

closedir(dir);
diff --git a/src/device.c b/src/device.c
index 515ee61..e07e7b8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1735,10 +1735,8 @@ failed:
}

static void load_info(struct btd_device *device, const gchar *local,
- const gchar *peer)
+ const gchar *peer, GKeyFile *key_file)
{
- char filename[PATH_MAX + 1];
- GKeyFile *key_file;
char *str;
gboolean store_needed = FALSE;
gboolean blocked;
@@ -1747,12 +1745,6 @@ static void load_info(struct btd_device *device, const gchar *local,
gboolean bredr = FALSE;
gboolean le = FALSE;

- snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
- filename[PATH_MAX] = '\0';
-
- key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, filename, 0, NULL);
-
/* Load device name from storage info file, if that fails fall back to
* the cache.
*/
@@ -1847,18 +1839,14 @@ next:

if (store_needed)
store_device_info(device);
-
- g_key_file_free(key_file);
}

-struct btd_device *device_create(struct btd_adapter *adapter,
- const gchar *address, uint8_t bdaddr_type)
+static struct btd_device *device_new(struct btd_adapter *adapter,
+ const gchar *address)
{
gchar *address_up;
struct btd_device *device;
const gchar *adapter_path = adapter_get_path(adapter);
- const bdaddr_t *src;
- char srcaddr[18];

device = g_try_malloc0(sizeof(struct btd_device));
if (device == NULL)
@@ -1882,11 +1870,60 @@ struct btd_device *device_create(struct btd_adapter *adapter,

str2ba(address, &device->bdaddr);
device->adapter = adapter;
+
+ return btd_device_ref(device);
+}
+
+struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
+ const char *address, GKeyFile *key_file)
+{
+ struct btd_device *device;
+ const bdaddr_t *src;
+ char srcaddr[18];
+
+ device = device_new(adapter, address);
+ if (device == NULL)
+ return NULL;
+
+ src = adapter_get_address(adapter);
+ ba2str(src, srcaddr);
+
+ load_info(device, srcaddr, address, key_file);
+
+ return device;
+}
+
+struct btd_device *device_create(struct btd_adapter *adapter,
+ const gchar *address, uint8_t bdaddr_type)
+{
+ struct btd_device *device;
+ const bdaddr_t *src;
+ char srcaddr[18];
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+
+ device = device_new(adapter, address);
+ if (device == NULL)
+ return NULL;
+
device->bdaddr_type = bdaddr_type;
src = adapter_get_address(adapter);
ba2str(src, srcaddr);

- load_info(device, srcaddr, address);
+ /*TODO: after all device load during start-up has been converted to
+ * new key file structure, this should be replaced by :
+ * str = load_cached_name(device, srcaddr, address);
+ * if (str) {
+ * strcpy(device->name, str);
+ * g_free(str);
+ * }
+ */
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", srcaddr,
+ address);
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ load_info(device, srcaddr, address, key_file);
+ g_key_file_free(key_file);

return btd_device_ref(device);
}
diff --git a/src/device.h b/src/device.h
index b569a71..a207a4f 100644
--- a/src/device.h
+++ b/src/device.h
@@ -28,6 +28,8 @@ struct btd_device;

struct btd_device *device_create(struct btd_adapter *adapter,
const char *address, uint8_t bdaddr_type);
+struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
+ const char *address, GKeyFile *key_file);

void device_set_name(struct btd_device *device, const char *name);
void device_get_name(struct btd_device *device, char *name, size_t len);
--
1.7.9.5


2012-12-13 20:39:18

by Frederic Danis

[permalink] [raw]
Subject: [PATCH v2 03/15] adapter: Convert device profiles list

---
src/adapter.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 940cc0a..3bb1ea6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2553,6 +2553,12 @@ static void convert_ltk_entry(GKeyFile *key_file, void *value)
g_free(str);
}

+static void convert_profiles_entry(GKeyFile *key_file, void *value)
+{
+ g_strdelimit(value, " ", ';');
+ g_key_file_set_string(key_file, "General", "Profiles", value);
+}
+
static void convert_entry(char *key, char *value, void *user_data)
{
struct device_converter *converter = user_data;
@@ -2660,6 +2666,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
/* Convert blocked */
convert_file("blocked", address, convert_blocked_entry, TRUE);

+ /* Convert profiles */
+ convert_file("profiles", address, convert_profiles_entry, TRUE);
+
/* Convert linkkeys */
convert_file("linkkeys", address, convert_linkkey_entry, TRUE);

--
1.7.9.5