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