aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnderson Lizardo <anderson.lizardo@openbossa.org>2010-08-13 14:59:17 -0400
committerAnderson Lizardo <anderson.lizardo@openbossa.org>2010-08-26 09:29:56 -0400
commit08f1b750295cda5beaa4d948f499cd7c93b85f70 (patch)
tree8fd111b6f005ca6182dd5ba20c0fd4328b789235
parenta5e5c9262a7fa20b03643c478f1620995a89ad79 (diff)
downloadbluez-08f1b750295cda5beaa4d948f499cd7c93b85f70.tar.gz
bluez-08f1b750295cda5beaa4d948f499cd7c93b85f70.tar.xz
bluez-08f1b750295cda5beaa4d948f499cd7c93b85f70.zip
Support for loading attribute data
-rw-r--r--attrib/client.c98
-rw-r--r--src/storage.c11
-rw-r--r--src/storage.h3
3 files changed, 112 insertions, 0 deletions
diff --git a/attrib/client.c b/attrib/client.c
index 838c6ef4..f2e8766d 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -637,6 +637,103 @@ fail:
gatt_service_free(gatt);
}
+static void *attr_data_from_string(const char *str)
+{
+ uint8_t *data;
+ int size, i;
+ char tmp[3];
+
+ size = strlen(str) / 2;
+ data = g_try_malloc0(size);
+ if (data == NULL)
+ return NULL;
+
+ tmp[2] = '\0';
+ for (i = 0; i < size; i++) {
+ memcpy(tmp, str + (i * 2), 2);
+ data[i] = (uint8_t) strtol(tmp, NULL, 16);
+ }
+
+ return data;
+}
+
+static int find_primary(gconstpointer a, gconstpointer b)
+{
+ const struct primary *primary = a;
+ uint16_t handle = GPOINTER_TO_UINT(b);
+
+ if (handle < primary->start)
+ return -1;
+
+ if (handle > primary->end)
+ return -1;
+
+ return 0;
+}
+
+static int find_characteristic(gconstpointer a, gconstpointer b)
+{
+ const struct characteristic *chr = a;
+ uint16_t handle = GPOINTER_TO_UINT(b);
+
+ if (handle < chr->handle)
+ return -1;
+
+ if (handle > chr->end)
+ return -1;
+
+ return 0;
+}
+
+static void load_attribute_data(char *key, char *value, void *data)
+{
+ struct gatt_service *gatt = data;
+ struct characteristic *chr;
+ struct primary *primary;
+ char addr[18], dst[18];
+ uint16_t handle;
+ uuid_t uuid;
+ GSList *l;
+ guint h;
+
+ if (sscanf(key, "%17s#%04hX", addr, &handle) < 2)
+ return;
+
+ ba2str(&gatt->dba, dst);
+
+ if (strcmp(addr, dst) != 0)
+ return;
+
+ h = handle;
+
+ l = g_slist_find_custom(gatt->primary, GUINT_TO_POINTER(h),
+ find_primary);
+ if (!l)
+ return;
+
+ primary = l->data;
+
+ l = g_slist_find_custom(primary->chars, GUINT_TO_POINTER(h),
+ find_characteristic);
+ if (!l)
+ return;
+
+ chr = l->data;
+
+ /* value[] contains "<UUID>#<data>", but bt_string2uuid() expects a
+ * string containing only the UUID. To avoid creating a new buffer,
+ * "truncate" the string in place before calling bt_string2uuid(). */
+ value[MAX_LEN_UUID_STR - 1] = '\0';
+ if (bt_string2uuid(&uuid, value) < 0)
+ return;
+
+ /* Fill the characteristic field according to the attribute type. */
+ if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0)
+ chr->desc = attr_data_from_string(value + MAX_LEN_UUID_STR);
+ else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0)
+ chr->format = attr_data_from_string(value + MAX_LEN_UUID_STR);
+}
+
static char *primary_list_to_string(GSList *primary_list)
{
GString *services;
@@ -743,6 +840,7 @@ static gboolean load_primary_services(struct gatt_service *gatt)
register_primary(gatt);
g_slist_foreach(gatt->primary, load_characteristics, gatt);
+ read_device_attributes(&gatt->sba, load_attribute_data, gatt);
return TRUE;
}
diff --git a/src/storage.c b/src/storage.c
index dcd6511d..1bfd9c5d 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1312,3 +1312,14 @@ int write_device_attribute(const bdaddr_t *sba, const bdaddr_t *dba,
return textfile_put(filename, key, chars);
}
+
+int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data)
+{
+ char filename[PATH_MAX + 1];
+
+ create_filename(filename, PATH_MAX, sba, "attributes");
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ return textfile_foreach(filename, func, data);
+}
diff --git a/src/storage.h b/src/storage.h
index dcba2ce5..cf1ffdcf 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -21,6 +21,8 @@
*
*/
+#include "textfile.h"
+
int read_device_alias(const char *src, const char *dst, char *alias, size_t size);
int write_device_alias(const char *src, const char *dst, const char *alias);
int write_discoverable_timeout(bdaddr_t *bdaddr, int timeout);
@@ -87,6 +89,7 @@ char *read_device_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
uint16_t handle);
int write_device_attribute(const bdaddr_t *sba, const bdaddr_t *dba,
uint16_t handle, const char *chars);
+int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data);
#define PNP_UUID "00001200-0000-1000-8000-00805f9b34fb"