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