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