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