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