• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2010  Nokia Corporation
6  *  Copyright (C) 2010  Marcel Holtmann <marcel@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 
characteristic_free(void * user_data)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 
watcher_free(void * user_data)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 
primary_free(void * user_data)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 
gatt_service_free(void * user_data)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 
gatt_dev_cmp(gconstpointer a,gconstpointer b)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 
characteristic_handle_cmp(gconstpointer a,gconstpointer b)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 
watcher_cmp(gconstpointer a,gconstpointer b)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 
append_char_dict(DBusMessageIter * iter,struct characteristic * chr)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 
watcher_exit(DBusConnection * conn,void * user_data)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 
characteristic_set_value(struct characteristic * chr,const uint8_t * value,size_t vlen)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 
update_watchers(gpointer data,gpointer user_data)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 
events_handler(const uint8_t * pdu,uint16_t len,gpointer user_data)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 
attrib_destroy(gpointer user_data)318 static void attrib_destroy(gpointer user_data)
319 {
320 	struct gatt_service *gatt = user_data;
321 
322 	gatt->attrib = NULL;
323 }
324 
attrib_disconnect(gpointer user_data)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 
connect_cb(GIOChannel * chan,GError * gerr,gpointer user_data)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 
l2cap_connect(struct gatt_service * gatt,GError ** gerr,gboolean listen)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 
register_watcher(DBusConnection * conn,DBusMessage * msg,void * data)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 
unregister_watcher(DBusConnection * conn,DBusMessage * msg,void * data)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 
set_value(DBusConnection * conn,DBusMessage * msg,DBusMessageIter * iter,struct characteristic * chr)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 
get_properties(DBusConnection * conn,DBusMessage * msg,void * data)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 
set_property(DBusConnection * conn,DBusMessage * msg,void * data)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 
characteristic_list_to_string(GSList * chars)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 
store_characteristics(struct gatt_service * gatt,struct primary * prim)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 
register_characteristics(struct primary * prim)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 
string_to_characteristic_list(struct primary * prim,const char * str)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 
load_characteristics(gpointer data,gpointer user_data)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 
store_attribute(struct gatt_service * gatt,uint16_t handle,uint16_t type,uint8_t * value,gsize len)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 
update_char_desc(guint8 status,const guint8 * pdu,guint16 len,gpointer user_data)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 
update_char_format(guint8 status,const guint8 * pdu,guint16 len,gpointer user_data)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 
update_char_value(guint8 status,const guint8 * pdu,guint16 len,gpointer user_data)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 
uuid_desc16_cmp(bt_uuid_t * uuid,guint16 desc)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 
descriptor_cb(guint8 status,const guint8 * pdu,guint16 plen,gpointer user_data)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 
update_all_chars(gpointer data,gpointer user_data)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 
char_discovered_cb(GSList * characteristics,guint8 status,gpointer user_data)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 
discover_char(DBusConnection * conn,DBusMessage * msg,void * data)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 
prim_get_properties(DBusConnection * conn,DBusMessage * msg,void * data)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 
register_primaries(struct gatt_service * gatt,GSList * primaries)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 
attrib_client_register(DBusConnection * connection,struct btd_device * device,int psm,GAttrib * attrib,GSList * primaries)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 
attrib_client_unregister(struct btd_device * device)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