3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2015 Google Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
28 #include "lib/bluetooth.h"
30 #include "lib/sdp_lib.h"
32 #include "btio/btio.h"
33 #include "gdbus/gdbus.h"
34 #include "src/shared/util.h"
35 #include "src/shared/queue.h"
36 #include "src/shared/att.h"
37 #include "src/shared/gatt-db.h"
38 #include "src/shared/gatt-server.h"
43 #include "gatt-database.h"
44 #include "dbus-common.h"
55 #define GATT_MANAGER_IFACE "org.bluez.GattManager1"
56 #define GATT_SERVICE_IFACE "org.bluez.GattService1"
57 #define GATT_CHRC_IFACE "org.bluez.GattCharacteristic1"
58 #define GATT_DESC_IFACE "org.bluez.GattDescriptor1"
60 #define UUID_GAP 0x1800
61 #define UUID_GATT 0x1801
64 #define MIN(a, b) ((a) < (b) ? (a) : (b))
67 struct btd_gatt_database {
68 struct btd_adapter *adapter;
75 struct queue *device_states;
76 struct queue *ccc_callbacks;
77 struct gatt_db_attribute *svc_chngd;
78 struct gatt_db_attribute *svc_chngd_ccc;
79 struct queue *services;
80 struct queue *profiles;
83 struct external_service {
84 struct btd_gatt_database *database;
87 char *path; /* Path to GattService1 */
91 struct gatt_db_attribute *attrib;
97 struct external_profile {
98 struct btd_gatt_database *database;
100 char *path; /* Path to GattProfile1 */
102 struct queue *profiles; /* btd_profile list */
105 struct external_chrc {
106 struct external_service *service;
111 struct gatt_db_attribute *attrib;
112 struct gatt_db_attribute *ccc;
113 struct queue *pending_reads;
114 struct queue *pending_writes;
115 unsigned int ntfy_cnt;
118 struct external_desc {
119 struct external_service *service;
123 struct gatt_db_attribute *attrib;
125 struct queue *pending_reads;
126 struct queue *pending_writes;
131 struct gatt_db_attribute *attrib;
132 struct queue *owner_queue;
136 struct device_state {
139 struct queue *ccc_states;
149 btd_gatt_database_ccc_write_t callback;
150 btd_gatt_database_destroy_t destroy;
159 static void ccc_cb_free(void *data)
161 struct ccc_cb_data *ccc_cb = data;
164 ccc_cb->destroy(ccc_cb->user_data);
169 static bool ccc_cb_match_service(const void *data, const void *match_data)
171 const struct ccc_cb_data *ccc_cb = data;
172 const struct gatt_db_attribute *attrib = match_data;
175 if (!gatt_db_attribute_get_service_handles(attrib, &start, &end))
178 return ccc_cb->handle >= start && ccc_cb->handle <= end;
181 static bool ccc_cb_match_handle(const void *data, const void *match_data)
183 const struct ccc_cb_data *ccc_cb = data;
184 uint16_t handle = PTR_TO_UINT(match_data);
186 return ccc_cb->handle == handle;
189 static bool dev_state_match(const void *a, const void *b)
191 const struct device_state *dev_state = a;
192 const struct device_info *dev_info = b;
194 return bacmp(&dev_state->bdaddr, &dev_info->bdaddr) == 0 &&
195 dev_state->bdaddr_type == dev_info->bdaddr_type;
198 static struct device_state *
199 find_device_state(struct btd_gatt_database *database, bdaddr_t *bdaddr,
202 struct device_info dev_info;
204 memset(&dev_info, 0, sizeof(dev_info));
206 bacpy(&dev_info.bdaddr, bdaddr);
207 dev_info.bdaddr_type = bdaddr_type;
209 return queue_find(database->device_states, dev_state_match, &dev_info);
212 static bool ccc_state_match(const void *a, const void *b)
214 const struct ccc_state *ccc = a;
215 uint16_t handle = PTR_TO_UINT(b);
217 return ccc->handle == handle;
220 static struct ccc_state *find_ccc_state(struct device_state *dev_state,
223 return queue_find(dev_state->ccc_states, ccc_state_match,
224 UINT_TO_PTR(handle));
227 static struct device_state *device_state_create(bdaddr_t *bdaddr,
230 struct device_state *dev_state;
232 dev_state = new0(struct device_state, 1);
236 dev_state->ccc_states = queue_new();
237 if (!dev_state->ccc_states) {
242 bacpy(&dev_state->bdaddr, bdaddr);
243 dev_state->bdaddr_type = bdaddr_type;
248 static struct device_state *get_device_state(struct btd_gatt_database *database,
252 struct device_state *dev_state;
255 * Find and return a device state. If a matching state doesn't exist,
256 * then create a new one.
258 dev_state = find_device_state(database, bdaddr, bdaddr_type);
262 dev_state = device_state_create(bdaddr, bdaddr_type);
266 queue_push_tail(database->device_states, dev_state);
271 static struct ccc_state *get_ccc_state(struct btd_gatt_database *database,
276 struct device_state *dev_state;
277 struct ccc_state *ccc;
279 dev_state = get_device_state(database, bdaddr, bdaddr_type);
283 ccc = find_ccc_state(dev_state, handle);
287 ccc = new0(struct ccc_state, 1);
291 ccc->handle = handle;
292 queue_push_tail(dev_state->ccc_states, ccc);
297 static void device_state_free(void *data)
299 struct device_state *state = data;
301 queue_destroy(state->ccc_states, free);
305 static void cancel_pending_read(void *data)
307 struct pending_op *op = data;
309 gatt_db_attribute_read_result(op->attrib, op->id,
310 BT_ATT_ERROR_REQUEST_NOT_SUPPORTED,
312 op->owner_queue = NULL;
315 static void cancel_pending_write(void *data)
317 struct pending_op *op = data;
319 gatt_db_attribute_write_result(op->attrib, op->id,
320 BT_ATT_ERROR_REQUEST_NOT_SUPPORTED);
321 op->owner_queue = NULL;
324 static void chrc_free(void *data)
326 struct external_chrc *chrc = data;
328 queue_destroy(chrc->pending_reads, cancel_pending_read);
329 queue_destroy(chrc->pending_writes, cancel_pending_write);
333 g_dbus_proxy_set_property_watch(chrc->proxy, NULL, NULL);
334 g_dbus_proxy_unref(chrc->proxy);
339 static void desc_free(void *data)
341 struct external_desc *desc = data;
343 queue_destroy(desc->pending_reads, cancel_pending_read);
344 queue_destroy(desc->pending_writes, cancel_pending_write);
346 g_dbus_proxy_unref(desc->proxy);
347 g_free(desc->chrc_path);
352 static void service_free(void *data)
354 struct external_service *service = data;
356 queue_destroy(service->chrcs, chrc_free);
357 queue_destroy(service->descs, desc_free);
359 gatt_db_remove_service(service->database->db, service->attrib);
361 if (service->client) {
362 g_dbus_client_set_disconnect_watch(service->client, NULL, NULL);
363 g_dbus_client_set_proxy_handlers(service->client, NULL, NULL,
365 g_dbus_client_set_ready_watch(service->client, NULL, NULL);
366 g_dbus_proxy_unref(service->proxy);
367 g_dbus_client_unref(service->client);
371 dbus_message_unref(service->reg);
373 g_free(service->owner);
374 g_free(service->path);
379 static void profile_remove(void *data)
381 struct btd_profile *p = data;
383 DBG("Removed \"%s\"", p->name);
385 adapter_foreach(adapter_remove_profile, p);
387 g_free((void *) p->name);
388 g_free((void *) p->remote_uuid);
393 static void profile_release(struct external_profile *profile)
400 DBG("Releasing \"%s\"", profile->owner);
402 g_dbus_remove_watch(btd_get_dbus_connection(), profile->id);
404 msg = dbus_message_new_method_call(profile->owner, profile->path,
405 "org.bluez.GattProfile1",
408 g_dbus_send_message(btd_get_dbus_connection(), msg);
411 static void profile_free(void *data)
413 struct external_profile *profile = data;
415 queue_destroy(profile->profiles, profile_remove);
417 profile_release(profile);
419 g_free(profile->owner);
420 g_free(profile->path);
425 static void gatt_database_free(void *data)
427 struct btd_gatt_database *database = data;
429 if (database->le_io) {
430 g_io_channel_shutdown(database->le_io, FALSE, NULL);
431 g_io_channel_unref(database->le_io);
434 if (database->l2cap_io) {
435 g_io_channel_shutdown(database->l2cap_io, FALSE, NULL);
436 g_io_channel_unref(database->l2cap_io);
439 if (database->gatt_handle)
440 adapter_service_remove(database->adapter,
441 database->gatt_handle);
443 if (database->gap_handle)
444 adapter_service_remove(database->adapter, database->gap_handle);
446 /* TODO: Persistently store CCC states before freeing them */
447 gatt_db_unregister(database->db, database->db_id);
449 queue_destroy(database->device_states, device_state_free);
450 queue_destroy(database->services, service_free);
451 queue_destroy(database->profiles, profile_free);
452 queue_destroy(database->ccc_callbacks, ccc_cb_free);
453 database->device_states = NULL;
454 database->ccc_callbacks = NULL;
456 gatt_db_unref(database->db);
458 btd_adapter_unref(database->adapter);
462 static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
464 struct btd_adapter *adapter;
465 struct btd_device *device;
469 DBG("New incoming LE ATT connection");
472 error("%s", gerr->message);
476 bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
477 BT_IO_OPT_DEST_BDADDR, &dst,
478 BT_IO_OPT_DEST_TYPE, &dst_type,
481 error("bt_io_get: %s", gerr->message);
486 adapter = adapter_find(&src);
490 device = btd_adapter_get_device(adapter, &dst, dst_type);
494 device_attach_att(device, io);
497 static void gap_device_name_read_cb(struct gatt_db_attribute *attrib,
498 unsigned int id, uint16_t offset,
499 uint8_t opcode, struct bt_att *att,
502 struct btd_gatt_database *database = user_data;
505 const uint8_t *value = NULL;
506 const char *device_name;
508 DBG("GAP Device Name read request\n");
510 device_name = btd_adapter_get_name(database->adapter);
511 len = strlen(device_name);
514 error = BT_ATT_ERROR_INVALID_OFFSET;
519 value = len ? (const uint8_t *) &device_name[offset] : NULL;
522 gatt_db_attribute_read_result(attrib, id, error, value, len);
525 static void gap_appearance_read_cb(struct gatt_db_attribute *attrib,
526 unsigned int id, uint16_t offset,
527 uint8_t opcode, struct bt_att *att,
530 struct btd_gatt_database *database = user_data;
533 const uint8_t *value = NULL;
534 uint8_t appearance[2];
537 DBG("GAP Appearance read request\n");
539 dev_class = btd_adapter_get_class(database->adapter);
542 error = BT_ATT_ERROR_INVALID_OFFSET;
546 appearance[0] = dev_class & 0x00ff;
547 appearance[1] = (dev_class >> 8) & 0x001f;
550 value = len ? &appearance[offset] : NULL;
553 gatt_db_attribute_read_result(attrib, id, error, value, len);
556 static sdp_record_t *record_new(uuid_t *uuid, uint16_t start, uint16_t end)
558 sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto;
559 uuid_t root_uuid, proto_uuid, l2cap;
560 sdp_record_t *record;
561 sdp_data_t *psm, *sh, *eh;
562 uint16_t lp = ATT_PSM;
570 record = sdp_record_alloc();
574 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
575 root = sdp_list_append(NULL, &root_uuid);
576 sdp_set_browse_groups(record, root);
577 sdp_list_free(root, NULL);
579 svclass_id = sdp_list_append(NULL, uuid);
580 sdp_set_service_classes(record, svclass_id);
581 sdp_list_free(svclass_id, NULL);
583 sdp_uuid16_create(&l2cap, L2CAP_UUID);
584 proto[0] = sdp_list_append(NULL, &l2cap);
585 psm = sdp_data_alloc(SDP_UINT16, &lp);
586 proto[0] = sdp_list_append(proto[0], psm);
587 apseq = sdp_list_append(NULL, proto[0]);
589 sdp_uuid16_create(&proto_uuid, ATT_UUID);
590 proto[1] = sdp_list_append(NULL, &proto_uuid);
591 sh = sdp_data_alloc(SDP_UINT16, &start);
592 proto[1] = sdp_list_append(proto[1], sh);
593 eh = sdp_data_alloc(SDP_UINT16, &end);
594 proto[1] = sdp_list_append(proto[1], eh);
595 apseq = sdp_list_append(apseq, proto[1]);
597 aproto = sdp_list_append(NULL, apseq);
598 sdp_set_access_protos(record, aproto);
603 sdp_list_free(proto[0], NULL);
604 sdp_list_free(proto[1], NULL);
605 sdp_list_free(apseq, NULL);
606 sdp_list_free(aproto, NULL);
611 static uint32_t database_add_record(struct btd_gatt_database *database,
613 struct gatt_db_attribute *attr,
616 sdp_record_t *record;
618 uuid_t svc, gap_uuid;
620 sdp_uuid16_create(&svc, uuid);
621 gatt_db_attribute_get_service_handles(attr, &start, &end);
623 record = record_new(&svc, start, end);
628 sdp_set_info_attr(record, name, "BlueZ", NULL);
630 sdp_uuid16_create(&gap_uuid, UUID_GAP);
631 if (sdp_uuid_cmp(&svc, &gap_uuid) == 0) {
632 sdp_set_url_attr(record, "http://www.bluez.org/",
633 "http://www.bluez.org/",
634 "http://www.bluez.org/");
637 if (adapter_service_add(database->adapter, record) == 0)
638 return record->handle;
640 sdp_record_free(record);
644 static void populate_gap_service(struct btd_gatt_database *database)
647 struct gatt_db_attribute *service;
649 /* Add the GAP service */
650 bt_uuid16_create(&uuid, UUID_GAP);
651 service = gatt_db_add_service(database->db, &uuid, true, 5);
652 database->gap_handle = database_add_record(database, UUID_GAP, service,
653 "Generic Access Profile");
656 * Device Name characteristic.
658 bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
659 gatt_db_service_add_characteristic(service, &uuid, BT_ATT_PERM_READ,
660 BT_GATT_CHRC_PROP_READ,
661 gap_device_name_read_cb,
665 * Device Appearance characteristic.
667 bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
668 gatt_db_service_add_characteristic(service, &uuid, BT_ATT_PERM_READ,
669 BT_GATT_CHRC_PROP_READ,
670 gap_appearance_read_cb,
673 gatt_db_service_set_active(service, true);
676 static bool get_dst_info(struct bt_att *att, bdaddr_t *dst, uint8_t *dst_type)
678 GIOChannel *io = NULL;
681 io = g_io_channel_unix_new(bt_att_get_fd(att));
685 bt_io_get(io, &gerr, BT_IO_OPT_DEST_BDADDR, dst,
686 BT_IO_OPT_DEST_TYPE, dst_type,
689 error("gatt: bt_io_get: %s", gerr->message);
691 g_io_channel_unref(io);
695 g_io_channel_unref(io);
699 static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
700 unsigned int id, uint16_t offset,
701 uint8_t opcode, struct bt_att *att,
704 struct btd_gatt_database *database = user_data;
705 struct ccc_state *ccc;
708 const uint8_t *value = NULL;
713 handle = gatt_db_attribute_get_handle(attrib);
715 DBG("CCC read called for handle: 0x%04x", handle);
718 ecode = BT_ATT_ERROR_INVALID_OFFSET;
722 if (!get_dst_info(att, &bdaddr, &bdaddr_type)) {
723 ecode = BT_ATT_ERROR_UNLIKELY;
727 ccc = get_ccc_state(database, &bdaddr, bdaddr_type, handle);
729 ecode = BT_ATT_ERROR_UNLIKELY;
734 value = len ? &ccc->value[offset] : NULL;
737 gatt_db_attribute_read_result(attrib, id, ecode, value, len);
740 static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
741 unsigned int id, uint16_t offset,
742 const uint8_t *value, size_t len,
743 uint8_t opcode, struct bt_att *att,
746 struct btd_gatt_database *database = user_data;
747 struct ccc_state *ccc;
748 struct ccc_cb_data *ccc_cb;
754 handle = gatt_db_attribute_get_handle(attrib);
756 DBG("CCC write called for handle: 0x%04x", handle);
758 if (!value || len != 2) {
759 ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
764 ecode = BT_ATT_ERROR_INVALID_OFFSET;
768 if (!get_dst_info(att, &bdaddr, &bdaddr_type)) {
769 ecode = BT_ATT_ERROR_UNLIKELY;
773 ccc = get_ccc_state(database, &bdaddr, bdaddr_type, handle);
775 ecode = BT_ATT_ERROR_UNLIKELY;
779 ccc_cb = queue_find(database->ccc_callbacks, ccc_cb_match_handle,
780 UINT_TO_PTR(gatt_db_attribute_get_handle(attrib)));
782 ecode = BT_ATT_ERROR_UNLIKELY;
786 /* If value is identical, then just succeed */
787 if (ccc->value[0] == value[0] && ccc->value[1] == value[1])
790 if (ccc_cb->callback)
791 ecode = ccc_cb->callback(get_le16(value), ccc_cb->user_data);
794 ccc->value[0] = value[0];
795 ccc->value[1] = value[1];
799 gatt_db_attribute_write_result(attrib, id, ecode);
802 static struct gatt_db_attribute *
803 service_add_ccc(struct gatt_db_attribute *service,
804 struct btd_gatt_database *database,
805 btd_gatt_database_ccc_write_t write_callback,
807 btd_gatt_database_destroy_t destroy)
809 struct gatt_db_attribute *ccc;
810 struct ccc_cb_data *ccc_cb;
813 ccc_cb = new0(struct ccc_cb_data, 1);
815 error("Could not allocate memory for callback data");
819 bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
820 ccc = gatt_db_service_add_descriptor(service, &uuid,
821 BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
822 gatt_ccc_read_cb, gatt_ccc_write_cb, database);
824 error("Failed to create CCC entry in database");
829 ccc_cb->handle = gatt_db_attribute_get_handle(ccc);
830 ccc_cb->callback = write_callback;
831 ccc_cb->destroy = destroy;
832 ccc_cb->user_data = user_data;
834 queue_push_tail(database->ccc_callbacks, ccc_cb);
839 struct gatt_db_attribute *
840 btd_gatt_database_add_ccc(struct btd_gatt_database *database,
841 uint16_t service_handle,
842 btd_gatt_database_ccc_write_t write_callback,
844 btd_gatt_database_destroy_t destroy)
846 struct gatt_db_attribute *service;
848 if (!database || !service_handle)
851 service = gatt_db_get_attribute(database->db, service_handle);
853 error("No service exists with handle: 0x%04x", service_handle);
857 return service_add_ccc(service, database, write_callback, user_data,
861 static void populate_gatt_service(struct btd_gatt_database *database)
864 struct gatt_db_attribute *service;
866 /* Add the GATT service */
867 bt_uuid16_create(&uuid, UUID_GATT);
868 service = gatt_db_add_service(database->db, &uuid, true, 4);
869 database->gatt_handle = database_add_record(database, UUID_GATT,
871 "Generic Attribute Profile");
873 bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
874 database->svc_chngd = gatt_db_service_add_characteristic(service, &uuid,
875 BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_INDICATE,
876 NULL, NULL, database);
878 database->svc_chngd_ccc = service_add_ccc(service, database, NULL, NULL,
881 gatt_db_service_set_active(service, true);
884 static void register_core_services(struct btd_gatt_database *database)
886 populate_gap_service(database);
887 populate_gatt_service(database);
891 struct btd_gatt_database *database;
892 uint16_t handle, ccc_handle;
893 const uint8_t *value;
898 static void conf_cb(void *user_data)
900 DBG("GATT server received confirmation");
903 static void send_notification_to_device(void *data, void *user_data)
905 struct device_state *device_state = data;
906 struct notify *notify = user_data;
907 struct ccc_state *ccc;
908 struct btd_device *device;
910 ccc = find_ccc_state(device_state, notify->ccc_handle);
914 if (!ccc->value[0] || (notify->indicate && !(ccc->value[0] & 0x02)))
917 device = btd_adapter_get_device(notify->database->adapter,
918 &device_state->bdaddr,
919 device_state->bdaddr_type);
924 * TODO: If the device is not connected but bonded, send the
925 * notification/indication when it becomes connected.
927 if (!notify->indicate) {
928 DBG("GATT server sending notification");
929 bt_gatt_server_send_notification(
930 btd_device_get_gatt_server(device),
931 notify->handle, notify->value,
936 DBG("GATT server sending indication");
937 bt_gatt_server_send_indication(btd_device_get_gatt_server(device),
940 notify->len, conf_cb,
944 static void send_notification_to_devices(struct btd_gatt_database *database,
945 uint16_t handle, const uint8_t *value,
946 uint16_t len, uint16_t ccc_handle,
949 struct notify notify;
951 memset(¬ify, 0, sizeof(notify));
953 notify.database = database;
954 notify.handle = handle;
955 notify.ccc_handle = ccc_handle;
956 notify.value = value;
958 notify.indicate = indicate;
960 queue_foreach(database->device_states, send_notification_to_device,
964 static void send_service_changed(struct btd_gatt_database *database,
965 struct gatt_db_attribute *attrib)
969 uint16_t handle, ccc_handle;
971 if (!gatt_db_attribute_get_service_handles(attrib, &start, &end)) {
972 error("Failed to obtain changed service handles");
976 handle = gatt_db_attribute_get_handle(database->svc_chngd);
977 ccc_handle = gatt_db_attribute_get_handle(database->svc_chngd_ccc);
979 if (!handle || !ccc_handle) {
980 error("Failed to obtain handles for \"Service Changed\""
985 put_le16(start, value);
986 put_le16(end, value + 2);
988 send_notification_to_devices(database, handle, value, sizeof(value),
992 static void gatt_db_service_added(struct gatt_db_attribute *attrib,
995 struct btd_gatt_database *database = user_data;
997 DBG("GATT Service added to local database");
999 send_service_changed(database, attrib);
1002 static bool ccc_match_service(const void *data, const void *match_data)
1004 const struct ccc_state *ccc = data;
1005 const struct gatt_db_attribute *attrib = match_data;
1006 uint16_t start, end;
1008 if (!gatt_db_attribute_get_service_handles(attrib, &start, &end))
1011 return ccc->handle >= start && ccc->handle <= end;
1014 static void remove_device_ccc(void *data, void *user_data)
1016 struct device_state *state = data;
1018 queue_remove_all(state->ccc_states, ccc_match_service, user_data, free);
1021 static void gatt_db_service_removed(struct gatt_db_attribute *attrib,
1024 struct btd_gatt_database *database = user_data;
1026 DBG("Local GATT service removed");
1028 send_service_changed(database, attrib);
1030 queue_foreach(database->device_states, remove_device_ccc, attrib);
1031 queue_remove_all(database->ccc_callbacks, ccc_cb_match_service, attrib,
1035 struct svc_match_data {
1040 static bool match_service(const void *a, const void *b)
1042 const struct external_service *service = a;
1043 const struct svc_match_data *data = b;
1045 return g_strcmp0(service->path, data->path) == 0 &&
1046 g_strcmp0(service->owner, data->sender) == 0;
1049 static gboolean service_free_idle_cb(void *data)
1056 static void service_remove_helper(void *data)
1058 struct external_service *service = data;
1060 queue_remove(service->database->services, service);
1063 * Do not run in the same loop, this may be a disconnect
1064 * watch call and GDBusClient should not be destroyed.
1066 g_idle_add(service_free_idle_cb, service);
1069 static void client_disconnect_cb(DBusConnection *conn, void *user_data)
1071 DBG("Client disconnected");
1073 service_remove_helper(user_data);
1076 static void service_remove(void *data)
1078 struct external_service *service = data;
1081 * Set callback to NULL to avoid potential race condition
1082 * when calling remove_service and GDBusClient unref.
1084 g_dbus_client_set_disconnect_watch(service->client, NULL, NULL);
1087 * Set proxy handlers to NULL, so that this gets called only once when
1088 * the first proxy that belongs to this service gets removed.
1090 g_dbus_client_set_proxy_handlers(service->client, NULL, NULL,
1093 service_remove_helper(service);
1096 static struct external_chrc *chrc_create(struct external_service *service,
1100 struct external_chrc *chrc;
1102 chrc = new0(struct external_chrc, 1);
1106 chrc->pending_reads = queue_new();
1107 if (!chrc->pending_reads) {
1112 chrc->pending_writes = queue_new();
1113 if (!chrc->pending_writes) {
1114 queue_destroy(chrc->pending_reads, NULL);
1119 chrc->path = g_strdup(path);
1121 queue_destroy(chrc->pending_reads, NULL);
1122 queue_destroy(chrc->pending_writes, NULL);
1127 chrc->service = service;
1128 chrc->proxy = g_dbus_proxy_ref(proxy);
1133 static struct external_desc *desc_create(struct external_service *service,
1135 const char *chrc_path)
1137 struct external_desc *desc;
1139 desc = new0(struct external_desc, 1);
1143 desc->pending_reads = queue_new();
1144 if (!desc->pending_reads) {
1149 desc->pending_writes = queue_new();
1150 if (!desc->pending_writes) {
1151 queue_destroy(desc->pending_reads, NULL);
1156 desc->chrc_path = g_strdup(chrc_path);
1157 if (!desc->chrc_path) {
1158 queue_destroy(desc->pending_reads, NULL);
1159 queue_destroy(desc->pending_writes, NULL);
1164 desc->service = service;
1165 desc->proxy = g_dbus_proxy_ref(proxy);
1170 static bool incr_attr_count(struct external_service *service, uint16_t incr)
1172 if (service->attr_cnt > UINT16_MAX - incr)
1175 service->attr_cnt += incr;
1180 static bool parse_path(GDBusProxy *proxy, const char *name, const char **path)
1182 DBusMessageIter iter;
1184 if (!g_dbus_proxy_get_property(proxy, name, &iter))
1187 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
1190 dbus_message_iter_get_basic(&iter, path);
1195 static bool check_service_path(GDBusProxy *proxy,
1196 struct external_service *service)
1198 const char *service_path;
1200 if (!parse_path(proxy, "Service", &service_path))
1203 return g_strcmp0(service_path, service->path) == 0;
1206 static bool parse_chrc_flags(DBusMessageIter *array, uint8_t *props,
1211 *props = *ext_props = 0;
1214 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_STRING)
1217 dbus_message_iter_get_basic(array, &flag);
1219 if (!strcmp("broadcast", flag))
1220 *props |= BT_GATT_CHRC_PROP_BROADCAST;
1221 else if (!strcmp("read", flag))
1222 *props |= BT_GATT_CHRC_PROP_READ;
1223 else if (!strcmp("write-without-response", flag))
1224 *props |= BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP;
1225 else if (!strcmp("write", flag))
1226 *props |= BT_GATT_CHRC_PROP_WRITE;
1227 else if (!strcmp("notify", flag))
1228 *props |= BT_GATT_CHRC_PROP_NOTIFY;
1229 else if (!strcmp("indicate", flag))
1230 *props |= BT_GATT_CHRC_PROP_INDICATE;
1231 else if (!strcmp("authenticated-signed-writes", flag))
1232 *props |= BT_GATT_CHRC_PROP_AUTH;
1233 else if (!strcmp("reliable-write", flag))
1234 *ext_props |= BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE;
1235 else if (!strcmp("writable-auxiliaries", flag))
1236 *ext_props |= BT_GATT_CHRC_EXT_PROP_WRITABLE_AUX;
1237 else if (!strcmp("encrypt-read", flag)) {
1238 *props |= BT_GATT_CHRC_PROP_READ;
1239 *ext_props |= BT_GATT_CHRC_EXT_PROP_ENC_READ;
1240 } else if (!strcmp("encrypt-write", flag)) {
1241 *props |= BT_GATT_CHRC_PROP_WRITE;
1242 *ext_props |= BT_GATT_CHRC_EXT_PROP_ENC_WRITE;
1243 } else if (!strcmp("encrypt-authenticated-read", flag)) {
1244 *props |= BT_GATT_CHRC_PROP_READ;
1245 *ext_props |= BT_GATT_CHRC_EXT_PROP_AUTH_READ;
1246 } else if (!strcmp("encrypt-authenticated-write", flag)) {
1247 *props |= BT_GATT_CHRC_PROP_WRITE;
1248 *ext_props |= BT_GATT_CHRC_EXT_PROP_AUTH_WRITE;
1250 error("Invalid characteristic flag: %s", flag);
1253 } while (dbus_message_iter_next(array));
1256 *props |= BT_GATT_CHRC_PROP_EXT_PROP;
1261 static bool parse_desc_flags(DBusMessageIter *array, uint32_t *perm)
1268 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_STRING)
1271 dbus_message_iter_get_basic(array, &flag);
1273 if (!strcmp("read", flag))
1274 *perm |= BT_ATT_PERM_READ;
1275 else if (!strcmp("write", flag))
1276 *perm |= BT_ATT_PERM_WRITE;
1277 else if (!strcmp("encrypt-read", flag))
1278 *perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_ENCRYPT;
1279 else if (!strcmp("encrypt-write", flag))
1280 *perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_ENCRYPT;
1281 else if (!strcmp("encrypt-authenticated-read", flag))
1282 *perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_AUTHEN;
1283 else if (!strcmp("encrypt-authenticated-write", flag))
1284 *perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_AUTHEN;
1286 error("Invalid descriptor flag: %s", flag);
1289 } while (dbus_message_iter_next(array));
1294 static bool parse_flags(GDBusProxy *proxy, uint8_t *props, uint8_t *ext_props,
1297 DBusMessageIter iter, array;
1299 if (!g_dbus_proxy_get_property(proxy, "Flags", &iter))
1302 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1305 dbus_message_iter_recurse(&iter, &array);
1308 return parse_desc_flags(&array, perm);
1310 return parse_chrc_flags(&array, props, ext_props);
1313 static void proxy_added_cb(GDBusProxy *proxy, void *user_data)
1315 struct external_service *service = user_data;
1316 const char *iface, *path;
1318 if (service->failed || service->attrib)
1321 iface = g_dbus_proxy_get_interface(proxy);
1322 path = g_dbus_proxy_get_path(proxy);
1324 if (!g_str_has_prefix(path, service->path))
1327 if (g_strcmp0(iface, GATT_SERVICE_IFACE) == 0) {
1332 * TODO: We may want to support adding included services in a
1335 if (g_strcmp0(path, service->path) != 0) {
1336 error("Multiple services added within hierarchy");
1337 service->failed = true;
1341 /* Add 1 for the service declaration */
1342 if (!incr_attr_count(service, 1)) {
1343 error("Failed to increment attribute count");
1344 service->failed = true;
1348 service->proxy = g_dbus_proxy_ref(proxy);
1349 } else if (g_strcmp0(iface, GATT_CHRC_IFACE) == 0) {
1350 struct external_chrc *chrc;
1352 if (g_strcmp0(path, service->path) == 0) {
1353 error("Characteristic path same as service path");
1354 service->failed = true;
1358 chrc = chrc_create(service, proxy, path);
1360 service->failed = true;
1365 * Add 2 for the characteristic declaration and the value
1368 if (!incr_attr_count(service, 2)) {
1369 error("Failed to increment attribute count");
1370 service->failed = true;
1375 * Parse characteristic flags (i.e. properties) here since they
1376 * are used to determine if any special descriptors should be
1379 if (!parse_flags(proxy, &chrc->props, &chrc->ext_props, NULL)) {
1380 error("Failed to parse characteristic properties");
1381 service->failed = true;
1385 if ((chrc->props & BT_GATT_CHRC_PROP_NOTIFY ||
1386 chrc->props & BT_GATT_CHRC_PROP_INDICATE) &&
1387 !incr_attr_count(service, 1)) {
1388 error("Failed to increment attribute count for CCC");
1389 service->failed = true;
1393 if (chrc->ext_props && !incr_attr_count(service, 1)) {
1394 error("Failed to increment attribute count for CEP");
1395 service->failed = true;
1399 queue_push_tail(service->chrcs, chrc);
1400 } else if (g_strcmp0(iface, GATT_DESC_IFACE) == 0) {
1401 struct external_desc *desc;
1402 const char *chrc_path;
1404 if (!parse_path(proxy, "Characteristic", &chrc_path)) {
1405 error("Failed to obtain characteristic path for "
1407 service->failed = true;
1411 desc = desc_create(service, proxy, chrc_path);
1413 service->failed = true;
1417 /* Add 1 for the descriptor attribute */
1418 if (!incr_attr_count(service, 1)) {
1419 error("Failed to increment attribute count");
1420 service->failed = true;
1425 * Parse descriptors flags here since they are used to
1426 * determine the permission the descriptor should have
1428 if (!parse_flags(proxy, NULL, NULL, &desc->perm)) {
1429 error("Failed to parse characteristic properties");
1430 service->failed = true;
1434 queue_push_tail(service->descs, desc);
1436 DBG("Ignoring unrelated interface: %s", iface);
1440 DBG("Object added to service - path: %s, iface: %s", path, iface);
1443 static void proxy_removed_cb(GDBusProxy *proxy, void *user_data)
1445 struct external_service *service = user_data;
1448 path = g_dbus_proxy_get_path(proxy);
1450 if (!g_str_has_prefix(path, service->path))
1453 DBG("Proxy removed - removing service: %s", service->path);
1455 service_remove(service);
1458 static bool parse_uuid(GDBusProxy *proxy, bt_uuid_t *uuid)
1460 DBusMessageIter iter;
1462 const char *uuidstr;
1464 if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
1467 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1470 dbus_message_iter_get_basic(&iter, &uuidstr);
1472 if (bt_string_to_uuid(uuid, uuidstr) < 0)
1475 /* GAP & GATT services are created and managed by BlueZ */
1476 bt_uuid16_create(&tmp, UUID_GAP);
1477 if (!bt_uuid_cmp(&tmp, uuid)) {
1478 error("GAP service must be handled by BlueZ");
1482 bt_uuid16_create(&tmp, UUID_GATT);
1483 if (!bt_uuid_cmp(&tmp, uuid)) {
1484 error("GATT service must be handled by BlueZ");
1491 static bool parse_primary(GDBusProxy *proxy, bool *primary)
1493 DBusMessageIter iter;
1496 if (!g_dbus_proxy_get_property(proxy, "Primary", &iter))
1499 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
1502 dbus_message_iter_get_basic(&iter, &val);
1509 static uint8_t dbus_error_to_att_ecode(const char *error_name)
1512 if (strcmp(error_name, "org.bluez.Error.Failed") == 0)
1513 return 0x80; /* For now return this "application error" */
1515 if (strcmp(error_name, "org.bluez.Error.NotSupported") == 0)
1516 return BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1518 if (strcmp(error_name, "org.bluez.Error.NotAuthorized") == 0)
1519 return BT_ATT_ERROR_AUTHORIZATION;
1521 if (strcmp(error_name, "org.bluez.Error.InvalidValueLength") == 0)
1522 return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
1524 if (strcmp(error_name, "org.bluez.Error.InProgress") == 0)
1525 return BT_ERROR_ALREADY_IN_PROGRESS;
1530 static void read_reply_cb(DBusMessage *message, void *user_data)
1532 struct pending_op *op = user_data;
1534 DBusMessageIter iter, array;
1536 uint8_t *value = NULL;
1539 if (!op->owner_queue) {
1540 DBG("Pending read was canceled when object got removed");
1544 dbus_error_init(&err);
1546 if (dbus_set_error_from_message(&err, message) == TRUE) {
1547 DBG("Failed to read value: %s: %s", err.name, err.message);
1548 ecode = dbus_error_to_att_ecode(err.name);
1549 ecode = ecode ? ecode : BT_ATT_ERROR_READ_NOT_PERMITTED;
1550 dbus_error_free(&err);
1554 dbus_message_iter_init(message, &iter);
1556 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
1558 * Return not supported for this, as the external app basically
1559 * doesn't properly support reading from this characteristic.
1561 ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1562 error("Invalid return value received for \"ReadValue\"");
1566 dbus_message_iter_recurse(&iter, &array);
1567 dbus_message_iter_get_fixed_array(&array, &value, &len);
1570 ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1576 /* Truncate the value if it's too large */
1577 len = MIN(BT_ATT_MAX_VALUE_LEN, len);
1578 value = len ? value : NULL;
1581 gatt_db_attribute_read_result(op->attrib, op->id, ecode, value, len);
1584 static void pending_op_free(void *data)
1586 struct pending_op *op = data;
1588 if (op->owner_queue)
1589 queue_remove(op->owner_queue, op);
1594 static struct pending_op *pending_read_new(struct queue *owner_queue,
1595 struct gatt_db_attribute *attrib,
1598 struct pending_op *op;
1600 op = new0(struct pending_op, 1);
1604 op->owner_queue = owner_queue;
1605 op->attrib = attrib;
1607 queue_push_tail(owner_queue, op);
1612 static void send_read(struct gatt_db_attribute *attrib, GDBusProxy *proxy,
1613 struct queue *owner_queue,
1616 struct pending_op *op;
1617 uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
1619 op = pending_read_new(owner_queue, attrib, id);
1621 error("Failed to allocate memory for pending read call");
1622 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
1626 if (g_dbus_proxy_method_call(proxy, "ReadValue", NULL, read_reply_cb,
1627 op, pending_op_free) == TRUE)
1630 pending_op_free(op);
1633 gatt_db_attribute_read_result(attrib, id, ecode, NULL, 0);
1636 static void write_setup_cb(DBusMessageIter *iter, void *user_data)
1638 struct pending_op *op = user_data;
1639 DBusMessageIter array;
1641 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &array);
1642 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
1643 &op->data.iov_base, op->data.iov_len);
1644 dbus_message_iter_close_container(iter, &array);
1647 static void write_reply_cb(DBusMessage *message, void *user_data)
1649 struct pending_op *op = user_data;
1651 DBusMessageIter iter;
1654 if (!op->owner_queue) {
1655 DBG("Pending write was canceled when object got removed");
1659 dbus_error_init(&err);
1661 if (dbus_set_error_from_message(&err, message) == TRUE) {
1662 DBG("Failed to write value: %s: %s", err.name, err.message);
1663 ecode = dbus_error_to_att_ecode(err.name);
1664 ecode = ecode ? ecode : BT_ATT_ERROR_WRITE_NOT_PERMITTED;
1665 dbus_error_free(&err);
1669 dbus_message_iter_init(message, &iter);
1670 if (dbus_message_iter_has_next(&iter)) {
1672 * Return not supported for this, as the external app basically
1673 * doesn't properly support the "WriteValue" API.
1675 ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1676 error("Invalid return value received for \"WriteValue\"");
1680 gatt_db_attribute_write_result(op->attrib, op->id, ecode);
1683 static struct pending_op *pending_write_new(struct queue *owner_queue,
1684 struct gatt_db_attribute *attrib,
1686 const uint8_t *value,
1689 struct pending_op *op;
1691 op = new0(struct pending_op, 1);
1695 op->data.iov_base = (uint8_t *) value;
1696 op->data.iov_len = len;
1698 op->owner_queue = owner_queue;
1699 op->attrib = attrib;
1701 queue_push_tail(owner_queue, op);
1706 static void send_write(struct gatt_db_attribute *attrib, GDBusProxy *proxy,
1707 struct queue *owner_queue,
1709 const uint8_t *value, size_t len)
1711 struct pending_op *op;
1712 uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
1714 op = pending_write_new(owner_queue, attrib, id, value, len);
1716 error("Failed to allocate memory for pending read call");
1717 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
1721 if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb,
1723 pending_op_free) == TRUE)
1726 pending_op_free(op);
1729 gatt_db_attribute_write_result(attrib, id, ecode);
1732 static uint32_t permissions_from_props(uint8_t props, uint8_t ext_props)
1736 if (props & BT_GATT_CHRC_PROP_WRITE ||
1737 props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP ||
1738 ext_props & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE ||
1739 ext_props & BT_GATT_CHRC_EXT_PROP_ENC_WRITE ||
1740 ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_WRITE)
1741 perm |= BT_ATT_PERM_WRITE;
1743 if (props & BT_GATT_CHRC_PROP_READ ||
1744 ext_props & BT_GATT_CHRC_EXT_PROP_ENC_READ ||
1745 ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_READ)
1746 perm |= BT_ATT_PERM_READ;
1748 if (ext_props & BT_GATT_CHRC_EXT_PROP_ENC_READ)
1749 perm |= BT_ATT_PERM_READ_ENCRYPT;
1751 if (ext_props & BT_GATT_CHRC_EXT_PROP_ENC_WRITE)
1752 perm |= BT_ATT_PERM_WRITE_ENCRYPT;
1754 if (ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_READ)
1755 perm |= BT_ATT_PERM_READ_AUTHEN;
1757 if (ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_WRITE)
1758 perm |= BT_ATT_PERM_WRITE_AUTHEN;
1763 static uint8_t ccc_write_cb(uint16_t value, void *user_data)
1765 struct external_chrc *chrc = user_data;
1767 DBG("External CCC write received with value: 0x%04x", value);
1769 /* Notifications/indications disabled */
1771 if (!chrc->ntfy_cnt)
1774 if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1))
1778 * Send request to stop notifying. This is best-effort
1779 * operation, so simply ignore the return the value.
1781 g_dbus_proxy_method_call(chrc->proxy, "StopNotify", NULL,
1787 * TODO: All of the errors below should fall into the so called
1788 * "Application Error" range. Since there is no well defined error for
1789 * these, we return a generic ATT protocol error for now.
1792 if (chrc->ntfy_cnt == UINT_MAX) {
1793 /* Maximum number of per-device CCC descriptors configured */
1794 return BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1797 /* Don't support undefined CCC values yet */
1799 (value == 1 && !(chrc->props & BT_GATT_CHRC_PROP_NOTIFY)) ||
1800 (value == 2 && !(chrc->props & BT_GATT_CHRC_PROP_INDICATE)))
1801 return BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1804 * Always call StartNotify for an incoming enable and ignore the return
1807 if (g_dbus_proxy_method_call(chrc->proxy,
1808 "StartNotify", NULL, NULL,
1809 NULL, NULL) == FALSE)
1810 return BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1812 __sync_fetch_and_add(&chrc->ntfy_cnt, 1);
1817 static void property_changed_cb(GDBusProxy *proxy, const char *name,
1818 DBusMessageIter *iter, void *user_data)
1820 struct external_chrc *chrc = user_data;
1821 DBusMessageIter array;
1822 uint8_t *value = NULL;
1825 if (strcmp(name, "Value"))
1828 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
1829 DBG("Malformed \"Value\" property received");
1833 dbus_message_iter_recurse(iter, &array);
1834 dbus_message_iter_get_fixed_array(&array, &value, &len);
1837 DBG("Malformed \"Value\" property received");
1841 /* Truncate the value if it's too large */
1842 len = MIN(BT_ATT_MAX_VALUE_LEN, len);
1843 value = len ? value : NULL;
1845 send_notification_to_devices(chrc->service->database,
1846 gatt_db_attribute_get_handle(chrc->attrib),
1848 gatt_db_attribute_get_handle(chrc->ccc),
1849 chrc->props & BT_GATT_CHRC_PROP_INDICATE);
1852 static bool database_add_ccc(struct external_service *service,
1853 struct external_chrc *chrc)
1855 if (!(chrc->props & BT_GATT_CHRC_PROP_NOTIFY) &&
1856 !(chrc->props & BT_GATT_CHRC_PROP_INDICATE))
1859 chrc->ccc = service_add_ccc(service->attrib, service->database,
1860 ccc_write_cb, chrc, NULL);
1862 error("Failed to create CCC entry for characteristic");
1866 if (g_dbus_proxy_set_property_watch(chrc->proxy, property_changed_cb,
1868 error("Failed to set up property watch for characteristic");
1872 DBG("Created CCC entry for characteristic");
1877 static void cep_write_cb(struct gatt_db_attribute *attrib, int err,
1881 DBG("Failed to store CEP value in the database");
1883 DBG("Stored CEP value in the database");
1886 static bool database_add_cep(struct external_service *service,
1887 struct external_chrc *chrc)
1889 struct gatt_db_attribute *cep;
1893 if (!chrc->ext_props)
1896 bt_uuid16_create(&uuid, GATT_CHARAC_EXT_PROPER_UUID);
1897 cep = gatt_db_service_add_descriptor(service->attrib, &uuid,
1901 error("Failed to create CEP entry for characteristic");
1905 memset(value, 0, sizeof(value));
1906 value[0] = chrc->ext_props;
1908 if (!gatt_db_attribute_write(cep, 0, value, sizeof(value), 0, NULL,
1909 cep_write_cb, NULL)) {
1910 DBG("Failed to store CEP value in the database");
1914 DBG("Created CEP entry for characteristic");
1919 static void desc_read_cb(struct gatt_db_attribute *attrib,
1920 unsigned int id, uint16_t offset,
1921 uint8_t opcode, struct bt_att *att,
1924 struct external_desc *desc = user_data;
1926 if (desc->attrib != attrib) {
1927 error("Read callback called with incorrect attribute");
1931 send_read(attrib, desc->proxy, desc->pending_reads, id);
1934 static void desc_write_cb(struct gatt_db_attribute *attrib,
1935 unsigned int id, uint16_t offset,
1936 const uint8_t *value, size_t len,
1937 uint8_t opcode, struct bt_att *att,
1940 struct external_desc *desc = user_data;
1942 if (desc->attrib != attrib) {
1943 error("Read callback called with incorrect attribute");
1947 send_write(attrib, desc->proxy, desc->pending_writes, id, value, len);
1950 static bool database_add_desc(struct external_service *service,
1951 struct external_desc *desc)
1955 if (!parse_uuid(desc->proxy, &uuid)) {
1956 error("Failed to read \"UUID\" property of descriptor");
1960 desc->attrib = gatt_db_service_add_descriptor(service->attrib, &uuid,
1963 desc_write_cb, desc);
1964 if (!desc->attrib) {
1965 error("Failed to create descriptor entry in database");
1969 desc->handled = true;
1974 static void chrc_read_cb(struct gatt_db_attribute *attrib,
1975 unsigned int id, uint16_t offset,
1976 uint8_t opcode, struct bt_att *att,
1979 struct external_chrc *chrc = user_data;
1981 if (chrc->attrib != attrib) {
1982 error("Read callback called with incorrect attribute");
1986 send_read(attrib, chrc->proxy, chrc->pending_reads, id);
1989 static void chrc_write_cb(struct gatt_db_attribute *attrib,
1990 unsigned int id, uint16_t offset,
1991 const uint8_t *value, size_t len,
1992 uint8_t opcode, struct bt_att *att,
1995 struct external_chrc *chrc = user_data;
1997 if (chrc->attrib != attrib) {
1998 error("Write callback called with incorrect attribute");
2002 send_write(attrib, chrc->proxy, chrc->pending_writes, id, value, len);
2005 static bool database_add_chrc(struct external_service *service,
2006 struct external_chrc *chrc)
2010 const struct queue_entry *entry;
2012 if (!parse_uuid(chrc->proxy, &uuid)) {
2013 error("Failed to read \"UUID\" property of characteristic");
2017 if (!check_service_path(chrc->proxy, service)) {
2018 error("Invalid service path for characteristic");
2023 * TODO: Once shared/gatt-server properly supports permission checks,
2024 * set the permissions based on a D-Bus property of the external
2027 perm = permissions_from_props(chrc->props, chrc->ext_props);
2028 chrc->attrib = gatt_db_service_add_characteristic(service->attrib,
2030 chrc->props, chrc_read_cb,
2031 chrc_write_cb, chrc);
2032 if (!chrc->attrib) {
2033 error("Failed to create characteristic entry in database");
2037 if (!database_add_ccc(service, chrc))
2040 if (!database_add_cep(service, chrc))
2043 /* Handle the descriptors that belong to this characteristic. */
2044 for (entry = queue_get_entries(service->descs); entry;
2045 entry = entry->next) {
2046 struct external_desc *desc = entry->data;
2048 if (desc->handled || g_strcmp0(desc->chrc_path, chrc->path))
2051 if (!database_add_desc(service, desc)) {
2052 chrc->attrib = NULL;
2053 error("Failed to create descriptor entry");
2061 static bool match_desc_unhandled(const void *a, const void *b)
2063 const struct external_desc *desc = a;
2065 return !desc->handled;
2068 static bool create_service_entry(struct external_service *service)
2072 const struct queue_entry *entry;
2074 if (!parse_uuid(service->proxy, &uuid)) {
2075 error("Failed to read \"UUID\" property of service");
2079 if (!parse_primary(service->proxy, &primary)) {
2080 error("Failed to read \"Primary\" property of service");
2084 service->attrib = gatt_db_add_service(service->database->db, &uuid,
2085 primary, service->attr_cnt);
2086 if (!service->attrib)
2089 entry = queue_get_entries(service->chrcs);
2091 struct external_chrc *chrc = entry->data;
2093 if (!database_add_chrc(service, chrc)) {
2094 error("Failed to add characteristic");
2098 entry = entry->next;
2101 /* If there are any unhandled descriptors, return an error */
2102 if (queue_find(service->descs, match_desc_unhandled, NULL)) {
2103 error("Found descriptor with no matching characteristic!");
2107 gatt_db_service_set_active(service->attrib, true);
2112 gatt_db_remove_service(service->database->db, service->attrib);
2113 service->attrib = NULL;
2118 static void client_ready_cb(GDBusClient *client, void *user_data)
2120 struct external_service *service = user_data;
2124 if (!service->proxy || service->failed) {
2125 error("No valid external GATT objects found");
2127 reply = btd_error_failed(service->reg,
2128 "No valid service object found");
2132 if (!create_service_entry(service)) {
2133 error("Failed to create GATT service entry in local database");
2135 reply = btd_error_failed(service->reg,
2136 "Failed to create entry in database");
2140 DBG("GATT service registered: %s", service->path);
2142 reply = dbus_message_new_method_return(service->reg);
2145 g_dbus_send_message(btd_get_dbus_connection(), reply);
2146 dbus_message_unref(service->reg);
2147 service->reg = NULL;
2150 service_remove(service);
2153 static struct external_service *service_create(DBusConnection *conn,
2154 DBusMessage *msg, const char *path)
2156 struct external_service *service;
2157 const char *sender = dbus_message_get_sender(msg);
2159 if (!path || !g_str_has_prefix(path, "/"))
2162 service = new0(struct external_service, 1);
2166 service->client = g_dbus_client_new_full(conn, sender, path, path);
2167 if (!service->client)
2170 service->owner = g_strdup(sender);
2171 if (!service->owner)
2174 service->path = g_strdup(path);
2178 service->chrcs = queue_new();
2179 if (!service->chrcs)
2182 service->descs = queue_new();
2183 if (!service->descs)
2186 service->reg = dbus_message_ref(msg);
2188 g_dbus_client_set_disconnect_watch(service->client,
2189 client_disconnect_cb, service);
2190 g_dbus_client_set_proxy_handlers(service->client, proxy_added_cb,
2191 proxy_removed_cb, NULL,
2193 g_dbus_client_set_ready_watch(service->client, client_ready_cb,
2199 service_free(service);
2203 static DBusMessage *manager_register_service(DBusConnection *conn,
2204 DBusMessage *msg, void *user_data)
2206 struct btd_gatt_database *database = user_data;
2207 const char *sender = dbus_message_get_sender(msg);
2208 DBusMessageIter args;
2210 struct external_service *service;
2211 struct svc_match_data match_data;
2213 if (!dbus_message_iter_init(msg, &args))
2214 return btd_error_invalid_args(msg);
2216 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
2217 return btd_error_invalid_args(msg);
2219 dbus_message_iter_get_basic(&args, &path);
2221 match_data.path = path;
2222 match_data.sender = sender;
2224 if (queue_find(database->services, match_service, &match_data))
2225 return btd_error_already_exists(msg);
2227 dbus_message_iter_next(&args);
2228 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
2229 return btd_error_invalid_args(msg);
2231 service = service_create(conn, msg, path);
2233 return btd_error_failed(msg, "Failed to register service");
2235 DBG("Registering service - path: %s", path);
2237 service->database = database;
2238 queue_push_tail(database->services, service);
2243 static DBusMessage *manager_unregister_service(DBusConnection *conn,
2244 DBusMessage *msg, void *user_data)
2246 struct btd_gatt_database *database = user_data;
2247 const char *sender = dbus_message_get_sender(msg);
2249 DBusMessageIter args;
2250 struct external_service *service;
2251 struct svc_match_data match_data;
2253 if (!dbus_message_iter_init(msg, &args))
2254 return btd_error_invalid_args(msg);
2256 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
2257 return btd_error_invalid_args(msg);
2259 dbus_message_iter_get_basic(&args, &path);
2261 match_data.path = path;
2262 match_data.sender = sender;
2264 service = queue_remove_if(database->services, match_service,
2267 return btd_error_does_not_exist(msg);
2269 service_free(service);
2271 return dbus_message_new_method_return(msg);
2274 static void profile_exited(DBusConnection *conn, void *user_data)
2276 struct external_profile *profile = user_data;
2278 DBG("\"%s\" exited", profile->owner);
2282 queue_remove(profile->database->profiles, profile);
2284 profile_free(profile);
2287 static int profile_add(struct external_profile *profile, const char *uuid)
2289 struct btd_profile *p;
2291 p = new0(struct btd_profile, 1);
2295 /* Assign directly to avoid having extra fields */
2296 p->name = (const void *) g_strdup_printf("%s%s/%s", profile->owner,
2297 profile->path, uuid);
2303 p->remote_uuid = (const void *) g_strdup(uuid);
2304 if (!p->remote_uuid) {
2305 g_free((void *) p->name);
2310 p->auto_connect = true;
2312 queue_push_tail(profile->profiles, p);
2314 DBG("Added \"%s\"", p->name);
2319 static void add_profile(void *data, void *user_data)
2321 struct btd_adapter *adapter = user_data;
2323 adapter_add_profile(adapter, data);
2326 static int profile_create(DBusConnection *conn,
2327 struct btd_gatt_database *database,
2328 const char *sender, const char *path,
2329 DBusMessageIter *iter)
2331 struct external_profile *profile;
2332 DBusMessageIter uuids;
2334 if (!path || !g_str_has_prefix(path, "/"))
2337 profile = new0(struct external_profile, 1);
2341 profile->owner = g_strdup(sender);
2342 if (!profile->owner)
2345 profile->path = g_strdup(path);
2349 profile->profiles = queue_new();
2350 if (!profile->profiles)
2353 profile->database = database;
2354 profile->id = g_dbus_add_disconnect_watch(conn, sender, profile_exited,
2357 dbus_message_iter_recurse(iter, &uuids);
2359 while (dbus_message_iter_get_arg_type(&uuids) == DBUS_TYPE_STRING) {
2362 dbus_message_iter_get_basic(&uuids, &uuid);
2364 if (profile_add(profile, uuid) < 0)
2367 dbus_message_iter_next(&uuids);
2370 if (queue_isempty(profile->profiles))
2373 queue_foreach(profile->profiles, add_profile, database->adapter);
2374 queue_push_tail(database->profiles, profile);
2379 profile_free(profile);
2383 static bool match_profile(const void *a, const void *b)
2385 const struct external_profile *profile = a;
2386 const struct svc_match_data *data = b;
2388 return g_strcmp0(profile->path, data->path) == 0 &&
2389 g_strcmp0(profile->owner, data->sender) == 0;
2392 static DBusMessage *manager_register_profile(DBusConnection *conn,
2393 DBusMessage *msg, void *user_data)
2395 struct btd_gatt_database *database = user_data;
2396 const char *sender = dbus_message_get_sender(msg);
2397 DBusMessageIter args;
2399 struct svc_match_data match_data;
2401 DBG("sender %s", sender);
2403 if (!dbus_message_iter_init(msg, &args))
2404 return btd_error_invalid_args(msg);
2406 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
2407 return btd_error_invalid_args(msg);
2409 dbus_message_iter_get_basic(&args, &path);
2411 match_data.path = path;
2412 match_data.sender = sender;
2414 if (queue_find(database->profiles, match_profile, &match_data))
2415 return btd_error_already_exists(msg);
2417 dbus_message_iter_next(&args);
2418 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
2419 return btd_error_invalid_args(msg);
2421 if (profile_create(conn, database, sender, path, &args) < 0)
2422 return btd_error_failed(msg, "Failed to register profile");
2424 return dbus_message_new_method_return(msg);
2427 static DBusMessage *manager_unregister_profile(DBusConnection *conn,
2428 DBusMessage *msg, void *user_data)
2430 struct btd_gatt_database *database = user_data;
2431 const char *sender = dbus_message_get_sender(msg);
2433 DBusMessageIter args;
2434 struct external_profile *profile;
2435 struct svc_match_data match_data;
2437 if (!dbus_message_iter_init(msg, &args))
2438 return btd_error_invalid_args(msg);
2440 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
2441 return btd_error_invalid_args(msg);
2443 dbus_message_iter_get_basic(&args, &path);
2445 match_data.path = path;
2446 match_data.sender = sender;
2448 profile = queue_remove_if(database->profiles, match_profile,
2451 return btd_error_does_not_exist(msg);
2453 profile_free(profile);
2455 return dbus_message_new_method_return(msg);
2458 static const GDBusMethodTable manager_methods[] = {
2459 { GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterService",
2460 GDBUS_ARGS({ "service", "o" }, { "options", "a{sv}" }),
2461 NULL, manager_register_service) },
2462 { GDBUS_EXPERIMENTAL_ASYNC_METHOD("UnregisterService",
2463 GDBUS_ARGS({ "service", "o" }),
2464 NULL, manager_unregister_service) },
2465 { GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterProfile",
2466 GDBUS_ARGS({ "profile", "o" }, { "UUIDs", "as" },
2467 { "options", "a{sv}" }), NULL,
2468 manager_register_profile) },
2469 { GDBUS_EXPERIMENTAL_ASYNC_METHOD("UnregisterProfile",
2470 GDBUS_ARGS({ "profile", "o" }),
2471 NULL, manager_unregister_profile) },
2475 struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
2477 struct btd_gatt_database *database;
2478 GError *gerr = NULL;
2479 const bdaddr_t *addr;
2484 database = new0(struct btd_gatt_database, 1);
2488 database->adapter = btd_adapter_ref(adapter);
2489 database->db = gatt_db_new();
2493 database->device_states = queue_new();
2494 if (!database->device_states)
2497 database->services = queue_new();
2498 if (!database->services)
2501 database->profiles = queue_new();
2502 if (!database->profiles)
2505 database->ccc_callbacks = queue_new();
2506 if (!database->ccc_callbacks)
2509 database->db_id = gatt_db_register(database->db, gatt_db_service_added,
2510 gatt_db_service_removed,
2512 if (!database->db_id)
2515 addr = btd_adapter_get_address(adapter);
2516 database->le_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
2517 BT_IO_OPT_SOURCE_BDADDR, addr,
2518 BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
2519 BT_IO_OPT_CID, ATT_CID,
2520 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
2522 if (!database->le_io) {
2523 error("Failed to start listening: %s", gerr->message);
2529 database->l2cap_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
2530 BT_IO_OPT_SOURCE_BDADDR, addr,
2531 BT_IO_OPT_PSM, ATT_PSM,
2532 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
2534 if (database->l2cap_io == NULL) {
2535 error("Failed to start listening: %s", gerr->message);
2540 if (g_dbus_register_interface(btd_get_dbus_connection(),
2541 adapter_get_path(adapter),
2543 manager_methods, NULL, NULL,
2545 DBG("GATT Manager registered for adapter: %s",
2546 adapter_get_path(adapter));
2548 register_core_services(database);
2553 gatt_database_free(database);
2558 void btd_gatt_database_destroy(struct btd_gatt_database *database)
2563 g_dbus_unregister_interface(btd_get_dbus_connection(),
2564 adapter_get_path(database->adapter),
2565 GATT_MANAGER_IFACE);
2567 gatt_database_free(database);
2570 struct gatt_db *btd_gatt_database_get_db(struct btd_gatt_database *database)
2575 return database->db;