2012-12-12 15:47:50

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 01/14] 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 e6afe64..d6f8a9a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -246,6 +246,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);

@@ -1902,6 +1931,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';
@@ -1938,6 +1970,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-12 15:47:54

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 05/14] 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 7ab2389..10aacbf 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1631,38 +1631,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_services(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;
@@ -1846,10 +1814,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);
@@ -1903,6 +1867,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-12 15:47:53

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 04/14] 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 99ef77c..242313d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -218,6 +218,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;
@@ -281,6 +282,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);
@@ -301,6 +315,7 @@ static gboolean store_device_info_cb(gpointer user_data)
g_free(str);

g_key_file_free(key_file);
+ g_free(uuids);

return FALSE;
}
@@ -1928,6 +1943,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;
@@ -2007,6 +2023,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) {
@@ -2316,6 +2353,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)
@@ -2455,35 +2497,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;
@@ -2652,24 +2675,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;
@@ -2759,7 +2764,7 @@ send_reply:
device_svc_resolved(device, err);

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

browse_request_free(req);
}
@@ -4023,7 +4028,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 5c55b35..1785a75 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 5798ccd..17dfc21 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -263,24 +263,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 c8ae6b0..fdee61c 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -36,8 +36,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-12 15:47:56

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 07/14] adapter: Convert device sdp file

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

diff --git a/src/adapter.c b/src/adapter.c
index 10aacbf..baeae79 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2607,6 +2607,127 @@ 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, "%hd", 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 convert_sdp_entry(char *key, char *value, void *user_data)
+{
+ char *address = user_data;
+ 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;
+ char *str;
+ gsize length = 0;
+ int err;
+
+ if (key[17] == '#')
+ key[17] = '\0';
+
+ if (bachk(key) != 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", address, key);
+ filename[PATH_MAX] = '\0';
+
+ err = stat(filename, &st);
+ if (err || !S_ISDIR(st.st_mode))
+ return;
+
+ sdp_uuid16_create(&uuid, ATT_UUID);
+ att_uuid = bt_uuid2string(&uuid);
+
+ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ prim_uuid = bt_uuid2string(&uuid);
+
+ /* Retrieve device record and check if there is an
+ * attribute entry in it */
+ 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", address,
+ key);
+ 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);
+
+ str = 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, str, length, NULL);
+ }
+
+ g_free(str);
+
+ 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];
@@ -2651,6 +2772,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-12 15:47:57

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 08/14] device: Load services from storage

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

diff --git a/src/device.c b/src/device.c
index da868b8..a515266 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2067,6 +2067,82 @@ 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);
+
+ prim = g_new0(struct gatt_primary, 1);
+ prim->range.start = atoi(*handle);
+ str = g_key_file_get_string(key_file, *handle, "Value", NULL);
+ if (!str) {
+ g_free(prim);
+ continue;
+ }
+
+ 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 + 1);
+ 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)
{
@@ -2115,6 +2191,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-12 15:47:55

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 06/14] 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 242313d..da868b8 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>
@@ -2219,6 +2220,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);
@@ -2250,15 +2279,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-12 15:47:51

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 02/14] 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 34af063..7fcd42c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1888,8 +1888,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) {
@@ -1897,9 +1895,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);
@@ -1909,6 +1908,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 d6f8a9a..99ef77c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1923,10 +1923,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;
@@ -1935,12 +1933,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.
*/
@@ -2035,18 +2027,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)
@@ -2070,11 +2058,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 1987a80..5c55b35 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-12 15:48:00

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 11/14] adapter: Register services after device creation

Add device_register_services_from_primaries() to device.c to allow
to register from device->primaries pre-loaded during device creation
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 | 28 +++++++++-----------
src/device.h | 1 +
3 files changed, 15 insertions(+), 94 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 754bc2a..1a220cf 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1728,80 +1728,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_services(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];
@@ -1814,10 +1740,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';

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

+ device_register_services_from_primaries(device);
+
l = device_get_uuids(device);
if (l)
device_probe_profiles(device, l);
diff --git a/src/device.c b/src/device.c
index 6c3d5e8..9c3211c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2202,8 +2202,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)
@@ -2213,24 +2212,21 @@ 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);
}

+void device_register_services_from_primaries(struct btd_device *device)
+{
+ device->services = attrib_client_register(device, -1, NULL,
+ device->primaries);
+}
+
void device_set_name(struct btd_device *device, const char *name)
{
if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
diff --git a/src/device.h b/src/device.h
index 1785a75..750b1ea 100644
--- a/src/device.h
+++ b/src/device.h
@@ -30,6 +30,7 @@ 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_register_services_from_primaries(struct btd_device *device);

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-12 15:48:02

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 13/14] device: Retrieve records from tmp_records only

SDP records are no more stored, so they can only be retrieved
from remote device (tmp_records during bonding).
---
src/device.c | 24 ++++++++++--------------
1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/device.c b/src/device.c
index 6cec4a0..a7f85d1 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4220,24 +4220,20 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid)
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid)
{
- if (device->tmp_records) {
- const sdp_record_t *record;
+ const sdp_record_t *record;

- record = find_record_in_list(device->tmp_records, uuid);
- if (record != NULL)
- return record;
-
- sdp_list_free(device->tmp_records,
- (sdp_free_func_t) sdp_record_free);
- device->tmp_records = NULL;
- }
-
- device->tmp_records = read_records(adapter_get_address(device->adapter),
- &device->bdaddr);
if (!device->tmp_records)
return NULL;

- return find_record_in_list(device->tmp_records, uuid);
+ record = find_record_in_list(device->tmp_records, uuid);
+ if (record != NULL)
+ return record;
+
+ sdp_list_free(device->tmp_records,
+ (sdp_free_func_t) sdp_record_free);
+ device->tmp_records = NULL;
+
+ return NULL;
}

struct btd_device *btd_device_ref(struct btd_device *device)
--
1.7.9.5


2012-12-12 15:48:03

by Frederic Danis

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

When an input device is probed, it tries to retrieve its SDP record
from "input" file in storage directory.
If this fails, during bonding phase, records is vailable from device
object.

During connection, retrieve SDP record from "input" file.
---
profiles/input/device.c | 17 ++++++++---
profiles/input/manager.c | 75 +++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 84 insertions(+), 8 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 2d8077a..5eba0be 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -316,7 +316,8 @@ 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;
+ char *filename, *data;
+ GKeyFile *key_file = NULL;
sdp_record_t *rec;
char src_addr[18], dst_addr[18];
GError *gerr = NULL;
@@ -331,15 +332,23 @@ 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);
+ filename = device_get_storage_path(idev->device, "input");

- 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);
+ data = g_key_file_get_string(key_file, "SDP", "Record", NULL);
+ g_key_file_free(key_file);
+ g_free(filename);
+
+ if (!data) {
error("Rejected connection from unknown device %s", dst_addr);
err = -EPERM;
goto cleanup;
}

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

diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index 622e24b..db42c34 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -27,6 +27,8 @@

#include <errno.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <fcntl.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
@@ -42,6 +44,7 @@
#include "device.h"
#include "server.h"
#include "manager.h"
+#include "storage.h"

static int idle_timeout = 0;

@@ -54,19 +57,83 @@ static void input_remove(struct btd_device *device, const char *uuid)
input_device_unregister(path, uuid);
}

+static void store_hid_record(char *filename, const sdp_record_t *rec)
+{
+ sdp_buf_t buf;
+ int size, i;
+ char *str, *data;
+ GKeyFile *key_file = NULL;
+ gsize length = 0;
+
+ 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]);
+
+ free(buf.data);
+
+ key_file = g_key_file_new();
+ g_key_file_set_string(key_file, "SDP", "Record", str);
+
+ 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_free(str);
+
+ g_key_file_free(key_file);
+}
+
static int hid_device_probe(struct btd_profile *p, struct btd_device *device,
GSList *uuids)
{
const gchar *path = device_get_path(device);
const sdp_record_t *rec = btd_device_get_record(device, uuids->data);
+ sdp_record_t *stored_rec;
+ char *filename, *data;
+ GKeyFile *key_file = NULL;
+ int err;

DBG("path %s", path);

- if (!rec)
- return -1;
+ filename = device_get_storage_path(device, "input");
+
+ if (rec) {
+ store_hid_record(filename, rec);
+
+ err = input_device_register(device, path, HID_UUID, rec,
+ idle_timeout * 60);
+ goto end;
+ }
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ data = g_key_file_get_string(key_file, "SDP", "Record", NULL);
+ g_key_file_free(key_file);
+
+ if (!data) {
+ err = -1;
+ goto end;
+ }
+
+ stored_rec = record_from_string(data);
+ g_free(data);
+
+ err = input_device_register(device, path, HID_UUID, stored_rec,
+ idle_timeout * 60);
+ sdp_record_free(stored_rec);
+
+end:
+ g_free(filename);

- return input_device_register(device, path, HID_UUID, rec,
- idle_timeout * 60);
+ return err;
}

static void hid_device_remove(struct btd_profile *p, struct btd_device *device)
--
1.7.9.5


2012-12-12 15:47:59

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 10/14] 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 baeae79..754bc2a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2728,6 +2728,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];
@@ -2761,6 +2843,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-12 15:47:58

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 09/14] device: Update services from SDP records

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

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

diff --git a/src/device.c b/src/device.c
index a515266..6c3d5e8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2643,6 +2643,52 @@ static void uuids_changed(struct btd_device *device)
g_free(uuids);
}

+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, "%hd", 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;
@@ -2656,10 +2702,23 @@ 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 filename[PATH_MAX + 1];
+ GKeyFile *key_file = NULL;
+ char *data;
+ gsize length = 0;

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

+ if (!device->temporary) {
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes",
+ srcaddr, dstaddr);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+ }
+
for (seq = recs; seq; seq = seq->next) {
sdp_record_t *rec = (sdp_record_t *) seq->data;
sdp_list_t *svcclass = NULL;
@@ -2713,7 +2772,8 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
continue;
}

- store_record(srcaddr, dstaddr, device->bdaddr_type, rec);
+ if (key_file)
+ store_primaries_from_sdp_record(key_file, rec);

/* Copy record */
req->records = sdp_list_append(req->records,
@@ -2734,6 +2794,19 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)

sdp_list_free(svcclass, free);
}
+
+ if (!key_file)
+ return;
+
+ 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 gint primary_cmp(gconstpointer a, gconstpointer b)
diff --git a/src/storage.c b/src/storage.c
index 17dfc21..5dfb8ea 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -288,39 +288,6 @@ int delete_entry(const bdaddr_t *src, const char *storage, const bdaddr_t *dst,
return err;
}

-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 fdee61c..c390e46 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -38,8 +38,6 @@ int write_lastused_info(const bdaddr_t *local, const bdaddr_t *peer,
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);
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-12 15:48:01

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 12/14] device: Add device_get_storage_path()

---
src/device.c | 15 +++++++++++++++
src/device.h | 2 ++
2 files changed, 17 insertions(+)

diff --git a/src/device.c b/src/device.c
index 9c3211c..6cec4a0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2227,6 +2227,21 @@ void device_register_services_from_primaries(struct btd_device *device)
device->primaries);
}

+char *device_get_storage_path(struct btd_device *device,
+ const char *filename)
+{
+ char srcaddr[18], dstaddr[18];
+
+ ba2str(adapter_get_address(device->adapter), srcaddr);
+ ba2str(&device->bdaddr, dstaddr);
+
+ if (!filename)
+ return g_strdup_printf(STORAGEDIR "/%s/%s", srcaddr, dstaddr);
+
+ return g_strdup_printf(STORAGEDIR "/%s/%s/%s", srcaddr, dstaddr,
+ filename);
+}
+
void device_set_name(struct btd_device *device, const char *name)
{
if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
diff --git a/src/device.h b/src/device.h
index 750b1ea..94adaa3 100644
--- a/src/device.h
+++ b/src/device.h
@@ -31,6 +31,8 @@ struct btd_device *device_create(struct btd_adapter *adapter,
struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
const char *address, GKeyFile *key_file);
void device_register_services_from_primaries(struct btd_device *device);
+char *device_get_storage_path(struct btd_device *device,
+ const char *filename);

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-12 15:47:52

by Frederic Danis

[permalink] [raw]
Subject: [PATCH 03/14] 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 7fcd42c..7ab2389 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2556,6 +2556,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;
@@ -2663,6 +2669,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