Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / src / gatt-database.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2015  Google Inc.
6  *
7  *
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.
12  *
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.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <errno.h>
27
28 #include "lib/bluetooth.h"
29 #include "lib/sdp.h"
30 #include "lib/sdp_lib.h"
31 #include "lib/uuid.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"
39 #include "log.h"
40 #include "error.h"
41 #include "adapter.h"
42 #include "device.h"
43 #include "gatt-database.h"
44 #include "dbus-common.h"
45 #include "profile.h"
46 #include "service.h"
47
48 #ifndef ATT_CID
49 #define ATT_CID 4
50 #endif
51
52 #ifndef ATT_PSM
53 #define ATT_PSM 31
54 #endif
55
56 #define GATT_MANAGER_IFACE      "org.bluez.GattManager1"
57 #define GATT_SERVICE_IFACE      "org.bluez.GattService1"
58 #define GATT_CHRC_IFACE         "org.bluez.GattCharacteristic1"
59 #define GATT_DESC_IFACE         "org.bluez.GattDescriptor1"
60
61 #define UUID_GAP        0x1800
62 #define UUID_GATT       0x1801
63
64 #ifndef MIN
65 #define MIN(a, b) ((a) < (b) ? (a) : (b))
66 #endif
67
68 struct btd_gatt_database {
69         struct btd_adapter *adapter;
70         struct gatt_db *db;
71         unsigned int db_id;
72         GIOChannel *le_io;
73         GIOChannel *l2cap_io;
74         uint32_t gap_handle;
75         uint32_t gatt_handle;
76         struct queue *device_states;
77         struct queue *ccc_callbacks;
78         struct gatt_db_attribute *svc_chngd;
79         struct gatt_db_attribute *svc_chngd_ccc;
80         struct queue *apps;
81         struct queue *profiles;
82 };
83
84 struct gatt_app {
85         struct btd_gatt_database *database;
86         char *owner;
87         char *path;
88         DBusMessage *reg;
89         GDBusClient *client;
90         bool failed;
91         struct queue *services;
92 };
93
94 struct external_service {
95         struct gatt_app *app;
96         char *path;     /* Path to GattService1 */
97         GDBusProxy *proxy;
98         struct gatt_db_attribute *attrib;
99         uint16_t attr_cnt;
100         struct queue *chrcs;
101         struct queue *descs;
102 };
103
104 struct external_profile {
105         struct btd_gatt_database *database;
106         char *owner;
107         char *path;     /* Path to GattProfile1 */
108         unsigned int id;
109         struct queue *profiles; /* btd_profile list */
110 };
111
112 struct external_chrc {
113         struct external_service *service;
114         char *path;
115         GDBusProxy *proxy;
116         uint8_t props;
117         uint8_t ext_props;
118         struct gatt_db_attribute *attrib;
119         struct gatt_db_attribute *ccc;
120         struct queue *pending_reads;
121         struct queue *pending_writes;
122         unsigned int ntfy_cnt;
123 };
124
125 struct external_desc {
126         struct external_service *service;
127         char *chrc_path;
128         GDBusProxy *proxy;
129         uint32_t perm;
130         struct gatt_db_attribute *attrib;
131         bool handled;
132         struct queue *pending_reads;
133         struct queue *pending_writes;
134 };
135
136 struct pending_op {
137         unsigned int id;
138         struct gatt_db_attribute *attrib;
139         struct queue *owner_queue;
140         struct iovec data;
141 #ifdef __TIZEN_PATCH__
142         bdaddr_t bdaddr;
143         uint8_t bdaddr_type;
144 #endif
145 };
146
147 struct device_state {
148         bdaddr_t bdaddr;
149         uint8_t bdaddr_type;
150         struct queue *ccc_states;
151 };
152
153 struct ccc_state {
154         uint16_t handle;
155         uint8_t value[2];
156 };
157
158 struct ccc_cb_data {
159         uint16_t handle;
160         btd_gatt_database_ccc_write_t callback;
161         btd_gatt_database_destroy_t destroy;
162         void *user_data;
163 };
164
165 struct device_info {
166         bdaddr_t bdaddr;
167         uint8_t bdaddr_type;
168 };
169
170 static void ccc_cb_free(void *data)
171 {
172         struct ccc_cb_data *ccc_cb = data;
173
174         if (ccc_cb->destroy)
175                 ccc_cb->destroy(ccc_cb->user_data);
176
177         free(ccc_cb);
178 }
179
180 static bool ccc_cb_match_service(const void *data, const void *match_data)
181 {
182         const struct ccc_cb_data *ccc_cb = data;
183         const struct gatt_db_attribute *attrib = match_data;
184         uint16_t start, end;
185
186         if (!gatt_db_attribute_get_service_handles(attrib, &start, &end))
187                 return false;
188
189         return ccc_cb->handle >= start && ccc_cb->handle <= end;
190 }
191
192 static bool ccc_cb_match_handle(const void *data, const void *match_data)
193 {
194         const struct ccc_cb_data *ccc_cb = data;
195         uint16_t handle = PTR_TO_UINT(match_data);
196
197         return ccc_cb->handle == handle;
198 }
199
200 static bool dev_state_match(const void *a, const void *b)
201 {
202         const struct device_state *dev_state = a;
203         const struct device_info *dev_info = b;
204
205         return bacmp(&dev_state->bdaddr, &dev_info->bdaddr) == 0 &&
206                                 dev_state->bdaddr_type == dev_info->bdaddr_type;
207 }
208
209 static struct device_state *
210 find_device_state(struct btd_gatt_database *database, bdaddr_t *bdaddr,
211                                                         uint8_t bdaddr_type)
212 {
213         struct device_info dev_info;
214
215         memset(&dev_info, 0, sizeof(dev_info));
216
217         bacpy(&dev_info.bdaddr, bdaddr);
218         dev_info.bdaddr_type = bdaddr_type;
219
220         return queue_find(database->device_states, dev_state_match, &dev_info);
221 }
222
223 #ifdef __TIZEN_PATCH__
224 static bool dev_addr_match(const void *a, const void *b)
225 {
226         const struct device_state *dev_state = a;
227         const struct device_info *dev_info = b;
228
229         if (bacmp(&dev_state->bdaddr, &dev_info->bdaddr) == 0)
230                 return TRUE;
231
232         return FALSE;
233 }
234
235 static struct device_state *
236 find_device_state_from_address(struct btd_gatt_database *database, const bdaddr_t *bdaddr)
237 {
238         struct device_info dev_info;
239
240         memset(&dev_info, 0, sizeof(dev_info));
241
242         bacpy(&dev_info.bdaddr, bdaddr);
243
244         return queue_find(database->device_states, dev_addr_match, &dev_info);
245 }
246 #endif
247
248 static bool ccc_state_match(const void *a, const void *b)
249 {
250         const struct ccc_state *ccc = a;
251         uint16_t handle = PTR_TO_UINT(b);
252
253         return ccc->handle == handle;
254 }
255
256 static struct ccc_state *find_ccc_state(struct device_state *dev_state,
257                                                                 uint16_t handle)
258 {
259         return queue_find(dev_state->ccc_states, ccc_state_match,
260                                                         UINT_TO_PTR(handle));
261 }
262
263 static struct device_state *device_state_create(bdaddr_t *bdaddr,
264                                                         uint8_t bdaddr_type)
265 {
266         struct device_state *dev_state;
267
268         dev_state = new0(struct device_state, 1);
269         dev_state->ccc_states = queue_new();
270         bacpy(&dev_state->bdaddr, bdaddr);
271         dev_state->bdaddr_type = bdaddr_type;
272
273         return dev_state;
274 }
275
276 static struct device_state *get_device_state(struct btd_gatt_database *database,
277                                                         bdaddr_t *bdaddr,
278                                                         uint8_t bdaddr_type)
279 {
280         struct device_state *dev_state;
281
282         /*
283          * Find and return a device state. If a matching state doesn't exist,
284          * then create a new one.
285          */
286         dev_state = find_device_state(database, bdaddr, bdaddr_type);
287         if (dev_state)
288                 return dev_state;
289
290         dev_state = device_state_create(bdaddr, bdaddr_type);
291
292         queue_push_tail(database->device_states, dev_state);
293
294         return dev_state;
295 }
296
297 static struct ccc_state *get_ccc_state(struct btd_gatt_database *database,
298                                                         bdaddr_t *bdaddr,
299                                                         uint8_t bdaddr_type,
300                                                         uint16_t handle)
301 {
302         struct device_state *dev_state;
303         struct ccc_state *ccc;
304
305         dev_state = get_device_state(database, bdaddr, bdaddr_type);
306
307         ccc = find_ccc_state(dev_state, handle);
308         if (ccc)
309                 return ccc;
310
311         ccc = new0(struct ccc_state, 1);
312         ccc->handle = handle;
313         queue_push_tail(dev_state->ccc_states, ccc);
314
315         return ccc;
316 }
317
318 static void device_state_free(void *data)
319 {
320         struct device_state *state = data;
321
322         queue_destroy(state->ccc_states, free);
323         free(state);
324 }
325
326 static void cancel_pending_read(void *data)
327 {
328         struct pending_op *op = data;
329
330         gatt_db_attribute_read_result(op->attrib, op->id,
331                                         BT_ATT_ERROR_REQUEST_NOT_SUPPORTED,
332                                         NULL, 0);
333         op->owner_queue = NULL;
334 }
335
336 static void cancel_pending_write(void *data)
337 {
338         struct pending_op *op = data;
339
340         gatt_db_attribute_write_result(op->attrib, op->id,
341                                         BT_ATT_ERROR_REQUEST_NOT_SUPPORTED);
342         op->owner_queue = NULL;
343 }
344
345 static void chrc_free(void *data)
346 {
347         struct external_chrc *chrc = data;
348
349         queue_destroy(chrc->pending_reads, cancel_pending_read);
350         queue_destroy(chrc->pending_writes, cancel_pending_write);
351
352         g_free(chrc->path);
353
354         g_dbus_proxy_set_property_watch(chrc->proxy, NULL, NULL);
355         g_dbus_proxy_unref(chrc->proxy);
356
357         free(chrc);
358 }
359
360 static void desc_free(void *data)
361 {
362         struct external_desc *desc = data;
363
364         queue_destroy(desc->pending_reads, cancel_pending_read);
365         queue_destroy(desc->pending_writes, cancel_pending_write);
366
367         g_dbus_proxy_unref(desc->proxy);
368         g_free(desc->chrc_path);
369
370         free(desc);
371 }
372
373 static void service_free(void *data)
374 {
375         struct external_service *service = data;
376
377         queue_destroy(service->chrcs, chrc_free);
378         queue_destroy(service->descs, desc_free);
379
380         if (service->attrib)
381                 gatt_db_remove_service(service->app->database->db,
382                                                         service->attrib);
383
384         if (service->app->client)
385                 g_dbus_proxy_unref(service->proxy);
386
387         g_free(service->path);
388
389         free(service);
390 }
391
392 static void app_free(void *data)
393 {
394         struct gatt_app *app = data;
395
396         queue_destroy(app->services, service_free);
397
398         if (app->client) {
399                 g_dbus_client_set_disconnect_watch(app->client, NULL, NULL);
400                 g_dbus_client_set_proxy_handlers(app->client, NULL, NULL,
401                                                                 NULL, NULL);
402                 g_dbus_client_set_ready_watch(app->client, NULL, NULL);
403                 g_dbus_client_unref(app->client);
404         }
405
406         if (app->reg)
407                 dbus_message_unref(app->reg);
408
409         g_free(app->owner);
410         g_free(app->path);
411
412         free(app);
413 }
414
415 static void profile_remove(void *data)
416 {
417         struct btd_profile *p = data;
418
419         DBG("Removed \"%s\"", p->name);
420
421         adapter_foreach(adapter_remove_profile, p);
422         btd_profile_unregister(p);
423
424         g_free((void *) p->name);
425         g_free((void *) p->remote_uuid);
426
427         free(p);
428 }
429
430 static void profile_release(struct external_profile *profile)
431 {
432         DBusMessage *msg;
433
434         if (!profile->id)
435                 return;
436
437         DBG("Releasing \"%s\"", profile->owner);
438
439         g_dbus_remove_watch(btd_get_dbus_connection(), profile->id);
440
441         msg = dbus_message_new_method_call(profile->owner, profile->path,
442                                                 "org.bluez.GattProfile1",
443                                                 "Release");
444         if (msg)
445                 g_dbus_send_message(btd_get_dbus_connection(), msg);
446 }
447
448 static void profile_free(void *data)
449 {
450         struct external_profile *profile = data;
451
452         queue_destroy(profile->profiles, profile_remove);
453
454         profile_release(profile);
455
456         g_free(profile->owner);
457         g_free(profile->path);
458
459         free(profile);
460 }
461
462 static void gatt_database_free(void *data)
463 {
464         struct btd_gatt_database *database = data;
465
466         if (database->le_io) {
467                 g_io_channel_shutdown(database->le_io, FALSE, NULL);
468                 g_io_channel_unref(database->le_io);
469         }
470
471         if (database->l2cap_io) {
472                 g_io_channel_shutdown(database->l2cap_io, FALSE, NULL);
473                 g_io_channel_unref(database->l2cap_io);
474         }
475
476         if (database->gatt_handle)
477                 adapter_service_remove(database->adapter,
478                                                         database->gatt_handle);
479
480         if (database->gap_handle)
481                 adapter_service_remove(database->adapter, database->gap_handle);
482
483         /* TODO: Persistently store CCC states before freeing them */
484         gatt_db_unregister(database->db, database->db_id);
485
486         queue_destroy(database->device_states, device_state_free);
487         queue_destroy(database->apps, app_free);
488         queue_destroy(database->profiles, profile_free);
489         queue_destroy(database->ccc_callbacks, ccc_cb_free);
490         database->device_states = NULL;
491         database->ccc_callbacks = NULL;
492
493         gatt_db_unref(database->db);
494
495         btd_adapter_unref(database->adapter);
496         free(database);
497 }
498
499 static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
500 {
501         struct btd_adapter *adapter;
502         struct btd_device *device;
503         uint8_t dst_type;
504         bdaddr_t src, dst;
505
506         DBG("New incoming LE ATT connection");
507
508         if (gerr) {
509                 error("%s", gerr->message);
510                 return;
511         }
512
513         bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
514                                                 BT_IO_OPT_DEST_BDADDR, &dst,
515                                                 BT_IO_OPT_DEST_TYPE, &dst_type,
516                                                 BT_IO_OPT_INVALID);
517         if (gerr) {
518                 error("bt_io_get: %s", gerr->message);
519                 g_error_free(gerr);
520                 return;
521         }
522
523         adapter = adapter_find(&src);
524         if (!adapter)
525                 return;
526
527         device = btd_adapter_get_device(adapter, &dst, dst_type);
528         if (!device)
529                 return;
530
531         device_attach_att(device, io);
532 }
533
534 #ifdef __TIZEN_PATCH__
535 #define LE_BEARER_POSTFIX       " LE"
536 #define LE_BEARER_POSTFIX_LEN   3
537
538 static bool get_dst_info(struct bt_att *att, bdaddr_t *dst, uint8_t *dst_type);
539 #endif
540
541 static void gap_device_name_read_cb(struct gatt_db_attribute *attrib,
542                                         unsigned int id, uint16_t offset,
543                                         uint8_t opcode, struct bt_att *att,
544                                         void *user_data)
545 {
546         struct btd_gatt_database *database = user_data;
547         uint8_t error = 0;
548         size_t len = 0;
549         const uint8_t *value = NULL;
550         const char *device_name;
551 #ifdef __TIZEN_PATCH__
552         bdaddr_t dst = { { 0 } };
553         uint8_t dst_type = 0;
554         char le_name[MAX_NAME_LENGTH + 1];
555 #endif
556
557         DBG("GAP Device Name read request\n");
558
559         device_name = btd_adapter_get_name(database->adapter);
560 #ifdef __TIZEN_PATCH__
561         if (get_dst_info(att, &dst, &dst_type) && dst_type != BDADDR_BREDR) {
562                 char *ptr = NULL;
563
564                 g_strlcpy(le_name, device_name,
565                                 sizeof(le_name) - LE_BEARER_POSTFIX_LEN);
566                 if (!g_utf8_validate(le_name, -1, (const char **)&ptr))
567                         *ptr = '\0';
568
569                 g_strlcat(le_name, LE_BEARER_POSTFIX, sizeof(le_name));
570                 DBG("Append LE bearer postfix : %s", le_name);
571
572                 device_name = le_name;
573         }
574 #endif
575         len = strlen(device_name);
576
577         if (offset > len) {
578                 error = BT_ATT_ERROR_INVALID_OFFSET;
579                 goto done;
580         }
581
582         len -= offset;
583         value = len ? (const uint8_t *) &device_name[offset] : NULL;
584
585 done:
586         gatt_db_attribute_read_result(attrib, id, error, value, len);
587 }
588
589 static void gap_appearance_read_cb(struct gatt_db_attribute *attrib,
590                                         unsigned int id, uint16_t offset,
591                                         uint8_t opcode, struct bt_att *att,
592                                         void *user_data)
593 {
594         struct btd_gatt_database *database = user_data;
595         uint8_t error = 0;
596         size_t len = 2;
597         const uint8_t *value = NULL;
598         uint8_t appearance[2];
599         uint32_t dev_class;
600
601         DBG("GAP Appearance read request\n");
602
603         dev_class = btd_adapter_get_class(database->adapter);
604
605         if (offset > 2) {
606                 error = BT_ATT_ERROR_INVALID_OFFSET;
607                 goto done;
608         }
609
610         appearance[0] = dev_class & 0x00ff;
611         appearance[1] = (dev_class >> 8) & 0x001f;
612
613         len -= offset;
614         value = len ? &appearance[offset] : NULL;
615
616 done:
617         gatt_db_attribute_read_result(attrib, id, error, value, len);
618 }
619
620 #ifdef __TIZEN_PATCH__
621 static void gap_rpa_res_support_read_cb(struct gatt_db_attribute *attrib,
622                                         unsigned int id, uint16_t offset,
623                                         uint8_t opcode, struct bt_att *att,
624                                         void *user_data)
625 {
626         struct btd_gatt_database *database = user_data;
627         uint8_t error = 0;
628         size_t len = 1;
629         const uint8_t *value = NULL;
630         uint8_t rpa_res_support = 0x00;
631
632         rpa_res_support = btd_adapter_get_rpa_res_support_value(database->adapter);
633
634         if (offset > 1) {
635                 error = BT_ATT_ERROR_INVALID_OFFSET;
636                 goto done;
637         }
638
639         len -= offset;
640         value = len ? &rpa_res_support : NULL;
641
642 done:
643         gatt_db_attribute_read_result(attrib, id, error, value, len);
644 }
645 #endif
646
647 static sdp_record_t *record_new(uuid_t *uuid, uint16_t start, uint16_t end)
648 {
649         sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto;
650         uuid_t root_uuid, proto_uuid, l2cap;
651         sdp_record_t *record;
652         sdp_data_t *psm, *sh, *eh;
653         uint16_t lp = ATT_PSM;
654
655         if (uuid == NULL)
656                 return NULL;
657
658         if (start > end)
659                 return NULL;
660
661         record = sdp_record_alloc();
662         if (record == NULL)
663                 return NULL;
664
665         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
666         root = sdp_list_append(NULL, &root_uuid);
667         sdp_set_browse_groups(record, root);
668         sdp_list_free(root, NULL);
669
670         svclass_id = sdp_list_append(NULL, uuid);
671         sdp_set_service_classes(record, svclass_id);
672         sdp_list_free(svclass_id, NULL);
673
674         sdp_uuid16_create(&l2cap, L2CAP_UUID);
675         proto[0] = sdp_list_append(NULL, &l2cap);
676         psm = sdp_data_alloc(SDP_UINT16, &lp);
677         proto[0] = sdp_list_append(proto[0], psm);
678         apseq = sdp_list_append(NULL, proto[0]);
679
680         sdp_uuid16_create(&proto_uuid, ATT_UUID);
681         proto[1] = sdp_list_append(NULL, &proto_uuid);
682         sh = sdp_data_alloc(SDP_UINT16, &start);
683         proto[1] = sdp_list_append(proto[1], sh);
684         eh = sdp_data_alloc(SDP_UINT16, &end);
685         proto[1] = sdp_list_append(proto[1], eh);
686         apseq = sdp_list_append(apseq, proto[1]);
687
688         aproto = sdp_list_append(NULL, apseq);
689         sdp_set_access_protos(record, aproto);
690
691         sdp_data_free(psm);
692         sdp_data_free(sh);
693         sdp_data_free(eh);
694         sdp_list_free(proto[0], NULL);
695         sdp_list_free(proto[1], NULL);
696         sdp_list_free(apseq, NULL);
697         sdp_list_free(aproto, NULL);
698
699         return record;
700 }
701
702 static uint32_t database_add_record(struct btd_gatt_database *database,
703                                         uint16_t uuid,
704                                         struct gatt_db_attribute *attr,
705                                         const char *name)
706 {
707         sdp_record_t *record;
708         uint16_t start, end;
709         uuid_t svc, gap_uuid;
710
711         sdp_uuid16_create(&svc, uuid);
712         gatt_db_attribute_get_service_handles(attr, &start, &end);
713
714         record = record_new(&svc, start, end);
715         if (!record)
716                 return 0;
717
718         if (name != NULL)
719                 sdp_set_info_attr(record, name, "BlueZ", NULL);
720
721         sdp_uuid16_create(&gap_uuid, UUID_GAP);
722         if (sdp_uuid_cmp(&svc, &gap_uuid) == 0) {
723                 sdp_set_url_attr(record, "http://www.bluez.org/",
724                                 "http://www.bluez.org/",
725                                 "http://www.bluez.org/");
726         }
727
728         if (adapter_service_add(database->adapter, record) == 0)
729                 return record->handle;
730
731         sdp_record_free(record);
732         return 0;
733 }
734
735 static void populate_gap_service(struct btd_gatt_database *database)
736 {
737         bt_uuid_t uuid;
738         struct gatt_db_attribute *service;
739
740         /* Add the GAP service */
741         bt_uuid16_create(&uuid, UUID_GAP);
742
743 #ifndef __TIZEN_PATCH__
744         service = gatt_db_add_service(database->db, &uuid, true, 5);
745 #else
746         service = gatt_db_add_service(database->db, &uuid, true, 7);
747 #endif
748
749         database->gap_handle = database_add_record(database, UUID_GAP, service,
750                                                 "Generic Access Profile");
751
752         /*
753          * Device Name characteristic.
754          */
755         bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
756         gatt_db_service_add_characteristic(service, &uuid, BT_ATT_PERM_READ,
757                                                         BT_GATT_CHRC_PROP_READ,
758                                                         gap_device_name_read_cb,
759                                                         NULL, database);
760
761         /*
762          * Device Appearance characteristic.
763          */
764         bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
765         gatt_db_service_add_characteristic(service, &uuid, BT_ATT_PERM_READ,
766                                                         BT_GATT_CHRC_PROP_READ,
767                                                         gap_appearance_read_cb,
768                                                         NULL, database);
769
770 #ifdef __TIZEN_PATCH__
771         /* Central address resolution characteristic */
772         bt_uuid16_create(&uuid, GATT_CHARAC_CENTRAL_RPA_RESOLUTION);
773         gatt_db_service_add_characteristic(service, &uuid, BT_ATT_PERM_READ,
774                                                         BT_GATT_CHRC_PROP_READ,
775                                                         gap_rpa_res_support_read_cb,
776                                                         NULL, database);
777 #endif
778
779         gatt_db_service_set_active(service, true);
780 }
781
782 static bool get_dst_info(struct bt_att *att, bdaddr_t *dst, uint8_t *dst_type)
783 {
784         GIOChannel *io = NULL;
785         GError *gerr = NULL;
786
787         io = g_io_channel_unix_new(bt_att_get_fd(att));
788         if (!io)
789                 return false;
790
791         bt_io_get(io, &gerr, BT_IO_OPT_DEST_BDADDR, dst,
792                                                 BT_IO_OPT_DEST_TYPE, dst_type,
793                                                 BT_IO_OPT_INVALID);
794         if (gerr) {
795                 error("gatt: bt_io_get: %s", gerr->message);
796                 g_error_free(gerr);
797                 g_io_channel_unref(io);
798                 return false;
799         }
800
801         g_io_channel_unref(io);
802         return true;
803 }
804
805 static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
806                                         unsigned int id, uint16_t offset,
807                                         uint8_t opcode, struct bt_att *att,
808                                         void *user_data)
809 {
810         struct btd_gatt_database *database = user_data;
811         struct ccc_state *ccc;
812         uint16_t handle;
813         uint8_t ecode = 0;
814         const uint8_t *value = NULL;
815         size_t len = 0;
816         bdaddr_t bdaddr;
817         uint8_t bdaddr_type;
818
819         handle = gatt_db_attribute_get_handle(attrib);
820
821         DBG("CCC read called for handle: 0x%04x", handle);
822
823         if (offset > 2) {
824                 ecode = BT_ATT_ERROR_INVALID_OFFSET;
825                 goto done;
826         }
827
828         if (!get_dst_info(att, &bdaddr, &bdaddr_type)) {
829                 ecode = BT_ATT_ERROR_UNLIKELY;
830                 goto done;
831         }
832
833         ccc = get_ccc_state(database, &bdaddr, bdaddr_type, handle);
834
835         len = 2 - offset;
836         value = len ? &ccc->value[offset] : NULL;
837
838 done:
839         gatt_db_attribute_read_result(attrib, id, ecode, value, len);
840 }
841
842 static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
843                                         unsigned int id, uint16_t offset,
844                                         const uint8_t *value, size_t len,
845                                         uint8_t opcode, struct bt_att *att,
846                                         void *user_data)
847 {
848         struct btd_gatt_database *database = user_data;
849         struct ccc_state *ccc;
850         struct ccc_cb_data *ccc_cb;
851         uint16_t handle;
852         uint8_t ecode = 0;
853         bdaddr_t bdaddr;
854         uint8_t bdaddr_type;
855
856         handle = gatt_db_attribute_get_handle(attrib);
857
858         DBG("CCC write called for handle: 0x%04x", handle);
859
860         if (!value || len != 2) {
861                 ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
862                 goto done;
863         }
864
865         if (offset > 2) {
866                 ecode = BT_ATT_ERROR_INVALID_OFFSET;
867                 goto done;
868         }
869
870         if (!get_dst_info(att, &bdaddr, &bdaddr_type)) {
871                 ecode = BT_ATT_ERROR_UNLIKELY;
872                 goto done;
873         }
874
875         ccc = get_ccc_state(database, &bdaddr, bdaddr_type, handle);
876
877         ccc_cb = queue_find(database->ccc_callbacks, ccc_cb_match_handle,
878                         UINT_TO_PTR(gatt_db_attribute_get_handle(attrib)));
879         if (!ccc_cb) {
880                 ecode = BT_ATT_ERROR_UNLIKELY;
881                 goto done;
882         }
883
884         /* If value is identical, then just succeed */
885         if (ccc->value[0] == value[0] && ccc->value[1] == value[1])
886                 goto done;
887
888         if (ccc_cb->callback)
889                 ecode = ccc_cb->callback(get_le16(value), ccc_cb->user_data);
890
891         if (!ecode) {
892                 ccc->value[0] = value[0];
893                 ccc->value[1] = value[1];
894         }
895
896 done:
897         gatt_db_attribute_write_result(attrib, id, ecode);
898 }
899
900 static struct gatt_db_attribute *
901 service_add_ccc(struct gatt_db_attribute *service,
902                                 struct btd_gatt_database *database,
903                                 btd_gatt_database_ccc_write_t write_callback,
904                                 void *user_data,
905                                 btd_gatt_database_destroy_t destroy)
906 {
907         struct gatt_db_attribute *ccc;
908         struct ccc_cb_data *ccc_cb;
909         bt_uuid_t uuid;
910
911         ccc_cb = new0(struct ccc_cb_data, 1);
912
913         bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
914         ccc = gatt_db_service_add_descriptor(service, &uuid,
915                                 BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
916                                 gatt_ccc_read_cb, gatt_ccc_write_cb, database);
917         if (!ccc) {
918                 error("Failed to create CCC entry in database");
919                 free(ccc_cb);
920                 return NULL;
921         }
922
923         ccc_cb->handle = gatt_db_attribute_get_handle(ccc);
924         ccc_cb->callback = write_callback;
925         ccc_cb->destroy = destroy;
926         ccc_cb->user_data = user_data;
927
928         queue_push_tail(database->ccc_callbacks, ccc_cb);
929
930         return ccc;
931 }
932
933 struct gatt_db_attribute *
934 btd_gatt_database_add_ccc(struct btd_gatt_database *database,
935                                 uint16_t service_handle,
936                                 btd_gatt_database_ccc_write_t write_callback,
937                                 void *user_data,
938                                 btd_gatt_database_destroy_t destroy)
939 {
940         struct gatt_db_attribute *service;
941
942         if (!database || !service_handle)
943                 return NULL;
944
945         service = gatt_db_get_attribute(database->db, service_handle);
946         if (!service) {
947                 error("No service exists with handle: 0x%04x", service_handle);
948                 return NULL;
949         }
950
951         return service_add_ccc(service, database, write_callback, user_data,
952                                                                 destroy);
953 }
954
955 static void populate_gatt_service(struct btd_gatt_database *database)
956 {
957         bt_uuid_t uuid;
958         struct gatt_db_attribute *service;
959
960         /* Add the GATT service */
961         bt_uuid16_create(&uuid, UUID_GATT);
962         service = gatt_db_add_service(database->db, &uuid, true, 4);
963         database->gatt_handle = database_add_record(database, UUID_GATT,
964                                                 service,
965                                                 "Generic Attribute Profile");
966
967         bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
968         database->svc_chngd = gatt_db_service_add_characteristic(service, &uuid,
969                                 BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_INDICATE,
970                                 NULL, NULL, database);
971
972         database->svc_chngd_ccc = service_add_ccc(service, database, NULL, NULL,
973                                                                         NULL);
974
975         gatt_db_service_set_active(service, true);
976 }
977
978 static void register_core_services(struct btd_gatt_database *database)
979 {
980         populate_gap_service(database);
981         populate_gatt_service(database);
982 }
983
984 struct notify {
985         struct btd_gatt_database *database;
986         uint16_t handle, ccc_handle;
987         const uint8_t *value;
988         uint16_t len;
989         bool indicate;
990 };
991
992 #ifdef __TIZEN_PATCH__
993 struct notify_indicate {
994         struct btd_gatt_database *database;
995         GDBusProxy *proxy;
996         uint16_t handle, ccc_handle;
997         const uint8_t *value;
998         uint16_t len;
999         bool indicate;
1000 };
1001
1002 struct notify_indicate_cb {
1003         GDBusProxy *proxy;
1004         struct btd_device *device;
1005 };
1006
1007 static void indicate_confirm_free(void *data)
1008 {
1009         struct notify_indicate_cb *indicate = data;
1010
1011         if (indicate)
1012                 free(indicate);
1013 }
1014
1015 static void indicate_confirm_setup_cb(DBusMessageIter *iter, void *user_data)
1016 {
1017         struct btd_device *device = user_data;
1018         char dstaddr[18] = { 0 };
1019         char *addr_value = NULL;
1020         gboolean complete = FALSE;
1021
1022         ba2str(device_get_address(device), dstaddr);
1023         addr_value = g_strdup(dstaddr);
1024
1025         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1026                                                         &addr_value);
1027
1028         complete = TRUE;
1029         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
1030                                                         &complete);
1031 }
1032
1033 static void indicate_confirm_reply_cb(DBusMessage *message, void *user_data)
1034 {
1035         DBusError error;
1036
1037         dbus_error_init(&error);
1038
1039         if (dbus_set_error_from_message(&error, message) == TRUE) {
1040                 DBG("Failed to send indication/notification");
1041                 dbus_error_free(&error);
1042                 return;
1043         }
1044 }
1045 #endif
1046
1047 static void conf_cb(void *user_data)
1048 {
1049         DBG("GATT server received confirmation");
1050 #ifdef __TIZEN_PATCH__
1051         struct notify_indicate_cb *confirm = user_data;
1052
1053         if (confirm) {
1054                 /* Send confirmation to application */
1055                 if (g_dbus_proxy_method_call(confirm->proxy, "IndicateConfirm",
1056                                                         indicate_confirm_setup_cb,
1057                                                         indicate_confirm_reply_cb, confirm->device,
1058                                                         NULL) == TRUE)
1059                         return;
1060         }
1061 #endif
1062 }
1063
1064 #ifdef __TIZEN_PATCH__
1065 static void send_notification_indication_to_device(void *data, void *user_data)
1066 {
1067         struct device_state *device_state = data;
1068         struct notify_indicate *notify_indicate = user_data;
1069         struct ccc_state *ccc;
1070         struct btd_device *device;
1071         struct notify_indicate_cb *confirm;
1072
1073         ccc = find_ccc_state(device_state, notify_indicate->ccc_handle);
1074         if (!ccc)
1075                 return;
1076
1077         if (!ccc->value[0] || (notify_indicate->indicate && !(ccc->value[0] & 0x02)))
1078                 return;
1079
1080         device = btd_adapter_get_device(notify_indicate->database->adapter,
1081                                                 &device_state->bdaddr,
1082                                                 device_state->bdaddr_type);
1083         if (!device)
1084                 return;
1085
1086         confirm = new0(struct notify_indicate_cb, 1);
1087         confirm->proxy = notify_indicate->proxy;
1088         confirm->device = device;
1089         /*
1090          * TODO: If the device is not connected but bonded, send the
1091          * notification/indication when it becomes connected.
1092          */
1093         if (!notify_indicate->indicate) {
1094                 DBG("GATT server sending notification");
1095                 bt_gatt_server_send_notification(
1096                                         btd_device_get_gatt_server(device),
1097                                         notify_indicate->handle, notify_indicate->value,
1098                                         notify_indicate->len);
1099                 /* In case of Notification, send response to application
1100                  * as remote device do not respond for notification */
1101                 conf_cb(confirm);
1102                 return;
1103         }
1104
1105         DBG("GATT server sending indication");
1106
1107         bt_gatt_server_send_indication(btd_device_get_gatt_server(device),
1108                                                         notify_indicate->handle,
1109                                                         notify_indicate->value,
1110                                                         notify_indicate->len, conf_cb,
1111                                                         confirm, indicate_confirm_free);
1112 }
1113
1114 static void send_notification_indication_to_devices(GDBusProxy *proxy,
1115                                         struct btd_gatt_database *database,
1116                                         uint16_t handle, const uint8_t *value,
1117                                         uint16_t len, uint16_t ccc_handle,
1118                                         bool indicate)
1119 {
1120         struct notify_indicate notify_indicate;
1121         DBG("");
1122         memset(&notify_indicate, 0, sizeof(notify_indicate));
1123
1124         notify_indicate.database = database;
1125         notify_indicate.proxy = proxy;
1126         notify_indicate.handle = handle;
1127         notify_indicate.ccc_handle = ccc_handle;
1128         notify_indicate.value = value;
1129         notify_indicate.len = len;
1130         notify_indicate.indicate = indicate;
1131
1132         queue_foreach(database->device_states, send_notification_indication_to_device,
1133                                                                 &notify_indicate);
1134 }
1135
1136 static void send_unicast_notification_indication_to_device(GDBusProxy *proxy,
1137                                         struct btd_gatt_database *database,
1138                                         uint16_t handle, const uint8_t *value,
1139                                         uint16_t len, uint16_t ccc_handle,
1140                                         bool indicate, const bdaddr_t *unicast_addr)
1141 {
1142         struct device_state *dev_state;
1143         struct notify_indicate notify_indicate;
1144         DBG("");
1145
1146         memset(&notify_indicate, 0, sizeof(notify_indicate));
1147
1148         notify_indicate.database = database;
1149         notify_indicate.proxy = proxy;
1150         notify_indicate.handle = handle;
1151         notify_indicate.ccc_handle = ccc_handle;
1152         notify_indicate.value = value;
1153         notify_indicate.len = len;
1154         notify_indicate.indicate = indicate;
1155
1156          /* Find and return a device state. */
1157         dev_state = find_device_state_from_address(database, unicast_addr);
1158
1159         if (dev_state)
1160                 send_notification_indication_to_device(dev_state, &notify_indicate);
1161 }
1162 #endif
1163
1164 static void send_notification_to_device(void *data, void *user_data)
1165 {
1166         struct device_state *device_state = data;
1167         struct notify *notify = user_data;
1168         struct ccc_state *ccc;
1169         struct btd_device *device;
1170
1171         ccc = find_ccc_state(device_state, notify->ccc_handle);
1172         if (!ccc)
1173                 return;
1174
1175         if (!ccc->value[0] || (notify->indicate && !(ccc->value[0] & 0x02)))
1176                 return;
1177
1178         device = btd_adapter_get_device(notify->database->adapter,
1179                                                 &device_state->bdaddr,
1180                                                 device_state->bdaddr_type);
1181         if (!device)
1182                 return;
1183
1184         /*
1185          * TODO: If the device is not connected but bonded, send the
1186          * notification/indication when it becomes connected.
1187          */
1188         if (!notify->indicate) {
1189                 DBG("GATT server sending notification");
1190                 bt_gatt_server_send_notification(
1191                                         btd_device_get_gatt_server(device),
1192                                         notify->handle, notify->value,
1193                                         notify->len);
1194                 return;
1195         }
1196
1197         DBG("GATT server sending indication");
1198         bt_gatt_server_send_indication(btd_device_get_gatt_server(device),
1199                                                         notify->handle,
1200                                                         notify->value,
1201                                                         notify->len, conf_cb,
1202                                                         NULL, NULL);
1203 }
1204
1205 static void send_notification_to_devices(struct btd_gatt_database *database,
1206                                         uint16_t handle, const uint8_t *value,
1207                                         uint16_t len, uint16_t ccc_handle,
1208                                         bool indicate)
1209 {
1210         struct notify notify;
1211
1212         memset(&notify, 0, sizeof(notify));
1213
1214         notify.database = database;
1215         notify.handle = handle;
1216         notify.ccc_handle = ccc_handle;
1217         notify.value = value;
1218         notify.len = len;
1219         notify.indicate = indicate;
1220
1221         queue_foreach(database->device_states, send_notification_to_device,
1222                                                                 &notify);
1223 }
1224
1225 static void send_service_changed(struct btd_gatt_database *database,
1226                                         struct gatt_db_attribute *attrib)
1227 {
1228         uint16_t start, end;
1229         uint8_t value[4];
1230         uint16_t handle, ccc_handle;
1231
1232         if (!gatt_db_attribute_get_service_handles(attrib, &start, &end)) {
1233                 error("Failed to obtain changed service handles");
1234                 return;
1235         }
1236
1237         handle = gatt_db_attribute_get_handle(database->svc_chngd);
1238         ccc_handle = gatt_db_attribute_get_handle(database->svc_chngd_ccc);
1239
1240         if (!handle || !ccc_handle) {
1241                 error("Failed to obtain handles for \"Service Changed\""
1242                                                         " characteristic");
1243                 return;
1244         }
1245
1246         put_le16(start, value);
1247         put_le16(end, value + 2);
1248
1249         send_notification_to_devices(database, handle, value, sizeof(value),
1250                                                         ccc_handle, true);
1251 }
1252
1253 static void gatt_db_service_added(struct gatt_db_attribute *attrib,
1254                                                                 void *user_data)
1255 {
1256         struct btd_gatt_database *database = user_data;
1257
1258         DBG("GATT Service added to local database");
1259
1260         send_service_changed(database, attrib);
1261 }
1262
1263 static bool ccc_match_service(const void *data, const void *match_data)
1264 {
1265         const struct ccc_state *ccc = data;
1266         const struct gatt_db_attribute *attrib = match_data;
1267         uint16_t start, end;
1268
1269         if (!gatt_db_attribute_get_service_handles(attrib, &start, &end))
1270                 return false;
1271
1272         return ccc->handle >= start && ccc->handle <= end;
1273 }
1274
1275 static void remove_device_ccc(void *data, void *user_data)
1276 {
1277         struct device_state *state = data;
1278
1279         queue_remove_all(state->ccc_states, ccc_match_service, user_data, free);
1280 }
1281
1282 static void gatt_db_service_removed(struct gatt_db_attribute *attrib,
1283                                                                 void *user_data)
1284 {
1285         struct btd_gatt_database *database = user_data;
1286
1287         DBG("Local GATT service removed");
1288
1289         send_service_changed(database, attrib);
1290
1291         queue_foreach(database->device_states, remove_device_ccc, attrib);
1292         queue_remove_all(database->ccc_callbacks, ccc_cb_match_service, attrib,
1293                                                                 ccc_cb_free);
1294 }
1295
1296 struct svc_match_data {
1297         const char *path;
1298         const char *sender;
1299 };
1300
1301 static bool match_app(const void *a, const void *b)
1302 {
1303         const struct gatt_app *app = a;
1304         const struct svc_match_data *data = b;
1305
1306         return g_strcmp0(app->path, data->path) == 0 &&
1307                                 g_strcmp0(app->owner, data->sender) == 0;
1308 }
1309
1310 static gboolean app_free_idle_cb(void *data)
1311 {
1312         app_free(data);
1313
1314         return FALSE;
1315 }
1316
1317 static void client_disconnect_cb(DBusConnection *conn, void *user_data)
1318 {
1319         struct gatt_app *app = user_data;
1320         struct btd_gatt_database *database = app->database;
1321
1322         DBG("Client disconnected");
1323
1324         if (queue_remove(database->apps, app))
1325                 app_free(app);
1326 }
1327
1328 static void remove_app(void *data)
1329 {
1330         struct gatt_app *app = data;
1331
1332         /*
1333          * Set callback to NULL to avoid potential race condition
1334          * when calling remove_app and GDBusClient unref.
1335          */
1336         g_dbus_client_set_disconnect_watch(app->client, NULL, NULL);
1337
1338         /*
1339          * Set proxy handlers to NULL, so that this gets called only once when
1340          * the first proxy that belongs to this service gets removed.
1341          */
1342         g_dbus_client_set_proxy_handlers(app->client, NULL, NULL, NULL, NULL);
1343
1344
1345         queue_remove(app->database->apps, app);
1346
1347         /*
1348          * Do not run in the same loop, this may be a disconnect
1349          * watch call and GDBusClient should not be destroyed.
1350          */
1351         g_idle_add(app_free_idle_cb, app);
1352 }
1353
1354 static bool match_service_by_path(const void *a, const void *b)
1355 {
1356         const struct external_service *service = a;
1357         const char *path = b;
1358
1359         return strcmp(service->path, path) == 0;
1360 }
1361
1362 static bool parse_path(GDBusProxy *proxy, const char *name, const char **path)
1363 {
1364         DBusMessageIter iter;
1365
1366         if (!g_dbus_proxy_get_property(proxy, name, &iter))
1367                 return false;
1368
1369         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
1370                 return false;
1371
1372         dbus_message_iter_get_basic(&iter, path);
1373
1374         return true;
1375 }
1376
1377 static bool incr_attr_count(struct external_service *service, uint16_t incr)
1378 {
1379         if (service->attr_cnt > UINT16_MAX - incr)
1380                 return false;
1381
1382         service->attr_cnt += incr;
1383
1384         return true;
1385 }
1386
1387 static bool parse_chrc_flags(DBusMessageIter *array, uint8_t *props,
1388                                                         uint8_t *ext_props)
1389 {
1390         const char *flag;
1391
1392         *props = *ext_props = 0;
1393
1394         do {
1395                 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_STRING)
1396                         return false;
1397
1398                 dbus_message_iter_get_basic(array, &flag);
1399
1400                 if (!strcmp("broadcast", flag))
1401                         *props |= BT_GATT_CHRC_PROP_BROADCAST;
1402                 else if (!strcmp("read", flag))
1403                         *props |= BT_GATT_CHRC_PROP_READ;
1404                 else if (!strcmp("write-without-response", flag))
1405                         *props |= BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP;
1406                 else if (!strcmp("write", flag))
1407                         *props |= BT_GATT_CHRC_PROP_WRITE;
1408                 else if (!strcmp("notify", flag))
1409                         *props |= BT_GATT_CHRC_PROP_NOTIFY;
1410                 else if (!strcmp("indicate", flag))
1411                         *props |= BT_GATT_CHRC_PROP_INDICATE;
1412                 else if (!strcmp("authenticated-signed-writes", flag))
1413                         *props |= BT_GATT_CHRC_PROP_AUTH;
1414                 else if (!strcmp("reliable-write", flag))
1415                         *ext_props |= BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE;
1416                 else if (!strcmp("writable-auxiliaries", flag))
1417                         *ext_props |= BT_GATT_CHRC_EXT_PROP_WRITABLE_AUX;
1418                 else if (!strcmp("encrypt-read", flag)) {
1419                         *props |= BT_GATT_CHRC_PROP_READ;
1420                         *ext_props |= BT_GATT_CHRC_EXT_PROP_ENC_READ;
1421                 } else if (!strcmp("encrypt-write", flag)) {
1422                         *props |= BT_GATT_CHRC_PROP_WRITE;
1423                         *ext_props |= BT_GATT_CHRC_EXT_PROP_ENC_WRITE;
1424                 } else if (!strcmp("encrypt-authenticated-read", flag)) {
1425                         *props |= BT_GATT_CHRC_PROP_READ;
1426                         *ext_props |= BT_GATT_CHRC_EXT_PROP_AUTH_READ;
1427                 } else if (!strcmp("encrypt-authenticated-write", flag)) {
1428                         *props |= BT_GATT_CHRC_PROP_WRITE;
1429                         *ext_props |= BT_GATT_CHRC_EXT_PROP_AUTH_WRITE;
1430                 } else {
1431                         error("Invalid characteristic flag: %s", flag);
1432                         return false;
1433                 }
1434         } while (dbus_message_iter_next(array));
1435
1436         if (*ext_props)
1437                 *props |= BT_GATT_CHRC_PROP_EXT_PROP;
1438
1439         return true;
1440 }
1441
1442 static bool parse_desc_flags(DBusMessageIter *array, uint32_t *perm)
1443 {
1444         const char *flag;
1445
1446         *perm = 0;
1447
1448         do {
1449                 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_STRING)
1450                         return false;
1451
1452                 dbus_message_iter_get_basic(array, &flag);
1453
1454                 if (!strcmp("read", flag))
1455                         *perm |= BT_ATT_PERM_READ;
1456                 else if (!strcmp("write", flag))
1457                         *perm |= BT_ATT_PERM_WRITE;
1458                 else if (!strcmp("encrypt-read", flag))
1459                         *perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_ENCRYPT;
1460                 else if (!strcmp("encrypt-write", flag))
1461                         *perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_ENCRYPT;
1462                 else if (!strcmp("encrypt-authenticated-read", flag))
1463                         *perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_AUTHEN;
1464                 else if (!strcmp("encrypt-authenticated-write", flag))
1465                         *perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_AUTHEN;
1466                 else {
1467                         error("Invalid descriptor flag: %s", flag);
1468                         return false;
1469                 }
1470         } while (dbus_message_iter_next(array));
1471
1472         return true;
1473 }
1474
1475 static bool parse_flags(GDBusProxy *proxy, uint8_t *props, uint8_t *ext_props,
1476                                                                 uint32_t *perm)
1477 {
1478         DBusMessageIter iter, array;
1479
1480         if (!g_dbus_proxy_get_property(proxy, "Flags", &iter))
1481                 return false;
1482
1483         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1484                 return false;
1485
1486         dbus_message_iter_recurse(&iter, &array);
1487
1488         if (perm)
1489                 return parse_desc_flags(&array, perm);
1490
1491         return parse_chrc_flags(&array, props, ext_props);
1492 }
1493
1494 static struct external_chrc *chrc_create(struct gatt_app *app,
1495                                                         GDBusProxy *proxy,
1496                                                         const char *path)
1497 {
1498         struct external_service *service;
1499         struct external_chrc *chrc;
1500         const char *service_path;
1501
1502         if (!parse_path(proxy, "Service", &service_path)) {
1503                 error("Failed to obtain service path for characteristic");
1504                 return NULL;
1505         }
1506
1507         service = queue_find(app->services, match_service_by_path,
1508                                                                 service_path);
1509         if (!service) {
1510                 error("Unable to find service for characteristic: %s", path);
1511                 return NULL;
1512         }
1513
1514         chrc = new0(struct external_chrc, 1);
1515         chrc->pending_reads = queue_new();
1516         chrc->pending_writes = queue_new();
1517
1518         chrc->path = g_strdup(path);
1519         if (!chrc->path)
1520                 goto fail;
1521
1522         chrc->service = service;
1523         chrc->proxy = g_dbus_proxy_ref(proxy);
1524
1525         /*
1526          * Add 2 for the characteristic declaration and the value
1527          * attribute.
1528          */
1529         if (!incr_attr_count(chrc->service, 2)) {
1530                 error("Failed to increment attribute count");
1531                 goto fail;
1532         }
1533
1534         /*
1535          * Parse characteristic flags (i.e. properties) here since they
1536          * are used to determine if any special descriptors should be
1537          * created.
1538          */
1539         if (!parse_flags(proxy, &chrc->props, &chrc->ext_props, NULL)) {
1540                 error("Failed to parse characteristic properties");
1541                 goto fail;
1542         }
1543
1544         if ((chrc->props & BT_GATT_CHRC_PROP_NOTIFY ||
1545                                 chrc->props & BT_GATT_CHRC_PROP_INDICATE) &&
1546                                 !incr_attr_count(chrc->service, 1)) {
1547                 error("Failed to increment attribute count for CCC");
1548                 goto fail;
1549         }
1550
1551         if (chrc->ext_props && !incr_attr_count(chrc->service, 1)) {
1552                 error("Failed to increment attribute count for CEP");
1553                 goto fail;
1554         }
1555
1556         queue_push_tail(chrc->service->chrcs, chrc);
1557
1558         return chrc;
1559
1560 fail:
1561         chrc_free(chrc);
1562         return NULL;
1563 }
1564
1565 static bool match_chrc(const void *a, const void *b)
1566 {
1567         const struct external_chrc *chrc = a;
1568         const char *path = b;
1569
1570         return strcmp(chrc->path, path) == 0;
1571 }
1572
1573 static bool match_service_by_chrc(const void *a, const void *b)
1574 {
1575         const struct external_service *service = a;
1576         const char *path = b;
1577
1578         return queue_find(service->chrcs, match_chrc, path);
1579 }
1580
1581 static struct external_desc *desc_create(struct gatt_app *app,
1582                                                         GDBusProxy *proxy)
1583 {
1584         struct external_service *service;
1585         struct external_desc *desc;
1586         const char *chrc_path;
1587
1588         if (!parse_path(proxy, "Characteristic", &chrc_path)) {
1589                 error("Failed to obtain characteristic path for descriptor");
1590                 return NULL;
1591         }
1592
1593         service = queue_find(app->services, match_service_by_chrc, chrc_path);
1594         if (!service) {
1595                 error("Unable to find service for characteristic: %s",
1596                                                                 chrc_path);
1597                 return NULL;
1598         }
1599
1600         desc = new0(struct external_desc, 1);
1601         desc->pending_reads = queue_new();
1602         desc->pending_writes = queue_new();
1603
1604         desc->chrc_path = g_strdup(chrc_path);
1605         if (!desc->chrc_path)
1606                 goto fail;
1607
1608         desc->service = service;
1609         desc->proxy = g_dbus_proxy_ref(proxy);
1610
1611         /* Add 1 for the descriptor attribute */
1612         if (!incr_attr_count(desc->service, 1)) {
1613                 error("Failed to increment attribute count");
1614                 goto fail;
1615         }
1616
1617         /*
1618          * Parse descriptors flags here since they are used to
1619          * determine the permission the descriptor should have
1620          */
1621         if (!parse_flags(proxy, NULL, NULL, &desc->perm)) {
1622                 error("Failed to parse characteristic properties");
1623                 goto fail;
1624         }
1625
1626         queue_push_tail(desc->service->descs, desc);
1627
1628         return desc;
1629
1630 fail:
1631         desc_free(desc);
1632         return NULL;
1633 }
1634
1635 static bool check_service_path(GDBusProxy *proxy,
1636                                         struct external_service *service)
1637 {
1638         const char *service_path;
1639
1640         if (!parse_path(proxy, "Service", &service_path))
1641                 return false;
1642
1643         return g_strcmp0(service_path, service->path) == 0;
1644 }
1645
1646 static struct external_service *create_service(struct gatt_app *app,
1647                                                 GDBusProxy *proxy,
1648                                                 const char *path)
1649 {
1650         struct external_service *service;
1651
1652         if (!path || !g_str_has_prefix(path, "/"))
1653                 return NULL;
1654
1655         service = queue_find(app->services, match_service_by_path, path);
1656         if (service) {
1657                 error("Duplicated service: %s", path);
1658                 return NULL;
1659         }
1660
1661         service = new0(struct external_service, 1);
1662
1663         service->app = app;
1664
1665         service->path = g_strdup(path);
1666         if (!service->path)
1667                 goto fail;
1668
1669         service->proxy = g_dbus_proxy_ref(proxy);
1670         service->chrcs = queue_new();
1671         service->descs = queue_new();
1672
1673         /* Add 1 for the service declaration */
1674         if (!incr_attr_count(service, 1)) {
1675                 error("Failed to increment attribute count");
1676                 goto fail;
1677         }
1678
1679         queue_push_tail(app->services, service);
1680
1681         return service;
1682
1683 fail:
1684         service_free(service);
1685         return NULL;
1686 }
1687
1688 static void proxy_added_cb(GDBusProxy *proxy, void *user_data)
1689 {
1690         struct gatt_app *app = user_data;
1691         const char *iface, *path;
1692
1693         if (app->failed)
1694                 return;
1695
1696         iface = g_dbus_proxy_get_interface(proxy);
1697         path = g_dbus_proxy_get_path(proxy);
1698
1699         if (g_strcmp0(iface, GATT_SERVICE_IFACE) == 0) {
1700                 struct external_service *service;
1701
1702                 service = create_service(app, proxy, path);
1703                 if (!service) {
1704                         app->failed = true;
1705                         return;
1706                 }
1707         } else if (g_strcmp0(iface, GATT_CHRC_IFACE) == 0) {
1708                 struct external_chrc *chrc;
1709
1710                 chrc = chrc_create(app, proxy, path);
1711                 if (!chrc) {
1712                         app->failed = true;
1713                         return;
1714                 }
1715         } else if (g_strcmp0(iface, GATT_DESC_IFACE) == 0) {
1716                 struct external_desc *desc;
1717
1718                 desc = desc_create(app, proxy);
1719                 if (!desc) {
1720                         app->failed = true;
1721                         return;
1722                 }
1723         } else {
1724                 DBG("Ignoring unrelated interface: %s", iface);
1725                 return;
1726         }
1727
1728         DBG("Object added: path: %s, iface: %s", path, iface);
1729 }
1730
1731 static void proxy_removed_cb(GDBusProxy *proxy, void *user_data)
1732 {
1733         struct gatt_app *app = user_data;
1734         struct external_service *service;
1735         const char *path;
1736
1737         path = g_dbus_proxy_get_path(proxy);
1738
1739         service = queue_remove_if(app->services, match_service_by_path,
1740                                                         (void *) path);
1741         if (!service)
1742                 return;
1743
1744         DBG("Proxy removed - removing service: %s", service->path);
1745
1746         service_free(service);
1747 }
1748
1749 static bool parse_uuid(GDBusProxy *proxy, bt_uuid_t *uuid)
1750 {
1751         DBusMessageIter iter;
1752         bt_uuid_t tmp;
1753         const char *uuidstr;
1754
1755         if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
1756                 return false;
1757
1758         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1759                 return false;
1760
1761         dbus_message_iter_get_basic(&iter, &uuidstr);
1762
1763         if (bt_string_to_uuid(uuid, uuidstr) < 0)
1764                 return false;
1765
1766         /* GAP & GATT services are created and managed by BlueZ */
1767         bt_uuid16_create(&tmp, UUID_GAP);
1768         if (!bt_uuid_cmp(&tmp, uuid)) {
1769                 error("GAP service must be handled by BlueZ");
1770                 return false;
1771         }
1772
1773         bt_uuid16_create(&tmp, UUID_GATT);
1774         if (!bt_uuid_cmp(&tmp, uuid)) {
1775                 error("GATT service must be handled by BlueZ");
1776                 return false;
1777         }
1778
1779         return true;
1780 }
1781
1782 static bool parse_primary(GDBusProxy *proxy, bool *primary)
1783 {
1784         DBusMessageIter iter;
1785         dbus_bool_t val;
1786
1787         if (!g_dbus_proxy_get_property(proxy, "Primary", &iter))
1788                 return false;
1789
1790         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
1791                 return false;
1792
1793         dbus_message_iter_get_basic(&iter, &val);
1794
1795         *primary = val;
1796
1797         return true;
1798 }
1799
1800 static uint8_t dbus_error_to_att_ecode(const char *error_name)
1801 {
1802
1803         if (strcmp(error_name, "org.bluez.Error.Failed") == 0)
1804                 return 0x80;  /* For now return this "application error" */
1805
1806         if (strcmp(error_name, "org.bluez.Error.NotSupported") == 0)
1807                 return BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1808
1809         if (strcmp(error_name, "org.bluez.Error.NotAuthorized") == 0)
1810                 return BT_ATT_ERROR_AUTHORIZATION;
1811
1812         if (strcmp(error_name, "org.bluez.Error.InvalidValueLength") == 0)
1813                 return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
1814
1815         if (strcmp(error_name, "org.bluez.Error.InProgress") == 0)
1816                 return BT_ERROR_ALREADY_IN_PROGRESS;
1817
1818         return 0;
1819 }
1820
1821 static void read_reply_cb(DBusMessage *message, void *user_data)
1822 {
1823         struct pending_op *op = user_data;
1824         DBusError err;
1825         DBusMessageIter iter, array;
1826         uint8_t ecode = 0;
1827         uint8_t *value = NULL;
1828         int len = 0;
1829
1830         if (!op->owner_queue) {
1831                 DBG("Pending read was canceled when object got removed");
1832                 return;
1833         }
1834
1835         dbus_error_init(&err);
1836
1837         if (dbus_set_error_from_message(&err, message) == TRUE) {
1838                 DBG("Failed to read value: %s: %s", err.name, err.message);
1839                 ecode = dbus_error_to_att_ecode(err.name);
1840                 ecode = ecode ? ecode : BT_ATT_ERROR_READ_NOT_PERMITTED;
1841                 dbus_error_free(&err);
1842                 goto done;
1843         }
1844
1845         dbus_message_iter_init(message, &iter);
1846
1847         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
1848                 /*
1849                  * Return not supported for this, as the external app basically
1850                  * doesn't properly support reading from this characteristic.
1851                  */
1852                 ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1853                 error("Invalid return value received for \"ReadValue\"");
1854                 goto done;
1855         }
1856
1857         dbus_message_iter_recurse(&iter, &array);
1858         dbus_message_iter_get_fixed_array(&array, &value, &len);
1859
1860         if (len < 0) {
1861                 ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
1862                 value = NULL;
1863                 len = 0;
1864                 goto done;
1865         }
1866
1867         /* Truncate the value if it's too large */
1868         len = MIN(BT_ATT_MAX_VALUE_LEN, len);
1869         value = len ? value : NULL;
1870
1871 done:
1872         gatt_db_attribute_read_result(op->attrib, op->id, ecode, value, len);
1873 }
1874
1875 static void pending_op_free(void *data)
1876 {
1877         struct pending_op *op = data;
1878
1879         if (op->owner_queue)
1880                 queue_remove(op->owner_queue, op);
1881
1882         free(op);
1883 }
1884
1885 #ifdef __TIZEN_PATCH__
1886 static struct pending_op *pending_read_new(struct queue *owner_queue,
1887                                         struct gatt_db_attribute *attrib,
1888                                         struct bt_att *att,
1889                                         unsigned int id)
1890 #else
1891 static struct pending_op *pending_read_new(struct queue *owner_queue,
1892                                         struct gatt_db_attribute *attrib,
1893                                         unsigned int id)
1894 #endif
1895 {
1896         struct pending_op *op;
1897 #ifdef __TIZEN_PATCH__
1898         bdaddr_t bdaddr;
1899         uint8_t bdaddr_type;
1900 #endif
1901
1902         op = new0(struct pending_op, 1);
1903         if (!op)
1904                 return NULL;
1905
1906 #ifdef __TIZEN_PATCH__
1907         if (!get_dst_info(att, &bdaddr, &bdaddr_type)) {
1908                 free(op);
1909                 return NULL;
1910         }
1911 #endif
1912
1913         op->owner_queue = owner_queue;
1914 #ifdef __TIZEN_PATCH__
1915         memcpy(&op->bdaddr, &bdaddr, sizeof(bdaddr_t));
1916         op->bdaddr_type = bdaddr_type;
1917 #endif
1918
1919         op->attrib = attrib;
1920         op->id = id;
1921         queue_push_tail(owner_queue, op);
1922
1923         return op;
1924 }
1925
1926 #ifdef __TIZEN_PATCH__
1927 static void read_setup_cb(DBusMessageIter *iter, void *user_data)
1928 {
1929         struct pending_op *op = user_data;
1930         char dstaddr[18] = { 0 };
1931         char *addr_value = NULL;
1932         uint16_t offset = 0;
1933
1934         ba2str(&op->bdaddr, dstaddr);
1935         addr_value = g_strdup(dstaddr);
1936
1937         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1938                                                         &addr_value);
1939
1940         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
1941                                                         &op->id);
1942
1943         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
1944                                                         &offset);
1945 }
1946 #endif
1947
1948 #ifdef __TIZEN_PATCH__
1949 static void send_read(struct gatt_db_attribute *attrib, struct bt_att *att,
1950                                                 GDBusProxy *proxy, struct queue *owner_queue,
1951                                                 unsigned int id)
1952 #else
1953 static void send_read(struct gatt_db_attribute *attrib, GDBusProxy *proxy,
1954                                                 struct queue *owner_queue,
1955                                                 unsigned int id)
1956 #endif
1957 {
1958         struct pending_op *op;
1959         uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
1960
1961 #ifdef __TIZEN_PATCH__
1962         op = pending_read_new(owner_queue, attrib, att, id);
1963 #else
1964         op = pending_read_new(owner_queue, attrib, id);
1965 #endif
1966         if (!op) {
1967                 error("Failed to allocate memory for pending read call");
1968                 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
1969                 goto error;
1970         }
1971
1972 #ifdef __TIZEN_PATCH__
1973         if (g_dbus_proxy_method_call(proxy, "ReadValue", read_setup_cb, read_reply_cb,
1974                                                 op, pending_op_free) == TRUE)
1975 #else
1976         if (g_dbus_proxy_method_call(proxy, "ReadValue", NULL, read_reply_cb,
1977                                                 op, pending_op_free) == TRUE)
1978 #endif
1979                 return;
1980
1981         pending_op_free(op);
1982
1983 error:
1984         gatt_db_attribute_read_result(attrib, id, ecode, NULL, 0);
1985 }
1986
1987 static void write_setup_cb(DBusMessageIter *iter, void *user_data)
1988 {
1989         struct pending_op *op = user_data;
1990         DBusMessageIter array;
1991 #ifdef __TIZEN_PATCH__
1992         char dstaddr[18] = { 0 };
1993         char *addr_value = NULL;
1994         uint16_t offset = 0;
1995 #endif
1996
1997 #ifdef __TIZEN_PATCH__
1998         ba2str(&op->bdaddr, dstaddr);
1999         addr_value = g_strdup(dstaddr);
2000
2001         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
2002                                                         &addr_value);
2003
2004         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
2005                                                         &op->id);
2006
2007         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
2008                                                         &offset);
2009 #endif
2010
2011         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &array);
2012         dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
2013                                         &op->data.iov_base, op->data.iov_len);
2014         dbus_message_iter_close_container(iter, &array);
2015 }
2016
2017 static void write_reply_cb(DBusMessage *message, void *user_data)
2018 {
2019         struct pending_op *op = user_data;
2020         DBusError err;
2021         DBusMessageIter iter;
2022         uint8_t ecode = 0;
2023
2024         if (!op->owner_queue) {
2025                 DBG("Pending write was canceled when object got removed");
2026                 return;
2027         }
2028
2029         dbus_error_init(&err);
2030
2031         if (dbus_set_error_from_message(&err, message) == TRUE) {
2032                 DBG("Failed to write value: %s: %s", err.name, err.message);
2033                 ecode = dbus_error_to_att_ecode(err.name);
2034                 ecode = ecode ? ecode : BT_ATT_ERROR_WRITE_NOT_PERMITTED;
2035                 dbus_error_free(&err);
2036                 goto done;
2037         }
2038
2039         dbus_message_iter_init(message, &iter);
2040         if (dbus_message_iter_has_next(&iter)) {
2041                 /*
2042                  * Return not supported for this, as the external app basically
2043                  * doesn't properly support the "WriteValue" API.
2044                  */
2045                 ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
2046                 error("Invalid return value received for \"WriteValue\"");
2047         }
2048
2049 done:
2050         gatt_db_attribute_write_result(op->attrib, op->id, ecode);
2051 }
2052
2053 #ifdef __TIZEN_PATCH__
2054 static struct pending_op *pending_write_new(struct queue *owner_queue,
2055                                         struct gatt_db_attribute *attrib, struct bt_att *att,
2056                                         unsigned int id,
2057                                         const uint8_t *value,
2058                                         size_t len)
2059 #else
2060 static struct pending_op *pending_write_new(struct queue *owner_queue,
2061                                         struct gatt_db_attribute *attrib,
2062                                         unsigned int id,
2063                                         const uint8_t *value,
2064                                         size_t len)
2065 #endif
2066 {
2067         struct pending_op *op;
2068 #ifdef __TIZEN_PATCH__
2069         bdaddr_t bdaddr;
2070         uint8_t bdaddr_type;
2071 #endif
2072
2073         op = new0(struct pending_op, 1);
2074         if (!op)
2075                 return NULL;
2076 #ifdef __TIZEN_PATCH__
2077         if (!get_dst_info(att, &bdaddr, &bdaddr_type)) {
2078                 free(op);
2079                 return NULL;
2080         }
2081 #endif
2082
2083         op->data.iov_base = (uint8_t *) value;
2084         op->data.iov_len = len;
2085 #ifdef __TIZEN_PATCH__
2086         memcpy(&op->bdaddr, &bdaddr, sizeof(bdaddr_t));
2087         op->bdaddr_type = bdaddr_type;
2088 #endif
2089
2090         op->owner_queue = owner_queue;
2091         op->attrib = attrib;
2092         op->id = id;
2093         queue_push_tail(owner_queue, op);
2094
2095         return op;
2096 }
2097
2098 #ifdef __TIZEN_PATCH__
2099 static void send_write(struct gatt_db_attribute *attrib, struct bt_att *att,
2100                                         GDBusProxy *proxy, struct queue *owner_queue,
2101                                         unsigned int id, const uint8_t *value, size_t len)
2102 #else
2103 static void send_write(struct gatt_db_attribute *attrib, GDBusProxy *proxy,
2104                                         struct queue *owner_queue,
2105                                         unsigned int id,
2106                                         const uint8_t *value, size_t len)
2107 #endif
2108 {
2109         struct pending_op *op;
2110         uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
2111
2112 #ifdef __TIZEN_PATCH__
2113         op = pending_write_new(owner_queue, attrib, att, id, value, len);
2114 #else
2115         op = pending_write_new(owner_queue, attrib, id, value, len);
2116 #endif
2117         if (!op) {
2118                 error("Failed to allocate memory for pending read call");
2119                 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
2120                 goto error;
2121         }
2122
2123         if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb,
2124                                                 write_reply_cb, op,
2125                                                 pending_op_free) == TRUE)
2126                 return;
2127
2128         pending_op_free(op);
2129
2130 error:
2131         gatt_db_attribute_write_result(attrib, id, ecode);
2132 }
2133
2134 static uint32_t permissions_from_props(uint8_t props, uint8_t ext_props)
2135 {
2136         uint32_t perm = 0;
2137
2138         if (props & BT_GATT_CHRC_PROP_WRITE ||
2139                         props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP ||
2140                         ext_props & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE ||
2141                         ext_props & BT_GATT_CHRC_EXT_PROP_ENC_WRITE ||
2142                         ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_WRITE)
2143                 perm |= BT_ATT_PERM_WRITE;
2144
2145         if (props & BT_GATT_CHRC_PROP_READ ||
2146                         ext_props & BT_GATT_CHRC_EXT_PROP_ENC_READ ||
2147                         ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_READ)
2148                 perm |= BT_ATT_PERM_READ;
2149
2150         if (ext_props & BT_GATT_CHRC_EXT_PROP_ENC_READ)
2151                 perm |= BT_ATT_PERM_READ_ENCRYPT;
2152
2153         if (ext_props & BT_GATT_CHRC_EXT_PROP_ENC_WRITE)
2154                 perm |= BT_ATT_PERM_WRITE_ENCRYPT;
2155
2156         if (ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_READ)
2157                 perm |= BT_ATT_PERM_READ_AUTHEN;
2158
2159         if (ext_props & BT_GATT_CHRC_EXT_PROP_AUTH_WRITE)
2160                 perm |= BT_ATT_PERM_WRITE_AUTHEN;
2161
2162         return perm;
2163 }
2164
2165 static uint8_t ccc_write_cb(uint16_t value, void *user_data)
2166 {
2167         struct external_chrc *chrc = user_data;
2168
2169         DBG("External CCC write received with value: 0x%04x", value);
2170
2171         /* Notifications/indications disabled */
2172         if (!value) {
2173                 if (!chrc->ntfy_cnt)
2174                         return 0;
2175
2176                 if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1))
2177                         return 0;
2178
2179                 /*
2180                  * Send request to stop notifying. This is best-effort
2181                  * operation, so simply ignore the return the value.
2182                  */
2183                 g_dbus_proxy_method_call(chrc->proxy, "StopNotify", NULL,
2184                                                         NULL, NULL, NULL);
2185                 return 0;
2186         }
2187
2188         if (chrc->ntfy_cnt == UINT_MAX) {
2189                 /* Maximum number of per-device CCC descriptors configured */
2190                 return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
2191         }
2192
2193         /* Don't support undefined CCC values yet */
2194         if (value > 2 ||
2195                 (value == 1 && !(chrc->props & BT_GATT_CHRC_PROP_NOTIFY)) ||
2196                 (value == 2 && !(chrc->props & BT_GATT_CHRC_PROP_INDICATE)))
2197                 return BT_ERROR_CCC_IMPROPERLY_CONFIGURED;
2198
2199         /*
2200          * Always call StartNotify for an incoming enable and ignore the return
2201          * value for now.
2202          */
2203         if (g_dbus_proxy_method_call(chrc->proxy,
2204                                                 "StartNotify", NULL, NULL,
2205                                                 NULL, NULL) == FALSE)
2206                 return BT_ATT_ERROR_UNLIKELY;
2207
2208         __sync_fetch_and_add(&chrc->ntfy_cnt, 1);
2209
2210         return 0;
2211 }
2212
2213 static void property_changed_cb(GDBusProxy *proxy, const char *name,
2214                                         DBusMessageIter *iter, void *user_data)
2215 {
2216         struct external_chrc *chrc = user_data;
2217         DBusMessageIter array;
2218         uint8_t *value = NULL;
2219         int len = 0;
2220 #ifdef __TIZEN_PATCH__
2221         bool enable = FALSE;
2222         const bdaddr_t *unicast_addr = NULL;
2223 #endif
2224
2225 #ifdef __TIZEN_PATCH__
2226         if (strcmp(name, "Value") == 0) {
2227                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
2228                         DBG("Malformed \"Value\" property received");
2229                         return;
2230                 }
2231
2232                 dbus_message_iter_recurse(iter, &array);
2233                 dbus_message_iter_get_fixed_array(&array, &value, &len);
2234
2235                 if (len < 0) {
2236                         DBG("Malformed \"Value\" property received");
2237                         return;
2238                 }
2239
2240                 /* Truncate the value if it's too large */
2241                 len = MIN(BT_ATT_MAX_VALUE_LEN, len);
2242                 value = len ? value : NULL;
2243         } else if (strcmp(name, "Notifying") == 0) {
2244                 gboolean notify_indicate = FALSE;
2245
2246                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) {
2247                         DBG("Malformed \"Notifying\" property received");
2248                         return;
2249                 }
2250
2251                 dbus_message_iter_get_basic(iter, &notify_indicate);
2252
2253                 DBG("Set Notification %d", notify_indicate);
2254                 /* Set notification/indication */
2255                 set_ccc_notify_indicate(chrc->ccc, notify_indicate);
2256                 return;
2257         } else if (strcmp(name, "Unicast") == 0) {
2258                 const char *address = NULL;
2259                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
2260                         DBG("Malformed \"Value\" property received");
2261                         return;
2262                 }
2263
2264                 dbus_message_iter_get_basic(iter, &address);
2265
2266                 if (address) {
2267                         /* Set the address for unicast notification/indication */
2268                         set_ccc_unicast_address(chrc->ccc, address);
2269                 }
2270                 return;
2271         } else
2272                 return;
2273
2274         enable = get_ccc_notify_indicate(chrc->ccc);
2275
2276         if (enable) {
2277                 unicast_addr = get_ccc_unicast_address(chrc->ccc);
2278
2279                 if (unicast_addr && bacmp(unicast_addr, BDADDR_ANY)) {
2280                         send_unicast_notification_indication_to_device(proxy,
2281                                         chrc->service->app->database,
2282                                         gatt_db_attribute_get_handle(chrc->attrib),
2283                                         value, len,
2284                                         gatt_db_attribute_get_handle(chrc->ccc),
2285                                         chrc->props & BT_GATT_CHRC_PROP_INDICATE,
2286                                         unicast_addr);
2287                         /* reset the unicast address */
2288                         set_ccc_unicast_address(chrc->ccc, NULL);
2289                 } else {
2290                         send_notification_indication_to_devices(proxy,
2291                                         chrc->service->app->database,
2292                                         gatt_db_attribute_get_handle(chrc->attrib),
2293                                         value, len,
2294                                         gatt_db_attribute_get_handle(chrc->ccc),
2295                                         chrc->props & BT_GATT_CHRC_PROP_INDICATE);
2296                 }
2297
2298                 set_ccc_notify_indicate(chrc->ccc, FALSE);
2299         }
2300 #else
2301         if (strcmp(name, "Value"))
2302                 return;
2303
2304         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
2305                 DBG("Malformed \"Value\" property received");
2306                 return;
2307         }
2308
2309         dbus_message_iter_recurse(iter, &array);
2310         dbus_message_iter_get_fixed_array(&array, &value, &len);
2311
2312         if (len < 0) {
2313                 DBG("Malformed \"Value\" property received");
2314                 return;
2315         }
2316
2317         /* Truncate the value if it's too large */
2318         len = MIN(BT_ATT_MAX_VALUE_LEN, len);
2319         value = len ? value : NULL;
2320
2321         send_notification_to_devices(chrc->service->app->database,
2322                                 gatt_db_attribute_get_handle(chrc->attrib),
2323                                 value, len,
2324                                 gatt_db_attribute_get_handle(chrc->ccc),
2325                                 chrc->props & BT_GATT_CHRC_PROP_INDICATE);
2326 #endif
2327 }
2328
2329 static bool database_add_ccc(struct external_service *service,
2330                                                 struct external_chrc *chrc)
2331 {
2332         if (!(chrc->props & BT_GATT_CHRC_PROP_NOTIFY) &&
2333                                 !(chrc->props & BT_GATT_CHRC_PROP_INDICATE))
2334                 return true;
2335
2336         chrc->ccc = service_add_ccc(service->attrib, service->app->database,
2337                                                 ccc_write_cb, chrc, NULL);
2338         if (!chrc->ccc) {
2339                 error("Failed to create CCC entry for characteristic");
2340                 return false;
2341         }
2342
2343         if (g_dbus_proxy_set_property_watch(chrc->proxy, property_changed_cb,
2344                                                         chrc) == FALSE) {
2345                 error("Failed to set up property watch for characteristic");
2346                 return false;
2347         }
2348
2349         DBG("Created CCC entry for characteristic");
2350
2351         return true;
2352 }
2353
2354 static void cep_write_cb(struct gatt_db_attribute *attrib, int err,
2355                                                                 void *user_data)
2356 {
2357         if (err)
2358                 DBG("Failed to store CEP value in the database");
2359         else
2360                 DBG("Stored CEP value in the database");
2361 }
2362
2363 static bool database_add_cep(struct external_service *service,
2364                                                 struct external_chrc *chrc)
2365 {
2366         struct gatt_db_attribute *cep;
2367         bt_uuid_t uuid;
2368         uint8_t value[2];
2369
2370         if (!chrc->ext_props)
2371                 return true;
2372
2373         bt_uuid16_create(&uuid, GATT_CHARAC_EXT_PROPER_UUID);
2374         cep = gatt_db_service_add_descriptor(service->attrib, &uuid,
2375                                                         BT_ATT_PERM_READ,
2376                                                         NULL, NULL, NULL);
2377         if (!cep) {
2378                 error("Failed to create CEP entry for characteristic");
2379                 return false;
2380         }
2381
2382         memset(value, 0, sizeof(value));
2383         value[0] = chrc->ext_props;
2384
2385         if (!gatt_db_attribute_write(cep, 0, value, sizeof(value), 0, NULL,
2386                                                         cep_write_cb, NULL)) {
2387                 DBG("Failed to store CEP value in the database");
2388                 return false;
2389         }
2390
2391         DBG("Created CEP entry for characteristic");
2392
2393         return true;
2394 }
2395
2396 static void desc_read_cb(struct gatt_db_attribute *attrib,
2397                                         unsigned int id, uint16_t offset,
2398                                         uint8_t opcode, struct bt_att *att,
2399                                         void *user_data)
2400 {
2401         struct external_desc *desc = user_data;
2402
2403         if (desc->attrib != attrib) {
2404                 error("Read callback called with incorrect attribute");
2405                 return;
2406         }
2407 #ifdef __TIZEN_PATCH__
2408         send_read(attrib, att, desc->proxy, desc->pending_reads, id);
2409 #else
2410         send_read(attrib, desc->proxy, desc->pending_reads, id);
2411 #endif
2412 }
2413
2414 static void desc_write_cb(struct gatt_db_attribute *attrib,
2415                                         unsigned int id, uint16_t offset,
2416                                         const uint8_t *value, size_t len,
2417                                         uint8_t opcode, struct bt_att *att,
2418                                         void *user_data)
2419 {
2420         struct external_desc *desc = user_data;
2421
2422         if (desc->attrib != attrib) {
2423                 error("Read callback called with incorrect attribute");
2424                 return;
2425         }
2426
2427 #ifdef __TIZEN_PATCH__
2428         send_write(attrib, att, desc->proxy, desc->pending_writes, id, value, len);
2429 #else
2430         send_write(attrib, desc->proxy, desc->pending_writes, id, value, len);
2431 #endif
2432 }
2433
2434 static bool database_add_desc(struct external_service *service,
2435                                                 struct external_desc *desc)
2436 {
2437         bt_uuid_t uuid;
2438
2439         if (!parse_uuid(desc->proxy, &uuid)) {
2440                 error("Failed to read \"UUID\" property of descriptor");
2441                 return false;
2442         }
2443
2444         desc->attrib = gatt_db_service_add_descriptor(service->attrib, &uuid,
2445                                                         desc->perm,
2446                                                         desc_read_cb,
2447                                                         desc_write_cb, desc);
2448         if (!desc->attrib) {
2449                 error("Failed to create descriptor entry in database");
2450                 return false;
2451         }
2452
2453         desc->handled = true;
2454
2455         return true;
2456 }
2457
2458 static void chrc_read_cb(struct gatt_db_attribute *attrib,
2459                                         unsigned int id, uint16_t offset,
2460                                         uint8_t opcode, struct bt_att *att,
2461                                         void *user_data)
2462 {
2463         struct external_chrc *chrc = user_data;
2464
2465         if (chrc->attrib != attrib) {
2466                 error("Read callback called with incorrect attribute");
2467                 return;
2468         }
2469
2470 #ifdef __TIZEN_PATCH__
2471         send_read(attrib, att, chrc->proxy, chrc->pending_reads, id);
2472 #else
2473         send_read(attrib, chrc->proxy, chrc->pending_reads, id);
2474 #endif
2475 }
2476
2477 #ifndef __TIZEN_PATCH__
2478 static void write_without_response_setup_cb(DBusMessageIter *iter,
2479                                                         void *user_data)
2480 {
2481         struct iovec *iov = user_data;
2482         DBusMessageIter array;
2483
2484         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &array);
2485         dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
2486                                                 &iov->iov_base, iov->iov_len);
2487         dbus_message_iter_close_container(iter, &array);
2488 }
2489
2490 static void send_write_without_response(struct gatt_db_attribute *attrib,
2491                                         GDBusProxy *proxy, unsigned int id,
2492                                         const uint8_t *value, size_t len)
2493 {
2494         struct iovec iov;
2495         uint8_t ecode = 0;
2496
2497         iov.iov_base = (uint8_t *) value;
2498         iov.iov_len = len;
2499
2500         if (!g_dbus_proxy_method_call(proxy, "WriteValue",
2501                                         write_without_response_setup_cb,
2502                                         NULL, &iov, NULL))
2503                 ecode = BT_ATT_ERROR_UNLIKELY;
2504
2505         gatt_db_attribute_write_result(attrib, id, ecode);
2506 }
2507 #endif
2508
2509 static void chrc_write_cb(struct gatt_db_attribute *attrib,
2510                                         unsigned int id, uint16_t offset,
2511                                         const uint8_t *value, size_t len,
2512                                         uint8_t opcode, struct bt_att *att,
2513                                         void *user_data)
2514 {
2515         struct external_chrc *chrc = user_data;
2516
2517         if (chrc->attrib != attrib) {
2518                 error("Write callback called with incorrect attribute");
2519                 return;
2520         }
2521
2522 #ifdef __TIZEN_PATCH__
2523         if ((!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP) &&
2524                         opcode == BT_ATT_OP_WRITE_CMD) ||
2525                 (!(chrc->props & BT_GATT_CHRC_PROP_WRITE) &&
2526                         opcode == BT_ATT_OP_WRITE_REQ)) {
2527                 uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
2528                 error("Property and opcode is not matched");
2529                 gatt_db_attribute_write_result(attrib, id, ecode);
2530                 return;
2531         }
2532
2533         send_write(attrib, att, chrc->proxy, chrc->pending_writes, id, value, len);
2534 #else
2535         if (chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP) {
2536                 send_write_without_response(attrib, chrc->proxy, id, value,
2537                                                                         len);
2538                 return;
2539         }
2540
2541         send_write(attrib, chrc->proxy, chrc->pending_writes, id, value, len);
2542 #endif
2543 }
2544
2545 #ifdef __TIZEN_PATCH__
2546 static bool database_check_ccc_desc(struct external_desc *desc)
2547 {
2548         bt_uuid_t uuid, uuid_ccc;
2549
2550         if (!parse_uuid(desc->proxy, &uuid)) {
2551                 error("Failed to read \"UUID\" property of descriptor");
2552                 return false;
2553         }
2554
2555         bt_uuid16_create(&uuid_ccc, GATT_CLIENT_CHARAC_CFG_UUID);
2556         if (bt_uuid_cmp(&uuid, &uuid_ccc) == 0)
2557                 return true;
2558         else
2559                 return false;
2560 }
2561 #endif
2562
2563 static bool database_add_chrc(struct external_service *service,
2564                                                 struct external_chrc *chrc)
2565 {
2566         bt_uuid_t uuid;
2567         uint32_t perm;
2568         const struct queue_entry *entry;
2569
2570         if (!parse_uuid(chrc->proxy, &uuid)) {
2571                 error("Failed to read \"UUID\" property of characteristic");
2572                 return false;
2573         }
2574
2575         if (!check_service_path(chrc->proxy, service)) {
2576                 error("Invalid service path for characteristic");
2577                 return false;
2578         }
2579
2580         /*
2581          * TODO: Once shared/gatt-server properly supports permission checks,
2582          * set the permissions based on a D-Bus property of the external
2583          * characteristic.
2584          */
2585         perm = permissions_from_props(chrc->props, chrc->ext_props);
2586         chrc->attrib = gatt_db_service_add_characteristic(service->attrib,
2587                                                 &uuid, perm,
2588                                                 chrc->props, chrc_read_cb,
2589                                                 chrc_write_cb, chrc);
2590         if (!chrc->attrib) {
2591                 error("Failed to create characteristic entry in database");
2592                 return false;
2593         }
2594
2595 #ifndef __TIZEN_PATCH__
2596         /* Existing implementation adds CCC descriptor by default
2597           * if notification and indication properties are set. But as per the requirment
2598           * CCCD shall be added by the application */
2599         if (!database_add_ccc(service, chrc))
2600                 return false;
2601 #endif
2602
2603         if (!database_add_cep(service, chrc))
2604                 return false;
2605
2606         /* Handle the descriptors that belong to this characteristic. */
2607         for (entry = queue_get_entries(service->descs); entry;
2608                                                         entry = entry->next) {
2609                 struct external_desc *desc = entry->data;
2610
2611                 if (desc->handled || g_strcmp0(desc->chrc_path, chrc->path))
2612                         continue;
2613
2614 #ifdef __TIZEN_PATCH__
2615                 /* Check if Application wants to add CCC and use existing
2616                  * implemenation to add CCC descriptors */
2617                 if (database_check_ccc_desc(desc)) {
2618                         if (!database_add_ccc(service, chrc)) {
2619                                 chrc->attrib = NULL;
2620                                 return false;
2621                         }
2622                         desc->attrib = chrc->ccc;
2623                         desc->handled = true;
2624                 } else if (!database_add_desc(service, desc)) {
2625                         chrc->attrib = NULL;
2626                         error("Failed to create descriptor entry");
2627                                 return false;
2628                 }
2629 #else
2630                 if (!database_add_desc(service, desc)) {
2631                         chrc->attrib = NULL;
2632                         error("Failed to create descriptor entry");
2633                         return false;
2634                 }
2635 #endif
2636         }
2637
2638         return true;
2639 }
2640
2641 static bool match_desc_unhandled(const void *a, const void *b)
2642 {
2643         const struct external_desc *desc = a;
2644
2645         return !desc->handled;
2646 }
2647
2648 static bool database_add_service(struct external_service *service)
2649 {
2650         bt_uuid_t uuid;
2651         bool primary;
2652         const struct queue_entry *entry;
2653
2654         if (!parse_uuid(service->proxy, &uuid)) {
2655                 error("Failed to read \"UUID\" property of service");
2656                 return false;
2657         }
2658
2659         if (!parse_primary(service->proxy, &primary)) {
2660                 error("Failed to read \"Primary\" property of service");
2661                 return false;
2662         }
2663
2664         service->attrib = gatt_db_add_service(service->app->database->db, &uuid,
2665                                                 primary, service->attr_cnt);
2666         if (!service->attrib)
2667                 return false;
2668
2669         entry = queue_get_entries(service->chrcs);
2670         while (entry) {
2671                 struct external_chrc *chrc = entry->data;
2672
2673                 if (!database_add_chrc(service, chrc)) {
2674                         error("Failed to add characteristic");
2675                         goto fail;
2676                 }
2677
2678                 entry = entry->next;
2679         }
2680
2681         /* If there are any unhandled descriptors, return an error */
2682         if (queue_find(service->descs, match_desc_unhandled, NULL)) {
2683                 error("Found descriptor with no matching characteristic!");
2684                 goto fail;
2685         }
2686
2687         gatt_db_service_set_active(service->attrib, true);
2688
2689         return true;
2690
2691 fail:
2692         gatt_db_remove_service(service->app->database->db, service->attrib);
2693         service->attrib = NULL;
2694
2695         return false;
2696 }
2697
2698 static bool database_add_app(struct gatt_app *app)
2699 {
2700         const struct queue_entry *entry;
2701
2702         if (queue_isempty(app->services))
2703                 return false;
2704
2705         entry = queue_get_entries(app->services);
2706         while (entry) {
2707                 if (!database_add_service(entry->data)) {
2708                         error("Failed to add service");
2709                         return false;
2710                 }
2711
2712                 entry = entry->next;
2713         }
2714
2715         return true;
2716 }
2717
2718 static void client_ready_cb(GDBusClient *client, void *user_data)
2719 {
2720         struct gatt_app *app = user_data;
2721         DBusMessage *reply;
2722         bool fail = false;
2723
2724         if (!app->services || app->failed) {
2725                 error("No valid external GATT objects found");
2726                 fail = true;
2727                 reply = btd_error_failed(app->reg,
2728                                         "No valid service object found");
2729                 goto reply;
2730         }
2731
2732         if (!database_add_app(app)) {
2733                 error("Failed to create GATT service entry in local database");
2734                 fail = true;
2735                 reply = btd_error_failed(app->reg,
2736                                         "Failed to create entry in database");
2737                 goto reply;
2738         }
2739
2740         DBG("GATT application registered: %s:%s", app->owner, app->path);
2741
2742         reply = dbus_message_new_method_return(app->reg);
2743
2744 reply:
2745         g_dbus_send_message(btd_get_dbus_connection(), reply);
2746         dbus_message_unref(app->reg);
2747         app->reg = NULL;
2748
2749         if (fail)
2750                 remove_app(app);
2751 }
2752
2753 static struct gatt_app *create_app(DBusConnection *conn, DBusMessage *msg,
2754                                                         const char *path)
2755 {
2756         struct gatt_app *app;
2757         const char *sender = dbus_message_get_sender(msg);
2758
2759         if (!path || !g_str_has_prefix(path, "/"))
2760                 return NULL;
2761
2762         app = new0(struct gatt_app, 1);
2763
2764         app->client = g_dbus_client_new_full(conn, sender, path, path);
2765         if (!app->client)
2766                 goto fail;
2767
2768         app->owner = g_strdup(sender);
2769         if (!app->owner)
2770                 goto fail;
2771
2772         app->path = g_strdup(path);
2773         if (!app->path)
2774                 goto fail;
2775
2776         app->services = queue_new();
2777         app->reg = dbus_message_ref(msg);
2778
2779         g_dbus_client_set_disconnect_watch(app->client, client_disconnect_cb,
2780                                                                         app);
2781         g_dbus_client_set_proxy_handlers(app->client, proxy_added_cb,
2782                                         proxy_removed_cb, NULL, app);
2783         g_dbus_client_set_ready_watch(app->client, client_ready_cb, app);
2784
2785         return app;
2786
2787 fail:
2788         app_free(app);
2789         return NULL;
2790 }
2791
2792 static DBusMessage *manager_register_app(DBusConnection *conn,
2793                                         DBusMessage *msg, void *user_data)
2794 {
2795         struct btd_gatt_database *database = user_data;
2796         const char *sender = dbus_message_get_sender(msg);
2797         DBusMessageIter args;
2798         const char *path;
2799         struct gatt_app *app;
2800         struct svc_match_data match_data;
2801
2802         if (!dbus_message_iter_init(msg, &args))
2803                 return btd_error_invalid_args(msg);
2804
2805         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
2806                 return btd_error_invalid_args(msg);
2807
2808         dbus_message_iter_get_basic(&args, &path);
2809
2810         match_data.path = path;
2811         match_data.sender = sender;
2812
2813         if (queue_find(database->apps, match_app, &match_data))
2814                 return btd_error_already_exists(msg);
2815
2816         dbus_message_iter_next(&args);
2817         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
2818                 return btd_error_invalid_args(msg);
2819
2820         app = create_app(conn, msg, path);
2821         if (!app)
2822                 return btd_error_failed(msg, "Failed to register application");
2823
2824         DBG("Registering application: %s:%s", sender, path);
2825
2826         app->database = database;
2827         queue_push_tail(database->apps, app);
2828
2829         return NULL;
2830 }
2831
2832 static DBusMessage *manager_unregister_app(DBusConnection *conn,
2833                                         DBusMessage *msg, void *user_data)
2834 {
2835         struct btd_gatt_database *database = user_data;
2836         const char *sender = dbus_message_get_sender(msg);
2837         const char *path;
2838         DBusMessageIter args;
2839         struct gatt_app *app;
2840         struct svc_match_data match_data;
2841
2842         if (!dbus_message_iter_init(msg, &args))
2843                 return btd_error_invalid_args(msg);
2844
2845         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
2846                 return btd_error_invalid_args(msg);
2847
2848         dbus_message_iter_get_basic(&args, &path);
2849
2850         match_data.path = path;
2851         match_data.sender = sender;
2852
2853         app = queue_remove_if(database->apps, match_app, &match_data);
2854         if (!app)
2855                 return btd_error_does_not_exist(msg);
2856
2857         app_free(app);
2858
2859         return dbus_message_new_method_return(msg);
2860 }
2861
2862 static void profile_exited(DBusConnection *conn, void *user_data)
2863 {
2864         struct external_profile *profile = user_data;
2865
2866         DBG("\"%s\" exited", profile->owner);
2867
2868         profile->id = 0;
2869
2870         queue_remove(profile->database->profiles, profile);
2871
2872         profile_free(profile);
2873 }
2874
2875 static int profile_device_probe(struct btd_service *service)
2876 {
2877         struct btd_profile *p = btd_service_get_profile(service);
2878
2879         DBG("%s probed", p->name);
2880
2881         return 0;
2882 }
2883
2884 static void profile_device_remove(struct btd_service *service)
2885 {
2886         struct btd_profile *p = btd_service_get_profile(service);
2887
2888         DBG("%s removed", p->name);
2889 }
2890
2891 static int profile_add(struct external_profile *profile, const char *uuid)
2892 {
2893         struct btd_profile *p;
2894
2895         p = new0(struct btd_profile, 1);
2896
2897         /* Assign directly to avoid having extra fields */
2898         p->name = (const void *) g_strdup_printf("%s%s/%s", profile->owner,
2899                                                         profile->path, uuid);
2900         if (!p->name) {
2901                 free(p);
2902                 return -ENOMEM;
2903         }
2904
2905         p->remote_uuid = (const void *) g_strdup(uuid);
2906         if (!p->remote_uuid) {
2907                 g_free((void *) p->name);
2908                 free(p);
2909                 return -ENOMEM;
2910         }
2911
2912         p->device_probe = profile_device_probe;
2913         p->device_remove = profile_device_remove;
2914         p->auto_connect = true;
2915         p->external = true;
2916
2917         queue_push_tail(profile->profiles, p);
2918
2919         DBG("Added \"%s\"", p->name);
2920
2921         return 0;
2922 }
2923
2924 static void add_profile(void *data, void *user_data)
2925 {
2926         struct btd_adapter *adapter = user_data;
2927
2928         btd_profile_register(data);
2929         adapter_add_profile(adapter, data);
2930 }
2931
2932 static int profile_create(DBusConnection *conn,
2933                                 struct btd_gatt_database *database,
2934                                 const char *sender, const char *path,
2935                                 DBusMessageIter *iter)
2936 {
2937         struct external_profile *profile;
2938         DBusMessageIter uuids;
2939
2940         if (!path || !g_str_has_prefix(path, "/"))
2941                 return -EINVAL;
2942
2943         profile = new0(struct external_profile, 1);
2944
2945         profile->owner = g_strdup(sender);
2946         if (!profile->owner)
2947                 goto fail;
2948
2949         profile->path = g_strdup(path);
2950         if (!profile->path)
2951                 goto fail;
2952
2953         profile->profiles = queue_new();
2954         profile->database = database;
2955         profile->id = g_dbus_add_disconnect_watch(conn, sender, profile_exited,
2956                                                                 profile, NULL);
2957
2958         dbus_message_iter_recurse(iter, &uuids);
2959
2960         while (dbus_message_iter_get_arg_type(&uuids) == DBUS_TYPE_STRING) {
2961                 const char *uuid;
2962
2963                 dbus_message_iter_get_basic(&uuids, &uuid);
2964
2965                 if (profile_add(profile, uuid) < 0)
2966                         goto fail;
2967
2968                 dbus_message_iter_next(&uuids);
2969         }
2970
2971         if (queue_isempty(profile->profiles))
2972                 goto fail;
2973
2974         queue_foreach(profile->profiles, add_profile, database->adapter);
2975         queue_push_tail(database->profiles, profile);
2976
2977         return 0;
2978
2979 fail:
2980         profile_free(profile);
2981         return -EINVAL;
2982 }
2983
2984 static bool match_profile(const void *a, const void *b)
2985 {
2986         const struct external_profile *profile = a;
2987         const struct svc_match_data *data = b;
2988
2989         return g_strcmp0(profile->path, data->path) == 0 &&
2990                                 g_strcmp0(profile->owner, data->sender) == 0;
2991 }
2992
2993 static DBusMessage *manager_register_profile(DBusConnection *conn,
2994                                         DBusMessage *msg, void *user_data)
2995 {
2996         struct btd_gatt_database *database = user_data;
2997         const char *sender = dbus_message_get_sender(msg);
2998         DBusMessageIter args;
2999         const char *path;
3000         struct svc_match_data match_data;
3001
3002         DBG("sender %s", sender);
3003
3004         if (!dbus_message_iter_init(msg, &args))
3005                 return btd_error_invalid_args(msg);
3006
3007         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
3008                 return btd_error_invalid_args(msg);
3009
3010         dbus_message_iter_get_basic(&args, &path);
3011
3012         match_data.path = path;
3013         match_data.sender = sender;
3014
3015         if (queue_find(database->profiles, match_profile, &match_data))
3016                 return btd_error_already_exists(msg);
3017
3018         dbus_message_iter_next(&args);
3019         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
3020                 return btd_error_invalid_args(msg);
3021
3022         if (profile_create(conn, database, sender, path, &args) < 0)
3023                 return btd_error_failed(msg, "Failed to register profile");
3024
3025         return dbus_message_new_method_return(msg);
3026 }
3027
3028 static DBusMessage *manager_unregister_profile(DBusConnection *conn,
3029                                         DBusMessage *msg, void *user_data)
3030 {
3031         struct btd_gatt_database *database = user_data;
3032         const char *sender = dbus_message_get_sender(msg);
3033         const char *path;
3034         DBusMessageIter args;
3035         struct external_profile *profile;
3036         struct svc_match_data match_data;
3037
3038         if (!dbus_message_iter_init(msg, &args))
3039                 return btd_error_invalid_args(msg);
3040
3041         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
3042                 return btd_error_invalid_args(msg);
3043
3044         dbus_message_iter_get_basic(&args, &path);
3045
3046         match_data.path = path;
3047         match_data.sender = sender;
3048
3049         profile = queue_remove_if(database->profiles, match_profile,
3050                                                                 &match_data);
3051         if (!profile)
3052                 return btd_error_does_not_exist(msg);
3053
3054         profile_free(profile);
3055
3056         return dbus_message_new_method_return(msg);
3057 }
3058
3059 static const GDBusMethodTable manager_methods[] = {
3060 #ifdef __TIZEN_PATCH__
3061         { GDBUS_ASYNC_METHOD("RegisterApplication",
3062                         GDBUS_ARGS({ "application", "o" },
3063                         { "options", "a{sv}" }), NULL,
3064                         manager_register_app) },
3065         { GDBUS_ASYNC_METHOD("UnregisterApplication",
3066                                         GDBUS_ARGS({ "application", "o" }),
3067                                         NULL, manager_unregister_app) },
3068         { GDBUS_ASYNC_METHOD("RegisterProfile",
3069                         GDBUS_ARGS({ "profile", "o" }, { "UUIDs", "as" },
3070                         { "options", "a{sv}" }), NULL,
3071                         manager_register_profile) },
3072         { GDBUS_ASYNC_METHOD("UnregisterProfile",
3073                                         GDBUS_ARGS({ "profile", "o" }),
3074                                         NULL, manager_unregister_profile) },
3075         { }
3076 #else
3077         { GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterApplication",
3078                         GDBUS_ARGS({ "application", "o" },
3079                         { "options", "a{sv}" }), NULL,
3080                         manager_register_app) },
3081         { GDBUS_EXPERIMENTAL_ASYNC_METHOD("UnregisterApplication",
3082                                         GDBUS_ARGS({ "application", "o" }),
3083                                         NULL, manager_unregister_app) },
3084         { GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterProfile",
3085                         GDBUS_ARGS({ "profile", "o" }, { "UUIDs", "as" },
3086                         { "options", "a{sv}" }), NULL,
3087                         manager_register_profile) },
3088         { GDBUS_EXPERIMENTAL_ASYNC_METHOD("UnregisterProfile",
3089                                         GDBUS_ARGS({ "profile", "o" }),
3090                                         NULL, manager_unregister_profile) },
3091         { }
3092 #endif
3093 };
3094
3095 struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
3096 {
3097         struct btd_gatt_database *database;
3098         GError *gerr = NULL;
3099         const bdaddr_t *addr;
3100
3101         if (!adapter)
3102                 return NULL;
3103
3104         database = new0(struct btd_gatt_database, 1);
3105         database->adapter = btd_adapter_ref(adapter);
3106         database->db = gatt_db_new();
3107         database->device_states = queue_new();
3108         database->apps = queue_new();
3109         database->profiles = queue_new();
3110         database->ccc_callbacks = queue_new();
3111
3112         database->db_id = gatt_db_register(database->db, gatt_db_service_added,
3113                                                         gatt_db_service_removed,
3114                                                         database, NULL);
3115         if (!database->db_id)
3116                 goto fail;
3117
3118         addr = btd_adapter_get_address(adapter);
3119         database->le_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
3120                                         BT_IO_OPT_SOURCE_BDADDR, addr,
3121                                         BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
3122                                         BT_IO_OPT_CID, ATT_CID,
3123                                         BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
3124                                         BT_IO_OPT_INVALID);
3125         if (!database->le_io) {
3126                 error("Failed to start listening: %s", gerr->message);
3127                 g_error_free(gerr);
3128                 goto fail;
3129         }
3130
3131         /* BR/EDR socket */
3132         database->l2cap_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
3133                                         BT_IO_OPT_SOURCE_BDADDR, addr,
3134                                         BT_IO_OPT_PSM, ATT_PSM,
3135                                         BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
3136                                         BT_IO_OPT_INVALID);
3137         if (database->l2cap_io == NULL) {
3138                 error("Failed to start listening: %s", gerr->message);
3139                 g_error_free(gerr);
3140                 goto fail;
3141         }
3142
3143         if (g_dbus_register_interface(btd_get_dbus_connection(),
3144                                                 adapter_get_path(adapter),
3145                                                 GATT_MANAGER_IFACE,
3146                                                 manager_methods, NULL, NULL,
3147                                                 database, NULL))
3148                 DBG("GATT Manager registered for adapter: %s",
3149                                                 adapter_get_path(adapter));
3150
3151         register_core_services(database);
3152
3153         return database;
3154
3155 fail:
3156         gatt_database_free(database);
3157
3158         return NULL;
3159 }
3160
3161 void btd_gatt_database_destroy(struct btd_gatt_database *database)
3162 {
3163         if (!database)
3164                 return;
3165
3166         g_dbus_unregister_interface(btd_get_dbus_connection(),
3167                                         adapter_get_path(database->adapter),
3168                                         GATT_MANAGER_IFACE);
3169
3170         gatt_database_free(database);
3171 }
3172
3173 struct gatt_db *btd_gatt_database_get_db(struct btd_gatt_database *database)
3174 {
3175         if (!database)
3176                 return NULL;
3177
3178         return database->db;
3179 }