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