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