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