Remove unused mashal codes
[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         *char_path = g_strdup(path);
2005
2006         new_char = TRUE;
2007
2008         g_free(path);
2009
2010         g_variant_builder_unref(inner_builder);
2011         g_variant_builder_unref(builder);
2012         g_variant_builder_unref(builder2);
2013         g_variant_builder_unref(builder3);
2014
2015         return BLUETOOTH_ERROR_NONE;
2016 }
2017
2018 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
2019                         const char *characteristic, const char *char_value,
2020                         int     value_length)
2021 {
2022         gchar **line_argv = NULL;
2023         char *serv_path = NULL;
2024         struct gatt_char_info *char_info = NULL;
2025         GVariantBuilder *builder1 = NULL;
2026         GVariantBuilder *builder = NULL;
2027         GVariantBuilder *inner_builder = NULL;
2028         GVariant *char_val = NULL;
2029         GError *error = NULL;
2030         int i = 0;
2031         int res = BLUETOOTH_ERROR_NONE;
2032
2033         line_argv = g_strsplit_set(characteristic, "/", 0);
2034         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2035
2036         char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2037
2038         if (char_info == NULL) {
2039                 /* Fix : RESOURCE_LEAK */
2040                 res = BLUETOOTH_ERROR_INVALID_PARAM;
2041                 goto done;
2042         }
2043
2044         char_info->value_length = value_length;
2045
2046         char_info->char_value = (char *)malloc(value_length);
2047         /* Fix : NULL_RETURNS */
2048         if (char_info->char_value == NULL) {
2049                 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2050                 goto done;
2051         }
2052
2053         for (i = 0; i < value_length; i++)
2054                 char_info->char_value[i] = char_value[i];
2055
2056         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2057         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2058
2059         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2060
2061         for (i = 0; i < value_length; i++)
2062                 g_variant_builder_add(builder1, "y", char_value[i]);
2063
2064         char_val = g_variant_new("ay", builder1);
2065                 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2066
2067         g_variant_builder_add(builder, "{sa{sv}}",
2068                         GATT_CHAR_INTERFACE,
2069                         inner_builder);
2070
2071         g_dbus_connection_emit_signal(g_conn, NULL, "/",
2072                         "org.freedesktop.Dbus.ObjectManager",
2073                         "InterfacesAdded",
2074                         g_variant_new("(oa{sa{sv}})",
2075                         char_info->char_path, builder),
2076                         &error);
2077
2078         g_variant_builder_unref(inner_builder);
2079         g_variant_builder_unref(builder);
2080         g_variant_builder_unref(builder1);
2081 done:
2082         g_strfreev(line_argv);
2083         g_free(serv_path);
2084
2085         return res;
2086 }
2087
2088 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2089                         const char *char_path, const char *desc_uuid,
2090                         bt_gatt_permission_t permissions,
2091                         char **desc_path)
2092 {
2093         static int desc_id = 1;
2094         GError *error = NULL;
2095         guint object_id;
2096         GDBusNodeInfo *node_info;
2097         gchar *path = NULL;
2098         GVariantBuilder *builder = NULL;
2099         GVariantBuilder *inner_builder = NULL;
2100         struct gatt_char_info *char_info = NULL;
2101         struct gatt_desc_info *desc_info = NULL;
2102         gchar **line_argv = NULL;
2103         char *serv_path;
2104         GVariantBuilder *builder2 = NULL;
2105         GVariant *flags_val = NULL;
2106         int i = 0;
2107         char *desc_flags[NUMBER_OF_FLAGS];
2108         int flag_count = 0;
2109
2110         if (new_char) {
2111                 desc_id = 1;
2112                 new_char = FALSE;
2113         }
2114
2115         line_argv = g_strsplit_set(char_path, "/", 0);
2116         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2117
2118         char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2119         if (char_info == NULL) {
2120                 g_strfreev(line_argv);
2121                 g_free(serv_path);
2122                 return BLUETOOTH_ERROR_INVALID_PARAM;
2123         }
2124
2125         node_info = __bt_gatt_create_method_node_info(
2126                                         descriptor_introspection_xml);
2127         if (node_info == NULL) {
2128                 g_strfreev(line_argv);
2129                 g_free(serv_path);
2130                 return BLUETOOTH_ERROR_INTERNAL;
2131         }
2132
2133         path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2134         BT_DBG("gatt descriptor path is [%s]", path);
2135
2136         object_id = g_dbus_connection_register_object(g_conn, path,
2137                                 node_info->interfaces[0],
2138                                 &desc_interface_vtable,
2139                                 NULL, NULL, &error);
2140         g_dbus_node_info_unref(node_info);
2141
2142         if (object_id == 0) {
2143                 BT_ERR("failed to register: %s", error->message);
2144                 g_error_free(error);
2145                 g_free(path);
2146                 g_strfreev(line_argv);
2147                 g_free(serv_path);
2148
2149                 return BLUETOOTH_ERROR_INTERNAL;
2150         }
2151
2152         flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2153
2154         desc_info = g_new0(struct gatt_desc_info, 1);
2155
2156         desc_info->desc_path = g_strdup(path);
2157         desc_info->desc_id = object_id;
2158         desc_info->desc_uuid = g_strdup(desc_uuid);
2159
2160         for (i = 0; i < flag_count; i++)
2161                 desc_info->desc_flags[i] = desc_flags[i];
2162
2163         desc_info->flags_length = flag_count;
2164
2165         char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2166
2167         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2168         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2169
2170         g_variant_builder_add(inner_builder, "{sv}", "UUID",
2171                                 g_variant_new("s", desc_uuid));
2172         g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2173                                 g_variant_new("o", char_path));
2174
2175         builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2176
2177         for (i = 0; i < flag_count; i++)
2178                 g_variant_builder_add(builder2, "s", desc_flags[i]);
2179
2180         flags_val = g_variant_new("as", builder2);
2181         g_variant_builder_add(inner_builder, "{sv}", "Flags",
2182                                 flags_val);
2183
2184         g_variant_builder_add(builder, "{sa{sv}}",
2185                                 GATT_DESC_INTERFACE,
2186                                 inner_builder);
2187
2188         g_dbus_connection_emit_signal(g_conn, NULL, "/",
2189                                 "org.freedesktop.Dbus.ObjectManager",
2190                                 "InterfacesAdded",
2191                                 g_variant_new("(oa{sa{sv}})",
2192                                 path, builder),
2193                                 &error);
2194
2195         *desc_path = g_strdup(path);
2196
2197         g_free(path);
2198         g_free(serv_path);
2199         g_strfreev(line_argv);
2200         g_variant_builder_unref(inner_builder);
2201         g_variant_builder_unref(builder);
2202         g_variant_builder_unref(builder2);
2203
2204         return BLUETOOTH_ERROR_NONE;
2205 }
2206
2207 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2208                         const char *desc_path, const char *desc_value,
2209                         int value_length)
2210 {
2211         GError *error = NULL;
2212         GVariantBuilder *builder = NULL;
2213         GVariantBuilder *inner_builder = NULL;
2214         GVariantBuilder *builder1 = NULL;
2215         struct gatt_desc_info *desc_info = NULL;
2216         gchar **line_argv = NULL;
2217         char *char_path;
2218         GVariant *desc_val = NULL;
2219         char *serv_path = NULL;
2220         int i ;
2221
2222         line_argv = g_strsplit_set(desc_path, "/", 0);
2223         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2224         char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2225
2226         desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2227
2228         /* Free the allocated memory */
2229         g_strfreev(line_argv);
2230         g_free(serv_path);
2231         g_free(char_path);
2232
2233         /* Fix : NULL_RETURNS */
2234         retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2235
2236         desc_info->desc_value = (char *)malloc(value_length);
2237
2238         /* Fix : NULL_RETURNS */
2239         retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2240
2241         for (i = 0; i < value_length; i++)
2242                 desc_info->desc_value[i] = desc_value[i];
2243
2244         desc_info->value_length = value_length;
2245
2246         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2247         inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2248
2249         builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2250
2251         for (i = 0; i < value_length; i++)
2252                 g_variant_builder_add(builder1, "y", desc_value[i]);
2253
2254         desc_val = g_variant_new("ay", builder1);
2255         g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2256
2257         g_variant_builder_add(builder, "{sa{sv}}",
2258                                 GATT_DESC_INTERFACE,
2259                                 inner_builder);
2260
2261         g_dbus_connection_emit_signal(g_conn, NULL, "/",
2262                                 "org.freedesktop.Dbus.ObjectManager",
2263                                 "InterfacesAdded",
2264                                 g_variant_new("(oa{sa{sv}})",
2265                                 desc_info->desc_path, builder),
2266                                 &error);
2267
2268         g_variant_builder_unref(inner_builder);
2269         g_variant_builder_unref(builder);
2270         g_variant_builder_unref(builder1);
2271
2272         return BLUETOOTH_ERROR_NONE;
2273 }
2274
2275 int bluetooth_gatt_get_service(const char *svc_uuid)
2276 {
2277         GDBusProxy *proxy = NULL;
2278         gchar *uuid = NULL;
2279
2280         proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2281                                         "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2282         if (proxy == NULL)
2283                 return BLUETOOTH_ERROR_INTERNAL;
2284
2285         uuid = g_strdup(svc_uuid);
2286
2287         g_dbus_proxy_call(proxy,
2288                         "GetService",
2289                         g_variant_new("(s)",
2290                         uuid),
2291                         G_DBUS_CALL_FLAGS_NONE, -1,
2292                         NULL,
2293                         (GAsyncReadyCallback) get_service_cb,
2294                         NULL);
2295
2296         g_free(uuid);
2297
2298         return BLUETOOTH_ERROR_NONE;
2299 }
2300
2301 BT_EXPORT_API int bluetooth_gatt_register_service(
2302                         const char *svc_path)
2303 {
2304         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2305                         == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2306                 BT_ERR("Don't have aprivilege to use this API");
2307                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2308         }
2309
2310         register_pending_cnt++;
2311
2312         if (__bt_gatt_get_service_state(svc_path)) {
2313                 BT_DBG("service already registered \n");
2314                 return BLUETOOTH_ERROR_NONE;
2315         }
2316
2317         __bt_gatt_set_service_state(svc_path, TRUE);
2318
2319         return BLUETOOTH_ERROR_NONE;
2320 }
2321
2322 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2323 {
2324         GDBusProxy *proxy = NULL;
2325
2326         if (!is_server_started) {
2327
2328                 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2329                                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2330                         BT_ERR("Don't have aprivilege to use this API");
2331                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
2332                 }
2333
2334                 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2335                                 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2336                 if (proxy == NULL || app_path == NULL)
2337                         return BLUETOOTH_ERROR_INTERNAL;
2338
2339                 BT_INFO("RegisterApplication");
2340
2341                 if (register_cancel) {
2342                         g_cancellable_cancel(register_cancel);
2343                         g_object_unref(register_cancel);
2344                 }
2345
2346                 register_cancel = g_cancellable_new();
2347
2348                 g_dbus_proxy_call(proxy,
2349                                 "RegisterApplication",
2350                                 g_variant_new("(oa{sv})",
2351                                         app_path, NULL),
2352                                 G_DBUS_CALL_FLAGS_NONE, -1,
2353                                 register_cancel,
2354                                 (GAsyncReadyCallback) register_application_cb,
2355                                 NULL);
2356
2357                 is_server_started = true;
2358
2359                 return BLUETOOTH_ERROR_NONE;
2360         }
2361
2362         BT_INFO("Already RegisterApplication");
2363
2364         return BLUETOOTH_ERROR_NONE;
2365 }
2366
2367 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2368 {
2369         GSList *l;
2370         int error = BLUETOOTH_ERROR_NONE;
2371         l = gatt_services;
2372
2373         if (l != NULL) {
2374                 for (l = gatt_services; l != NULL; l = l->next) {
2375                         struct gatt_service_info *info = l->data;
2376                         BT_DBG("svc_path is %s", info->serv_path);
2377                         if (bluetooth_gatt_unregister_service(info->serv_path)
2378                                         != BLUETOOTH_ERROR_NONE) {
2379                                 error = BLUETOOTH_ERROR_INTERNAL;
2380                                 BT_ERR("Error in removing service %s \n",
2381                                                  info->serv_path);
2382                         }
2383                 }
2384                 BT_DBG(" All services removed successfully.\n ");
2385         } else {
2386                 BT_DBG(" There are no registered services.\n ");
2387         }
2388
2389         g_slist_free(gatt_services);
2390         gatt_services = NULL;
2391         serv_id = 1;
2392
2393         if (error != BLUETOOTH_ERROR_NONE)
2394                 return error;
2395
2396         return BLUETOOTH_ERROR_NONE;
2397 }
2398
2399 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2400                         const char *char_path, const char* char_value,
2401                         int value_length)
2402 {
2403         GVariantBuilder *outer_builder;
2404         GVariantBuilder *inner_builder;
2405         GVariantBuilder *invalidated_builder;
2406         GVariant *update_value = NULL;
2407         GError *error = NULL;
2408         gboolean ret = FALSE;
2409         int err = BLUETOOTH_ERROR_NONE;
2410         int i = 0;
2411         gchar **line_argv = NULL;
2412         gchar *serv_path = NULL;
2413         const char *value = NULL;
2414
2415         line_argv = g_strsplit_set(char_path, "/", 0);
2416         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2417
2418         if (!__bt_gatt_get_service_state(serv_path)) {
2419                 BT_DBG("service not registered for this characteristic \n");
2420                 g_free(serv_path);
2421                 g_strfreev(line_argv);
2422                 return BLUETOOTH_ERROR_INTERNAL;
2423         }
2424
2425         outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2426         invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2427
2428         inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2429         for (i = 0; i < value_length; i++)
2430                 g_variant_builder_add(inner_builder, "y", char_value[i]);
2431
2432         update_value = g_variant_new("ay", inner_builder);
2433
2434         outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2435         g_variant_builder_add(outer_builder, "{sv}", "Value",
2436                                         update_value);
2437
2438         BT_DBG("Updating characteristic value \n");
2439         ret = g_dbus_connection_emit_signal(g_conn, NULL,
2440                                         char_path,
2441                                         "org.freedesktop.DBus.Properties",
2442                                         "PropertiesChanged",
2443                                         g_variant_new("(sa{sv}as)",
2444                                         "org.bluez.GattCharacteristic1",
2445                                         outer_builder, invalidated_builder),
2446                                         &error);
2447
2448         if (!ret) {
2449                 if (error != NULL) {
2450                         BT_ERR("D-Bus API failure: errCode[%x], \
2451                                         message[%s]",
2452                                         error->code, error->message);
2453                         g_clear_error(&error);
2454                 }
2455                 err = BLUETOOTH_ERROR_INTERNAL;
2456         } else {
2457                 struct gatt_char_info *char_info = NULL;
2458
2459                 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2460                 if (char_info == NULL) {
2461                         g_free(serv_path);
2462                         g_strfreev(line_argv);
2463                         g_variant_builder_unref(inner_builder);
2464                         g_variant_builder_unref(outer_builder);
2465                         g_variant_builder_unref(invalidated_builder);
2466
2467                         return BLUETOOTH_ERROR_INVALID_DATA;
2468                 }
2469
2470                 char_info->value_length = value_length;
2471
2472                 value = (char *)realloc(char_info->char_value, value_length);
2473                 if (value == NULL) {
2474                         g_free(serv_path);
2475                         g_strfreev(line_argv);
2476                         g_variant_builder_unref(inner_builder);
2477                         g_variant_builder_unref(outer_builder);
2478                         g_variant_builder_unref(invalidated_builder);
2479
2480                         return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2481                 }
2482
2483                 char_info->char_value = (char*)value;
2484                 if (char_info->char_value) {
2485                         for (i = 0; i < value_length; i++)
2486                                 char_info->char_value[i] = char_value[i];
2487                 }
2488         }
2489
2490         g_free(serv_path);
2491         g_strfreev(line_argv);
2492         g_variant_builder_unref(inner_builder);
2493         g_variant_builder_unref(outer_builder);
2494         g_variant_builder_unref(invalidated_builder);
2495
2496         return err;
2497 }
2498
2499 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2500 {
2501         int i;
2502
2503         if (!desc_info)
2504                 return;
2505
2506         g_free(desc_info->desc_path);
2507         g_free(desc_info->desc_uuid);
2508         g_free(desc_info->desc_value);
2509
2510         for (i = 0; i < desc_info->flags_length; i++)
2511                 g_free(desc_info->desc_flags[i]);
2512
2513         g_free(desc_info);
2514 }
2515
2516 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2517 {
2518         int i;
2519
2520         if (!char_info)
2521                 return;
2522
2523         g_free(char_info->char_path);
2524         g_free(char_info->char_uuid);
2525         g_free(char_info->char_value);
2526
2527         for (i = 0; i < char_info->flags_length; i++)
2528                 g_free(char_info->char_flags[i]);
2529
2530         g_free(char_info);
2531 }
2532
2533 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2534 {
2535         if (!svc_info)
2536                 return;
2537
2538         g_free(svc_info->serv_path);
2539         g_free(svc_info->service_uuid);
2540         g_free(svc_info);
2541 }
2542
2543 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2544 {
2545         GSList *l, *l1;
2546         struct gatt_service_info *svc_info;
2547         gboolean ret;
2548         int err = BLUETOOTH_ERROR_NONE;
2549
2550         BT_DBG("svc_path %s", svc_path);
2551         svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2552
2553         if (!svc_info) {
2554                 BT_ERR("Unable to find service info");
2555                 return BLUETOOTH_ERROR_NOT_FOUND;
2556         }
2557
2558         err = __bt_gatt_unregister_service(svc_path);
2559         if (err != BLUETOOTH_ERROR_NONE) {
2560                 BT_ERR("Could not unregister application");
2561                 return err;
2562         }
2563
2564         for (l = svc_info->char_data; l != NULL; l = l->next) {
2565                 struct gatt_char_info *char_info = l->data;
2566
2567                 if (char_info == NULL)
2568                         break;
2569
2570                 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2571                         struct gatt_desc_info *desc_info = l1->data;
2572
2573                         if (desc_info == NULL)
2574                                 break;
2575
2576                         ret = g_dbus_connection_unregister_object(g_conn,
2577                                                 desc_info->desc_id);
2578                         if (ret) {
2579                                 __bt_gatt_emit_interface_removed(
2580                                                 desc_info->desc_path,
2581                                                 GATT_DESC_INTERFACE);
2582                         } else {
2583                                 err = BLUETOOTH_ERROR_INTERNAL;
2584                         }
2585
2586                         /* list remove & free */
2587                         char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2588                         __bt_gatt_free_descriptor_info(desc_info);
2589                 }
2590
2591                 g_slist_free(char_info->desc_data);
2592                 char_info->desc_data = NULL;
2593
2594                 ret = g_dbus_connection_unregister_object(g_conn,
2595                                         char_info->char_id);
2596                 if (ret) {
2597                         __bt_gatt_emit_interface_removed(char_info->char_path,
2598                                                 GATT_CHAR_INTERFACE);
2599                 } else {
2600                         err = BLUETOOTH_ERROR_INTERNAL;
2601                 }
2602
2603                 /* list remove & free */
2604                 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2605                 __bt_gatt_free_characteristic_info(char_info);
2606         }
2607
2608         g_slist_free(svc_info->char_data);
2609         svc_info->char_data = NULL;
2610
2611         ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2612         if (ret) {
2613                 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2614                                                 GATT_SERV_INTERFACE);
2615         } else {
2616                 err = BLUETOOTH_ERROR_INTERNAL;
2617         }
2618
2619         ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2620         if (ret)
2621                 BT_DBG("Unregistered the service on properties interface");
2622
2623         /* list remove & free */
2624         gatt_services = g_slist_remove(gatt_services, svc_info);
2625         __bt_gatt_free_service_info(svc_info);
2626
2627         new_service = FALSE;
2628
2629         if (gatt_services == NULL)
2630                 serv_id = 1;
2631         else if (gatt_services->next == NULL)
2632                 serv_id--;
2633
2634         return err;
2635 }
2636
2637 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2638                                         int resp_state, int offset, char *value, int value_length)
2639 {
2640         struct gatt_req_info *req_info = NULL;
2641
2642         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2643                         == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2644                 BT_ERR("Don't have aprivilege to use this API");
2645                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2646         }
2647
2648         req_info = __bt_gatt_find_request_info(request_id);
2649         if (req_info == NULL) {
2650                 BT_ERR("Coundn't find request id [%d]", request_id);
2651                 return BLUETOOTH_ERROR_INTERNAL;
2652         }
2653
2654         if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2655                 BT_ERR("resp_state is 0x%X", resp_state);
2656                 char err_msg[20] = { 0, };
2657                 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2658                 g_dbus_method_invocation_return_dbus_error(req_info->context,
2659                                                 "org.bluez.Error.Failed", err_msg);
2660
2661                 gatt_requests = g_slist_remove(gatt_requests, req_info);
2662
2663                 req_info->context = NULL;
2664                 if (req_info->attr_path)
2665                         g_free(req_info->attr_path);
2666                 if (req_info->svc_path)
2667                         g_free(req_info->svc_path);
2668                 g_free(req_info);
2669
2670                 return BLUETOOTH_ERROR_NONE;
2671         }
2672
2673         if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2674                 int i;
2675                 GVariantBuilder *inner_builder = NULL;
2676                 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2677                 if (value_length > 0 && value != NULL) {
2678                         for (i = 0; i < value_length; i++)
2679                                 g_variant_builder_add(inner_builder, "y", value[i]);
2680                 }
2681                 g_dbus_method_invocation_return_value(req_info->context,
2682                                 g_variant_new("(ay)", inner_builder));
2683                 g_variant_builder_unref(inner_builder);
2684         } else {
2685                 g_dbus_method_invocation_return_value(req_info->context, NULL);
2686         }
2687         gatt_requests = g_slist_remove(gatt_requests, req_info);
2688
2689         req_info->context = NULL;
2690         if (req_info->attr_path)
2691                 g_free(req_info->attr_path);
2692         if (req_info->svc_path)
2693                 g_free(req_info->svc_path);
2694         g_free(req_info);
2695
2696         return BLUETOOTH_ERROR_NONE;
2697 }
2698
2699 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2700                                                 bluetooth_device_address_t *unicast_address)
2701 {
2702         GVariantBuilder *outer_builder;
2703         GVariantBuilder *invalidated_builder;
2704         GError *error = NULL;
2705         gboolean notify = TRUE;
2706         gboolean ret = TRUE;
2707         int err = BLUETOOTH_ERROR_NONE;
2708         gchar **line_argv = NULL;
2709         gchar *serv_path = NULL;
2710         char addr[20] = { 0 };
2711
2712         line_argv = g_strsplit_set(char_path, "/", 0);
2713         serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2714
2715         if (!__bt_gatt_get_service_state(serv_path)) {
2716                 BT_DBG("service not registered for this characteristic \n");
2717                 g_free(serv_path);
2718                 g_strfreev(line_argv);
2719                 return BLUETOOTH_ERROR_INTERNAL;
2720         }
2721
2722         g_free(serv_path);
2723
2724         outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2725         invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2726
2727         g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2728                                         g_variant_new("b", notify));
2729
2730         if (unicast_address) {
2731                 _bt_convert_addr_type_to_string(addr,
2732                                         (unsigned char *)unicast_address->addr);
2733         }
2734         g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2735                                 g_variant_new("s", addr));
2736
2737         BT_DBG("Set characteristic Notification \n");
2738         ret = g_dbus_connection_emit_signal(g_conn, NULL,
2739                                         char_path,
2740                                         "org.freedesktop.DBus.Properties",
2741                                         "PropertiesChanged",
2742                                         g_variant_new("(sa{sv}as)",
2743                                         "org.bluez.GattCharacteristic1",
2744                                         outer_builder, invalidated_builder),
2745                                         &error);
2746
2747         if (!ret) {
2748                 if (error != NULL) {
2749                         BT_ERR("D-Bus API failure: errCode[%x], \
2750                                         message[%s]",
2751                                         error->code, error->message);
2752                         g_clear_error(&error);
2753                 }
2754                 err = BLUETOOTH_ERROR_INTERNAL;
2755         }
2756
2757         g_strfreev(line_argv);
2758         g_variant_builder_unref(outer_builder);
2759         g_variant_builder_unref(invalidated_builder);
2760
2761         return err;
2762 }
2763
2764
2765 #if 0
2766 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2767 {
2768         BT_INIT_PARAMS();
2769
2770         if (!is_server_started) {
2771
2772                 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2773                                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2774                         BT_ERR("Don't have aprivilege to use this API");
2775                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
2776                 }
2777
2778                 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2779                 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2780
2781                 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2782                                 in_param1, in_param2, in_param3, in_param4, &out_param);
2783                 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2784
2785                 if (ret != BLUETOOTH_ERROR_NONE) {
2786                         BT_ERR("Register application failed");
2787                         return ret;
2788                 }
2789                 is_server_started = true;
2790
2791                 return BLUETOOTH_ERROR_NONE;
2792         }
2793
2794         BT_INFO("Already RegisterApplication");
2795         return BLUETOOTH_ERROR_NONE;
2796 }
2797 #endif
2798
2799 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2800                                                 void *user_data)
2801 {
2802         int ret = BLUETOOTH_ERROR_NONE;
2803
2804         BT_INIT_PARAMS();
2805         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2806
2807         /* Register event handler for GATT */
2808         ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2809
2810         if (ret != BLUETOOTH_ERROR_NONE &&
2811                         ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2812                 BT_ERR("Fail to init the event handler");
2813                 return ret;
2814         }
2815
2816         ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2817                         in_param1, in_param2, in_param3, in_param4, &out_param);
2818
2819         /* App ID -1 is invalid */
2820         if (ret != BLUETOOTH_ERROR_NONE) {
2821                 BT_INFO("GATT Server Registration failed result [%d]", ret);
2822                 *instance_id = -1;
2823         } else {
2824                 *instance_id = g_array_index(out_param, int, 0);
2825                 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2826         }
2827
2828         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2829
2830         BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2831         return ret;
2832 }
2833
2834 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2835 {
2836         int ret;
2837         BT_INFO("GATT Server Deinitialize");
2838         /* Unregister the event */
2839         ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2840
2841         if (ret != BLUETOOTH_ERROR_NONE) {
2842                 BT_ERR("Fail to deinit the event handler");
2843                 return ret;
2844         }
2845
2846         _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2847
2848         return ret;
2849 }
2850
2851 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2852                 int instance_id, int *service_handle)
2853 {
2854         BT_CHECK_ENABLED(return);
2855         BT_CHECK_PARAMETER(svc_uuid, return);
2856
2857         int result;
2858         char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2859
2860         g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2861
2862         BT_INIT_PARAMS();
2863         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2864
2865         g_array_append_vals(in_param1, &type, sizeof(int));
2866         g_array_append_vals(in_param2, &numhandles, sizeof(int));
2867         g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2868         g_array_append_vals(in_param4, &instance_id, sizeof(int));
2869
2870         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2871                         in_param1, in_param2, in_param3, in_param4, &out_param);
2872
2873         /* ATT handle 0 is reserved, hence it can not be used by app.
2874            It will be used to indicate error in regsitering attribute */
2875         if (result != BLUETOOTH_ERROR_NONE)
2876                 *service_handle = 0;
2877         else
2878                 *service_handle = g_array_index(out_param, int, 0);
2879
2880         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2881
2882         return result;
2883 }
2884
2885 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2886                 const bluetooth_gatt_server_attribute_params_t *param,
2887                                                 int *char_handle)
2888 {
2889         BT_CHECK_ENABLED(return);
2890         BT_CHECK_PARAMETER(char_uuid, return);
2891         BT_CHECK_PARAMETER(param, return);
2892
2893         int result;
2894         char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2895         int flag_count = 0;
2896         char *char_flags[NUMBER_OF_FLAGS];
2897
2898         g_strlcpy(uuid, char_uuid, sizeof(uuid));
2899         flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2900         BT_INFO("Flag count [%d]", flag_count);
2901
2902         BT_INIT_PARAMS();
2903         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2904
2905         g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2906         g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2907
2908         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2909                         in_param1, in_param2, in_param3, in_param4, &out_param);
2910
2911         /* ATT handle 0 is reserved, hence it can not be used by app.
2912            It will be used to indicate error in regsitering attribute */
2913         if (result != BLUETOOTH_ERROR_NONE) {
2914                 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2915                 *char_handle = 0;
2916         } else {
2917                 *char_handle = g_array_index(out_param, int, 0);
2918                 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2919         }
2920
2921         return result;
2922 }
2923
2924 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2925                 int service_handle, int instance_id, int *descriptor_handle)
2926 {
2927         BT_CHECK_ENABLED(return);
2928         BT_CHECK_PARAMETER(desc_uuid, return);
2929
2930         int result;
2931         char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2932
2933         g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2934
2935         BT_INIT_PARAMS();
2936         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2937
2938         g_array_append_vals(in_param1, &service_handle, sizeof(int));
2939         g_array_append_vals(in_param2, &instance_id, sizeof(int));
2940         g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2941         g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2942
2943         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2944                         in_param1, in_param2, in_param3, in_param4, &out_param);
2945
2946         /* ATT handle 0 is reserved, hence it can not be used by app.
2947            It will be used to indicate error in regsitering attribute */
2948         if (result != BLUETOOTH_ERROR_NONE) {
2949                 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2950                 *descriptor_handle = 0;
2951         } else {
2952                 *descriptor_handle = g_array_index(out_param, int, 0);
2953                 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2954         }
2955
2956         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2957
2958         return result;
2959 }
2960
2961 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2962 {
2963         BT_CHECK_ENABLED(return);
2964         int result;
2965
2966         BT_INIT_PARAMS();
2967         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2968
2969         g_array_append_vals(in_param1, &service_handle, sizeof(int));
2970         g_array_append_vals(in_param2, &instance_id, sizeof(int));
2971
2972         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2973                         in_param1, in_param2, in_param3, in_param4, &out_param);
2974
2975         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2976
2977         return result;
2978 }
2979
2980 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2981                 const bluetooth_gatt_att_data_t *value)
2982 {
2983         BT_CHECK_PARAMETER(param, return);
2984         BT_CHECK_PARAMETER(value, return);
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, value, sizeof(bluetooth_gatt_att_data_t));
2992         g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2993
2994         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
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
3003 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
3004                 const bluetooth_gatt_server_indication_params_t *param,
3005                 const bluetooth_gatt_att_data_t *att_value)
3006 {
3007         BT_CHECK_PARAMETER(param, return);
3008         BT_CHECK_PARAMETER(att_value, return);
3009         BT_CHECK_ENABLED(return);
3010         int result;
3011
3012         BT_INIT_PARAMS();
3013         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3014
3015         g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
3016         g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
3017         g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
3018
3019         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
3020                         in_param1, in_param2, in_param3, in_param4, &out_param);
3021
3022         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3023
3024         return result;
3025 }
3026
3027 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
3028 {
3029         BT_CHECK_ENABLED(return);
3030         int result;
3031
3032         BT_INIT_PARAMS();
3033         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3034
3035         g_array_append_vals(in_param1, &service_handle, sizeof(int));
3036         g_array_append_vals(in_param2, &instance_id, sizeof(int));
3037
3038         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
3039                         in_param1, in_param2, in_param3, in_param4, &out_param);
3040
3041         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3042
3043         return result;
3044 }
3045
3046 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
3047 {
3048         BT_CHECK_ENABLED(return);
3049         int result;
3050
3051         BT_INIT_PARAMS();
3052         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3053
3054         g_array_append_vals(in_param1, &service_handle, sizeof(int));
3055         g_array_append_vals(in_param2, &instance_id, sizeof(int));
3056
3057         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3058                         in_param1, in_param2, in_param3, in_param4, &out_param);
3059
3060         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3061
3062         return result;
3063 }
3064
3065 /* Tizen Platform Specific */
3066 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3067                                 const bluetooth_gatt_server_update_value_t *value)
3068 {
3069         BT_CHECK_ENABLED(return);
3070         BT_CHECK_PARAMETER(value, 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, &instance_id, sizeof(int));
3077         g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3078
3079         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
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 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3088 {
3089         BT_CHECK_ENABLED(return);
3090         int result;
3091
3092         BT_INIT_PARAMS();
3093         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3094
3095         g_array_append_vals(in_param1, &instance_id, sizeof(int));
3096
3097         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3098                         in_param1, in_param2, in_param3, in_param4, &out_param);
3099
3100         if (result != BLUETOOTH_ERROR_NONE)
3101                 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3102         else
3103                 BT_INFO("GATT Server Unregistration successful");
3104
3105         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3106         return result;
3107 }
3108