Code Sync [Tizen3.0]: Merged the tizen_2.4 Spin code to tizen.org
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-service.c
1 /*
2  * Bluetooth-frwk low energy
3  *
4  * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7  *                  Chanyeol Park <chanyeol.park@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *              http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include<gio/gio.h>
24 #include<glib.h>
25 #include<glib/gprintf.h>
26 #include<stdlib.h>
27 #include<unistd.h>
28 #include<stdint.h>
29
30 #include "bt-common.h"
31
32 #define NUMBER_OF_FLAGS 10
33
34 GDBusConnection *g_conn;
35 guint owner_id;
36 guint manager_id;
37 static gboolean new_service = FALSE;
38 static gboolean new_char = FALSE;
39 static int serv_id = 1;
40
41 /* Introspection data for the service we are exporting */
42 static const gchar service_introspection_xml[] =
43 "<node name='/'>"
44 "  <interface name='org.bluez.GattService1'>"
45 "    <property type='s' name='UUID' access='read'>"
46 "    </property>"
47 "    <property type='s' name='Includes' access='read'>"
48 "    </property>"
49 "  </interface>"
50 "</node>";
51
52 /* Introspection data for the characteristics we are exporting */
53 static const gchar characteristics_introspection_xml[] =
54 "<node name='/'>"
55 "  <interface name='org.bluez.GattCharacteristic1'>"
56 "    <property type='s' name='UUID' access='read'>"
57 "    </property>"
58 "    <property type='o' name='Service' access='read'>"
59 "    </property>"
60 "    <property type='ay' name='Value' access='readwrite'>"
61 "    </property>"
62 "    <property type='as' name='Flags' access='read'>"
63 "    </property>"
64 "  </interface>"
65 "</node>";
66
67 /* Introspection data for the descriptor we are exporting */
68 static const gchar descriptor_introspection_xml[] =
69 "<node name='/'>"
70 "  <interface name='org.bluez.GattDescriptor1'>"
71 "    <property type='s' name='UUID' access='read'>"
72 "    </property>"
73 "    <property type='o' name='Characteristic' access='read'>"
74 "    </property>"
75 "    <property type='ay' name='Value' access='readwrite'>"
76 "    </property>"
77 "    <property type='s' name='Permissions' access='read'>"
78 "    </property>"
79 "  </interface>"
80 "</node>";
81
82 static const gchar manager_introspection_xml[] =
83 "<node name='/'>"
84 "  <interface name='org.freedesktop.DBus.ObjectManager'>"
85 "    <method name='GetManagedObjects'>"
86 "     <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
87 "        </method>"
88 "  </interface>"
89 "</node>";
90
91 static const gchar properties_introspection_xml[] =
92 "<node name='/'>"
93 "  <interface name='org.freedesktop.DBus.Properties'>"
94 "        <method name='Set'>"
95 "               <arg type='s' name='interface' direction='in'/>"
96 "               <arg type='s' name='name' direction='in'/>"
97 "               <arg type='v' name='value' direction='in'/>"
98 "        </method>"
99 "  </interface>"
100 "</node>";
101
102 struct gatt_service_info {
103         gchar *serv_path;
104         guint serv_id;
105         gchar *service_uuid;
106         guint manager_id;
107         guint prop_id;
108         GSList *char_data;
109         gboolean is_svc_registered;
110 };
111
112 struct gatt_char_info {
113         gchar *char_path;
114         guint char_id;
115         gchar *char_uuid;
116         gchar *char_value;
117         gchar *char_flags[NUMBER_OF_FLAGS];
118         int value_length;
119         int flags_length;
120         GSList *desc_data;
121 };
122
123 struct gatt_desc_info {
124         gchar *desc_path;
125         guint desc_id;
126         gchar *desc_uuid;
127         gchar *desc_value;
128         int value_length;
129 };
130
131 static GSList *gatt_services = NULL;
132
133 #define BT_GATT_SERVICE_NAME    "org.frwk.gatt_service"
134 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
135
136 #define GATT_SERV_OBJECT_PATH   "/service"
137
138 #define GATT_MNGR_INTERFACE             "org.bluez.GattManager1"
139 #define GATT_SERV_INTERFACE             "org.bluez.GattService1"
140 #define GATT_CHAR_INTERFACE             "org.bluez.GattCharacteristic1"
141 #define GATT_DESC_INTERFACE             "org.bluez.GattDescriptor1"
142
143 static GDBusProxy *manager_gproxy = NULL;
144
145 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
146                                         const gchar *sender,
147                                         const gchar *object_path,
148                                         const gchar *interface_name,
149                                         const gchar *method_name,
150                                         GVariant *parameters,
151                                         GDBusMethodInvocation *invocation,
152                                         gpointer user_data)
153 {
154         if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
155
156                 BT_DBG("Getting values for service, chars and descriptors");
157                 GVariantBuilder *builder;
158                 /*Main Builder */
159                 builder = g_variant_builder_new(
160                                 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
161
162                 /* Prepare inner builder for GattService1 interface */
163
164                 GVariantBuilder *svc_builder = NULL;
165                 GVariantBuilder *inner_builder = NULL;
166
167                 GSList *l1 = g_slist_last(gatt_services);
168                 struct gatt_service_info *serv_info = l1->data;
169                 if (serv_info == NULL) {
170                         BT_ERR("service info value is NULL");
171                         g_dbus_method_invocation_return_value(invocation, NULL);
172                         return;
173                 }
174
175                 /* Prepare inner builder for GattService1 interface */
176                 BT_DBG("Creating builder for service");
177                 svc_builder = g_variant_builder_new(
178                                         G_VARIANT_TYPE("a{sa{sv}}"));
179                 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
180
181                 g_variant_builder_add(inner_builder, "{sv}", "UUID",
182                                 g_variant_new_string(serv_info->service_uuid));
183
184                 g_variant_builder_add(svc_builder, "{sa{sv}}",
185                                                         GATT_SERV_INTERFACE,
186                                                         inner_builder);
187
188                 g_variant_builder_add(builder, "{oa{sa{sv}}}",
189                                                         serv_info->serv_path,
190                                                         svc_builder);
191
192                 /* Prepare inner builder for GattCharacteristic1 interface */
193
194                 GSList *l2 = serv_info->char_data;
195                 BT_DBG("Creating builder for characteristics \n");
196
197                 if (l2 == NULL)
198                         BT_DBG("characteristic data is NULL");
199
200                 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
201
202                         GVariantBuilder *char_builder = NULL;
203                         GVariantBuilder *inner_builder = NULL;
204                         GVariantBuilder *builder1 = NULL;
205                         GVariantBuilder *builder2 = NULL;
206                         GVariant *char_val = NULL;
207                         GVariant *flags_val = NULL;
208                         int i = 0;
209
210                         char_builder = g_variant_builder_new(
211                                                         G_VARIANT_TYPE(
212                                                                 "a{sa{sv}}"));
213                         inner_builder = g_variant_builder_new(
214                                                         G_VARIANT_TYPE(
215                                                                 "a{sv}"));
216
217                         struct gatt_char_info *char_info = l2->data;
218                         if (char_info == NULL) {
219                                 BT_ERR("char_info is NULL");
220                                 continue;
221                         }
222
223                         /*Uuid*/
224                         g_variant_builder_add(inner_builder, "{sv}", "UUID",
225                                 g_variant_new_string(char_info->char_uuid));
226                         /*Service*/
227                         g_variant_builder_add(inner_builder, "{sv}", "Service",
228                                 g_variant_new("o", serv_info->serv_path));
229                         /*Value*/
230                         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
231
232                         if(char_info->char_value != NULL) {
233                                 for (i = 0; i < char_info->value_length; i++) {
234                                         g_variant_builder_add(builder1, "y",
235                                                 char_info->char_value[i]);
236                                 }
237                                 char_val = g_variant_new("ay", builder1);
238                                 g_variant_builder_add(inner_builder, "{sv}",
239                                                 "Value", char_val);
240                         }
241                         /*Flags*/
242                         builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
243
244                         for (i = 0; i < char_info->flags_length; i++) {
245                                 g_variant_builder_add(builder2, "s",
246                                         char_info->char_flags[i]);
247                         }
248
249                         flags_val = g_variant_new("as", builder2);
250                         g_variant_builder_add(inner_builder, "{sv}", "Flags",
251                                                 flags_val);
252
253                         g_variant_builder_add(char_builder, "{sa{sv}}",
254                                         GATT_CHAR_INTERFACE , inner_builder);
255                         g_variant_builder_add(builder, "{oa{sa{sv}}}",
256                                         char_info->char_path, char_builder);
257
258                         /*Prepare inner builder for GattDescriptor1 interface*/
259
260                         GSList *l3 = char_info->desc_data;
261
262                         if (l3 == NULL)
263                                 BT_DBG("descriptor data is NULL");
264
265                         for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
266
267                                 BT_DBG("Creating builder for descriptor \n");
268
269                                 GVariantBuilder *desc_builder = NULL;
270                                 GVariantBuilder *inner_builder = NULL;
271                                 GVariantBuilder *builder1 = NULL;
272                                 GVariant *desc_val = NULL;
273
274                                 desc_builder = g_variant_builder_new(
275                                                         G_VARIANT_TYPE(
276                                                         "a{sa{sv}}"));
277                                 inner_builder = g_variant_builder_new(
278                                                         G_VARIANT_TYPE(
279                                                         "a{sv}"));
280
281                                 struct gatt_desc_info *desc_info = l3->data;
282                                 if (desc_info == NULL) {
283                                         BT_ERR("desc_info is NULL");
284                                         continue;
285                                 }
286
287                                 /*Uuid*/
288                                 g_variant_builder_add(inner_builder,
289                                         "{sv}", "UUID",
290                                         g_variant_new_string(
291                                                 desc_info->desc_uuid));
292
293                                 /*Characteristic*/
294                                 g_variant_builder_add(inner_builder, "{sv}",
295                                         "Characteristic",
296                                         g_variant_new("o",
297                                                 char_info->char_path));
298
299                                 /*Value*/
300                                 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
301
302                                 if(desc_info->desc_value != NULL) {
303                                         for (i = 0; i < desc_info->value_length; i++) {
304                                                 g_variant_builder_add(builder1, "y",
305                                                         desc_info->desc_value[i]);
306                                         }
307                                         desc_val = g_variant_new("ay", builder1);
308                                         g_variant_builder_add(inner_builder, "{sv}",
309                                                         "Value", desc_val);
310                                 }
311
312                                 g_variant_builder_add(desc_builder, "{sa{sv}}",
313                                                 GATT_DESC_INTERFACE,
314                                                 inner_builder);
315
316                                 g_variant_builder_add(builder, "{oa{sa{sv}}}",
317                                                 desc_info->desc_path,
318                                                 desc_builder);
319
320                                 /*unref descriptor builder pointers*/
321                                 g_variant_builder_unref(builder1);
322                                 g_variant_builder_unref(inner_builder);
323                                 g_variant_builder_unref(desc_builder);
324                         }
325
326                         /*unref char builder pointers*/
327                         g_variant_builder_unref(builder1);
328                         g_variant_builder_unref(builder2);
329                         g_variant_builder_unref(inner_builder);
330                         g_variant_builder_unref(char_builder);
331                 }
332
333                 /*unref service builder pointers*/
334                 g_variant_builder_unref(inner_builder);
335                 g_variant_builder_unref(svc_builder);
336
337                 /* Return builder as method reply */
338                 BT_DBG("Sending gatt service builder values to Bluez");
339                 g_dbus_method_invocation_return_value(invocation,
340                                                 g_variant_new(
341                                                 "(a{oa{sa{sv}}})",
342                                                 builder));
343         }
344 }
345
346 static void __bt_gatt_prop_method_call(GDBusConnection *connection,
347                                         const gchar *sender,
348                                         const gchar *object_path,
349                                         const gchar *interface_name,
350                                         const gchar *method_name,
351                                         GVariant *parameters,
352                                         GDBusMethodInvocation *invocation,
353                                         gpointer user_data)
354 {
355         g_dbus_method_invocation_return_value(invocation, NULL);
356 }
357
358 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
359 {
360         gboolean ret;
361         GError *error = NULL;
362         GVariantBuilder *array_builder;
363
364         array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
365         g_variant_builder_init(array_builder, G_VARIANT_TYPE ("as"));
366         g_variant_builder_add(array_builder, "s", interface);
367
368         ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
369                                         "org.freedesktop.Dbus.Objectmanager",
370                                         "InterfacesRemoved",
371                                         g_variant_new ("(oas)",
372                                         object_path, array_builder),
373                                         &error);
374
375         if (!ret) {
376                 if (error != NULL) {
377                         /* dbus gives error cause */
378                         BT_ERR("d-bus api failure: errcode[%x], message[%s]",
379                                 error->code, error->message);
380                         g_clear_error(&error);
381                 }
382         }
383         g_variant_builder_unref(array_builder);
384
385         return ret;
386 }
387
388 static gboolean __bt_gatt_desc_set_property(GDBusConnection *connection,
389                                 const gchar *sender, const gchar *object_path,
390                                 const gchar *interface_name,
391                                 const gchar *property_name,
392                                 GVariant *value,
393                                 GError **err, gpointer user_data)
394 {
395         BT_DBG("+");
396
397         return TRUE;
398 }
399
400 static gboolean __bt_gatt_char_set_property(GDBusConnection *connection,
401                                 const gchar *sender, const gchar *object_path,
402                                 const gchar *interface_name,
403                                 const gchar *property_name,
404                                 GVariant *value,
405                                 GError **err, gpointer user_data)
406 {
407         BT_DBG("+");
408
409         if (g_strcmp0(property_name, "Value") == 0) {
410                 GVariantIter *var = NULL;
411                 bt_gatt_char_value_t char_val = {0, };
412                 bt_user_info_t *user_info = NULL;
413                 int len = 0, i;
414
415                 g_variant_get(value, "ay", &var);
416                 len = g_variant_get_size(var);
417
418                 char_val.char_handle = object_path;
419                 if (len > 0) {
420                         char_val.char_value = (guint8 *)malloc(len);
421                         if (!char_val.char_value)
422                                 return FALSE;
423                 }
424                 for (i = 0; i < len; i++)
425                         g_variant_iter_loop(var, "y",  &char_val.char_value[i]);
426                 char_val.val_len = len;
427                 user_info = _bt_get_user_data(BT_COMMON);
428                 if (user_info != NULL)
429                         _bt_common_event_cb(
430                                 BLUETOOTH_EVENT_GATT_SERVER_CHARACTERISTIC_VALUE_CHANGED,
431                                 BLUETOOTH_ERROR_NONE, &char_val,
432                                 user_info->cb, user_info->user_data);
433
434                 bluetooth_gatt_update_characteristic(object_path, char_val.char_value,
435                                                                         char_val.val_len);
436
437                 free(char_val.char_value);
438         }
439
440         return TRUE;
441 }
442
443 static GVariant *__bt_gatt_desc_get_property(GDBusConnection *connection,
444                                 const gchar *sender, const gchar *object_path,
445                                 const gchar *interface_name,
446                                 const gchar *property_name,
447                                 GError **error, gpointer user_data)
448 {
449         BT_DBG("+");
450
451         return NULL;
452 }
453
454 static GVariant *__bt_gatt_char_get_property(GDBusConnection *connection,
455                                 const gchar *sender, const gchar *object_path,
456                                 const gchar *interface_name,
457                                 const gchar *property_name,
458                                 GError **error, gpointer user_data)
459 {
460         BT_DBG("+");
461
462         return NULL;
463 }
464
465 static GVariant *__bt_gatt_serv_get_property(GDBusConnection *connection,
466                                 const gchar *sender, const gchar *object_path,
467                                 const gchar *interface_name,
468                                 const gchar *property_name,
469                                 GError **error, gpointer user_data)
470 {
471         BT_DBG("+");
472
473         return NULL;
474 }
475
476 static const GDBusInterfaceVTable desc_interface_vtable = {
477         NULL,
478         __bt_gatt_desc_get_property,
479         __bt_gatt_desc_set_property
480 };
481
482 static const GDBusInterfaceVTable char_interface_vtable = {
483         NULL,
484         __bt_gatt_char_get_property,
485         __bt_gatt_char_set_property,
486 };
487
488 static const GDBusInterfaceVTable serv_interface_vtable = {
489         NULL,
490         __bt_gatt_serv_get_property,
491         NULL,
492 };
493
494 static const GDBusInterfaceVTable manager_interface_vtable = {
495         __bt_gatt_manager_method_call,
496         NULL,
497         NULL
498 };
499
500 static const GDBusInterfaceVTable properties_interface_vtable = {
501         __bt_gatt_prop_method_call,
502         NULL,
503         NULL
504 };
505
506 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
507                                 const gchar *introspection_data)
508 {
509         GError *err = NULL;
510         GDBusNodeInfo *node_info = NULL;
511
512         if (introspection_data == NULL)
513                 return NULL;
514
515         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
516
517         if (err) {
518                 BT_ERR("Unable to create node: %s", err->message);
519                 g_clear_error(&err);
520         }
521         return node_info;
522 }
523
524 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
525                         const char *service_path)
526 {
527         GSList *l;
528
529         for (l = gatt_services; l != NULL; l = l->next) {
530                 struct gatt_service_info *info = l->data;
531
532                 if (g_strcmp0(info->serv_path, service_path) == 0)
533                         return info;
534         }
535         BT_ERR("Gatt service not found");
536         return NULL;
537 }
538
539 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
540                         const char *service_path, const char *char_path)
541 {
542         GSList *l1, *l2;
543
544         for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
545                 struct gatt_service_info *serv_info = l1->data;
546
547                 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
548
549                         for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
550                                 struct gatt_char_info *char_info = l2->data;
551
552                                 if (g_strcmp0(char_info->char_path, char_path)
553                                                         == 0)
554                                         return char_info;
555                         }
556                         BT_ERR("Gatt characteristic not found");
557                         return NULL;
558                 }
559         }
560         BT_ERR("Gatt service not found");
561         return NULL;
562 }
563
564 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
565                         const char *serv_path, const char *char_path,
566                         const char *desc_path)
567 {
568         GSList *l1, *l2, *l3;
569
570         for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
571                 struct gatt_service_info *serv_info = l1->data;
572
573                 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
574                         for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
575                                 struct gatt_char_info *char_info = l2->data;
576
577                                 if (g_strcmp0(char_info->char_path, char_path)
578                                                         == 0) {
579                                         for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
580                                                 struct gatt_desc_info *desc_info = l3->data;
581                                                 if (g_strcmp0(desc_info->desc_path,
582                                                         desc_path) == 0) {
583                                                         return desc_info;
584                                                 }
585                                         }
586                                 }
587                         }
588                 }
589         }
590         BT_ERR("Gatt descriptor not found");
591         return NULL;
592 }
593
594
595 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
596                                 const gchar *path, const gchar *interface)
597 {
598         GDBusProxy *proxy;
599         GError *err = NULL;
600
601         if (g_conn == NULL)
602                 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
603                                                         NULL, &err);
604
605         if (!g_conn) {
606                 if (err) {
607                         BT_ERR("Unable to connect to gdbus: %s", err->message);
608                         g_clear_error(&err);
609                 }
610                 return NULL;
611         }
612
613         proxy =  g_dbus_proxy_new_sync(g_conn,
614                         G_DBUS_PROXY_FLAGS_NONE, NULL,
615                         service, path,
616                         interface, NULL, &err);
617
618         if (!proxy) {
619                 if (err) {
620                         BT_ERR("Unable to create proxy: %s", err->message);
621                         g_clear_error(&err);
622                 }
623                 return NULL;
624         }
625         manager_gproxy = proxy;
626
627         return proxy;
628 }
629
630 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
631                                 const gchar *path, const gchar *interface)
632 {
633         return (manager_gproxy) ? manager_gproxy :
634                         __bt_gatt_gdbus_init_manager_proxy(service,
635                                 path, interface);
636 }
637
638 static gboolean __bt_gatt_export_properties_method(const char *svc_path)
639 {
640         guint prop_id;
641         GDBusNodeInfo *prop_info;
642         GError *error = NULL;
643         struct gatt_service_info *svc_info;
644
645         BT_DBG("svc_path %s", svc_path);
646         svc_info = __bt_gatt_find_gatt_service_info(svc_path);
647
648         if (!svc_info) {
649             BT_ERR("Unable to find service info");
650                 return FALSE;
651         }
652
653         /* Register ObjectManager interface */
654         prop_info = __bt_gatt_create_method_node_info(
655                                                 properties_introspection_xml);
656
657         if (prop_info == NULL) {
658                 BT_ERR("failed to get node info");
659                 return FALSE;
660         }
661
662         prop_id = g_dbus_connection_register_object(g_conn, svc_path,
663                                                 prop_info->interfaces[0],
664                                                 &properties_interface_vtable,
665                                                 NULL, NULL, &error);
666
667         if (prop_id == 0) {
668                 BT_ERR("failed to register: %s", error->message);
669                 g_error_free(error);
670                 return FALSE;
671         }
672         svc_info->prop_id = prop_id;
673
674         return TRUE;
675 }
676
677 int bluetooth_gatt_convert_prop2string(
678                         bt_gatt_characteristic_property_t properties,
679                         char *char_properties[])
680 {
681         int flag_count = 0;
682
683         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
684                 char_properties[flag_count] = g_strdup("broadcast");
685                 flag_count++;
686         }
687         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
688                 char_properties[flag_count] = g_strdup("read");
689                 flag_count++;
690         }
691         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
692                 char_properties[flag_count] = g_strdup("write-without-response");
693                 flag_count++;
694         }
695         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
696                 char_properties[flag_count] = g_strdup("write");
697                 flag_count++;
698         }
699         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
700                 char_properties[flag_count] = g_strdup("notify");
701                 flag_count++;
702         }
703         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
704                 char_properties[flag_count] = g_strdup("indicate");
705                 flag_count++;
706         }
707         if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
708                 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
709                 flag_count++;
710         }
711
712         if (flag_count == 0) {
713                 char_properties[flag_count] = g_strdup("read");
714                 flag_count++;
715         }
716
717         return flag_count;
718 }
719
720 static void __bt_gatt_set_service_state(const char *service_path,
721                         gboolean state)
722 {
723         struct gatt_service_info *svc_info = NULL;
724         svc_info = __bt_gatt_find_gatt_service_info(service_path);
725
726         if (svc_info != NULL) {
727                 BT_DBG("Updating the gatt service register state %d", state);
728                 svc_info->is_svc_registered = state;
729                 return;
730         }
731
732         BT_DBG("gatt service not found");
733 }
734
735 static gboolean __bt_gatt_get_service_state(const char *service_path)
736 {
737         struct gatt_service_info *svc_info = NULL;
738
739         svc_info = __bt_gatt_find_gatt_service_info(service_path);
740
741         if (svc_info != NULL) {
742                 BT_DBG("Return the state of the gatt service %d",
743                         svc_info->is_svc_registered);
744                 return svc_info->is_svc_registered;
745         }
746
747         BT_DBG("gatt service info is NULL");
748         return FALSE;
749 }
750
751 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
752 {
753         GError *error = NULL;
754         GVariant *result;
755         GVariantIter *iter = NULL;
756         const gchar *key = NULL;
757         GVariant *value = NULL;
758         gchar *service = NULL;
759         gchar *characteristic = NULL;
760         gchar *descriptor = NULL;
761         int n_char = 1;
762
763         BT_DBG(" ");
764         result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
765
766         if (result == NULL) {
767                 /* dBUS-RPC is failed */
768                 BT_ERR("Dbus-RPC is failed\n");
769
770                 if (error != NULL) {
771                 /* dBUS gives error cause */
772                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
773                                                 error->code, error->message);
774                         g_clear_error(&error);
775                 }
776         } else {
777                 char *char_cmp = NULL;
778                 g_variant_get (result, "(a{sv})", &iter);
779                 char_cmp = g_strdup_printf("Characteristic%d", n_char);
780
781                 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
782                         if (g_strcmp0(key, "Service") == 0) {
783                                 service = g_variant_get_string(value, NULL);
784                                 BT_DBG("Service %s", service);
785                         } else if (g_strcmp0(key, char_cmp) == 0) {
786                                 characteristic = g_variant_get_string(value, NULL);
787                                 g_free(char_cmp);
788                                 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
789                                 BT_DBG("%s", characteristic);
790                         } else if (g_strcmp0(key, "Descriptor") == 0) {
791                                 descriptor = g_variant_get_string(value, NULL);
792                                 BT_DBG("Descriptor %s", descriptor);
793                         }
794                 }
795                 /* TODO: Store the service informationa and
796                  * Send respponse to CAPI layer. */
797
798                 g_variant_unref(result);
799                 if (char_cmp);
800                         g_free(char_cmp);
801         }
802 }
803 void register_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
804 {
805         BT_DBG("register_service_cb\n");
806
807         GError *error = NULL;
808         GVariant *result;
809
810         result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
811
812         if (result == NULL) {
813                 /* dBUS-RPC is failed */
814                 BT_ERR("Dbus-RPC is failed\n");
815
816                 if (error != NULL) {
817                 /* dBUS gives error cause */
818                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
819                                                 error->code, error->message);
820                         g_clear_error(&error);
821                 }
822         }
823 }
824
825 void unregister_service_cb(GObject *object, GAsyncResult *res,
826                 gpointer user_data)
827 {
828         BT_DBG("unregister_service_cb\n");
829
830         GError *error = NULL;
831         GVariant *result;
832
833         result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
834
835         if (result == NULL) {
836                 /* dBUS-RPC is failed */
837                 BT_ERR("Dbus-RPC is failed\n");
838
839                 if (error != NULL) {
840                         /* dBUS gives error cause */
841                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
842                                         error->code, error->message);
843                         g_clear_error(&error);
844                 }
845         }
846 }
847
848 static int __bt_gatt_unregister_service(const char *service_path)
849 {
850         if (!__bt_gatt_get_service_state(service_path)) {
851                 BT_DBG("service not registered \n");
852                 return BLUETOOTH_ERROR_NOT_FOUND;
853         }
854
855         GDBusProxy *proxy = NULL;
856
857         proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
858                                         "/org/bluez", GATT_MNGR_INTERFACE);
859
860         if (proxy == NULL)
861                 return BLUETOOTH_ERROR_INTERNAL;
862
863         /* Async Call to Unregister Service */
864         g_dbus_proxy_call(proxy,
865                                 "UnregisterService",
866                                 g_variant_new("(o)",
867                                 service_path),
868                                 G_DBUS_CALL_FLAGS_NONE, -1,
869                                 NULL,
870                                 (GAsyncReadyCallback) unregister_service_cb,
871                                 NULL);
872
873         __bt_gatt_set_service_state(service_path, FALSE);
874
875         return BLUETOOTH_ERROR_NONE;
876 }
877
878 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
879 {
880         GDBusConnection *local_system_gconn = NULL;
881         GError *err = NULL;
882
883         if (g_conn == NULL) {
884                 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
885                 if (!g_conn) {
886                         if (err) {
887                                 BT_ERR("Unable to connect to dbus: %s", err->message);
888                                 g_clear_error(&err);
889                         }
890                         g_conn = NULL;
891                 }
892         } else if (g_dbus_connection_is_closed(g_conn)) {
893                 local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
894
895                 if (!local_system_gconn) {
896                         BT_ERR("Unable to connect to dbus: %s", err->message);
897                         g_clear_error(&err);
898                 }
899
900                 g_conn = local_system_gconn;
901         }
902
903         return g_conn;
904 }
905
906 BT_EXPORT_API int bluetooth_gatt_init(void)
907 {
908         guint object_id;
909         GDBusConnection *conn;
910         GDBusNodeInfo *obj_info;
911         GError *error = NULL;
912
913         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
914                                 BT_GATT_SERVICE_NAME,
915                                 G_BUS_NAME_OWNER_FLAGS_NONE,
916                                 NULL, NULL, NULL, NULL, NULL);
917
918         BT_DBG("owner_id is [%d]", owner_id);
919
920         serv_id = 1;
921
922         conn = __bt_gatt_get_gdbus_connection();
923         if (!conn) {
924                 BT_ERR("Unable to get connection");
925                 return BLUETOOTH_ERROR_INTERNAL;
926         }
927
928         /* Register ObjectManager interface */
929         obj_info = __bt_gatt_create_method_node_info(
930                                         manager_introspection_xml);
931
932         if (obj_info == NULL) {
933                 BT_ERR("failed to get node info");
934                 return BLUETOOTH_ERROR_INTERNAL;
935         }
936
937         manager_id = g_dbus_connection_register_object(g_conn, "/",
938                                                 obj_info->interfaces[0],
939                                                 &manager_interface_vtable,
940                                                 NULL, NULL, &error);
941
942         if (manager_id == 0) {
943                 BT_ERR("failed to register: %s", error->message);
944                 g_error_free(error);
945                 return BLUETOOTH_ERROR_INTERNAL;
946         }
947
948         return BLUETOOTH_ERROR_NONE;
949 }
950
951 BT_EXPORT_API int bluetooth_gatt_deinit()
952 {
953         /* Unown gdbus bus */
954         if (owner_id) {
955
956                 /* remove/unregister all services */
957                 BT_DBG("removing all registered gatt service\n");
958                 bluetooth_gatt_delete_services();
959
960                 g_bus_unown_name(owner_id);
961
962                 /* unregister the exported interface for object manager */
963                 g_dbus_connection_unregister_object(g_conn,
964                                         manager_id);
965
966                 BT_DBG("Gatt service deinitialized \n");
967
968                 g_slist_free(gatt_services);
969                 gatt_services = NULL;
970
971                 return BLUETOOTH_ERROR_NONE;
972         }
973
974         return BLUETOOTH_ERROR_NOT_FOUND;
975 }
976
977 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
978                         char **svc_path)
979 {
980         GError *error = NULL;
981         guint object_id;
982         GDBusNodeInfo *node_info;
983         gchar *path = NULL;
984         GVariantBuilder *builder = NULL;
985         GVariantBuilder *inner_builder = NULL;
986         struct gatt_service_info *serv_info = NULL;
987
988         node_info = __bt_gatt_create_method_node_info(
989                                         service_introspection_xml);
990
991         if (node_info == NULL)
992                 return BLUETOOTH_ERROR_INTERNAL;
993
994         path = g_strdup_printf(GATT_SERV_OBJECT_PATH"%d", serv_id++);
995         BT_DBG("gatt service path is [%s]", path);
996
997         object_id = g_dbus_connection_register_object(g_conn, path,
998                                         node_info->interfaces[0],
999                                         &serv_interface_vtable,
1000                                         NULL, NULL, &error);
1001
1002         if (object_id == 0) {
1003                 BT_ERR("failed to register: %s", error->message);
1004                 g_error_free(error);
1005                 g_free(path);
1006
1007                 return BLUETOOTH_ERROR_INTERNAL;
1008         }
1009
1010         /* Add object_id/gatt service information; it's required at the time of
1011          *  service unregister and Getmanagedobjects
1012          */
1013         serv_info = g_new0(struct gatt_service_info, 1);
1014
1015         serv_info->serv_path = g_strdup(path);
1016         serv_info->serv_id = object_id;
1017         serv_info->service_uuid = g_strdup(svc_uuid);
1018         serv_info->is_svc_registered = FALSE;
1019
1020         gatt_services = g_slist_append(gatt_services, serv_info);
1021
1022         /* emit interfacesadded signal here for service path */
1023         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1024         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1025
1026         g_variant_builder_add(inner_builder, "{sv}",
1027                 "UUID", g_variant_new_string(svc_uuid));
1028
1029         g_variant_builder_add(builder, "{sa{sv}}",
1030                 GATT_SERV_INTERFACE, inner_builder);
1031
1032         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1033                                 "org.freedesktop.Dbus.ObjectManager",
1034                                 "InterfacesAdded",
1035                                 g_variant_new("(oa{sa{sv}})",
1036                                 path, builder),
1037                                 &error);
1038
1039         new_service = TRUE;
1040
1041         *svc_path = g_strdup(path);
1042
1043         g_free(path);
1044         g_variant_builder_unref(inner_builder);
1045         g_variant_builder_unref(builder);
1046
1047         return BLUETOOTH_ERROR_NONE;
1048 }
1049
1050 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1051                         const char *svc_path, const char *char_uuid,
1052                         bt_gatt_characteristic_property_t properties,
1053                         char **char_path)
1054 {
1055         static int char_id;
1056         GError *error = NULL;
1057         guint object_id;
1058         GDBusNodeInfo *node_info;
1059         gchar *path = NULL;
1060         GVariantBuilder *builder = NULL;
1061         GVariantBuilder *inner_builder = NULL;
1062         struct gatt_service_info *serv_info = NULL;
1063         struct gatt_char_info *char_info = NULL;
1064         GVariantBuilder *builder2 = NULL;
1065         GVariant *flags_val = NULL;
1066         int i = 0;
1067         char *char_flags[NUMBER_OF_FLAGS];
1068         int flag_count = 0;
1069
1070         if (new_service) {
1071                 char_id = 1;
1072                 new_service = FALSE;
1073         }
1074
1075         BT_DBG("gatt svc_path path is [%s]", svc_path);
1076         serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1077         if (serv_info == NULL)
1078                 return BLUETOOTH_ERROR_INVALID_PARAM;
1079
1080         node_info = __bt_gatt_create_method_node_info(
1081                                         characteristics_introspection_xml);
1082
1083         if (node_info == NULL)
1084                 return BLUETOOTH_ERROR_INTERNAL;
1085
1086         path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1087         BT_DBG("gatt characteristic path is [%s]", path);
1088
1089         object_id = g_dbus_connection_register_object(g_conn, path,
1090                                         node_info->interfaces[0],
1091                                         &char_interface_vtable,
1092                                         NULL, NULL, &error);
1093
1094         if (object_id == 0) {
1095                 BT_ERR("failed to register: %s", error->message);
1096                 g_error_free(error);
1097                 g_free(path);
1098
1099                 return BLUETOOTH_ERROR_INTERNAL;
1100         }
1101
1102         flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1103
1104         char_info = g_new0(struct gatt_char_info, 1);
1105
1106         char_info->char_path = g_strdup(path);
1107         char_info->char_id = object_id;
1108         char_info->char_uuid = g_strdup(char_uuid);
1109
1110         for (i = 0; i < flag_count; i++) {
1111                 char_info->char_flags[i] = char_flags[i];
1112                 }
1113
1114         char_info->flags_length = flag_count;
1115
1116         serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1117
1118         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1119         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1120
1121         g_variant_builder_add(inner_builder, "{sv}", "UUID",
1122                                 g_variant_new("s", char_uuid));
1123         g_variant_builder_add(inner_builder, "{sv}", "Service",
1124                                 g_variant_new("o", svc_path));
1125
1126         builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1127
1128         for (i = 0; i < flag_count; i++) {
1129                 g_variant_builder_add(builder2, "s", char_flags[i]);
1130         }
1131
1132         flags_val = g_variant_new("as", builder2);
1133         g_variant_builder_add(inner_builder, "{sv}", "Flags",
1134                                 flags_val);
1135
1136         g_variant_builder_add(builder, "{sa{sv}}",
1137                                 GATT_CHAR_INTERFACE,
1138                                 inner_builder);
1139
1140         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1141                                 "org.freedesktop.Dbus.ObjectManager",
1142                                 "InterfacesAdded",
1143                                 g_variant_new("(oa{sa{sv}})",
1144                                 path, builder),
1145                                 &error);
1146
1147         *char_path = g_strdup(path);
1148
1149         new_char = TRUE;
1150
1151         g_free(path);
1152
1153         g_variant_builder_unref(inner_builder);
1154         g_variant_builder_unref(builder);
1155         g_variant_builder_unref(builder2);
1156
1157         return BLUETOOTH_ERROR_NONE;
1158 }
1159
1160 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1161                         const char *characteristic, const char *char_value,
1162                         int     value_length)
1163 {
1164         gchar **line_argv = NULL;
1165         char *serv_path = NULL;
1166         struct gatt_char_info *char_info = NULL;
1167         GVariantBuilder *builder1 = NULL;
1168         GVariantBuilder *builder = NULL;
1169         GVariantBuilder *inner_builder = NULL;
1170         GVariant *char_val = NULL;
1171         GError *error = NULL;
1172         int i = 0;
1173
1174         line_argv = g_strsplit_set(characteristic, "/", 0);
1175         serv_path = g_strdup_printf("/%s", line_argv[1]);
1176
1177         char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1178
1179         if (char_info == NULL) {
1180                 g_strfreev(line_argv);
1181                 return BLUETOOTH_ERROR_INVALID_PARAM;
1182         }
1183
1184         char_info->value_length = value_length;
1185
1186         char_info->char_value = (char *)malloc(value_length);
1187         for (i = 0; i < value_length; i++)
1188                 char_info->char_value[i] = char_value[i];
1189
1190         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1191         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1192
1193         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1194
1195         for (i = 0; i < value_length; i++) {
1196                 g_variant_builder_add(builder1, "y", char_value[i]);
1197         }
1198
1199         char_val = g_variant_new("ay", builder1);
1200                 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1201
1202         g_variant_builder_add(builder, "{sa{sv}}",
1203                         GATT_CHAR_INTERFACE,
1204                         inner_builder);
1205
1206         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1207                         "org.freedesktop.Dbus.ObjectManager",
1208                         "InterfacesAdded",
1209                         g_variant_new("(oa{sa{sv}})",
1210                         char_info->char_path, builder),
1211                         &error);
1212
1213         g_strfreev(line_argv);
1214         g_variant_builder_unref(inner_builder);
1215         g_variant_builder_unref(builder);
1216         g_variant_builder_unref(builder1);
1217
1218         return BLUETOOTH_ERROR_NONE;
1219 }
1220
1221 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1222                         const char *char_path, const char *desc_uuid,
1223                         char **desc_path)
1224 {
1225         static int desc_id = 1;
1226         GError *error = NULL;
1227         guint object_id;
1228         GDBusNodeInfo *node_info;
1229         gchar *path = NULL;
1230         GVariantBuilder *builder = NULL;
1231         GVariantBuilder *inner_builder = NULL;
1232         struct gatt_char_info *char_info = NULL;
1233         struct gatt_desc_info *desc_info = NULL;
1234         gchar **line_argv = NULL;
1235         char *serv_path;
1236
1237         if (new_char) {
1238                 desc_id = 1;
1239                 new_char = FALSE;
1240         }
1241
1242         line_argv = g_strsplit_set(char_path, "/", 0);
1243         serv_path = g_strdup_printf("/%s", line_argv[1]);
1244
1245         char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
1246
1247         g_free(serv_path);
1248
1249         if (char_info == NULL) {
1250                 g_strfreev(line_argv);
1251                 return BLUETOOTH_ERROR_INVALID_PARAM;
1252         }
1253
1254         node_info = __bt_gatt_create_method_node_info(
1255                                         descriptor_introspection_xml);
1256
1257         if (node_info == NULL) {
1258                 g_strfreev(line_argv);
1259                 return BLUETOOTH_ERROR_INTERNAL;
1260         }
1261
1262         path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
1263         BT_DBG("gatt descriptor path is [%s]", path);
1264
1265         object_id = g_dbus_connection_register_object(g_conn, path,
1266                                 node_info->interfaces[0],
1267                                 &desc_interface_vtable,
1268                                 NULL, NULL, &error);
1269
1270         if (object_id == 0) {
1271                 BT_ERR("failed to register: %s", error->message);
1272                 g_error_free(error);
1273                 g_free(path);
1274                 g_strfreev(line_argv);
1275
1276                 return BLUETOOTH_ERROR_INTERNAL;
1277         }
1278
1279         desc_info = g_new0(struct gatt_desc_info, 1);
1280
1281         desc_info->desc_path = g_strdup(path);
1282         desc_info->desc_id = object_id;
1283         desc_info->desc_uuid = g_strdup(desc_uuid);
1284
1285         char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
1286
1287         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1288         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1289
1290         g_variant_builder_add(inner_builder, "{sv}", "UUID",
1291                                 g_variant_new("s", desc_uuid));
1292         g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
1293                                 g_variant_new("o", char_path));
1294
1295         g_variant_builder_add(builder, "{sa{sv}}",
1296                                 GATT_DESC_INTERFACE,
1297                                 inner_builder);
1298
1299         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1300                                 "org.freedesktop.Dbus.ObjectManager",
1301                                 "InterfacesAdded",
1302                                 g_variant_new("(oa{sa{sv}})",
1303                                 path, builder),
1304                                 &error);
1305
1306         *desc_path = g_strdup(path);
1307
1308         g_free(path);
1309         g_strfreev(line_argv);
1310         g_variant_builder_unref(inner_builder);
1311         g_variant_builder_unref(builder);
1312
1313         return BLUETOOTH_ERROR_NONE;
1314 }
1315
1316 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
1317                         const char *desc_path, const char *desc_value,
1318                         int value_length)
1319 {
1320         GError *error = NULL;
1321         GVariantBuilder *builder = NULL;
1322         GVariantBuilder *inner_builder = NULL;
1323         GVariantBuilder *builder1 = NULL;
1324         struct gatt_desc_info *desc_info = NULL;
1325         gchar **line_argv = NULL;
1326         char *char_path;
1327         GVariant *desc_val = NULL;
1328         char *serv_path = NULL;
1329         int i ;
1330
1331         line_argv = g_strsplit_set(desc_path, "/", 0);
1332         serv_path = g_strdup_printf("/%s", line_argv[1]);
1333         char_path = g_strdup_printf("%s/%s", serv_path, line_argv[2]);
1334
1335         desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
1336
1337         if (desc_info == NULL) {
1338                 g_strfreev(line_argv);
1339                 return BLUETOOTH_ERROR_INVALID_PARAM;
1340         }
1341
1342         desc_info->desc_value = (char *)malloc(value_length);
1343
1344         for (i = 0; i < value_length; i++)
1345                 desc_info->desc_value[i] = desc_value[i];
1346
1347         desc_info->value_length = value_length;
1348
1349         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1350         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1351
1352         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1353
1354         for (i = 0; i < value_length; i++) {
1355                 g_variant_builder_add(builder1, "y", desc_value[i]);
1356         }
1357         desc_val = g_variant_new("ay", builder1);
1358         g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
1359
1360         g_variant_builder_add(builder, "{sa{sv}}",
1361                                 GATT_DESC_INTERFACE,
1362                                 inner_builder);
1363
1364         g_dbus_connection_emit_signal(g_conn, NULL, "/",
1365                                 "org.freedesktop.Dbus.ObjectManager",
1366                                 "InterfacesAdded",
1367                                 g_variant_new("(oa{sa{sv}})",
1368                                 desc_info->desc_path, builder),
1369                                 &error);
1370
1371         g_strfreev(line_argv);
1372         g_variant_builder_unref(inner_builder);
1373         g_variant_builder_unref(builder);
1374         g_variant_builder_unref(builder1);
1375
1376         return BLUETOOTH_ERROR_NONE;
1377 }
1378
1379 int bluetooth_gatt_get_service(const char *svc_uuid)
1380 {
1381         GDBusProxy *proxy = NULL;
1382         gchar *uuid = NULL;
1383
1384         proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1385                                         "/org/bluez", GATT_MNGR_INTERFACE);
1386         if (proxy == NULL)
1387                 return BLUETOOTH_ERROR_INTERNAL;
1388
1389         uuid = g_strdup(svc_uuid);
1390
1391         g_dbus_proxy_call(proxy,
1392                         "GetService",
1393                         g_variant_new("(s)",
1394                         uuid),
1395                         G_DBUS_CALL_FLAGS_NONE, -1,
1396                         NULL,
1397                         (GAsyncReadyCallback) get_service_cb,
1398                         NULL);
1399
1400         g_free(uuid);
1401
1402         return BLUETOOTH_ERROR_NONE;
1403 }
1404
1405 BT_EXPORT_API int bluetooth_gatt_register_service(
1406                         const char *svc_path)
1407 {
1408         GDBusProxy *proxy = NULL;
1409         gchar *path = NULL;
1410
1411         if (__bt_gatt_get_service_state(svc_path)) {
1412                 BT_DBG("service already registered \n");
1413                 return BLUETOOTH_ERROR_NONE;
1414         }
1415
1416         if (!__bt_gatt_export_properties_method(svc_path)) {
1417                 BT_ERR("Failed to export Object manager method");
1418                 return BLUETOOTH_ERROR_INTERNAL;
1419         }
1420
1421         proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1422                                         "/org/bluez", GATT_MNGR_INTERFACE);
1423         if (proxy == NULL)
1424                 return BLUETOOTH_ERROR_INTERNAL;
1425
1426         path = g_strdup(svc_path);
1427
1428         g_dbus_proxy_call(proxy,
1429                         "RegisterService",
1430                         g_variant_new("(oa{sv})",
1431                         path, NULL),
1432                         G_DBUS_CALL_FLAGS_NONE, -1,
1433                         NULL,
1434                         (GAsyncReadyCallback) register_service_cb,
1435                         NULL);
1436
1437         __bt_gatt_set_service_state(svc_path, TRUE);
1438
1439         g_free(path);
1440
1441         return BLUETOOTH_ERROR_NONE;
1442 }
1443
1444 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
1445 {
1446         GSList *l;
1447         int error = BLUETOOTH_ERROR_NONE;
1448         l = gatt_services;
1449
1450         if (l != NULL) {
1451                 for (l = gatt_services; l != NULL; l = l->next) {
1452                         struct gatt_service_info *info = l->data;
1453                         BT_DBG("svc_path is %s", info->serv_path);
1454                         if (bluetooth_gatt_unregister_service(info->serv_path)
1455                                         != BLUETOOTH_ERROR_NONE) {
1456                                 error = BLUETOOTH_ERROR_INTERNAL;
1457                                 BT_DBG(" Error in removing service %s \n",
1458                                                  info->serv_path);
1459                         }
1460                 }
1461                 BT_DBG(" All services removed successfully.\n ");
1462         }
1463         else {
1464                 BT_DBG(" There are no registered services.\n ");
1465         }
1466
1467         g_slist_free(gatt_services);
1468         gatt_services = NULL;
1469         serv_id = 1;
1470
1471         if (error != BLUETOOTH_ERROR_NONE)
1472                 return error;
1473
1474         return BLUETOOTH_ERROR_NONE;
1475 }
1476
1477 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
1478                         const char *char_path, const char* char_value,
1479                         int value_length)
1480 {
1481         GVariantBuilder *outer_builder;
1482         GVariantBuilder *inner_builder;
1483         GVariantBuilder *invalidated_builder;
1484         GVariant *update_value = NULL;
1485         GError *error = NULL;
1486         gboolean ret = FALSE;
1487         int err = BLUETOOTH_ERROR_NONE;
1488         int i = 0;
1489         gchar **line_argv = NULL;
1490         gchar *serv_path = NULL;
1491
1492         line_argv = g_strsplit_set(char_path, "/", 0);
1493         serv_path = g_strdup_printf("/%s", line_argv[1]);
1494
1495         if (!__bt_gatt_get_service_state(serv_path)) {
1496                 BT_DBG("service not registered for this characteristic \n");
1497                 g_strfreev(line_argv);
1498                 g_free(serv_path);
1499                 return BLUETOOTH_ERROR_INTERNAL;
1500         }
1501         g_free(serv_path);
1502
1503         outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1504         invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
1505
1506         inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1507         for (i = 0; i < value_length; i++) {
1508                 g_variant_builder_add(inner_builder, "y", char_value[i]);
1509         }
1510
1511         update_value = g_variant_new("ay", inner_builder);
1512
1513         outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1514         g_variant_builder_add(outer_builder, "{sv}", "Value",
1515                                         update_value);
1516
1517         BT_DBG("Updating characteristic value \n");
1518         ret = g_dbus_connection_emit_signal(g_conn, NULL,
1519                                         char_path,
1520                                         "org.freedesktop.DBus.Properties",
1521                                         "PropertiesChanged",
1522                                         g_variant_new("(sa{sv}as)",
1523                                         "org.bluez.GattCharacteristic1",
1524                                         outer_builder, invalidated_builder),
1525                                         &error);
1526
1527         if (!ret) {
1528                 if (error != NULL) {
1529                         BT_ERR("D-Bus API failure: errCode[%x], \
1530                                         message[%s]",
1531                                         error->code, error->message);
1532                         g_clear_error(&error);
1533                 }
1534                 err = BLUETOOTH_ERROR_INTERNAL;
1535         }
1536
1537         g_strfreev(line_argv);
1538         g_variant_builder_unref(inner_builder);
1539         g_variant_builder_unref(outer_builder);
1540         g_variant_builder_unref(invalidated_builder);
1541
1542         return err;
1543 }
1544
1545 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
1546 {
1547         GSList *l, *l1;
1548         struct gatt_service_info *svc_info;
1549         gboolean ret;
1550         int err = BLUETOOTH_ERROR_NONE;
1551         GSList *tmp;
1552
1553         BT_DBG("svc_path %s", svc_path);
1554         svc_info = __bt_gatt_find_gatt_service_info(svc_path);
1555
1556         if (!svc_info) {
1557                 BT_ERR("Unable to find service info");
1558                 return BLUETOOTH_ERROR_NOT_FOUND;
1559         }
1560
1561         err = __bt_gatt_unregister_service(svc_path);
1562         if (err != BLUETOOTH_ERROR_NONE) {
1563                 BT_DBG("Could not unregister application");
1564                 return err;
1565         }
1566
1567         for (l = svc_info->char_data; l != NULL; l = l->next) {
1568                 struct gatt_char_info *char_info = l->data;
1569
1570                 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
1571                         struct gatt_desc_info *desc_info = l1->data;
1572
1573                         ret = g_dbus_connection_unregister_object(g_conn,
1574                                                 desc_info->desc_id);
1575                         if (ret) {
1576                                 __bt_gatt_emit_interface_removed(
1577                                                 desc_info->desc_path,
1578                                                 GATT_DESC_INTERFACE);
1579                         } else {
1580                                 err = BLUETOOTH_ERROR_INTERNAL;
1581                         }
1582                 }
1583                 ret = g_dbus_connection_unregister_object(g_conn,
1584                                         char_info->char_id);
1585                 if (ret) {
1586                         __bt_gatt_emit_interface_removed(char_info->char_path,
1587                                                 GATT_CHAR_INTERFACE);
1588                 } else {
1589                         err = BLUETOOTH_ERROR_INTERNAL;
1590                 }
1591         }
1592         ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
1593         if (ret) {
1594                 __bt_gatt_emit_interface_removed(svc_info->serv_path,
1595                                                 GATT_SERV_INTERFACE);
1596         } else {
1597                 err = BLUETOOTH_ERROR_INTERNAL;
1598         }
1599
1600         ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
1601         if (ret) {
1602                 BT_DBG("Unregistered the service on properties interface");
1603         }
1604
1605         for (tmp = gatt_services; tmp != NULL; tmp = tmp->next) {
1606                 struct gatt_service_info *info = tmp->data;
1607
1608                 if (g_strcmp0(info->serv_path, svc_path) == 0) {
1609                         g_slist_delete_link(gatt_services, tmp->data);
1610                 }
1611         }
1612
1613         new_service = FALSE;
1614
1615         if (gatt_services->next == NULL)
1616                 serv_id--;
1617
1618         return err;
1619 }