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