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