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