Home | History | Annotate | Download | only in attrib
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2010  Nokia Corporation
      6  *  Copyright (C) 2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 
     26 #ifdef HAVE_CONFIG_H
     27 #include <config.h>
     28 #endif
     29 
     30 #include <errno.h>
     31 #include <stdlib.h>
     32 #include <glib.h>
     33 
     34 #include <bluetooth/bluetooth.h>
     35 #include <bluetooth/uuid.h>
     36 
     37 #include "adapter.h"
     38 #include "device.h"
     39 #include "log.h"
     40 #include "gdbus.h"
     41 #include "error.h"
     42 #include "dbus-common.h"
     43 #include "btio.h"
     44 #include "storage.h"
     45 
     46 #include "att.h"
     47 #include "gattrib.h"
     48 #include "gatt.h"
     49 #include "client.h"
     50 
     51 #define CHAR_INTERFACE "org.bluez.Characteristic"
     52 
     53 struct gatt_service {
     54 	struct btd_device *dev;
     55 	DBusConnection *conn;
     56 	bdaddr_t sba;
     57 	bdaddr_t dba;
     58 	char *path;
     59 	GSList *primary;
     60 	GAttrib *attrib;
     61 	DBusMessage *msg;
     62 	int psm;
     63 	gboolean listen;
     64 };
     65 
     66 struct format {
     67 	guint8 format;
     68 	guint8 exponent;
     69 	guint16 unit;
     70 	guint8 namespace;
     71 	guint16 desc;
     72 } __attribute__ ((packed));
     73 
     74 struct primary {
     75 	struct gatt_service *gatt;
     76 	struct att_primary *att;
     77 	char *path;
     78 	GSList *chars;
     79 	GSList *watchers;
     80 };
     81 
     82 struct characteristic {
     83 	struct primary *prim;
     84 	char *path;
     85 	uint16_t handle;
     86 	uint16_t end;
     87 	uint8_t perm;
     88 	char type[MAX_LEN_UUID_STR + 1];
     89 	char *name;
     90 	char *desc;
     91 	struct format *format;
     92 	uint8_t *value;
     93 	size_t vlen;
     94 };
     95 
     96 struct query_data {
     97 	struct primary *prim;
     98 	struct characteristic *chr;
     99 	DBusMessage *msg;
    100 	uint16_t handle;
    101 };
    102 
    103 struct watcher {
    104 	guint id;
    105 	char *name;
    106 	char *path;
    107 	struct primary *prim;
    108 };
    109 
    110 static GSList *gatt_services = NULL;
    111 
    112 static void characteristic_free(void *user_data)
    113 {
    114 	struct characteristic *chr = user_data;
    115 
    116 	g_free(chr->path);
    117 	g_free(chr->desc);
    118 	g_free(chr->format);
    119 	g_free(chr->value);
    120 	g_free(chr->name);
    121 	g_free(chr);
    122 }
    123 
    124 static void watcher_free(void *user_data)
    125 {
    126 	struct watcher *watcher = user_data;
    127 
    128 	g_free(watcher->path);
    129 	g_free(watcher->name);
    130 	g_free(watcher);
    131 }
    132 
    133 static void primary_free(void *user_data)
    134 {
    135 	struct primary *prim = user_data;
    136 	GSList *l;
    137 
    138 	for (l = prim->watchers; l; l = l->next) {
    139 		struct watcher *watcher = l->data;
    140 		g_dbus_remove_watch(prim->gatt->conn, watcher->id);
    141 	}
    142 
    143 	g_slist_foreach(prim->chars, (GFunc) characteristic_free, NULL);
    144 	g_slist_free(prim->chars);
    145 	g_free(prim->path);
    146 	g_free(prim);
    147 }
    148 
    149 static void gatt_service_free(void *user_data)
    150 {
    151 	struct gatt_service *gatt = user_data;
    152 
    153 	g_slist_foreach(gatt->primary, (GFunc) primary_free, NULL);
    154 	g_slist_free(gatt->primary);
    155 	g_attrib_unref(gatt->attrib);
    156 	g_free(gatt->path);
    157 	btd_device_unref(gatt->dev);
    158 	dbus_connection_unref(gatt->conn);
    159 	g_free(gatt);
    160 }
    161 
    162 static int gatt_dev_cmp(gconstpointer a, gconstpointer b)
    163 {
    164 	const struct gatt_service *gatt = a;
    165 	const struct btd_device *dev = b;
    166 
    167 	return gatt->dev != dev;
    168 }
    169 
    170 static int characteristic_handle_cmp(gconstpointer a, gconstpointer b)
    171 {
    172 	const struct characteristic *chr = a;
    173 	uint16_t handle = GPOINTER_TO_UINT(b);
    174 
    175 	return chr->handle - handle;
    176 }
    177 
    178 static int watcher_cmp(gconstpointer a, gconstpointer b)
    179 {
    180 	const struct watcher *watcher = a;
    181 	const struct watcher *match = b;
    182 	int ret;
    183 
    184 	ret = g_strcmp0(watcher->name, match->name);
    185 	if (ret != 0)
    186 		return ret;
    187 
    188 	return g_strcmp0(watcher->path, match->path);
    189 }
    190 
    191 static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr)
    192 {
    193 	DBusMessageIter dict;
    194 	const char *name = "";
    195 	char *uuid;
    196 
    197 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
    198 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    199 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    200 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    201 
    202 	uuid = g_strdup(chr->type);
    203 	dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
    204 	g_free(uuid);
    205 
    206 	/* FIXME: Translate UUID to name. */
    207 	dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &name);
    208 
    209 	if (chr->desc)
    210 		dict_append_entry(&dict, "Description", DBUS_TYPE_STRING,
    211 								&chr->desc);
    212 
    213 	if (chr->value)
    214 		dict_append_array(&dict, "Value", DBUS_TYPE_BYTE, &chr->value,
    215 								chr->vlen);
    216 
    217 	/* FIXME: Missing Format, Value and Representation */
    218 
    219 	dbus_message_iter_close_container(iter, &dict);
    220 }
    221 
    222 static void watcher_exit(DBusConnection *conn, void *user_data)
    223 {
    224 	struct watcher *watcher = user_data;
    225 	struct primary *prim = watcher->prim;
    226 	struct gatt_service *gatt = prim->gatt;
    227 
    228 	DBG("%s watcher %s exited", prim->path, watcher->name);
    229 
    230 	prim->watchers = g_slist_remove(prim->watchers, watcher);
    231 
    232 	g_attrib_unref(gatt->attrib);
    233 }
    234 
    235 static int characteristic_set_value(struct characteristic *chr,
    236 					const uint8_t *value, size_t vlen)
    237 {
    238 	chr->value = g_try_realloc(chr->value, vlen);
    239 	if (chr->value == NULL)
    240 		return -ENOMEM;
    241 
    242 	memcpy(chr->value, value, vlen);
    243 	chr->vlen = vlen;
    244 
    245 	return 0;
    246 }
    247 
    248 static void update_watchers(gpointer data, gpointer user_data)
    249 {
    250 	struct watcher *w = data;
    251 	struct characteristic *chr = user_data;
    252 	DBusConnection *conn = w->prim->gatt->conn;
    253 	DBusMessage *msg;
    254 
    255 	msg = dbus_message_new_method_call(w->name, w->path,
    256 				"org.bluez.Watcher", "ValueChanged");
    257 	if (msg == NULL)
    258 		return;
    259 
    260 	dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &chr->path,
    261 			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
    262 			&chr->value, chr->vlen, DBUS_TYPE_INVALID);
    263 
    264 	dbus_message_set_no_reply(msg, TRUE);
    265 	g_dbus_send_message(conn, msg);
    266 }
    267 
    268 static void events_handler(const uint8_t *pdu, uint16_t len,
    269 							gpointer user_data)
    270 {
    271 	struct gatt_service *gatt = user_data;
    272 	struct characteristic *chr;
    273 	struct primary *prim;
    274 	GSList *lprim, *lchr;
    275 	uint8_t opdu[ATT_MAX_MTU];
    276 	guint handle;
    277 	uint16_t olen;
    278 
    279 	if (len < 3) {
    280 		DBG("Malformed notification/indication packet (opcode 0x%02x)",
    281 									pdu[0]);
    282 		return;
    283 	}
    284 
    285 	handle = att_get_u16(&pdu[1]);
    286 
    287 	for (lprim = gatt->primary, prim = NULL, chr = NULL; lprim;
    288 						lprim = lprim->next) {
    289 		prim = lprim->data;
    290 
    291 		lchr = g_slist_find_custom(prim->chars,
    292 			GUINT_TO_POINTER(handle), characteristic_handle_cmp);
    293 		if (lchr) {
    294 			chr = lchr->data;
    295 			break;
    296 		}
    297 	}
    298 
    299 	if (chr == NULL) {
    300 		DBG("Attribute handle 0x%02x not found", handle);
    301 		return;
    302 	}
    303 
    304 	switch (pdu[0]) {
    305 	case ATT_OP_HANDLE_IND:
    306 		olen = enc_confirmation(opdu, sizeof(opdu));
    307 		g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
    308 						NULL, NULL, NULL);
    309 	case ATT_OP_HANDLE_NOTIFY:
    310 		if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
    311 			DBG("Can't change Characteristic 0x%02x", handle);
    312 
    313 		g_slist_foreach(prim->watchers, update_watchers, chr);
    314 		break;
    315 	}
    316 }
    317 
    318 static void attrib_destroy(gpointer user_data)
    319 {
    320 	struct gatt_service *gatt = user_data;
    321 
    322 	gatt->attrib = NULL;
    323 }
    324 
    325 static void attrib_disconnect(gpointer user_data)
    326 {
    327 	struct gatt_service *gatt = user_data;
    328 
    329 	/* Remote initiated disconnection only */
    330 	g_attrib_unref(gatt->attrib);
    331 }
    332 
    333 static void connect_cb(GIOChannel *chan, GError *gerr, gpointer user_data)
    334 {
    335 	struct gatt_service *gatt = user_data;
    336 
    337 	if (gerr) {
    338 		if (gatt->msg) {
    339 			DBusMessage *reply = btd_error_failed(gatt->msg,
    340 							gerr->message);
    341 			g_dbus_send_message(gatt->conn, reply);
    342 		}
    343 
    344 		error("%s", gerr->message);
    345 		goto fail;
    346 	}
    347 
    348 	if (gatt->attrib == NULL)
    349 		return;
    350 
    351 	/* Listen mode: used for notification and indication */
    352 	if (gatt->listen == TRUE) {
    353 		g_attrib_register(gatt->attrib,
    354 					ATT_OP_HANDLE_NOTIFY,
    355 					events_handler, gatt, NULL);
    356 		g_attrib_register(gatt->attrib,
    357 					ATT_OP_HANDLE_IND,
    358 					events_handler, gatt, NULL);
    359 		return;
    360 	}
    361 
    362 	return;
    363 fail:
    364 	g_attrib_unref(gatt->attrib);
    365 }
    366 
    367 static int l2cap_connect(struct gatt_service *gatt, GError **gerr,
    368 								gboolean listen)
    369 {
    370 	GIOChannel *io;
    371 
    372 	if (gatt->attrib != NULL) {
    373 		gatt->attrib = g_attrib_ref(gatt->attrib);
    374 		gatt->listen = listen;
    375 		return 0;
    376 	}
    377 
    378 	/*
    379 	 * FIXME: If the service doesn't support Client Characteristic
    380 	 * Configuration it is necessary to poll the server from time
    381 	 * to time checking for modifications.
    382 	 */
    383 	if (gatt->psm < 0)
    384 		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr,
    385 			BT_IO_OPT_SOURCE_BDADDR, &gatt->sba,
    386 			BT_IO_OPT_DEST_BDADDR, &gatt->dba,
    387 			BT_IO_OPT_CID, ATT_CID,
    388 			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
    389 			BT_IO_OPT_INVALID);
    390 	else
    391 		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr,
    392 			BT_IO_OPT_SOURCE_BDADDR, &gatt->sba,
    393 			BT_IO_OPT_DEST_BDADDR, &gatt->dba,
    394 			BT_IO_OPT_PSM, gatt->psm,
    395 			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
    396 			BT_IO_OPT_INVALID);
    397 	if (!io)
    398 		return -1;
    399 
    400 	gatt->attrib = g_attrib_new(io);
    401 	g_io_channel_unref(io);
    402 	gatt->listen = listen;
    403 
    404 	g_attrib_set_destroy_function(gatt->attrib, attrib_destroy, gatt);
    405 	g_attrib_set_disconnect_function(gatt->attrib, attrib_disconnect,
    406 									gatt);
    407 
    408 	return 0;
    409 }
    410 
    411 static DBusMessage *register_watcher(DBusConnection *conn,
    412 						DBusMessage *msg, void *data)
    413 {
    414 	const char *sender = dbus_message_get_sender(msg);
    415 	struct primary *prim = data;
    416 	struct watcher *watcher;
    417 	GError *gerr = NULL;
    418 	char *path;
    419 
    420 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
    421 							DBUS_TYPE_INVALID))
    422 		return btd_error_invalid_args(msg);
    423 
    424 	if (l2cap_connect(prim->gatt, &gerr, TRUE) < 0) {
    425 		DBusMessage *reply = btd_error_failed(msg, gerr->message);
    426 		g_error_free(gerr);
    427 		return reply;
    428 	}
    429 
    430 	watcher = g_new0(struct watcher, 1);
    431 	watcher->name = g_strdup(sender);
    432 	watcher->prim = prim;
    433 	watcher->path = g_strdup(path);
    434 	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
    435 							watcher, watcher_free);
    436 
    437 	prim->watchers = g_slist_append(prim->watchers, watcher);
    438 
    439 	return dbus_message_new_method_return(msg);
    440 }
    441 
    442 static DBusMessage *unregister_watcher(DBusConnection *conn,
    443 						DBusMessage *msg, void *data)
    444 {
    445 	const char *sender = dbus_message_get_sender(msg);
    446 	struct primary *prim = data;
    447 	struct watcher *watcher, *match;
    448 	GSList *l;
    449 	char *path;
    450 
    451 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
    452 							DBUS_TYPE_INVALID))
    453 		return btd_error_invalid_args(msg);
    454 
    455 	match = g_new0(struct watcher, 1);
    456 	match->name = g_strdup(sender);
    457 	match->path = g_strdup(path);
    458 	l = g_slist_find_custom(prim->watchers, match, watcher_cmp);
    459 	watcher_free(match);
    460 	if (!l)
    461 		return btd_error_not_authorized(msg);
    462 
    463 	watcher = l->data;
    464 	g_dbus_remove_watch(conn, watcher->id);
    465 	prim->watchers = g_slist_remove(prim->watchers, watcher);
    466 	watcher_free(watcher);
    467 
    468 	return dbus_message_new_method_return(msg);
    469 }
    470 
    471 static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
    472 			DBusMessageIter *iter, struct characteristic *chr)
    473 {
    474 	struct gatt_service *gatt = chr->prim->gatt;
    475 	DBusMessageIter sub;
    476 	GError *gerr = NULL;
    477 	uint8_t *value;
    478 	int len;
    479 
    480 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
    481 			dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE)
    482 		return btd_error_invalid_args(msg);
    483 
    484 	dbus_message_iter_recurse(iter, &sub);
    485 
    486 	dbus_message_iter_get_fixed_array(&sub, &value, &len);
    487 
    488 	if (l2cap_connect(gatt, &gerr, FALSE) < 0) {
    489 		DBusMessage *reply = btd_error_failed(msg, gerr->message);
    490 		g_error_free(gerr);
    491 		return reply;
    492 	}
    493 
    494 	gatt_write_cmd(gatt->attrib, chr->handle, value, len, NULL, NULL);
    495 
    496 	characteristic_set_value(chr, value, len);
    497 
    498 	return dbus_message_new_method_return(msg);
    499 }
    500 
    501 static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
    502 								void *data)
    503 {
    504 	struct characteristic *chr = data;
    505 	DBusMessage *reply;
    506 	DBusMessageIter iter;
    507 
    508 	reply = dbus_message_new_method_return(msg);
    509 	if (!reply)
    510 		return NULL;
    511 
    512 	dbus_message_iter_init_append(reply, &iter);
    513 
    514 	append_char_dict(&iter, chr);
    515 
    516 	return reply;
    517 }
    518 
    519 static DBusMessage *set_property(DBusConnection *conn,
    520 					DBusMessage *msg, void *data)
    521 {
    522 	struct characteristic *chr = data;
    523 	DBusMessageIter iter;
    524 	DBusMessageIter sub;
    525 	const char *property;
    526 
    527 	if (!dbus_message_iter_init(msg, &iter))
    528 		return btd_error_invalid_args(msg);
    529 
    530 	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
    531 		return btd_error_invalid_args(msg);
    532 
    533 	dbus_message_iter_get_basic(&iter, &property);
    534 	dbus_message_iter_next(&iter);
    535 
    536 	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
    537 		return btd_error_invalid_args(msg);
    538 
    539 	dbus_message_iter_recurse(&iter, &sub);
    540 
    541 	if (g_str_equal("Value", property))
    542 		return set_value(conn, msg, &sub, chr);
    543 
    544 	return btd_error_invalid_args(msg);
    545 }
    546 
    547 static GDBusMethodTable char_methods[] = {
    548 	{ "GetProperties",	"",	"a{sv}", get_properties },
    549 	{ "SetProperty",	"sv",	"",	set_property,
    550 						G_DBUS_METHOD_FLAG_ASYNC},
    551 	{ }
    552 };
    553 
    554 static char *characteristic_list_to_string(GSList *chars)
    555 {
    556 	GString *characteristics;
    557 	GSList *l;
    558 
    559 	characteristics = g_string_new(NULL);
    560 
    561 	for (l = chars; l; l = l->next) {
    562 		struct characteristic *chr = l->data;
    563 		char chr_str[64];
    564 
    565 		memset(chr_str, 0, sizeof(chr_str));
    566 
    567 		snprintf(chr_str, sizeof(chr_str), "%04X#%02X#%04X#%s ",
    568 				chr->handle, chr->perm, chr->end, chr->type);
    569 
    570 		characteristics = g_string_append(characteristics, chr_str);
    571 	}
    572 
    573 	return g_string_free(characteristics, FALSE);
    574 }
    575 
    576 static void store_characteristics(struct gatt_service *gatt,
    577 							struct primary *prim)
    578 {
    579 	char *characteristics;
    580 	struct att_primary *att = prim->att;
    581 
    582 	characteristics = characteristic_list_to_string(prim->chars);
    583 
    584 	write_device_characteristics(&gatt->sba, &gatt->dba, att->start,
    585 							characteristics);
    586 
    587 	g_free(characteristics);
    588 }
    589 
    590 static void register_characteristics(struct primary *prim)
    591 {
    592 	GSList *lc;
    593 
    594 	for (lc = prim->chars; lc; lc = lc->next) {
    595 		struct characteristic *chr = lc->data;
    596 		g_dbus_register_interface(prim->gatt->conn, chr->path,
    597 				CHAR_INTERFACE, char_methods,
    598 				NULL, NULL, chr, NULL);
    599 		DBG("Registered: %s", chr->path);
    600 	}
    601 }
    602 
    603 static GSList *string_to_characteristic_list(struct primary *prim,
    604 							const char *str)
    605 {
    606 	GSList *l = NULL;
    607 	char **chars;
    608 	int i;
    609 
    610 	if (str == NULL)
    611 		return NULL;
    612 
    613 	chars = g_strsplit(str, " ", 0);
    614 	if (chars == NULL)
    615 		return NULL;
    616 
    617 	for (i = 0; chars[i]; i++) {
    618 		struct characteristic *chr;
    619 		int ret;
    620 
    621 		chr = g_new0(struct characteristic, 1);
    622 
    623 		ret = sscanf(chars[i], "%04hX#%02hhX#%04hX#%s", &chr->handle,
    624 				&chr->perm, &chr->end, chr->type);
    625 		if (ret < 4) {
    626 			g_free(chr);
    627 			continue;
    628 		}
    629 
    630 		chr->prim = prim;
    631 		chr->path = g_strdup_printf("%s/characteristic%04x",
    632 						prim->path, chr->handle);
    633 
    634 		l = g_slist_append(l, chr);
    635 	}
    636 
    637 	g_strfreev(chars);
    638 
    639 	return l;
    640 }
    641 
    642 static void load_characteristics(gpointer data, gpointer user_data)
    643 {
    644 	struct primary *prim = data;
    645 	struct att_primary *att = prim->att;
    646 	struct gatt_service *gatt = user_data;
    647 	GSList *chrs_list;
    648 	char *str;
    649 
    650 	if (prim->chars) {
    651 		DBG("Characteristics already loaded");
    652 		return;
    653 	}
    654 
    655 	str = read_device_characteristics(&gatt->sba, &gatt->dba, att->start);
    656 	if (str == NULL)
    657 		return;
    658 
    659 	chrs_list = string_to_characteristic_list(prim, str);
    660 
    661 	free(str);
    662 
    663 	if (chrs_list == NULL)
    664 		return;
    665 
    666 	prim->chars = chrs_list;
    667 	register_characteristics(prim);
    668 
    669 	return;
    670 }
    671 
    672 static void store_attribute(struct gatt_service *gatt, uint16_t handle,
    673 				uint16_t type, uint8_t *value, gsize len)
    674 {
    675 	bt_uuid_t uuid;
    676 	char *str, *tmp;
    677 	guint i;
    678 
    679 	str = g_malloc0(MAX_LEN_UUID_STR + len * 2 + 1);
    680 
    681 	bt_uuid16_create(&uuid, type);
    682 	bt_uuid_to_string(&uuid, str, MAX_LEN_UUID_STR);
    683 
    684 	str[MAX_LEN_UUID_STR - 1] = '#';
    685 
    686 	for (i = 0, tmp = str + MAX_LEN_UUID_STR; i < len; i++, tmp += 2)
    687 		sprintf(tmp, "%02X", value[i]);
    688 
    689 	write_device_attribute(&gatt->sba, &gatt->dba, handle, str);
    690 	g_free(str);
    691 }
    692 
    693 static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
    694 							gpointer user_data)
    695 {
    696 	struct query_data *current = user_data;
    697 	struct gatt_service *gatt = current->prim->gatt;
    698 	struct characteristic *chr = current->chr;
    699 
    700 	if (status == 0) {
    701 
    702 		g_free(chr->desc);
    703 
    704 		chr->desc = g_malloc(len);
    705 		memcpy(chr->desc, pdu + 1, len - 1);
    706 		chr->desc[len - 1] = '\0';
    707 
    708 		store_attribute(gatt, current->handle,
    709 				GATT_CHARAC_USER_DESC_UUID,
    710 				(void *) chr->desc, len);
    711 	} else if (status == ATT_ECODE_INSUFF_ENC) {
    712 		GIOChannel *io = g_attrib_get_channel(gatt->attrib);
    713 
    714 		if (bt_io_set(io, BT_IO_L2CAP, NULL,
    715 				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
    716 				BT_IO_OPT_INVALID)) {
    717 			gatt_read_char(gatt->attrib, current->handle, 0,
    718 					update_char_desc, current);
    719 			return;
    720 		}
    721 	}
    722 
    723 	g_attrib_unref(gatt->attrib);
    724 	g_free(current);
    725 }
    726 
    727 static void update_char_format(guint8 status, const guint8 *pdu, guint16 len,
    728 								gpointer user_data)
    729 {
    730 	struct query_data *current = user_data;
    731 	struct gatt_service *gatt = current->prim->gatt;
    732 	struct characteristic *chr = current->chr;
    733 
    734 	if (status != 0)
    735 		goto done;
    736 
    737 	if (len < 8)
    738 		goto done;
    739 
    740 	g_free(chr->format);
    741 
    742 	chr->format = g_new0(struct format, 1);
    743 	memcpy(chr->format, pdu + 1, 7);
    744 
    745 	store_attribute(gatt, current->handle, GATT_CHARAC_FMT_UUID,
    746 				(void *) chr->format, sizeof(*chr->format));
    747 
    748 done:
    749 	g_attrib_unref(gatt->attrib);
    750 	g_free(current);
    751 }
    752 
    753 static void update_char_value(guint8 status, const guint8 *pdu,
    754 					guint16 len, gpointer user_data)
    755 {
    756 	struct query_data *current = user_data;
    757 	struct gatt_service *gatt = current->prim->gatt;
    758 	struct characteristic *chr = current->chr;
    759 
    760 	if (status == 0)
    761 		characteristic_set_value(chr, pdu + 1, len - 1);
    762 	else if (status == ATT_ECODE_INSUFF_ENC) {
    763 		GIOChannel *io = g_attrib_get_channel(gatt->attrib);
    764 
    765 		if (bt_io_set(io, BT_IO_L2CAP, NULL,
    766 				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
    767 				BT_IO_OPT_INVALID)) {
    768 			gatt_read_char(gatt->attrib, chr->handle, 0,
    769 					update_char_value, current);
    770 			return;
    771 		}
    772 	}
    773 
    774 	g_attrib_unref(gatt->attrib);
    775 	g_free(current);
    776 }
    777 
    778 static int uuid_desc16_cmp(bt_uuid_t *uuid, guint16 desc)
    779 {
    780 	bt_uuid_t u16;
    781 
    782 	bt_uuid16_create(&u16, desc);
    783 
    784 	return bt_uuid_cmp(uuid, &u16);
    785 }
    786 
    787 static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
    788 							gpointer user_data)
    789 {
    790 	struct query_data *current = user_data;
    791 	struct gatt_service *gatt = current->prim->gatt;
    792 	struct att_data_list *list;
    793 	guint8 format;
    794 	int i;
    795 
    796 	if (status != 0)
    797 		goto done;
    798 
    799 	DBG("Find Information Response received");
    800 
    801 	list = dec_find_info_resp(pdu, plen, &format);
    802 	if (list == NULL)
    803 		goto done;
    804 
    805 	for (i = 0; i < list->num; i++) {
    806 		guint16 handle;
    807 		bt_uuid_t uuid;
    808 		uint8_t *info = list->data[i];
    809 		struct query_data *qfmt;
    810 
    811 		handle = att_get_u16(info);
    812 
    813 		if (format == 0x01) {
    814 			uuid = att_get_uuid16(&info[2]);
    815 		} else {
    816 			/* Currently, only "user description" and "presentation
    817 			 * format" descriptors are used, and both have 16-bit
    818 			 * UUIDs. Therefore there is no need to support format
    819 			 * 0x02 yet. */
    820 			continue;
    821 		}
    822 		qfmt = g_new0(struct query_data, 1);
    823 		qfmt->prim = current->prim;
    824 		qfmt->chr = current->chr;
    825 		qfmt->handle = handle;
    826 
    827 		if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0) {
    828 			gatt->attrib = g_attrib_ref(gatt->attrib);
    829 			gatt_read_char(gatt->attrib, handle, 0, update_char_desc,
    830 									qfmt);
    831 		} else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0) {
    832 			gatt->attrib = g_attrib_ref(gatt->attrib);
    833 			gatt_read_char(gatt->attrib, handle, 0,
    834 						update_char_format, qfmt);
    835 		} else
    836 			g_free(qfmt);
    837 	}
    838 
    839 	att_data_list_free(list);
    840 done:
    841 	g_attrib_unref(gatt->attrib);
    842 	g_free(current);
    843 }
    844 
    845 static void update_all_chars(gpointer data, gpointer user_data)
    846 {
    847 	struct query_data *qdesc, *qvalue;
    848 	struct characteristic *chr = data;
    849 	struct primary *prim = user_data;
    850 	struct gatt_service *gatt = prim->gatt;
    851 
    852 	qdesc = g_new0(struct query_data, 1);
    853 	qdesc->prim = prim;
    854 	qdesc->chr = chr;
    855 
    856 	gatt->attrib = g_attrib_ref(gatt->attrib);
    857 	gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb,
    858 									qdesc);
    859 
    860 	qvalue = g_new0(struct query_data, 1);
    861 	qvalue->prim = prim;
    862 	qvalue->chr = chr;
    863 
    864 	gatt->attrib = g_attrib_ref(gatt->attrib);
    865 	gatt_read_char(gatt->attrib, chr->handle, 0, update_char_value, qvalue);
    866 }
    867 
    868 static void char_discovered_cb(GSList *characteristics, guint8 status,
    869 							gpointer user_data)
    870 {
    871 	DBusMessage *reply;
    872 	DBusMessageIter iter, array_iter;
    873 	struct query_data *current = user_data;
    874 	struct primary *prim = current->prim;
    875 	struct att_primary *att = prim->att;
    876 	struct gatt_service *gatt = prim->gatt;
    877 	uint16_t *previous_end = NULL;
    878 	GSList *l;
    879 
    880 	if (status != 0) {
    881 		const char *str = att_ecode2str(status);
    882 
    883 		DBG("Discover all characteristics failed: %s", str);
    884 		reply = btd_error_failed(current->msg, str);
    885 		goto fail;
    886 	}
    887 
    888 	for (l = characteristics; l; l = l->next) {
    889 		struct att_char *current_chr = l->data;
    890 		struct characteristic *chr;
    891 		guint handle = current_chr->value_handle;
    892 		GSList *lchr;
    893 
    894 		lchr = g_slist_find_custom(prim->chars,
    895 			GUINT_TO_POINTER(handle), characteristic_handle_cmp);
    896 		if (lchr)
    897 			continue;
    898 
    899 		chr = g_new0(struct characteristic, 1);
    900 		chr->prim = prim;
    901 		chr->perm = current_chr->properties;
    902 		chr->handle = current_chr->value_handle;
    903 		chr->path = g_strdup_printf("%s/characteristic%04x",
    904 						prim->path, chr->handle);
    905 		strncpy(chr->type, current_chr->uuid, sizeof(chr->type));
    906 
    907 		if (previous_end)
    908 			*previous_end = current_chr->handle;
    909 
    910 		previous_end = &chr->end;
    911 
    912 		prim->chars = g_slist_append(prim->chars, chr);
    913 	}
    914 
    915 	if (previous_end)
    916 		*previous_end = att->end;
    917 
    918 	store_characteristics(gatt, prim);
    919 	register_characteristics(prim);
    920 
    921 	reply = dbus_message_new_method_return(current->msg);
    922 
    923 	dbus_message_iter_init_append(reply, &iter);
    924 
    925 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    926 				DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);
    927 
    928 	for (l = prim->chars; l; l = l->next) {
    929 		struct characteristic *chr = l->data;
    930 
    931 		dbus_message_iter_append_basic(&array_iter,
    932 					DBUS_TYPE_OBJECT_PATH, &chr->path);
    933 	}
    934 
    935 	dbus_message_iter_close_container(&iter, &array_iter);
    936 
    937 	g_slist_foreach(prim->chars, update_all_chars, prim);
    938 
    939 fail:
    940 	g_dbus_send_message(gatt->conn, reply);
    941 	g_attrib_unref(gatt->attrib);
    942 	g_free(current);
    943 }
    944 
    945 static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg,
    946 								void *data)
    947 {
    948 	struct primary *prim = data;
    949 	struct att_primary *att = prim->att;
    950 	struct gatt_service *gatt = prim->gatt;
    951 	struct query_data *qchr;
    952 	GError *gerr = NULL;
    953 
    954 	if (l2cap_connect(prim->gatt, &gerr, FALSE) < 0) {
    955 		DBusMessage *reply = btd_error_failed(msg, gerr->message);
    956 		g_error_free(gerr);
    957 		return reply;
    958 	}
    959 
    960 	qchr = g_new0(struct query_data, 1);
    961 	qchr->prim = prim;
    962 	qchr->msg = dbus_message_ref(msg);
    963 
    964 	gatt_discover_char(gatt->attrib, att->start, att->end, NULL,
    965 						char_discovered_cb, qchr);
    966 
    967 	return NULL;
    968 }
    969 
    970 static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg,
    971 								void *data)
    972 {
    973 	struct primary *prim = data;
    974 	DBusMessage *reply;
    975 	DBusMessageIter iter;
    976 	DBusMessageIter dict;
    977 	GSList *l;
    978 	char **chars;
    979 	const char *uuid;
    980 	int i;
    981 
    982 	reply = dbus_message_new_method_return(msg);
    983 	if (!reply)
    984 		return NULL;
    985 
    986 	dbus_message_iter_init_append(reply, &iter);
    987 
    988 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    989 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    990 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    991 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    992 
    993 	chars = g_new0(char *, g_slist_length(prim->chars) + 1);
    994 
    995 	for (i = 0, l = prim->chars; l; l = l->next, i++) {
    996 		struct characteristic *chr = l->data;
    997 		chars[i] = chr->path;
    998 	}
    999 
   1000 	dict_append_array(&dict, "Characteristics", DBUS_TYPE_OBJECT_PATH,
   1001 								&chars, i);
   1002 	uuid = prim->att->uuid;
   1003 	dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
   1004 
   1005 	g_free(chars);
   1006 
   1007 	dbus_message_iter_close_container(&iter, &dict);
   1008 
   1009 	return reply;
   1010 }
   1011 
   1012 static GDBusMethodTable prim_methods[] = {
   1013 	{ "DiscoverCharacteristics",	"",	"ao",	discover_char,
   1014 					G_DBUS_METHOD_FLAG_ASYNC	},
   1015 	{ "RegisterCharacteristicsWatcher",	"o", "",
   1016 						register_watcher	},
   1017 	{ "UnregisterCharacteristicsWatcher",	"o", "",
   1018 						unregister_watcher	},
   1019 	{ "GetProperties",	"",	"a{sv}",prim_get_properties	},
   1020 	{ }
   1021 };
   1022 
   1023 static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries)
   1024 {
   1025 	GSList *l, *paths;
   1026 
   1027 	for (paths = NULL, l = primaries; l; l = l->next) {
   1028 		struct att_primary *att = l->data;
   1029 		struct primary *prim;
   1030 
   1031 		prim = g_new0(struct primary, 1);
   1032 		prim->att = att;
   1033 		prim->gatt = gatt;
   1034 		prim->path = g_strdup_printf("%s/service%04x", gatt->path,
   1035 								att->start);
   1036 
   1037 		g_dbus_register_interface(gatt->conn, prim->path,
   1038 				CHAR_INTERFACE, prim_methods,
   1039 				NULL, NULL, prim, NULL);
   1040 		DBG("Registered: %s", prim->path);
   1041 
   1042 		gatt->primary = g_slist_append(gatt->primary, prim);
   1043 		paths = g_slist_append(paths, g_strdup(prim->path));
   1044 		load_characteristics(prim, gatt);
   1045 	}
   1046 
   1047 	return paths;
   1048 }
   1049 
   1050 GSList *attrib_client_register(DBusConnection *connection,
   1051 					struct btd_device *device, int psm,
   1052 					GAttrib *attrib, GSList *primaries)
   1053 {
   1054 	struct btd_adapter *adapter = device_get_adapter(device);
   1055 	const char *path = device_get_path(device);
   1056 	struct gatt_service *gatt;
   1057 	bdaddr_t sba, dba;
   1058 
   1059 	adapter_get_address(adapter, &sba);
   1060 	device_get_address(device, &dba);
   1061 
   1062 	gatt = g_new0(struct gatt_service, 1);
   1063 	gatt->dev = btd_device_ref(device);
   1064 	gatt->conn = dbus_connection_ref(connection);
   1065 	gatt->listen = FALSE;
   1066 	gatt->path = g_strdup(path);
   1067 	bacpy(&gatt->sba, &sba);
   1068 	bacpy(&gatt->dba, &dba);
   1069 	gatt->psm = psm;
   1070 
   1071 	if (attrib)
   1072 		gatt->attrib = g_attrib_ref(attrib);
   1073 
   1074 	gatt_services = g_slist_append(gatt_services, gatt);
   1075 
   1076 	return register_primaries(gatt, primaries);
   1077 }
   1078 
   1079 void attrib_client_unregister(struct btd_device *device)
   1080 {
   1081 	struct gatt_service *gatt;
   1082 	GSList *l, *lp, *lc;
   1083 
   1084 	l = g_slist_find_custom(gatt_services, device, gatt_dev_cmp);
   1085 	if (!l)
   1086 		return;
   1087 
   1088 	gatt = l->data;
   1089 	gatt_services = g_slist_remove(gatt_services, gatt);
   1090 
   1091 	for (lp = gatt->primary; lp; lp = lp->next) {
   1092 		struct primary *prim = lp->data;
   1093 		for (lc = prim->chars; lc; lc = lc->next) {
   1094 			struct characteristic *chr = lc->data;
   1095 			g_dbus_unregister_interface(gatt->conn, chr->path,
   1096 								CHAR_INTERFACE);
   1097 		}
   1098 		g_dbus_unregister_interface(gatt->conn, prim->path,
   1099 								CHAR_INTERFACE);
   1100 	}
   1101 
   1102 	gatt_service_free(gatt);
   1103 }
   1104