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