Add the gatt server check flag
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-service.c
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include<gio/gio.h>
19 #include<glib.h>
20 #include<glib/gprintf.h>
21 #include<stdlib.h>
22 #include<unistd.h>
23 #include<stdint.h>
24 #include<stdbool.h>
25
26 #include "bt-common.h"
27 #include "bt-internal-types.h"
28
29 #define NUMBER_OF_FLAGS 10
30
31 GDBusConnection *g_conn;
32 guint owner_id;
33 guint manager_id;
34 static gboolean new_service = FALSE;
35 static gboolean new_char = FALSE;
36 static int serv_id = 1;
37 static int register_pending_cnt = 0;
38 static bool is_server_started = false;
39
40 /* Introspection data for the service we are exporting */
41 static const gchar service_introspection_xml[] =
42 "<node name='/'>"
43 "  <interface name='org.freedesktop.DBus.Properties'>"
44 "    <property type='s' name='UUID' access='read'>"
45 "    </property>"
46 "        <property type='b' name='primary' access='read'>"
47 "        </property>"
48 "        <property type='o' name='Device' access='read'>"
49 "        </property>"
50 "        <property type='ao' name='Characteristics' access='read'>"
51 "        </property>"
52 "        <property type='s' name='Includes' access='read'>"
53 "        </property>"
54 "  </interface>"
55 "</node>";
56
57 /* Introspection data for the characteristics we are exporting */
58 static const gchar characteristics_introspection_xml[] =
59 "<node name='/'>"
60 "  <interface name='org.bluez.GattCharacteristic1'>"
61 "        <method name='ReadValue'>"
62 "               <arg type='s' name='address' direction='in'/>"
63 "               <arg type='y' name='id' direction='in'/>"
64 "               <arg type='q' name='offset' direction='in'/>"
65 "               <arg type='ay' name='Value' direction='out'/>"
66 "        </method>"
67 "        <method name='WriteValue'>"
68 "               <arg type='s' name='address' direction='in'/>"
69 "               <arg type='y' name='id' direction='in'/>"
70 "               <arg type='q' name='offset' direction='in'/>"
71 "               <arg type='ay' name='value' direction='in'/>"
72 "        </method>"
73 "        <method name='StartNotify'>"
74 "        </method>"
75 "        <method name='StopNotify'>"
76 "        </method>"
77 "        <method name='IndicateConfirm'>"
78 "               <arg type='s' name='address' direction='in'/>"
79 "               <arg type='b' name='complete' direction='in'/>"
80 "        </method>"
81 "  </interface>"
82 "  <interface name='org.freedesktop.DBus.Properties'>"
83 "    <property type='s' name='UUID' access='read'>"
84 "    </property>"
85 "    <property type='o' name='Service' access='read'>"
86 "    </property>"
87 "    <property type='ay' name='Value' access='readwrite'>"
88 "    </property>"
89 "        <property type='b' name='Notifying' access='read'>"
90 "        </property>"
91 "    <property type='as' name='Flags' access='read'>"
92 "    </property>"
93 "    <property type='s' name='Unicast' access='read'>"
94 "    </property>"
95 "        <property type='ao' name='Descriptors' access='read'>"
96 "        </property>"
97 "  </interface>"
98 "</node>";
99
100 /* Introspection data for the descriptor we are exporting */
101 static const gchar descriptor_introspection_xml[] =
102 "<node name='/'>"
103 "  <interface name='org.bluez.GattDescriptor1'>"
104 "        <method name='ReadValue'>"
105 "               <arg type='s' name='address' direction='in'/>"
106 "               <arg type='y' name='id' direction='in'/>"
107 "               <arg type='q' name='offset' direction='in'/>"
108 "               <arg type='ay' name='Value' direction='out'/>"
109 "        </method>"
110 "        <method name='WriteValue'>"
111 "               <arg type='s' name='address' direction='in'/>"
112 "               <arg type='y' name='id' direction='in'/>"
113 "               <arg type='q' name='offset' direction='in'/>"
114 "               <arg type='ay' name='value' direction='in'/>"
115 "        </method>"
116 "  </interface>"
117 "  <interface name='org.freedesktop.DBus.Properties'>"
118 "    <property type='s' name='UUID' access='read'>"
119 "    </property>"
120 "    <property type='o' name='Characteristic' access='read'>"
121 "    </property>"
122 "    <property type='ay' name='Value' access='read'>"
123 "    </property>"
124 "    <property type='as' name='Flags' access='read'>"
125 "    </property>"
126 "  </interface>"
127 "</node>";
128
129 static const gchar manager_introspection_xml[] =
130 "<node name='/'>"
131 "  <interface name='org.freedesktop.DBus.ObjectManager'>"
132 "    <method name='GetManagedObjects'>"
133 "     <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
134 "        </method>"
135 "  </interface>"
136 "</node>";
137
138 struct gatt_service_info {
139         gchar *serv_path;
140         guint serv_id;
141         gchar *service_uuid;
142         guint manager_id;
143         guint prop_id;
144         GSList *char_data;
145         gboolean is_svc_registered;
146         gboolean is_svc_primary;
147 };
148
149 struct gatt_char_info {
150         gchar *char_path;
151         guint char_id;
152         gchar *char_uuid;
153         gchar *char_value;
154         gchar *char_flags[NUMBER_OF_FLAGS];
155         int value_length;
156         int flags_length;
157         GSList *desc_data;
158 };
159
160 struct gatt_desc_info {
161         gchar *desc_path;
162         guint desc_id;
163         gchar *desc_uuid;
164         gchar *desc_value;
165         gchar *desc_flags[NUMBER_OF_FLAGS];
166         int value_length;
167         int flags_length;
168 };
169
170 struct gatt_req_info {
171         gchar *attr_path;
172         gchar *svc_path;
173         guint  request_id;
174         guint  offset;
175         GDBusMethodInvocation *context;
176 };
177
178 static GSList *gatt_services = NULL;
179 static GSList *gatt_requests = NULL;
180 static gchar *app_path = NULL;
181
182 #define BT_GATT_SERVICE_NAME    "org.frwk.gatt_service"
183 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
184
185 #define GATT_SERV_OBJECT_PATH   "/service"
186
187 #define GATT_MNGR_INTERFACE             "org.bluez.GattManager1"
188 #define GATT_SERV_INTERFACE             "org.bluez.GattService1"
189 #define GATT_CHAR_INTERFACE             "org.bluez.GattCharacteristic1"
190 #define GATT_DESC_INTERFACE             "org.bluez.GattDescriptor1"
191
192 #ifdef HPS_FEATURE
193 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
194 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
195 #define PROPERTIES_CHANGED "PropertiesChanged"
196 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
197 #endif
198
199 static GDBusProxy *manager_gproxy = NULL;
200
201 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
202                         const char *service_path, const char *char_path);
203 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
204                         const char *serv_path, const char *char_path,
205                         const char *desc_path);
206
207 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
208
209 #ifdef HPS_FEATURE
210 static int __bt_send_event_to_hps(int event, GVariant *var)
211 {
212         GError *error = NULL;
213         GVariant *parameters;
214         GDBusMessage *msg = NULL;
215
216         BT_DBG(" ");
217
218         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
219
220         if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
221                 GVariantBuilder *inner_builder;
222                 GVariantBuilder *invalidated_builder;
223
224                 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
225                 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
226
227                 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
228
229                 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
230
231                 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
232                 g_variant_builder_unref(invalidated_builder);
233                 g_variant_builder_unref(inner_builder);
234         } else if (BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
235                 GVariantBuilder *inner_builder;
236                 GVariantBuilder *invalidated_builder;
237
238                 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
239                 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
240
241                 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
242
243                 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
244
245                 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
246                 g_variant_builder_unref(invalidated_builder);
247                 g_variant_builder_unref(inner_builder);
248         }
249
250         msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
251         g_dbus_message_set_body(msg, parameters);
252         if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
253                 if (error != NULL) {
254                         BT_ERR("D-Bus API failure: errCode[%x], \
255                                         message[%s]",
256                                         error->code, error->message);
257                         g_clear_error(&error);
258                 }
259                 return BLUETOOTH_ERROR_INTERNAL;
260         }
261         return BLUETOOTH_ERROR_NONE;
262 }
263 #endif
264
265 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
266                                         const gchar *sender,
267                                         const gchar *object_path,
268                                         const gchar *interface_name,
269                                         const gchar *method_name,
270                                         GVariant *parameters,
271                                         GDBusMethodInvocation *invocation,
272                                         gpointer user_data)
273 {
274         GSList *l1;
275         int len = 0;
276         int i = 0;
277
278         if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
279                 BT_DBG("Getting values for service, chars and descriptors");
280
281                 GVariantBuilder *builder;
282                 GVariantBuilder *inner_builder1 = NULL;
283                 GVariant *svc_char = NULL;
284                 GSList *l4;
285                 /*Main Builder */
286                 builder = g_variant_builder_new(
287                                 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
288
289                 /* Prepare inner builder for GattService1 interface */
290
291                 len = g_slist_length(gatt_services);
292
293                 for (i = 0; i <= len; i++) {
294                         GVariantBuilder *svc_builder = NULL;
295                         GVariantBuilder *inner_builder = NULL;
296
297                         if (register_pending_cnt > 1) {
298                                 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
299                         } else {
300                                 l1 = g_slist_last(gatt_services);
301                         }
302                         register_pending_cnt--;
303
304                         struct gatt_service_info *serv_info = l1->data;
305                         if (serv_info == NULL) {
306                                 BT_ERR("service info value is NULL");
307                                 g_dbus_method_invocation_return_value(invocation, NULL);
308                                 return;
309                         }
310
311                         /* Prepare inner builder for GattService1 interface */
312                         BT_DBG("Creating builder for service");
313                         svc_builder = g_variant_builder_new(
314                                                 G_VARIANT_TYPE("a{sa{sv}}"));
315                         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
316
317                         g_variant_builder_add(inner_builder, "{sv}", "UUID",
318                                         g_variant_new_string(serv_info->service_uuid));
319
320                         g_variant_builder_add(inner_builder, "{sv}", "Primary",
321                                         g_variant_new_boolean(serv_info->is_svc_primary));
322
323                         /*Characteristics*/
324                         inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
325                         BT_DBG("Adding Charatarisitcs list");
326                         for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
327                                 struct gatt_char_info *char_info = l4->data;
328                                         g_variant_builder_add(inner_builder1, "o",
329                                                 char_info->char_path);
330                                         BT_DBG("%s", char_info->char_path);
331                         }
332
333                         svc_char = g_variant_new("ao", inner_builder1);
334                         g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
335                                                 svc_char);
336
337                         g_variant_builder_add(svc_builder, "{sa{sv}}",
338                                                                 GATT_SERV_INTERFACE,
339                                                                 inner_builder);
340
341                         g_variant_builder_add(builder, "{oa{sa{sv}}}",
342                                                                 serv_info->serv_path,
343                                                                 svc_builder);
344
345                         g_variant_builder_unref(inner_builder1);
346
347                         /* Prepare inner builder for GattCharacteristic1 interface */
348
349                         GSList *l2 = serv_info->char_data;
350                         BT_DBG("Creating builder for characteristics \n");
351
352                         if (l2 == NULL)
353                                 BT_DBG("characteristic data is NULL");
354
355                         for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
356
357                                 GVariantBuilder *char_builder = NULL;
358                                 GVariantBuilder *inner_builder = NULL;
359                                 GVariantBuilder *builder1 = NULL;
360                                 GVariantBuilder *builder2 = NULL;
361                                 GVariantBuilder *builder3 = NULL;
362                                 GVariant *char_val = NULL;
363                                 GVariant *flags_val = NULL;
364                                 GVariant *char_desc = NULL;
365                                 char *unicast = NULL;
366                                 gboolean notify = FALSE;
367                                 int i = 0;
368
369                                 char_builder = g_variant_builder_new(
370                                                                 G_VARIANT_TYPE(
371                                                                         "a{sa{sv}}"));
372                                 inner_builder = g_variant_builder_new(
373                                                                 G_VARIANT_TYPE(
374                                                                         "a{sv}"));
375
376                                 struct gatt_char_info *char_info = l2->data;
377                                 if (char_info == NULL) {
378                                         BT_ERR("char_info is NULL");
379                                         continue;
380                                 }
381
382                                 /*Uuid*/
383                                 g_variant_builder_add(inner_builder, "{sv}", "UUID",
384                                         g_variant_new_string(char_info->char_uuid));
385                                 /*Service*/
386                                 g_variant_builder_add(inner_builder, "{sv}", "Service",
387                                         g_variant_new("o", serv_info->serv_path));
388                                 /*Value*/
389                                 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
390
391                                 if (char_info->char_value != NULL) {
392                                         for (i = 0; i < char_info->value_length; i++) {
393                                                 g_variant_builder_add(builder1, "y",
394                                                         char_info->char_value[i]);
395                                         }
396                                         char_val = g_variant_new("ay", builder1);
397                                         g_variant_builder_add(inner_builder, "{sv}",
398                                                         "Value", char_val);
399                                 }
400                                 /*Flags*/
401                                 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
402
403                                 for (i = 0; i < char_info->flags_length; i++) {
404                                         g_variant_builder_add(builder2, "s",
405                                                 char_info->char_flags[i]);
406                                 }
407
408                                 flags_val = g_variant_new("as", builder2);
409                                 g_variant_builder_add(inner_builder, "{sv}", "Flags",
410                                                         flags_val);
411
412                                 /* Notifying */
413                                 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
414                                                         g_variant_new("b", notify));
415
416                                 /* Unicast */
417                                 unicast = g_strdup("00:00:00:00:00:00");
418                                 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
419                                                         g_variant_new("s", unicast));
420
421                                 /*Descriptors*/
422                                 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
423                                 BT_DBG("Adding Descriptors list");
424
425                                 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
426                                         struct gatt_desc_info *desc_info = l4->data;
427                                                 g_variant_builder_add(builder3, "o",
428                                                         desc_info->desc_path);
429                                                 BT_DBG("%s", desc_info->desc_path);
430                                 }
431
432                                 char_desc = g_variant_new("ao", builder3);
433                                 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
434                                                         char_desc);
435
436                                 g_variant_builder_add(char_builder, "{sa{sv}}",
437                                                 GATT_CHAR_INTERFACE , inner_builder);
438                                 g_variant_builder_add(builder, "{oa{sa{sv}}}",
439                                                 char_info->char_path, char_builder);
440
441                                 /*Prepare inner builder for GattDescriptor1 interface*/
442
443                                 GSList *l3 = char_info->desc_data;
444
445                                 if (l3 == NULL)
446                                         BT_DBG("descriptor data is NULL");
447
448                                 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
449
450                                         BT_DBG("Creating builder for descriptor \n");
451
452                                         GVariantBuilder *desc_builder = NULL;
453                                         GVariantBuilder *inner_builder = NULL;
454                                         GVariantBuilder *builder1 = NULL;
455                                         GVariantBuilder *builder2 = NULL;
456                                         GVariant *desc_val = NULL;
457
458                                         desc_builder = g_variant_builder_new(
459                                                                 G_VARIANT_TYPE(
460                                                                 "a{sa{sv}}"));
461                                         inner_builder = g_variant_builder_new(
462                                                                 G_VARIANT_TYPE(
463                                                                 "a{sv}"));
464
465                                         struct gatt_desc_info *desc_info = l3->data;
466                                         if (desc_info == NULL) {
467                                                 BT_ERR("desc_info is NULL");
468                                                 continue;
469                                         }
470
471                                         /*Uuid*/
472                                         g_variant_builder_add(inner_builder,
473                                                 "{sv}", "UUID",
474                                                 g_variant_new_string(
475                                                         desc_info->desc_uuid));
476
477                                         /*Characteristic*/
478                                         g_variant_builder_add(inner_builder, "{sv}",
479                                                 "Characteristic",
480                                                 g_variant_new("o",
481                                                         char_info->char_path));
482
483                                         /*Value*/
484                                         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
485
486                                         if (desc_info->desc_value != NULL) {
487                                                 for (i = 0; i < desc_info->value_length; i++) {
488                                                         g_variant_builder_add(builder1, "y",
489                                                                 desc_info->desc_value[i]);
490                                                 }
491                                                 desc_val = g_variant_new("ay", builder1);
492                                                 g_variant_builder_add(inner_builder, "{sv}",
493                                                                 "Value", desc_val);
494                                         }
495
496                                         /*Flags*/
497                                         builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
498
499                                         for (i = 0; i < desc_info->flags_length; i++) {
500                                                 g_variant_builder_add(builder2, "s",
501                                                         desc_info->desc_flags[i]);
502                                         }
503
504                                         flags_val = g_variant_new("as", builder2);
505                                         g_variant_builder_add(inner_builder, "{sv}", "Flags",
506                                                                 flags_val);
507
508                                         g_variant_builder_add(desc_builder, "{sa{sv}}",
509                                                         GATT_DESC_INTERFACE,
510                                                         inner_builder);
511
512                                         g_variant_builder_add(builder, "{oa{sa{sv}}}",
513                                                         desc_info->desc_path,
514                                                         desc_builder);
515
516                                         /*unref descriptor builder pointers*/
517                                         g_variant_builder_unref(builder1);
518                                         g_variant_builder_unref(builder2);
519                                         g_variant_builder_unref(inner_builder);
520                                         g_variant_builder_unref(desc_builder);
521                                 }
522
523                                 if (unicast)
524                                         g_free(unicast);
525                                 /*unref char builder pointers*/
526                                 g_variant_builder_unref(builder1);
527                                 g_variant_builder_unref(builder2);
528                                 g_variant_builder_unref(builder3);
529                                 g_variant_builder_unref(inner_builder);
530                                 g_variant_builder_unref(char_builder);
531                         }
532
533                         /*unref service builder pointers*/
534                         g_variant_builder_unref(inner_builder);
535                         g_variant_builder_unref(svc_builder);
536                 }
537
538                 /* Return builder as method reply */
539                 BT_DBG("Sending gatt service builder values to Bluez");
540                 g_dbus_method_invocation_return_value(invocation,
541                                                 g_variant_new(
542                                                 "(a{oa{sa{sv}}})",
543                                                 builder));
544         }
545 }
546
547 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
548 {
549         GSList *l1, *l2;
550
551         for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
552                 struct gatt_service_info *serv_info = l1->data;
553
554                 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
555                         struct gatt_char_info *char_info = l2->data;
556
557                         if (g_strcmp0(char_info->char_path, char_path)
558                                                 == 0)
559                                 return serv_info;
560                 }
561         }
562         BT_ERR("Gatt service not found");
563         return NULL;
564 }
565
566 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
567 {
568         GSList *l1, *l2, *l3;
569
570         for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
571                 struct gatt_service_info *serv_info = l1->data;
572
573                 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
574                         struct gatt_char_info *char_info = l2->data;
575
576                         for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
577                                 struct gatt_desc_info *desc_info = l3->data;
578
579                                 if (g_strcmp0(desc_info->desc_path, desc_path)
580                                                         == 0)
581                                         return serv_info;
582                         }
583                 }
584         }
585         BT_ERR("Gatt service not found");
586         return NULL;
587 }
588
589 static void __bt_gatt_char_method_call(GDBusConnection *connection,
590                                         const gchar *sender,
591                                         const gchar *object_path,
592                                         const gchar *interface_name,
593                                         const gchar *method_name,
594                                         GVariant *parameters,
595                                         GDBusMethodInvocation *invocation,
596                                         gpointer user_data)
597 {
598
599         if (g_strcmp0(method_name, "ReadValue") == 0) {
600                 gchar *addr = NULL;
601                 guint8 req_id = 1;
602                 guint16 offset = 0;
603                 bt_gatt_read_req_t read_req = {0, };
604                 bt_user_info_t *user_info = NULL;
605                 struct gatt_req_info *req_info = NULL;
606                 struct gatt_service_info *svc_info = NULL;
607
608                 BT_DBG("ReadValue");
609
610                 g_variant_get(parameters, "(&syq)", &addr, &req_id, &offset);
611
612                 BT_DBG("Application path = %s", object_path);
613
614                 BT_DBG("Remote Device address number = %s", addr);
615                 BT_DBG("Request id = %d, Offset = %d", req_id, offset);
616
617                 BT_DBG("Sender = %s", sender);
618
619                 read_req.att_handle = g_strdup(object_path);
620                 read_req.address = g_strdup(addr);
621                 read_req.req_id = req_id;
622                 read_req.offset = offset;
623                 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
624                 if (svc_info != NULL) {
625                         read_req.service_handle = g_strdup(svc_info->serv_path);
626                         user_info = _bt_get_user_data(BT_COMMON);
627 #ifdef HPS_FEATURE
628                         GVariant *param = NULL;
629 #endif
630
631                         /* Store requets information */
632                         req_info = g_new0(struct gatt_req_info, 1);
633                         req_info->attr_path = g_strdup(object_path);
634                         req_info->svc_path = g_strdup(read_req.service_handle);
635                         req_info->request_id = req_id;
636                         req_info->offset = offset;
637                         req_info->context = invocation;
638                         gatt_requests = g_slist_append(gatt_requests, req_info);
639
640                         if (user_info != NULL) {
641                                 _bt_common_event_cb(
642                                         BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
643                                         BLUETOOTH_ERROR_NONE, &read_req,
644                                         user_info->cb, user_info->user_data);
645                         }
646 #ifdef HPS_FEATURE
647                         param = g_variant_new("(sssyq)",
648                                         read_req.att_handle,
649                                         read_req.service_handle,
650                                         read_req.address,
651                                         read_req.req_id,
652                                         read_req.offset);
653                         __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
654 #endif
655                 }
656
657                 if (read_req.att_handle)
658                         g_free(read_req.att_handle);
659                 if (read_req.address)
660                         g_free(read_req.address);
661                 if (read_req.service_handle)
662                         g_free(read_req.service_handle);
663                 return;
664         } else if (g_strcmp0(method_name, "WriteValue") == 0) {
665                 GVariant *var = NULL;
666                 gchar *addr = NULL;
667                 guint8 req_id = 0;
668                 guint16 offset = 0;
669                 bt_gatt_value_change_t value_change = {0, };
670                 bt_user_info_t *user_info = NULL;
671                 int len = 0;
672                 struct gatt_service_info *svc_info = NULL;
673                 struct gatt_req_info *req_info = NULL;
674 #ifdef HPS_FEATURE
675                 GVariant *param = NULL;
676 #endif
677
678                 BT_DBG("WriteValue");
679                 BT_DBG("Application path = %s", object_path);
680                 BT_DBG("Sender = %s", sender);
681
682                 g_variant_get(parameters, "(&syq@ay)", &addr, &req_id, &offset, &var);
683
684                 value_change.att_handle = g_strdup(object_path);
685                 value_change.address = g_strdup(addr);
686                 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
687                 if (svc_info == NULL) {
688                         g_variant_unref(var);
689                         g_dbus_method_invocation_return_value(invocation, NULL);
690                         return;
691                 }
692
693                 value_change.service_handle = g_strdup(svc_info->serv_path);
694                 value_change.offset = offset;
695                 value_change.req_id = req_id;
696
697                 len = g_variant_get_size(var);
698                 if (len > 0) {
699                         char *data;
700
701                         value_change.att_value = (guint8 *)malloc(len);
702                         if (!value_change.att_value) {
703                                 BT_ERR("att_value is NULL");
704                                 g_variant_unref(var);
705                                 g_dbus_method_invocation_return_value(invocation, NULL);
706                                 return;
707                         }
708
709                         data = (char *)g_variant_get_data(var);
710                         memcpy(value_change.att_value, data, len);
711                 }
712
713                 value_change.val_len = len;
714
715                 /* Store requets information */
716                 req_info = g_new0(struct gatt_req_info, 1);
717                 req_info->attr_path = g_strdup(object_path);
718                 req_info->svc_path = g_strdup(value_change.service_handle);
719                 req_info->request_id = req_id;
720                 req_info->offset = offset;
721                 req_info->context = invocation;
722                 gatt_requests = g_slist_append(gatt_requests, req_info);
723
724                 user_info = _bt_get_user_data(BT_COMMON);
725                 if (user_info != NULL) {
726                         _bt_common_event_cb(
727                                 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
728                                 BLUETOOTH_ERROR_NONE, &value_change,
729                                 user_info->cb, user_info->user_data);
730                 }
731 #ifdef HPS_FEATURE
732                 if (len > 0) {
733                         gchar *svc_path;
734                         svc_path = g_strdup(svc_info->serv_path);
735                         param = g_variant_new("(sssyq@ay)",
736                                         object_path,
737                                         svc_path,
738                                         addr,
739                                         req_id,
740                                         offset,
741                                         var);
742                         __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
743                         if (svc_path)
744                                 g_free(svc_path);
745                 }
746 #endif
747                 g_variant_unref(var);
748                 return;
749         } else if (g_strcmp0(method_name, "StartNotify") == 0) {
750                 bt_user_info_t *user_info = NULL;
751                 bt_gatt_char_notify_change_t notify_change = {0, };
752                 BT_DBG("StartNotify");
753                 user_info = _bt_get_user_data(BT_COMMON);
754                 if (user_info != NULL) {
755                         struct gatt_service_info *svc_info = NULL;
756                         svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
757                         if (svc_info) {
758                                 notify_change.service_handle = g_strdup(svc_info->serv_path);
759                                 notify_change.att_handle = g_strdup(object_path);
760                                 notify_change.att_notify = TRUE;
761                                 _bt_common_event_cb(
762                                         BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
763                                         BLUETOOTH_ERROR_NONE, &notify_change,
764                                         user_info->cb, user_info->user_data);
765                         }
766                 }
767         } else if (g_strcmp0(method_name, "StopNotify") == 0) {
768                 bt_user_info_t *user_info = NULL;
769                 bt_gatt_char_notify_change_t notify_change = {0, };
770                 BT_DBG("StopNotify");
771                 user_info = _bt_get_user_data(BT_COMMON);
772                 if (user_info != NULL) {
773                         struct gatt_service_info *svc_info = NULL;
774                         svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
775                         if (svc_info) {
776                                 notify_change.service_handle = g_strdup(svc_info->serv_path);
777                                 notify_change.att_handle = g_strdup(object_path);
778                                 notify_change.att_notify = FALSE;
779                                 _bt_common_event_cb(
780                                         BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
781                                         BLUETOOTH_ERROR_NONE, &notify_change,
782                                         user_info->cb, user_info->user_data);
783                         }
784                 }
785         } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
786                 gchar *addr = NULL;
787                 bt_gatt_indicate_confirm_t confirm = {0, };
788                 bt_user_info_t *user_info = NULL;
789                 gboolean complete = 0;
790                 struct gatt_service_info *svc_info = NULL;
791
792                 BT_DBG("IndicateConfirm");
793                 BT_DBG("Application path = %s", object_path);
794                 BT_DBG("Sender = %s", sender);
795
796                 g_variant_get(parameters, "(&sb)", &addr, &complete);
797
798                 BT_DBG("Remote Device address number = %s", addr);
799                 confirm.att_handle = g_strdup(object_path);
800                 confirm.address = g_strdup(addr);
801                 confirm.complete = complete;
802
803                 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
804                 if (svc_info != NULL) {
805                         confirm.service_handle = g_strdup(svc_info->serv_path);
806                         user_info = _bt_get_user_data(BT_COMMON);
807
808                         if (user_info != NULL) {
809                                 _bt_common_event_cb(
810                                         BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
811                                         BLUETOOTH_ERROR_NONE, &confirm,
812                                         user_info->cb, user_info->user_data);
813                         }
814                 }
815         }
816         g_dbus_method_invocation_return_value(invocation, NULL);
817 }
818
819 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
820                                         const gchar *sender,
821                                         const gchar *object_path,
822                                         const gchar *interface_name,
823                                         const gchar *method_name,
824                                         GVariant *parameters,
825                                         GDBusMethodInvocation *invocation,
826                                         gpointer user_data)
827 {
828         if (g_strcmp0(method_name, "ReadValue") == 0) {
829                 gchar *addr = NULL;
830                 guint8 req_id = 1;
831                 guint16 offset = 0;
832                 bt_gatt_read_req_t read_req = {0, };
833                 bt_user_info_t *user_info = NULL;
834                 struct gatt_req_info *req_info = NULL;
835                 struct gatt_service_info *svc_info = NULL;
836                 BT_DBG("ReadValue");
837
838                 g_variant_get(parameters, "(&syq)", &addr, &req_id, &offset);
839
840                 BT_DBG("Application path = %s", object_path);
841
842                 BT_DBG("Remote Device address number = %s", addr);
843                 BT_DBG("Request id = %d, Offset = %d", req_id, offset);
844
845                 BT_DBG("Sender = %s", sender);
846
847                 read_req.att_handle = g_strdup(object_path);
848                 read_req.address = g_strdup(addr);
849                 read_req.req_id = req_id;
850                 read_req.offset = offset;
851                 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
852                 if (svc_info != NULL) {
853                         read_req.service_handle = g_strdup(svc_info->serv_path);
854                         user_info = _bt_get_user_data(BT_COMMON);
855
856                         /* Store requets information */
857                         req_info = g_new0(struct gatt_req_info, 1);
858                         req_info->attr_path = g_strdup(object_path);
859                         req_info->svc_path = g_strdup(read_req.service_handle);
860                         req_info->request_id = req_id;
861                         req_info->offset = offset;
862                         req_info->context = invocation;
863                         gatt_requests = g_slist_append(gatt_requests, req_info);
864
865                         if (user_info != NULL) {
866                                 _bt_common_event_cb(
867                                         BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
868                                         BLUETOOTH_ERROR_NONE, &read_req,
869                                         user_info->cb, user_info->user_data);
870                         }
871                 }
872
873                 if (read_req.att_handle)
874                         g_free(read_req.att_handle);
875                 if (read_req.address)
876                         g_free(read_req.address);
877                 if (read_req.service_handle)
878                         g_free(read_req.service_handle);
879
880                 return;
881         } else if (g_strcmp0(method_name, "WriteValue") == 0) {
882                 GVariant *var = NULL;
883                 gchar *addr = NULL;
884                 guint8 req_id = 0;
885                 guint16 offset = 0;
886                 bt_gatt_value_change_t value_change = {0, };
887                 bt_user_info_t *user_info = NULL;
888                 int len = 0;
889                 struct gatt_service_info *svc_info = NULL;
890                 struct gatt_req_info *req_info = NULL;
891
892                 BT_DBG("WriteValue");
893                 BT_DBG("Application path = %s", object_path);
894                 BT_DBG("Sender = %s", sender);
895
896                 g_variant_get(parameters, "(&syq@ay)", &addr, &req_id, &offset, &var);
897
898                 value_change.att_handle = g_strdup(object_path);
899                 value_change.address = g_strdup(addr);
900                 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
901                 if (svc_info == NULL) {
902                         g_variant_unref(var);
903                         g_dbus_method_invocation_return_value(invocation, NULL);
904                         return;
905                 }
906
907                 value_change.service_handle = g_strdup(svc_info->serv_path);
908                 value_change.offset = offset;
909                 value_change.req_id = req_id;
910
911                 len = g_variant_get_size(var);
912                 if (len > 0) {
913                         char *data;
914
915                         value_change.att_value = (guint8 *)malloc(len);
916                         if (!value_change.att_value) {
917                                 BT_ERR("att_value is NULL");
918                                 g_variant_unref(var);
919                                 g_dbus_method_invocation_return_value(invocation, NULL);
920                                 return;
921                         }
922                         data = (char *)g_variant_get_data(var);
923                         memcpy(value_change.att_value, data, len);
924                 }
925                 g_variant_unref(var);
926
927                 value_change.val_len = len;
928
929                 /* Store requets information */
930                 req_info = g_new0(struct gatt_req_info, 1);
931                 req_info->attr_path = g_strdup(object_path);
932                 req_info->svc_path = g_strdup(value_change.service_handle);
933                 req_info->request_id = req_id;
934                 req_info->offset = offset;
935                 req_info->context = invocation;
936                 gatt_requests = g_slist_append(gatt_requests, req_info);
937
938                 user_info = _bt_get_user_data(BT_COMMON);
939                 if (user_info != NULL) {
940                         _bt_common_event_cb(
941                                 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
942                                 BLUETOOTH_ERROR_NONE, &value_change,
943                                 user_info->cb, user_info->user_data);
944                 }
945                 return;
946         }
947         g_dbus_method_invocation_return_value(invocation, NULL);
948 }
949
950 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
951 {
952         gboolean ret;
953         GError *error = NULL;
954         GVariantBuilder *array_builder;
955
956         array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
957         g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
958         g_variant_builder_add(array_builder, "s", interface);
959
960         ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
961                                         "org.freedesktop.Dbus.Objectmanager",
962                                         "InterfacesRemoved",
963                                         g_variant_new("(oas)",
964                                         object_path, array_builder),
965                                         &error);
966
967         if (!ret) {
968                 if (error != NULL) {
969                         /* dbus gives error cause */
970                         BT_ERR("d-bus api failure: errcode[%x], message[%s]",
971                                 error->code, error->message);
972                         g_clear_error(&error);
973                 }
974         }
975         g_variant_builder_unref(array_builder);
976
977         return ret;
978 }
979
980 static const GDBusInterfaceVTable desc_interface_vtable = {
981         __bt_gatt_desc_method_call,
982         NULL,
983         NULL,
984 };
985
986 static const GDBusInterfaceVTable char_interface_vtable = {
987         __bt_gatt_char_method_call,
988         NULL,
989         NULL,
990 };
991
992 static const GDBusInterfaceVTable serv_interface_vtable = {
993         NULL,
994         NULL,
995         NULL,
996 };
997
998 static const GDBusInterfaceVTable manager_interface_vtable = {
999         __bt_gatt_manager_method_call,
1000         NULL,
1001         NULL
1002 };
1003
1004 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1005                                 const gchar *introspection_data)
1006 {
1007         GError *err = NULL;
1008         GDBusNodeInfo *node_info = NULL;
1009
1010         if (introspection_data == NULL)
1011                 return NULL;
1012
1013         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1014
1015         if (err) {
1016                 BT_ERR("Unable to create node: %s", err->message);
1017                 g_clear_error(&err);
1018         }
1019         return node_info;
1020 }
1021
1022 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1023                         const char *service_path)
1024 {
1025         GSList *l;
1026
1027         for (l = gatt_services; l != NULL; l = l->next) {
1028                 struct gatt_service_info *info = l->data;
1029
1030                 if (g_strcmp0(info->serv_path, service_path) == 0)
1031                         return info;
1032         }
1033         BT_ERR("Gatt service not found");
1034         return NULL;
1035 }
1036
1037 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1038                         const char *service_path, const char *char_path)
1039 {
1040         GSList *l1, *l2;
1041
1042         for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1043                 struct gatt_service_info *serv_info = l1->data;
1044
1045                 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1046
1047                         for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1048                                 struct gatt_char_info *char_info = l2->data;
1049
1050                                 if (g_strcmp0(char_info->char_path, char_path)
1051                                                         == 0)
1052                                         return char_info;
1053                         }
1054                         BT_ERR("Gatt characteristic not found");
1055                         return NULL;
1056                 }
1057         }
1058         BT_ERR("Gatt service not found");
1059         return NULL;
1060 }
1061
1062 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1063                         const char *serv_path, const char *char_path,
1064                         const char *desc_path)
1065 {
1066         GSList *l1, *l2, *l3;
1067
1068         for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1069                 struct gatt_service_info *serv_info = l1->data;
1070
1071                 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1072                         for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1073                                 struct gatt_char_info *char_info = l2->data;
1074
1075                                 if (g_strcmp0(char_info->char_path, char_path)
1076                                                         == 0) {
1077                                         for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1078                                                 struct gatt_desc_info *desc_info = l3->data;
1079                                                 if (g_strcmp0(desc_info->desc_path,
1080                                                         desc_path) == 0) {
1081                                                         return desc_info;
1082                                                 }
1083                                         }
1084                                 }
1085                         }
1086                 }
1087         }
1088         BT_ERR("Gatt descriptor not found");
1089         return NULL;
1090 }
1091
1092 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1093 {
1094         GSList *l;
1095
1096         for (l = gatt_requests; l != NULL; l = l->next) {
1097                 struct gatt_req_info *req_info = l->data;
1098
1099                 if (req_info && req_info->request_id == request_id) {
1100                         return req_info;
1101                 }
1102         }
1103         BT_ERR("Gatt Request not found");
1104         return NULL;
1105 }
1106
1107 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1108                                 const gchar *path, const gchar *interface)
1109 {
1110         GDBusProxy *proxy;
1111         GError *err = NULL;
1112
1113         if (g_conn == NULL)
1114                 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1115                                                         NULL, &err);
1116
1117         if (!g_conn) {
1118                 if (err) {
1119                         BT_ERR("Unable to connect to gdbus: %s", err->message);
1120                         g_clear_error(&err);
1121                 }
1122                 return NULL;
1123         }
1124
1125         proxy =  g_dbus_proxy_new_sync(g_conn,
1126                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1127                         service, path,
1128                         interface, NULL, &err);
1129
1130         if (!proxy) {
1131                 if (err) {
1132                         BT_ERR("Unable to create proxy: %s", err->message);
1133                         g_clear_error(&err);
1134                 }
1135                 return NULL;
1136         }
1137         manager_gproxy = proxy;
1138
1139         return proxy;
1140 }
1141
1142 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1143                                 const gchar *path, const gchar *interface)
1144 {
1145         return (manager_gproxy) ? manager_gproxy :
1146                         __bt_gatt_gdbus_init_manager_proxy(service,
1147                                 path, interface);
1148 }
1149
1150 int bluetooth_gatt_convert_prop2string(
1151                         bt_gatt_characteristic_property_t properties,
1152                         char *char_properties[])
1153 {
1154         int flag_count = 0;
1155
1156         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1157                 char_properties[flag_count] = g_strdup("broadcast");
1158                 flag_count++;
1159         }
1160         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1161                 char_properties[flag_count] = g_strdup("read");
1162                 flag_count++;
1163         }
1164         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1165                 char_properties[flag_count] = g_strdup("write-without-response");
1166                 flag_count++;
1167         }
1168         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1169                 char_properties[flag_count] = g_strdup("write");
1170                 flag_count++;
1171         }
1172         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1173                 char_properties[flag_count] = g_strdup("notify");
1174                 flag_count++;
1175         }
1176         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1177                 char_properties[flag_count] = g_strdup("indicate");
1178                 flag_count++;
1179         }
1180         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1181                 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1182                 flag_count++;
1183         }
1184         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1185                 char_properties[flag_count] = g_strdup("reliable-write");
1186                 flag_count++;
1187         }
1188         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1189                 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1190                 flag_count++;
1191         }
1192         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1193                 char_properties[flag_count] = g_strdup("encrypt-read");
1194                 flag_count++;
1195         }
1196         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1197                 char_properties[flag_count] = g_strdup("encrypt-write");
1198                 flag_count++;
1199         }
1200         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1201                 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1202                 flag_count++;
1203         }
1204         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1205                 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1206                 flag_count++;
1207         }
1208
1209         if (flag_count == 0) {
1210                 char_properties[flag_count] = g_strdup("read");
1211                 flag_count++;
1212         }
1213
1214         return flag_count;
1215 }
1216
1217 int bluetooth_gatt_convert_perm2string(
1218                         bt_gatt_permission_t properties,
1219                         char *char_properties[])
1220 {
1221         int flag_count = 0;
1222
1223         if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1224                 char_properties[flag_count] = g_strdup("read");
1225                 flag_count++;
1226         }
1227         if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1228                 char_properties[flag_count] = g_strdup("write");
1229                 flag_count++;
1230         }
1231         if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1232                 char_properties[flag_count] = g_strdup("encrypt-read");
1233                 flag_count++;
1234         }
1235         if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1236                 char_properties[flag_count] = g_strdup("encrypt-write");
1237                 flag_count++;
1238         }
1239         if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1240                 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1241                 flag_count++;
1242         }
1243         if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
1244                 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1245                 flag_count++;
1246         }
1247
1248         if (flag_count == 0) {
1249                 char_properties[flag_count] = g_strdup("read");
1250                 flag_count++;
1251         }
1252
1253         return flag_count;
1254 }
1255
1256 static void __bt_gatt_set_service_state(const char *service_path,
1257                         gboolean state)
1258 {
1259         struct gatt_service_info *svc_info = NULL;
1260         svc_info = __bt_gatt_find_gatt_service_info(service_path);
1261
1262         if (svc_info != NULL) {
1263                 BT_DBG("Updating the gatt service register state %d", state);
1264                 svc_info->is_svc_registered = state;
1265                 return;
1266         }
1267
1268         BT_DBG("gatt service not found");
1269 }
1270
1271 static gboolean __bt_gatt_get_service_state(const char *service_path)
1272 {
1273         struct gatt_service_info *svc_info = NULL;
1274
1275         svc_info = __bt_gatt_find_gatt_service_info(service_path);
1276
1277         if (svc_info != NULL) {
1278                 BT_DBG("Return the state of the gatt service %d",
1279                         svc_info->is_svc_registered);
1280                 return svc_info->is_svc_registered;
1281         }
1282
1283         BT_DBG("gatt service info is NULL");
1284         return FALSE;
1285 }
1286
1287 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1288 {
1289         GError *error = NULL;
1290         GVariant *result;
1291         GVariantIter *iter = NULL;
1292         const gchar *key = NULL;
1293         GVariant *value = NULL;
1294         const gchar *service = NULL;
1295         const gchar *characteristic = NULL;
1296         const gchar *descriptor = NULL;
1297         int n_char = 1;
1298
1299         BT_DBG(" ");
1300         result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1301
1302         if (result == NULL) {
1303                 /* dBUS-RPC is failed */
1304                 BT_ERR("Dbus-RPC is failed\n");
1305
1306                 if (error != NULL) {
1307                 /* dBUS gives error cause */
1308                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1309                                                 error->code, error->message);
1310                         g_clear_error(&error);
1311                 }
1312         } else {
1313                 char *char_cmp = NULL;
1314                 g_variant_get(result, "(a{sv})", &iter);
1315                 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1316
1317                 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1318                         if (g_strcmp0(key, "Service") == 0) {
1319                                 service = g_variant_get_string(value, NULL);
1320                                 BT_DBG("Service %s", service);
1321                         } else if (g_strcmp0(key, char_cmp) == 0) {
1322                                 characteristic = g_variant_get_string(value, NULL);
1323                                 g_free(char_cmp);
1324                                 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1325                                 BT_DBG("%s", characteristic);
1326                         } else if (g_strcmp0(key, "Descriptor") == 0) {
1327                                 descriptor = g_variant_get_string(value, NULL);
1328                                 BT_DBG("Descriptor %s", descriptor);
1329                         }
1330                 }
1331                 g_variant_iter_free(iter);
1332
1333                 /* TODO: Store the service informationa and
1334                  * Send respponse to CAPI layer. */
1335
1336                 g_variant_unref(result);
1337                 if (char_cmp)
1338                         g_free(char_cmp);
1339         }
1340 }
1341 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1342 {
1343         BT_INFO("RegisterApplication is completed");
1344
1345         GError *error = NULL;
1346         GVariant *result;
1347
1348         register_pending_cnt = 0;
1349
1350         result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1351
1352         if (result == NULL) {
1353                 /* dBUS-RPC is failed */
1354                 BT_ERR("Dbus-RPC is failed\n");
1355
1356                 if (error != NULL) {
1357                 /* dBUS gives error cause */
1358                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1359                                                 error->code, error->message);
1360                         g_clear_error(&error);
1361                 }
1362         }
1363 }
1364
1365 void unregister_application_cb(GObject *object, GAsyncResult *res,
1366                 gpointer user_data)
1367 {
1368         BT_INFO("UnregisterApplication is completed");
1369
1370         GError *error = NULL;
1371         GVariant *result;
1372
1373         result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1374
1375         if (result == NULL) {
1376                 /* dBUS-RPC is failed */
1377                 BT_ERR("Dbus-RPC is failed\n");
1378
1379                 if (error != NULL) {
1380                         /* dBUS gives error cause */
1381                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1382                                         error->code, error->message);
1383                         g_clear_error(&error);
1384                 }
1385         }
1386 }
1387
1388 static int __bt_gatt_unregister_service(const char *service_path)
1389 {
1390         if (!__bt_gatt_get_service_state(service_path)) {
1391                 BT_DBG("service not registered \n");
1392                 return BLUETOOTH_ERROR_NOT_FOUND;
1393         }
1394
1395         return BLUETOOTH_ERROR_NONE;
1396 }
1397
1398 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1399 {
1400         GDBusProxy *proxy = NULL;
1401
1402         if (is_server_started) {
1403                 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1404                                 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1405
1406                 if (proxy == NULL || app_path == NULL)
1407                         return BLUETOOTH_ERROR_INTERNAL;
1408
1409                 BT_INFO("UnregisterApplication");
1410
1411                 /* Async Call to Unregister Service */
1412                 g_dbus_proxy_call(proxy,
1413                                 "UnregisterApplication",
1414                                 g_variant_new("(o)",
1415                                         app_path),
1416                                 G_DBUS_CALL_FLAGS_NONE, -1,
1417                                 NULL,
1418                                 (GAsyncReadyCallback) unregister_application_cb,
1419                                 NULL);
1420
1421                 is_server_started = false;
1422                 return BLUETOOTH_ERROR_NONE;
1423         }
1424
1425         BT_INFO("GATT server not started");
1426         return BLUETOOTH_ERROR_NONE;
1427 }
1428
1429 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1430 {
1431         GDBusConnection *local_system_gconn = NULL;
1432         GError *err = NULL;
1433
1434         if (g_conn == NULL) {
1435                 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1436                 if (!g_conn) {
1437                         if (err) {
1438                                 BT_ERR("Unable to connect to dbus: %s", err->message);
1439                                 g_clear_error(&err);
1440                         }
1441                         g_conn = NULL;
1442                 }
1443         } else if (g_dbus_connection_is_closed(g_conn)) {
1444                 local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1445
1446                 if (!local_system_gconn) {
1447                         BT_ERR("Unable to connect to dbus: %s", err->message);
1448                         g_clear_error(&err);
1449                 }
1450
1451                 g_conn = local_system_gconn;
1452         }
1453
1454         return g_conn;
1455 }
1456
1457 BT_EXPORT_API int bluetooth_gatt_init(void)
1458 {
1459         GDBusConnection *conn;
1460         GDBusNodeInfo *obj_info;
1461         GError *error = NULL;
1462
1463         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1464                                 BT_GATT_SERVICE_NAME,
1465                                 G_BUS_NAME_OWNER_FLAGS_NONE,
1466                                 NULL, NULL, NULL, NULL, NULL);
1467
1468         BT_DBG("owner_id is [%d]", owner_id);
1469         app_path = g_strdup_printf("/com/%d", getpid());
1470
1471         serv_id = 1;
1472
1473         conn = __bt_gatt_get_gdbus_connection();
1474         if (!conn) {
1475                 BT_ERR("Unable to get connection");
1476                 return BLUETOOTH_ERROR_INTERNAL;
1477         }
1478
1479         /* Register ObjectManager interface */
1480         obj_info = __bt_gatt_create_method_node_info(
1481                                         manager_introspection_xml);
1482
1483         if (obj_info == NULL) {
1484                 BT_ERR("failed to get node info");
1485                 return BLUETOOTH_ERROR_INTERNAL;
1486         }
1487
1488         manager_id = g_dbus_connection_register_object(g_conn, app_path,
1489                                                 obj_info->interfaces[0],
1490                                                 &manager_interface_vtable,
1491                                                 NULL, NULL, &error);
1492
1493         if (manager_id == 0) {
1494                 BT_ERR("failed to register: %s", error->message);
1495                 g_error_free(error);
1496                 return BLUETOOTH_ERROR_INTERNAL;
1497         }
1498
1499         return BLUETOOTH_ERROR_NONE;
1500 }
1501
1502 BT_EXPORT_API int bluetooth_gatt_deinit()
1503 {
1504         int ret = BLUETOOTH_ERROR_NONE;
1505         /* Unown gdbus bus */
1506         if (owner_id) {
1507
1508                 /* remove/unregister all services */
1509                 BT_DBG("removing all registered gatt service\n");
1510                 bluetooth_gatt_delete_services();
1511
1512                 g_bus_unown_name(owner_id);
1513
1514                 /* unregister the exported interface for object manager */
1515                 g_dbus_connection_unregister_object(g_conn,
1516                                         manager_id);
1517
1518                 BT_DBG("Gatt service deinitialized \n");
1519
1520                 g_slist_free(gatt_services);
1521                 gatt_services = NULL;
1522
1523                 ret = bluetooth_gatt_unregister_application();
1524
1525                 if (ret == BLUETOOTH_ERROR_NONE) {
1526                         g_free(app_path);
1527                         app_path = NULL;
1528                 }
1529
1530                 return ret;
1531         }
1532
1533         return BLUETOOTH_ERROR_NOT_FOUND;
1534 }
1535
1536 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1537                         char **svc_path)
1538 {
1539         GError *error = NULL;
1540         guint object_id;
1541         GDBusNodeInfo *node_info;
1542         gchar *path = NULL;
1543         GVariantBuilder *builder = NULL;
1544         GVariantBuilder *builder1 = NULL;
1545         GVariantBuilder *inner_builder = NULL;
1546         gboolean svc_primary = TRUE;
1547         struct gatt_service_info *serv_info = NULL;
1548
1549         node_info = __bt_gatt_create_method_node_info(
1550                                         service_introspection_xml);
1551
1552         if (node_info == NULL)
1553                 return BLUETOOTH_ERROR_INTERNAL;
1554
1555         path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1556         BT_DBG("gatt service path is [%s]", path);
1557
1558         object_id = g_dbus_connection_register_object(g_conn, path,
1559                                         node_info->interfaces[0],
1560                                         &serv_interface_vtable,
1561                                         NULL, NULL, &error);
1562
1563         if (object_id == 0) {
1564                 BT_ERR("failed to register: %s", error->message);
1565                 g_error_free(error);
1566                 g_free(path);
1567
1568                 return BLUETOOTH_ERROR_INTERNAL;
1569         }
1570
1571         /* Add object_id/gatt service information; it's required at the time of
1572          *  service unregister and Getmanagedobjects
1573          */
1574         serv_info = g_new0(struct gatt_service_info, 1);
1575
1576         serv_info->serv_path = g_strdup(path);
1577         serv_info->serv_id = object_id;
1578         serv_info->service_uuid = g_strdup(svc_uuid);
1579         serv_info->is_svc_registered = FALSE;
1580         serv_info->is_svc_primary = svc_primary;
1581
1582         gatt_services = g_slist_append(gatt_services, serv_info);
1583
1584         /* emit interfacesadded signal here for service path */
1585         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1586         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1587
1588         g_variant_builder_add(inner_builder, "{sv}",
1589                 "UUID", g_variant_new_string(svc_uuid));
1590
1591         g_variant_builder_add(inner_builder, "{sv}",
1592                 "Primary", g_variant_new_boolean(svc_primary));
1593
1594         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1595
1596         g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1597                                 g_variant_new("ao", builder1));
1598
1599         g_variant_builder_add(builder, "{sa{sv}}",
1600                 GATT_SERV_INTERFACE, inner_builder);
1601
1602         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1603                                 "org.freedesktop.Dbus.ObjectManager",
1604                                 "InterfacesAdded",
1605                                 g_variant_new("(oa{sa{sv}})",
1606                                 path, builder),
1607                                 &error);
1608
1609         new_service = TRUE;
1610
1611         *svc_path = g_strdup(path);
1612
1613         g_free(path);
1614         g_variant_builder_unref(inner_builder);
1615         g_variant_builder_unref(builder);
1616         g_variant_builder_unref(builder1);
1617
1618         return BLUETOOTH_ERROR_NONE;
1619 }
1620
1621 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1622                         const char *svc_path, const char *char_uuid,
1623                         bt_gatt_permission_t permissions,
1624                         bt_gatt_characteristic_property_t properties,
1625                         char **char_path)
1626 {
1627         static int char_id;
1628         GError *error = NULL;
1629         guint object_id;
1630         GDBusNodeInfo *node_info;
1631         gchar *path = NULL;
1632         GVariantBuilder *builder = NULL;
1633         GVariantBuilder *inner_builder = NULL;
1634         struct gatt_service_info *serv_info = NULL;
1635         struct gatt_char_info *char_info = NULL;
1636         GVariantBuilder *builder2 = NULL;
1637         GVariantBuilder *builder3 = NULL;
1638         GVariant *flags_val = NULL;
1639         int i = 0;
1640         char *char_flags[NUMBER_OF_FLAGS];
1641         int flag_count = 0;
1642
1643         if (new_service) {
1644                 char_id = 1;
1645                 new_service = FALSE;
1646         }
1647
1648         BT_DBG("gatt svc_path path is [%s]", svc_path);
1649         serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1650         if (serv_info == NULL)
1651                 return BLUETOOTH_ERROR_INVALID_PARAM;
1652
1653         node_info = __bt_gatt_create_method_node_info(
1654                                         characteristics_introspection_xml);
1655
1656         if (node_info == NULL)
1657                 return BLUETOOTH_ERROR_INTERNAL;
1658
1659         path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1660         BT_DBG("gatt characteristic path is [%s]", path);
1661
1662         object_id = g_dbus_connection_register_object(g_conn, path,
1663                                         node_info->interfaces[0],
1664                                         &char_interface_vtable,
1665                                         NULL, NULL, &error);
1666
1667         if (object_id == 0) {
1668                 BT_ERR("failed to register: %s", error->message);
1669                 g_error_free(error);
1670                 g_free(path);
1671
1672                 return BLUETOOTH_ERROR_INTERNAL;
1673         }
1674
1675         if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1676                 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1677         if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1678                 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1679         if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1680                 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1681         if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1682                 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1683
1684         flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1685
1686         char_info = g_new0(struct gatt_char_info, 1);
1687
1688         char_info->char_path = g_strdup(path);
1689         char_info->char_id = object_id;
1690         char_info->char_uuid = g_strdup(char_uuid);
1691
1692         for (i = 0; i < flag_count; i++) {
1693                 char_info->char_flags[i] = char_flags[i];
1694                 }
1695
1696         char_info->flags_length = flag_count;
1697
1698         serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1699
1700         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1701         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1702
1703         g_variant_builder_add(inner_builder, "{sv}", "UUID",
1704                                 g_variant_new("s", char_uuid));
1705         g_variant_builder_add(inner_builder, "{sv}", "Service",
1706                                 g_variant_new("o", svc_path));
1707
1708         builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1709
1710         for (i = 0; i < flag_count; i++) {
1711                 g_variant_builder_add(builder2, "s", char_flags[i]);
1712         }
1713
1714         flags_val = g_variant_new("as", builder2);
1715         g_variant_builder_add(inner_builder, "{sv}", "Flags",
1716                                 flags_val);
1717
1718         builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1719
1720         g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1721                                 g_variant_new("ao", builder3));
1722
1723         g_variant_builder_add(builder, "{sa{sv}}",
1724                                 GATT_CHAR_INTERFACE,
1725                                 inner_builder);
1726
1727         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1728                                 "org.freedesktop.Dbus.ObjectManager",
1729                                 "InterfacesAdded",
1730                                 g_variant_new("(oa{sa{sv}})",
1731                                 path, builder),
1732                                 &error);
1733
1734         *char_path = g_strdup(path);
1735
1736         new_char = TRUE;
1737
1738         g_free(path);
1739
1740         g_variant_builder_unref(inner_builder);
1741         g_variant_builder_unref(builder);
1742         g_variant_builder_unref(builder2);
1743         g_variant_builder_unref(builder3);
1744
1745         return BLUETOOTH_ERROR_NONE;
1746 }
1747
1748 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1749                         const char *characteristic, const char *char_value,
1750                         int     value_length)
1751 {
1752         gchar **line_argv = NULL;
1753         char *serv_path = NULL;
1754         struct gatt_char_info *char_info = NULL;
1755         GVariantBuilder *builder1 = NULL;
1756         GVariantBuilder *builder = NULL;
1757         GVariantBuilder *inner_builder = NULL;
1758         GVariant *char_val = NULL;
1759         GError *error = NULL;
1760         int i = 0;
1761         int res = BLUETOOTH_ERROR_NONE;
1762
1763         line_argv = g_strsplit_set(characteristic, "/", 0);
1764         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1765
1766         char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1767
1768         if (char_info == NULL) {
1769                 /* Fix : RESOURCE_LEAK */
1770                 res = BLUETOOTH_ERROR_INVALID_PARAM;
1771                 goto done;
1772         }
1773
1774         char_info->value_length = value_length;
1775
1776         char_info->char_value = (char *)malloc(value_length);
1777         /* Fix : NULL_RETURNS */
1778         if (char_info->char_value == NULL) {
1779                 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1780                 goto done;
1781         }
1782
1783         for (i = 0; i < value_length; i++)
1784                 char_info->char_value[i] = char_value[i];
1785
1786         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1787         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1788
1789         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1790
1791         for (i = 0; i < value_length; i++) {
1792                 g_variant_builder_add(builder1, "y", char_value[i]);
1793         }
1794
1795         char_val = g_variant_new("ay", builder1);
1796                 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1797
1798         g_variant_builder_add(builder, "{sa{sv}}",
1799                         GATT_CHAR_INTERFACE,
1800                         inner_builder);
1801
1802         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1803                         "org.freedesktop.Dbus.ObjectManager",
1804                         "InterfacesAdded",
1805                         g_variant_new("(oa{sa{sv}})",
1806                         char_info->char_path, builder),
1807                         &error);
1808
1809         g_variant_builder_unref(inner_builder);
1810         g_variant_builder_unref(builder);
1811         g_variant_builder_unref(builder1);
1812 done:
1813         g_strfreev(line_argv);
1814         g_free(serv_path);
1815
1816         return res;
1817 }
1818
1819 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1820                         const char *char_path, const char *desc_uuid,
1821                         bt_gatt_permission_t permissions,
1822                         char **desc_path)
1823 {
1824         static int desc_id = 1;
1825         GError *error = NULL;
1826         guint object_id;
1827         GDBusNodeInfo *node_info;
1828         gchar *path = NULL;
1829         GVariantBuilder *builder = NULL;
1830         GVariantBuilder *inner_builder = NULL;
1831         struct gatt_char_info *char_info = NULL;
1832         struct gatt_desc_info *desc_info = NULL;
1833         gchar **line_argv = NULL;
1834         char *serv_path;
1835         GVariantBuilder *builder2 = NULL;
1836         GVariant *flags_val = NULL;
1837         int i = 0;
1838         char *desc_flags[NUMBER_OF_FLAGS];
1839         int flag_count = 0;
1840
1841         if (new_char) {
1842                 desc_id = 1;
1843                 new_char = FALSE;
1844         }
1845
1846         line_argv = g_strsplit_set(char_path, "/", 0);
1847         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1848
1849         char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
1850         if (char_info == NULL) {
1851                 g_strfreev(line_argv);
1852                 return BLUETOOTH_ERROR_INVALID_PARAM;
1853         }
1854
1855         node_info = __bt_gatt_create_method_node_info(
1856                                         descriptor_introspection_xml);
1857
1858         if (node_info == NULL) {
1859                 g_strfreev(line_argv);
1860                 return BLUETOOTH_ERROR_INTERNAL;
1861         }
1862
1863         path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
1864         BT_DBG("gatt descriptor path is [%s]", path);
1865
1866         object_id = g_dbus_connection_register_object(g_conn, path,
1867                                 node_info->interfaces[0],
1868                                 &desc_interface_vtable,
1869                                 NULL, NULL, &error);
1870
1871         if (object_id == 0) {
1872                 BT_ERR("failed to register: %s", error->message);
1873                 g_error_free(error);
1874                 g_free(path);
1875                 g_strfreev(line_argv);
1876
1877                 return BLUETOOTH_ERROR_INTERNAL;
1878         }
1879
1880         flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
1881
1882         desc_info = g_new0(struct gatt_desc_info, 1);
1883
1884         desc_info->desc_path = g_strdup(path);
1885         desc_info->desc_id = object_id;
1886         desc_info->desc_uuid = g_strdup(desc_uuid);
1887
1888         for (i = 0; i < flag_count; i++) {
1889                 desc_info->desc_flags[i] = desc_flags[i];
1890                 }
1891
1892         desc_info->flags_length = flag_count;
1893
1894         char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
1895
1896         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1897         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1898
1899         g_variant_builder_add(inner_builder, "{sv}", "UUID",
1900                                 g_variant_new("s", desc_uuid));
1901         g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
1902                                 g_variant_new("o", char_path));
1903
1904         builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1905
1906         for (i = 0; i < flag_count; i++) {
1907                 g_variant_builder_add(builder2, "s", desc_flags[i]);
1908         }
1909
1910         flags_val = g_variant_new("as", builder2);
1911         g_variant_builder_add(inner_builder, "{sv}", "Flags",
1912                                 flags_val);
1913
1914         g_variant_builder_add(builder, "{sa{sv}}",
1915                                 GATT_DESC_INTERFACE,
1916                                 inner_builder);
1917
1918         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1919                                 "org.freedesktop.Dbus.ObjectManager",
1920                                 "InterfacesAdded",
1921                                 g_variant_new("(oa{sa{sv}})",
1922                                 path, builder),
1923                                 &error);
1924
1925         *desc_path = g_strdup(path);
1926
1927         g_free(path);
1928         g_strfreev(line_argv);
1929         g_variant_builder_unref(inner_builder);
1930         g_variant_builder_unref(builder);
1931
1932         return BLUETOOTH_ERROR_NONE;
1933 }
1934
1935 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
1936                         const char *desc_path, const char *desc_value,
1937                         int value_length)
1938 {
1939         GError *error = NULL;
1940         GVariantBuilder *builder = NULL;
1941         GVariantBuilder *inner_builder = NULL;
1942         GVariantBuilder *builder1 = NULL;
1943         struct gatt_desc_info *desc_info = NULL;
1944         gchar **line_argv = NULL;
1945         char *char_path;
1946         GVariant *desc_val = NULL;
1947         char *serv_path = NULL;
1948         int i ;
1949
1950         line_argv = g_strsplit_set(desc_path, "/", 0);
1951         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1952         char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
1953
1954         desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
1955
1956         /* Free the allocated memory */
1957         g_strfreev(line_argv);
1958         g_free(serv_path);
1959         g_free(char_path);
1960
1961         /* Fix : NULL_RETURNS */
1962         retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
1963
1964         desc_info->desc_value = (char *)malloc(value_length);
1965
1966         /* Fix : NULL_RETURNS */
1967         retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
1968
1969         for (i = 0; i < value_length; i++)
1970                 desc_info->desc_value[i] = desc_value[i];
1971
1972         desc_info->value_length = value_length;
1973
1974         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1975         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1976
1977         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1978
1979         for (i = 0; i < value_length; i++) {
1980                 g_variant_builder_add(builder1, "y", desc_value[i]);
1981         }
1982         desc_val = g_variant_new("ay", builder1);
1983         g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
1984
1985         g_variant_builder_add(builder, "{sa{sv}}",
1986                                 GATT_DESC_INTERFACE,
1987                                 inner_builder);
1988
1989         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1990                                 "org.freedesktop.Dbus.ObjectManager",
1991                                 "InterfacesAdded",
1992                                 g_variant_new("(oa{sa{sv}})",
1993                                 desc_info->desc_path, builder),
1994                                 &error);
1995
1996         g_variant_builder_unref(inner_builder);
1997         g_variant_builder_unref(builder);
1998         g_variant_builder_unref(builder1);
1999
2000         return BLUETOOTH_ERROR_NONE;
2001 }
2002
2003 int bluetooth_gatt_get_service(const char *svc_uuid)
2004 {
2005         GDBusProxy *proxy = NULL;
2006         gchar *uuid = NULL;
2007
2008         proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2009                                         "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2010         if (proxy == NULL)
2011                 return BLUETOOTH_ERROR_INTERNAL;
2012
2013         uuid = g_strdup(svc_uuid);
2014
2015         g_dbus_proxy_call(proxy,
2016                         "GetService",
2017                         g_variant_new("(s)",
2018                         uuid),
2019                         G_DBUS_CALL_FLAGS_NONE, -1,
2020                         NULL,
2021                         (GAsyncReadyCallback) get_service_cb,
2022                         NULL);
2023
2024         g_free(uuid);
2025
2026         return BLUETOOTH_ERROR_NONE;
2027 }
2028
2029 BT_EXPORT_API int bluetooth_gatt_register_service(
2030                         const char *svc_path)
2031 {
2032         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2033                         == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2034                 BT_ERR("Don't have aprivilege to use this API");
2035                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2036         }
2037
2038         register_pending_cnt++;
2039
2040         if (__bt_gatt_get_service_state(svc_path)) {
2041                 BT_DBG("service already registered \n");
2042                 return BLUETOOTH_ERROR_NONE;
2043         }
2044
2045         __bt_gatt_set_service_state(svc_path, TRUE);
2046
2047         return BLUETOOTH_ERROR_NONE;
2048 }
2049
2050 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2051 {
2052         GDBusProxy *proxy = NULL;
2053
2054         if (!is_server_started) {
2055
2056                 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2057                                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2058                         BT_ERR("Don't have aprivilege to use this API");
2059                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
2060                 }
2061
2062                 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2063                                 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2064                 if (proxy == NULL || app_path == NULL)
2065                         return BLUETOOTH_ERROR_INTERNAL;
2066
2067                 BT_INFO("RegisterApplication");
2068
2069                 g_dbus_proxy_call(proxy,
2070                                 "RegisterApplication",
2071                                 g_variant_new("(oa{sv})",
2072                                         app_path, NULL),
2073                                 G_DBUS_CALL_FLAGS_NONE, -1,
2074                                 NULL,
2075                                 (GAsyncReadyCallback) register_application_cb,
2076                                 NULL);
2077
2078                 is_server_started = true;
2079
2080                 return BLUETOOTH_ERROR_NONE;
2081         }
2082
2083         BT_INFO("Already RegisterApplication");
2084
2085         return BLUETOOTH_ERROR_NONE;
2086 }
2087
2088 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2089 {
2090         GSList *l;
2091         int error = BLUETOOTH_ERROR_NONE;
2092         l = gatt_services;
2093
2094         if (l != NULL) {
2095                 for (l = gatt_services; l != NULL; l = l->next) {
2096                         struct gatt_service_info *info = l->data;
2097                         BT_DBG("svc_path is %s", info->serv_path);
2098                         if (bluetooth_gatt_unregister_service(info->serv_path)
2099                                         != BLUETOOTH_ERROR_NONE) {
2100                                 error = BLUETOOTH_ERROR_INTERNAL;
2101                                 BT_DBG(" Error in removing service %s \n",
2102                                                  info->serv_path);
2103                         }
2104                 }
2105                 BT_DBG(" All services removed successfully.\n ");
2106         } else {
2107                 BT_DBG(" There are no registered services.\n ");
2108         }
2109
2110         g_slist_free(gatt_services);
2111         gatt_services = NULL;
2112         serv_id = 1;
2113
2114         if (error != BLUETOOTH_ERROR_NONE)
2115                 return error;
2116
2117         return BLUETOOTH_ERROR_NONE;
2118 }
2119
2120 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2121                         const char *char_path, const char* char_value,
2122                         int value_length)
2123 {
2124         GVariantBuilder *outer_builder;
2125         GVariantBuilder *inner_builder;
2126         GVariantBuilder *invalidated_builder;
2127         GVariant *update_value = NULL;
2128         GError *error = NULL;
2129         gboolean ret = FALSE;
2130         int err = BLUETOOTH_ERROR_NONE;
2131         int i = 0;
2132         gchar **line_argv = NULL;
2133         gchar *serv_path = NULL;
2134
2135         line_argv = g_strsplit_set(char_path, "/", 0);
2136         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2137
2138         if (!__bt_gatt_get_service_state(serv_path)) {
2139                 BT_DBG("service not registered for this characteristic \n");
2140                 g_strfreev(line_argv);
2141                 return BLUETOOTH_ERROR_INTERNAL;
2142         }
2143
2144         outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2145         invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2146
2147         inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2148         for (i = 0; i < value_length; i++) {
2149                 g_variant_builder_add(inner_builder, "y", char_value[i]);
2150         }
2151
2152         update_value = g_variant_new("ay", inner_builder);
2153
2154         outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2155         g_variant_builder_add(outer_builder, "{sv}", "Value",
2156                                         update_value);
2157
2158         BT_DBG("Updating characteristic value \n");
2159         ret = g_dbus_connection_emit_signal(g_conn, NULL,
2160                                         char_path,
2161                                         "org.freedesktop.DBus.Properties",
2162                                         "PropertiesChanged",
2163                                         g_variant_new("(sa{sv}as)",
2164                                         "org.bluez.GattCharacteristic1",
2165                                         outer_builder, invalidated_builder),
2166                                         &error);
2167
2168         if (!ret) {
2169                 if (error != NULL) {
2170                         BT_ERR("D-Bus API failure: errCode[%x], \
2171                                         message[%s]",
2172                                         error->code, error->message);
2173                         g_clear_error(&error);
2174                 }
2175                 err = BLUETOOTH_ERROR_INTERNAL;
2176         } else {
2177                 struct gatt_char_info *char_info = NULL;
2178
2179                 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2180                 if (char_info == NULL) {
2181                         return BLUETOOTH_ERROR_INVALID_DATA;
2182                 }
2183
2184                 char_info->value_length = value_length;
2185
2186                 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2187                 if (char_info->char_value) {
2188                         for (i = 0; i < value_length; i++) {
2189                                 char_info->char_value[i] = char_value[i];
2190                         }
2191                 }
2192         }
2193
2194         g_strfreev(line_argv);
2195         g_variant_builder_unref(inner_builder);
2196         g_variant_builder_unref(outer_builder);
2197         g_variant_builder_unref(invalidated_builder);
2198
2199         return err;
2200 }
2201
2202 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2203 {
2204         GSList *l, *l1;
2205         struct gatt_service_info *svc_info;
2206         gboolean ret;
2207         int err = BLUETOOTH_ERROR_NONE;
2208         GSList *tmp;
2209
2210         BT_DBG("svc_path %s", svc_path);
2211         svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2212
2213         if (!svc_info) {
2214                 BT_ERR("Unable to find service info");
2215                 return BLUETOOTH_ERROR_NOT_FOUND;
2216         }
2217
2218         err = __bt_gatt_unregister_service(svc_path);
2219         if (err != BLUETOOTH_ERROR_NONE) {
2220                 BT_DBG("Could not unregister application");
2221                 return err;
2222         }
2223
2224         for (l = svc_info->char_data; l != NULL; l = l->next) {
2225                 struct gatt_char_info *char_info = l->data;
2226
2227                 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2228                         struct gatt_desc_info *desc_info = l1->data;
2229
2230                         ret = g_dbus_connection_unregister_object(g_conn,
2231                                                 desc_info->desc_id);
2232                         if (ret) {
2233                                 __bt_gatt_emit_interface_removed(
2234                                                 desc_info->desc_path,
2235                                                 GATT_DESC_INTERFACE);
2236                         } else {
2237                                 err = BLUETOOTH_ERROR_INTERNAL;
2238                         }
2239                 }
2240                 ret = g_dbus_connection_unregister_object(g_conn,
2241                                         char_info->char_id);
2242                 if (ret) {
2243                         __bt_gatt_emit_interface_removed(char_info->char_path,
2244                                                 GATT_CHAR_INTERFACE);
2245                 } else {
2246                         err = BLUETOOTH_ERROR_INTERNAL;
2247                 }
2248         }
2249         ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2250         if (ret) {
2251                 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2252                                                 GATT_SERV_INTERFACE);
2253         } else {
2254                 err = BLUETOOTH_ERROR_INTERNAL;
2255         }
2256
2257         ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2258         if (ret) {
2259                 BT_DBG("Unregistered the service on properties interface");
2260         }
2261
2262         for (tmp = gatt_services; tmp != NULL; tmp = tmp->next) {
2263                 struct gatt_service_info *info = tmp->data;
2264
2265                 if (g_strcmp0(info->serv_path, svc_path) == 0) {
2266                         gatt_services = g_slist_delete_link(gatt_services, tmp->data);
2267                 }
2268         }
2269
2270         new_service = FALSE;
2271
2272         if (gatt_services->next == NULL)
2273                 serv_id--;
2274
2275         return err;
2276 }
2277
2278 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2279                                         int resp_state, int offset, char *value, int value_length)
2280 {
2281         struct gatt_req_info *req_info = NULL;
2282
2283         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2284                         == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2285                 BT_ERR("Don't have aprivilege to use this API");
2286                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2287         }
2288
2289         req_info = __bt_gatt_find_request_info(request_id);
2290
2291         if (req_info) {
2292                 if (resp_state != BLUETOOTH_ERROR_NONE) {
2293
2294                         GQuark quark = g_quark_from_string("gatt-server");
2295                         GError *err = g_error_new(quark, 0, "Application Error");
2296                         g_dbus_method_invocation_return_gerror(req_info->context, err);
2297                         g_error_free(err);
2298
2299                         gatt_requests = g_slist_remove(gatt_requests, req_info);
2300
2301                         req_info->context = NULL;
2302                         if (req_info->attr_path)
2303                                 g_free(req_info->attr_path);
2304                         if (req_info->svc_path)
2305                                 g_free(req_info->svc_path);
2306                         g_free(req_info);
2307
2308                         return BLUETOOTH_ERROR_NONE;
2309                 }
2310                 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2311                         int i;
2312                         GVariantBuilder *inner_builder = NULL;
2313                         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2314                         if (value_length > 0 && value != NULL) {
2315                                 for (i = 0; i < value_length; i++)
2316                                         g_variant_builder_add(inner_builder, "y", value[i]);
2317                         }
2318                         g_dbus_method_invocation_return_value(req_info->context,
2319                                                 g_variant_new("(ay)", inner_builder));
2320                         g_variant_builder_unref(inner_builder);
2321                 } else {
2322                         g_dbus_method_invocation_return_value(req_info->context, NULL);
2323                 }
2324                 gatt_requests = g_slist_remove(gatt_requests, req_info);
2325
2326                 req_info->context = NULL;
2327                 if (req_info->attr_path)
2328                         g_free(req_info->attr_path);
2329                 if (req_info->svc_path)
2330                         g_free(req_info->svc_path);
2331                 g_free(req_info);
2332         } else {
2333                 return BLUETOOTH_ERROR_INTERNAL;
2334         }
2335
2336         return BLUETOOTH_ERROR_NONE;
2337 }
2338
2339 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2340                                                 bluetooth_device_address_t *unicast_address)
2341 {
2342         GVariantBuilder *outer_builder;
2343         GVariantBuilder *invalidated_builder;
2344         GError *error = NULL;
2345         gboolean notify = TRUE;
2346         gboolean ret = TRUE;
2347         int err = BLUETOOTH_ERROR_NONE;
2348         gchar **line_argv = NULL;
2349         gchar *serv_path = NULL;
2350         char addr[20] = { 0 };
2351
2352         line_argv = g_strsplit_set(char_path, "/", 0);
2353         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2354
2355         if (!__bt_gatt_get_service_state(serv_path)) {
2356                 BT_DBG("service not registered for this characteristic \n");
2357                 g_strfreev(line_argv);
2358                 return BLUETOOTH_ERROR_INTERNAL;
2359         }
2360
2361         outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2362         invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2363
2364         g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2365                                         g_variant_new("b", notify));
2366
2367         if (unicast_address) {
2368                 _bt_convert_addr_type_to_string(addr,
2369                                         (unsigned char *)unicast_address->addr);
2370         }
2371         g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2372                                 g_variant_new("s", addr));
2373
2374         BT_DBG("Set characteristic Notification \n");
2375         ret = g_dbus_connection_emit_signal(g_conn, NULL,
2376                                         char_path,
2377                                         "org.freedesktop.DBus.Properties",
2378                                         "PropertiesChanged",
2379                                         g_variant_new("(sa{sv}as)",
2380                                         "org.bluez.GattCharacteristic1",
2381                                         outer_builder, invalidated_builder),
2382                                         &error);
2383
2384         if (!ret) {
2385                 if (error != NULL) {
2386                         BT_ERR("D-Bus API failure: errCode[%x], \
2387                                         message[%s]",
2388                                         error->code, error->message);
2389                         g_clear_error(&error);
2390                 }
2391                 err = BLUETOOTH_ERROR_INTERNAL;
2392         }
2393
2394         g_strfreev(line_argv);
2395         g_variant_builder_unref(outer_builder);
2396         g_variant_builder_unref(invalidated_builder);
2397
2398         return err;
2399 }