SVACE Fixes
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-otp.c
1 /*
2  * Copyright (c) 2011 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 <glib.h>
19 #include <gio/gio.h>
20 #include <dlog.h>
21 #include <string.h>
22 #include <syspopup_caller.h>
23 #include <vconf.h>
24 #include <bundle_internal.h>
25
26 #include "bluetooth-api.h"
27 #include "bt-internal-types.h"
28
29 #include "bt-service-common.h"
30 #include "bt-service-device.h"
31 #include "bt-service-util.h"
32 #include "bt-service-event.h"
33 #include "bt-service-otp.h"
34
35 #define BT_OTP_SERVICE_NAME "org.projectx.otp"
36 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
37 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
38
39 #define BT_OTP_BASE_DIR_PATH "/home/owner/media/otp/"
40
41 #define GATT_CHAR_INTERFACE             "org.bluez.GattCharacteristic1"
42
43 #define GATT_DEFAULT_TIMEOUT  (6 * 1000) /* Dependent on supervision timeout 6 sec */
44 #define BT_INDICATION_TIMEOUT_MAX 30000 /* Timeout for Indication from OTP Server in msec */
45
46 /* OTP Notification Request structure */
47 typedef struct {
48         char *handle;
49         char *sender;
50         unsigned int notification_timeout_id;
51         int req_id;
52 } bt_otp_notification_info;
53
54 /* OTP transport specific data read Request info structure */
55 typedef struct {
56         char *handle;
57         char *sender;
58         int req_id;
59 } bt_otp_read_req_info;
60
61 static GSList *otp_read_req_info_list = NULL;
62
63 static GSList *otp_notification_info_list = NULL;
64
65 static GDBusProxy *otp_gproxy;
66
67 static GDBusProxy *_bt_core_gdbus_init_otp_proxy(void)
68 {
69         GDBusProxy *proxy;
70         GError *err = NULL;
71         GDBusConnection *conn;
72
73         BT_DBG(" ");
74
75         conn = _bt_gdbus_get_system_gconn();
76         if (!conn)
77                 return NULL;
78
79         proxy =  g_dbus_proxy_new_sync(conn,
80                         G_DBUS_PROXY_FLAGS_NONE, NULL,
81                         BT_OTP_SERVICE_NAME,
82                         BT_OTP_OBJECT_PATH,
83                         BT_OTP_INTERFACE_NAME,
84                         NULL, &err);
85         if (proxy == NULL) {
86                 if (err) {
87                          BT_ERR("Unable to create proxy: %s", err->message);
88                          g_clear_error(&err);
89                 }
90                 return NULL;
91         }
92         BT_DBG("1");
93         otp_gproxy = proxy;
94
95         return proxy;
96 }
97
98 GDBusProxy *_bt_core_gdbus_get_otp_proxy(void)
99 {
100         return (otp_gproxy) ? otp_gproxy : _bt_core_gdbus_init_otp_proxy();
101 }
102
103 void server_init_cb(GObject *object, GAsyncResult *res,
104                                 gpointer user_data)
105 {
106         BT_INFO("Server Init completed");
107         GError *error = NULL;
108         GVariant *result, *out_param, *param;
109         request_info_t *req_info = NULL;
110         int status = BLUETOOTH_ERROR_NONE;
111         bool server_state = false;
112
113         result = g_dbus_proxy_call_finish(otp_gproxy, res, &error);
114
115         if (result == NULL) {
116                 BT_ERR("Dbus-RPC is failed\n");
117                 if (error != NULL) {
118                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
119                                 error->code, error->message);
120                         g_clear_error(&error);
121                         status = BLUETOOTH_ERROR_INTERNAL;
122                 }
123         } else {
124                 g_variant_get(result, "(i)", &status);
125                 g_variant_unref(result);
126         }
127
128         BT_DBG("Status [%d]", status);
129
130         if (status == BLUETOOTH_ERROR_NONE)
131                 server_state = true;
132
133         param = g_variant_new("(ib)", status, server_state);
134
135         req_info = _bt_get_request_info(GPOINTER_TO_INT(user_data));
136
137         /* Send the event to application */
138         _bt_send_event(BT_OTP_EVENT,
139                 BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,
140                 param);
141
142         out_param = g_variant_new_from_data((const GVariantType*)"i",
143                                 &status, sizeof(int), TRUE, NULL, NULL);
144
145         if (req_info) {
146                 g_dbus_method_invocation_return_value(req_info->context,
147                                 g_variant_new("(iv)", status, out_param));
148
149                 _bt_delete_request_list(req_info->req_id);
150         }
151 }
152
153 int bt_otp_server_init(int request_id, const char *directory)
154 {
155         BT_INFO("relative_path: [%s]", directory);
156         char *base_dir = g_strconcat(BT_OTP_BASE_DIR_PATH, directory, NULL);
157
158         BT_DBG(" ");
159
160         otp_gproxy = _bt_core_gdbus_get_otp_proxy();
161         if (!otp_gproxy) {
162                 BT_DBG("Couldn't get service proxy");
163                 g_free(base_dir);
164                 return BLUETOOTH_ERROR_INTERNAL;
165         }
166
167         g_dbus_proxy_call(otp_gproxy,
168                         "enable",
169                         g_variant_new("(s)",
170                                 base_dir),
171                         G_DBUS_CALL_FLAGS_NONE, -1,
172                         NULL,
173                         (GAsyncReadyCallback) server_init_cb,
174                         GINT_TO_POINTER(request_id));
175
176         g_free(base_dir);
177
178         return BLUETOOTH_ERROR_NONE;
179 }
180
181 void server_deinit_cb(GObject *object, GAsyncResult *res,
182                                 gpointer user_data)
183 {
184         BT_INFO("Server Deinit completed");
185         GError *error = NULL;
186         GVariant *result, *out_param, *param;
187         request_info_t *req_info = NULL;
188         int status = BLUETOOTH_ERROR_NONE;
189         bool server_state = false;
190
191         result = g_dbus_proxy_call_finish(otp_gproxy, res, &error);
192
193         if (result == NULL) {
194                 BT_ERR("Dbus-RPC is failed\n");
195                 if (error != NULL) {
196                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
197                                 error->code, error->message);
198                         g_clear_error(&error);
199                         status = BLUETOOTH_ERROR_INTERNAL;
200                 }
201         } else {
202                 g_variant_get(result, "(i)", &status);
203                 g_variant_unref(result);
204         }
205
206         BT_DBG("Status [%d]", status);
207
208         param = g_variant_new("(ib)", status, server_state);
209
210         req_info = _bt_get_request_info(GPOINTER_TO_INT(user_data));
211
212         /* Send the event to application */
213         _bt_send_event(BT_OTP_EVENT,
214                         BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,
215                         param);
216
217         if (req_info) {
218                 out_param = g_variant_new_from_data((const GVariantType*)"i",
219                                 &status, sizeof(int), TRUE, NULL, NULL);
220
221                 g_dbus_method_invocation_return_value(req_info->context,
222                                 g_variant_new("(iv)", status, out_param));
223
224                 _bt_delete_request_list(req_info->req_id);
225         }
226
227         if (otp_gproxy) {
228                 g_object_unref(otp_gproxy);
229                 otp_gproxy = NULL;
230         }
231 }
232
233 int bt_otp_server_deinit(int request_id)
234 {
235         BT_DBG("+");
236
237         otp_gproxy = _bt_core_gdbus_get_otp_proxy();
238         if (!otp_gproxy) {
239                 BT_DBG("Couldn't get service proxy");
240                 return BLUETOOTH_ERROR_INTERNAL;
241         }
242
243         g_dbus_proxy_call(otp_gproxy,
244                         "disable",
245                         NULL, G_DBUS_CALL_FLAGS_NONE,
246                         -1, NULL,
247                         (GAsyncReadyCallback) server_deinit_cb,
248                         GINT_TO_POINTER(request_id));
249
250         BT_DBG("-");
251         return BLUETOOTH_ERROR_NONE;
252 }
253
254 int __get_handle_length(char *handle)
255 {
256         int i = 0;
257
258         while (handle && (handle[i] != '\0'))
259                 i++;
260
261         return i;
262 }
263
264 static bt_otp_read_req_info *__bt_otp_get_read_info(char *handle)
265 {
266         GSList *l;
267         bt_otp_read_req_info *info = NULL;
268         BT_INFO("Found waiting for OTP Read from charc handle[%s]", handle);
269         for (l = otp_read_req_info_list; l != NULL; l = g_slist_next(l)) {
270                 info = (bt_otp_read_req_info *)l->data;
271                 if (info == NULL)
272                         continue;
273
274                 if (!g_strcmp0(info->handle, handle)) {
275                         BT_INFO("Found waiting for OTP Read from remote addr[%s]",
276                                         info->handle);
277                         return info;
278                 }
279         }
280         return NULL;
281 }
282
283 static void __bt_otp_remove_read_info(bt_otp_read_req_info *info)
284 {
285         BT_DBG("Removing Read Req Info [%s]", info->handle);
286
287         otp_read_req_info_list = g_slist_remove(otp_read_req_info_list, info);
288         if (info->handle)
289                 g_free(info->handle);
290         if (info->sender)
291                 g_free(info->sender);
292         g_free(info);
293 }
294
295 static int __bluetooth_get_att_error_code(GError *error)
296 {
297         int att_ecode = 0;
298         int len;
299         char *str = NULL;
300
301         BT_ERR("Error : %s", error->message);
302         str = g_strrstr(error->message, "ATT error: 0x");
303         if (str) {
304                 len = strlen(str);
305                 att_ecode =  g_ascii_xdigit_value(str[len-2]) << 4;
306                 att_ecode += g_ascii_xdigit_value(str[len-1]);
307         } else
308                 return BLUETOOTH_ATT_ERROR_INTERNAL;
309
310         return att_ecode;
311 }
312
313 static void __bt_otp_read_char_cb(GObject *source_object,
314                         GAsyncResult *res, gpointer user_data)
315 {
316         bt_gatt_char_descriptor_property_t att_value =  { 0, };
317         GDBusConnection *system_gconn = NULL;
318         GVariant *var_data, *param = NULL;
319         int result = BLUETOOTH_ATT_ERROR_NONE;
320         bt_otp_read_req_info *info = NULL;
321         GByteArray *gp_byte_array = NULL;
322         request_info_t *req_info = NULL;
323         GVariantIter *iter = NULL;
324         GVariant *value = NULL;
325         char *otp_data = NULL;
326         GVariant *out_param1;
327         GError *error = NULL;
328         guint8 g_byte;
329         char *handle;
330
331         BT_DBG("+");
332         system_gconn = _bt_gdbus_get_system_gconn();
333
334         handle = (char *)user_data;
335         info = __bt_otp_get_read_info(handle);
336
337         value = g_dbus_connection_call_finish(system_gconn, res, &error);
338
339         if (error) {
340                 result = __bluetooth_get_att_error_code(error);
341                 att_value.val_len = 0;
342                 goto dbus_return;
343         }
344
345         g_variant_get(value, "(ay)", &iter);
346
347         gp_byte_array = g_byte_array_new();
348
349         while (g_variant_iter_loop(iter, "y",  &g_byte))
350                 g_byte_array_append(gp_byte_array, &g_byte, 1);
351
352         if (gp_byte_array->len != 0) {
353                 att_value.val_len = (unsigned int)gp_byte_array->len;
354                 att_value.val = (unsigned char *)gp_byte_array->data;
355         }
356
357         otp_data = (char *)g_memdup(att_value.val, att_value.val_len);
358
359 dbus_return:
360         var_data = g_variant_new_from_data((const GVariantType*)"ay",
361                         otp_data, att_value.val_len, TRUE, NULL, NULL);
362
363         if (info) {
364                 param = g_variant_new("(isn@ay)", result, handle, att_value.val_len, var_data);
365                 _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
366                                 BLUETOOTH_EVENT_OTP_READ_CHAR_VAL,
367                                 param);
368                 req_info = _bt_get_request_info(info->req_id);
369                 __bt_otp_remove_read_info(info);
370         }
371
372         if (req_info == NULL) {
373                 BT_ERR("OTP data read Request not found!!");
374                 goto done;
375         }
376
377         if (req_info->context == NULL)
378                 goto done;
379
380         out_param1 = g_variant_new_from_data((const GVariantType*)"ay",
381                         handle, __get_handle_length(handle), TRUE, NULL, NULL);
382         g_dbus_method_invocation_return_value(req_info->context,
383                         g_variant_new("(iv)", result, out_param1));
384
385         _bt_delete_request_list(req_info->req_id);
386
387 done:
388         /* Data free */
389         if (error)
390                 g_clear_error(&error);
391         if (gp_byte_array)
392                 g_byte_array_free(gp_byte_array, TRUE);
393         if (handle)
394                 g_free(handle);
395         if (value)
396                 g_variant_unref(value);
397         if (iter)
398                 g_variant_iter_free(iter);
399         if (otp_data)
400                 g_free(otp_data);
401         BT_DBG("-");
402 }
403
404 int _bt_otp_read_characteristic_value(int request_id, char *sender, char *handle)
405 {
406         GDBusConnection *conn;
407         bt_otp_read_req_info *info = NULL;
408         char *charc_handle = NULL;
409         GVariantBuilder *builder = NULL;
410         guint16 offset = 0;
411
412         BT_CHECK_PARAMETER(handle, return);
413         BT_CHECK_PARAMETER(sender, return);
414
415         conn = _bt_gdbus_get_system_gconn();
416         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
417
418         BT_DBG("Read OTP Characteristic from server handle [%s]", handle);
419
420         /* If OTP data read already pending on same Server, then return In progress */
421         if (__bt_otp_get_read_info(handle) != NULL) {
422                 BT_ERR("Read Req is ongoing in remote server [%s]", handle);
423                 return BLUETOOTH_ERROR_IN_PROGRESS;
424         }
425
426         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
427         /*offset*/
428         g_variant_builder_add(builder, "{sv}", "offset",
429                 g_variant_new("q", offset));
430
431         charc_handle = g_strdup(handle);
432
433         g_dbus_connection_call(conn,
434                         BT_BLUEZ_NAME,
435                         handle,
436                         GATT_CHAR_INTERFACE,
437                         "ReadValue",
438                         g_variant_new("(a{sv})", builder),
439                         G_VARIANT_TYPE("(ay)"),
440                         G_DBUS_CALL_FLAGS_NONE,
441                         -1,
442                         NULL,
443                         (GAsyncReadyCallback)__bt_otp_read_char_cb,
444                         (gpointer)charc_handle);
445
446         /* Save Info in pending list */
447         info = g_malloc0(sizeof(bt_otp_read_req_info));
448         info->handle = g_strdup(handle);
449         BT_INFO("Found waiting for OTP Read from charc handle[%s] [%s]", info->handle, handle);
450         info->sender = g_strdup(sender);
451         info->req_id = request_id;
452         otp_read_req_info_list = g_slist_append(otp_read_req_info_list, info);
453
454         BT_DBG("-");
455         return BLUETOOTH_ERROR_NONE;
456 }
457
458 static bt_otp_notification_info *__bt_otp_get_notification_info(char *handle)
459 {
460         GSList *l;
461         bt_otp_notification_info *info = NULL;
462
463         for (l = otp_notification_info_list; l != NULL; l = g_slist_next(l)) {
464                 info = (bt_otp_notification_info *)l->data;
465                 if (info == NULL)
466                         continue;
467
468                 if (!g_strcmp0(info->handle, handle)) {
469                         BT_INFO("Found waiting for Ind from Server addr[%s]",
470                                         info->handle);
471                                 return info;
472                 }
473         }
474         return NULL;
475 }
476
477 static void __bt_otp_remove_notification_info(bt_otp_notification_info *info)
478 {
479         BT_DBG("Removing Notification Info [%s]", info->handle);
480
481         otp_notification_info_list = g_slist_remove(otp_notification_info_list, info);
482         if (info->handle)
483                 g_free(info->handle);
484         if (info->sender)
485                 g_free(info->sender);
486         if (info->notification_timeout_id > 0) {
487                 g_source_remove(info->notification_timeout_id);
488                 info->notification_timeout_id = 0;
489         }
490         g_free(info);
491 }
492
493 static void __bt_otp_notification_enable_request_cb(GObject *source_object,
494                         GAsyncResult *res, gpointer user_data)
495 {
496         GError *error = NULL;
497         GDBusConnection *system_gconn = NULL;
498         GVariant *value = NULL;
499         GVariant *param = NULL;
500         GVariant *out_param1 = NULL;
501         int result = BLUETOOTH_ERROR_NONE;
502         char *handle = NULL;
503         bt_otp_notification_info *info = NULL;
504         request_info_t *req_info = NULL;
505         BT_DBG("+");
506
507         system_gconn = _bt_gdbus_get_system_gconn();
508         value = g_dbus_connection_call_finish(system_gconn, res, &error);
509
510         if (error) {
511                 BT_ERR("Error : %s \n", error->message);
512                 if (g_strrstr(error->message, "Already notifying"))
513                         result = BLUETOOTH_ERROR_NONE;
514                 else if (g_strrstr(error->message, "In Progress"))
515                         result = BLUETOOTH_ERROR_IN_PROGRESS;
516                 else if (g_strrstr(error->message, "Operation is not supported"))
517                         result = BLUETOOTH_ERROR_NOT_SUPPORT;
518                 else if (g_strrstr(error->message, "Write not permitted") ||
519                                 g_strrstr(error->message, "Operation Not Authorized"))
520                         result = BLUETOOTH_ERROR_PERMISSION_DEINED;
521                 else if (g_strrstr(error->message, "Not paired"))
522                         result = BLUETOOTH_ERROR_NOT_PAIRED;
523                 else
524                         result = BLUETOOTH_ERROR_INTERNAL;
525         } else {
526                 BT_DBG("OTP CCCD enable request successful, send event to BT App");
527         }
528
529         handle = (char *)user_data;
530         info = __bt_otp_get_notification_info(handle);
531
532         if (info)
533                 req_info = _bt_get_request_info(info->req_id);
534
535         /* If CCCD Enable request failed for any reason, reset timer */
536         if (result != BLUETOOTH_ERROR_NONE && info != NULL) {
537                 BT_ERR("Activation Request failed");
538                 /* Reset Timer */
539                 if (info->notification_timeout_id > 0) {
540                         g_source_remove(info->notification_timeout_id);
541                         info->notification_timeout_id = 0;
542                 }
543
544                 /* Remove Indication Info */
545                 __bt_otp_remove_notification_info(info);
546         } else {
547                 /* CCCD Enable Request successful */
548                 if (info) {
549                         param = g_variant_new("(is)", result, handle);
550                         _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
551                                         BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED,
552                                         param);
553                 }
554         }
555
556         if (req_info == NULL) {
557                 BT_ERR("OTP Control Point CCCD Enable Request is not found!!");
558                 goto done;
559         }
560
561         if (req_info->context == NULL)
562                 goto done;
563
564         out_param1 = g_variant_new_from_data((const GVariantType*)"ay",
565                         handle, __get_handle_length(handle), TRUE, NULL, NULL);
566         g_dbus_method_invocation_return_value(req_info->context,
567                         g_variant_new("(iv)", result, out_param1));
568
569         _bt_delete_request_list(req_info->req_id);
570
571 done:
572         if (value)
573                 g_variant_unref(value);
574         if (error)
575                 g_clear_error(&error);
576         if (handle)
577                 g_free(handle);
578
579         BT_DBG("-");
580         return;
581 }
582
583 int _bt_otp_enable_notification(int request_id, char *sender, char *handle)
584 {
585         bt_otp_notification_info *info = NULL;
586         char *charc_handle = NULL;
587         GDBusConnection *conn;
588
589         BT_CHECK_PARAMETER(handle, return);
590         BT_CHECK_PARAMETER(sender, return);
591
592         conn = _bt_gdbus_get_system_gconn();
593         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
594
595         BT_DBG("OTP Control point CCCD Handle [%s]", handle);
596
597         if (__bt_otp_get_notification_info(handle) != NULL) {
598                 BT_ERR("Activation is already ongoing for same remote server");
599                 return BLUETOOTH_ERROR_IN_PROGRESS;
600         }
601
602         charc_handle = g_strdup(handle);
603
604         BT_INFO("Start Notify to Bluez");
605         g_dbus_connection_call(conn,
606                         BT_BLUEZ_NAME,
607                         handle,
608                         GATT_CHAR_INTERFACE,
609                         "StartNotify",
610                         NULL,
611                         NULL,
612                         G_DBUS_CALL_FLAGS_NONE,
613                         GATT_DEFAULT_TIMEOUT, NULL,
614                         (GAsyncReadyCallback)__bt_otp_notification_enable_request_cb,
615                         (gpointer)charc_handle);
616
617         info = g_malloc0(sizeof(bt_otp_notification_info));
618         info->handle = g_strdup(handle);
619         info->sender = g_strdup(sender);
620         info->req_id = request_id;
621         otp_notification_info_list = g_slist_append(otp_notification_info_list, info);
622
623         BT_DBG("-");
624         return BLUETOOTH_ERROR_NONE;
625 }
626
627 static void __bt_otp_write_request_cb(GObject *source_object,
628                         GAsyncResult *res, gpointer user_data)
629 {
630         GError *error = NULL;
631         GDBusConnection *system_gconn = NULL;
632         GVariant *value = NULL;
633         GVariant *param = NULL;
634         GVariant *out_param1 = NULL;
635         int result = BLUETOOTH_ATT_ERROR_NONE;
636         char *handle = NULL;
637         bt_otp_notification_info *info = NULL;
638         request_info_t *req_info = NULL;
639         BT_DBG("+");
640
641         system_gconn = _bt_gdbus_get_system_gconn();
642         value = g_dbus_connection_call_finish(system_gconn, res, &error);
643
644         if (error)
645                 result = __bluetooth_get_att_error_code(error);
646
647         handle = (char *)user_data;
648         info = __bt_otp_get_notification_info(handle);
649         if (info)
650                 req_info = _bt_get_request_info(info->req_id);
651
652         /* Is Activation request failed for any reason, reset timer */
653         if (result != BLUETOOTH_ATT_ERROR_NONE && info != NULL) {
654                 BT_ERR("Activation Request failed");
655                 /* Remove Indication Info */
656                 __bt_otp_remove_notification_info(info);
657         }
658
659         /* Activation Request successful */
660         if (info) {
661                 param = g_variant_new("(is)", result, handle);
662                 _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
663                                 BLUETOOTH_EVENT_OTP_WRITE_CHAR_VAL,
664                                 param);
665         }
666
667         if (req_info == NULL) {
668                 BT_ERR("OTP Write Request is not found!!");
669                 goto done;
670         }
671
672         if (req_info->context == NULL)
673                 goto done;
674
675         out_param1 = g_variant_new_from_data((const GVariantType*)"ay",
676                         handle, __get_handle_length(handle), TRUE, NULL, NULL);
677         g_dbus_method_invocation_return_value(req_info->context,
678                         g_variant_new("(iv)", result, out_param1));
679
680         _bt_delete_request_list(req_info->req_id);
681
682 done:
683         if (value)
684                 g_variant_unref(value);
685         if (error)
686                 g_clear_error(&error);
687         if (handle)
688                 g_free(handle);
689
690         BT_DBG("-");
691         return;
692 }
693
694 static void __bt_otp_send_indication_event(bt_otp_notification_info *info,
695                                                 unsigned char *buffer, int len, int result)
696 {
697         GVariant *otp_data;
698         GVariant *param;
699
700         otp_data = g_variant_new_from_data((const GVariantType*)"ay",
701                         buffer, len, TRUE, NULL, NULL);
702
703         BT_DBG("Send Indication event to sender");
704         param = g_variant_new("(is@ay)", result, info->handle, otp_data);
705         _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
706                                         BLUETOOTH_EVENT_OTP_INDICATION,
707                                         param);
708
709         /* Remove info from list */
710         __bt_otp_remove_notification_info(info);
711 }
712
713 static bool __bt_otp_indication_timeout_cb(gpointer user_data)
714 {
715         char *handle = NULL;
716         handle = (char *) user_data;
717         bt_otp_notification_info *info = NULL;
718         /* Indication:Fail*/
719         info = __bt_otp_get_notification_info(handle);
720         if (info) {
721                 BT_DBG("Activation timer Expired [Server] [%s]", info->handle);
722                 __bt_otp_send_indication_event(info, NULL, 0, BLUETOOTH_ERROR_INTERNAL);
723         }
724
725         return FALSE;
726 }
727
728 int _bt_otp_write_characteristic_value(int request_id, char *sender, char *handle,
729                                                         unsigned char *param, int length)
730 {
731         GVariantBuilder *builder1;
732         GVariant *val;
733         GVariant *options;
734         GVariantBuilder *builder2;
735         guint16 offset = 0;
736         bt_otp_notification_info *info = NULL;
737         GDBusConnection *conn;
738         char *charc_handle = NULL;
739         int i;
740
741         BT_DBG("+");
742
743         BT_CHECK_PARAMETER(handle, return);
744         BT_CHECK_PARAMETER(sender, return);
745         BT_CHECK_PARAMETER(param, return);
746
747         conn = _bt_gdbus_get_system_gconn();
748         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
749
750         BT_DBG("OTP Write Characteristic value handle [%s] data length [%d]", handle, length);
751         /* Check if activation is ongoing for the same Remote Server */
752
753         info = __bt_otp_get_notification_info(handle);
754         if (info && info->notification_timeout_id > 0) {
755                 BT_ERR("Write Request is already ongoing in remote server");
756                 return BLUETOOTH_ERROR_IN_PROGRESS;
757         }
758
759         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
760
761         for (i = 0; i < length; i++)
762                 g_variant_builder_add(builder1, "y", param[i]);
763
764         val = g_variant_new("ay", builder1);
765         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
766         /*offset*/
767         g_variant_builder_add(builder2, "{sv}", "offset",
768                                 g_variant_new_uint16(offset));
769
770         options = g_variant_new("a{sv}", builder2);
771
772         charc_handle = g_strdup(handle);
773
774         /* Activate Control Point */
775         g_dbus_connection_call(conn,
776                         BT_BLUEZ_NAME,
777                         handle,
778                         GATT_CHAR_INTERFACE,
779                         "WriteValue",
780                         g_variant_new("(@ay@a{sv})",
781                         val, options),
782                         NULL,
783                         G_DBUS_CALL_FLAGS_NONE,
784                         -1, NULL,
785                         (GAsyncReadyCallback)__bt_otp_write_request_cb,
786                         (gpointer)charc_handle);
787
788         g_variant_builder_unref(builder1);
789         g_variant_builder_unref(builder2);
790
791         if (info == NULL) {
792                 info = g_malloc0(sizeof(bt_otp_notification_info));
793                 info->handle = g_strdup(handle);
794                 info->sender = g_strdup(sender);
795                 otp_notification_info_list = g_slist_append(otp_notification_info_list, info);
796         }
797         info->req_id = request_id;
798         /* Set timeout only for cp charc */
799         info->notification_timeout_id = g_timeout_add(BT_INDICATION_TIMEOUT_MAX,
800                         (GSourceFunc)__bt_otp_indication_timeout_cb, (gpointer)info->handle);
801
802         BT_DBG("-");
803         return BLUETOOTH_ERROR_NONE;
804 }
805
806 void _bt_otp_check_indication(const char *path, GVariant *msg)
807 {
808         bt_otp_notification_info *info = NULL;
809         unsigned char *buffer = NULL;
810         int len = 0;
811         int i;
812         GVariant *value = NULL;
813         BT_DBG("+");
814
815         info = __bt_otp_get_notification_info((char *)path);
816
817         if (info) {
818                 /* Reset Timer */
819                 if (info->notification_timeout_id > 0)
820                         g_source_remove(info->notification_timeout_id);
821
822                 g_variant_get(msg, "(is@ay)", NULL, NULL, &value);
823
824                 if (value) {
825                         len = g_variant_get_size(value);
826                         BT_DBG("Indication data from Server len[%d]", len);
827                         if (len > 0) {
828                                 buffer = (unsigned char *)g_variant_get_data(value);
829                                 /* DEBUG */
830                                 for (i = 0; i < len; i++)
831                                         BT_DBG("%.2x", buffer[i]);
832                         }
833
834                         /* Send Indication & info removed internally */
835                         __bt_otp_send_indication_event(info, buffer, len, BLUETOOTH_ERROR_NONE);
836
837                         g_variant_unref(value);
838                 } else {
839                         BT_ERR("No Indication data from Server");
840                         /* Send Error Indication & info removed internally */
841                         __bt_otp_send_indication_event(info, NULL, 0, BLUETOOTH_ERROR_INTERNAL);
842                 }
843         }
844         BT_DBG("-");
845 }
846
847 int _bt_otp_connect_otc(int req_id, const bluetooth_device_address_t *bd_addr)
848 {
849         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
850         gchar *device_path = NULL;
851         GDBusProxy *device_proxy = NULL;
852         GDBusConnection *conn;
853         int ret = BLUETOOTH_ERROR_NONE;
854         GVariant *result = NULL;
855         GError *err = NULL;
856
857         BT_CHECK_PARAMETER(bd_addr, return);
858
859         _bt_convert_addr_type_to_string(device_address,
860                         (unsigned char *)bd_addr->addr);
861
862         conn = _bt_gdbus_get_system_gconn();
863         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
864
865         device_path = _bt_get_device_object_path(device_address);
866         if (device_path == NULL) {
867                 BT_DBG("device_path NULL");
868                 ret = BLUETOOTH_ERROR_INTERNAL;
869                 goto fail;
870         }
871
872         retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
873
874         device_proxy = g_dbus_proxy_new_sync(conn,
875                                         G_DBUS_PROXY_FLAGS_NONE,
876                                         NULL, BT_BLUEZ_NAME,
877                                         device_path, BT_DEVICE_INTERFACE,
878                                         NULL, NULL);
879         g_free(device_path);
880         retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
881
882         result = g_dbus_proxy_call_sync(device_proxy, "ConnectOtc",
883                                 NULL,
884                                 G_DBUS_CALL_FLAGS_NONE,
885                                 -1,
886                                 NULL,
887                                 &err);
888
889         if (result == NULL) {
890                 if (err != NULL) {
891                         g_dbus_error_strip_remote_error(err);
892                         BT_ERR("OTC Connect Error: %s\n", err->message);
893                         if (g_strcmp0(err->message, "Already Exists") == 0)
894                                 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
895                         else
896                                 ret = BLUETOOTH_ERROR_INTERNAL;
897                         g_error_free(err);
898                 }
899         }
900         g_variant_unref(result);
901
902 fail:
903         g_object_unref(device_proxy);
904         return ret;
905 }
906
907 int _bt_otp_disconnect_otc(const bluetooth_device_address_t *bd_addr)
908 {
909         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
910         gchar *device_path = NULL;
911         GError *error = NULL;
912         GDBusProxy *device_proxy = NULL;
913         GDBusProxy *adapter_proxy;
914         GDBusConnection *conn;
915         int ret = BLUETOOTH_ERROR_NONE;
916
917         BT_CHECK_PARAMETER(bd_addr, return);
918
919         _bt_convert_addr_type_to_string(device_address,
920                         (unsigned char *)bd_addr->addr);
921
922         conn = _bt_gdbus_get_system_gconn();
923         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
924
925         adapter_proxy = _bt_get_adapter_proxy();
926         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
927
928         device_path = _bt_get_device_object_path(device_address);
929         if (device_path == NULL) {
930                 BT_DBG("device_path NULL");
931                 return BLUETOOTH_ERROR_INTERNAL;
932         }
933
934         retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
935
936         device_proxy = g_dbus_proxy_new_sync(conn,
937                                         G_DBUS_PROXY_FLAGS_NONE,
938                                         NULL, BT_BLUEZ_NAME,
939                                         device_path,
940                                         BT_DEVICE_INTERFACE,
941                                         NULL, NULL);
942         g_free(device_path);
943         retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
944
945         g_dbus_proxy_call_sync(device_proxy, "DisconnectOtc",
946                                 NULL,
947                                 G_DBUS_CALL_FLAGS_NONE,
948                                 -1,
949                                 NULL,
950                                 &error);
951
952         if (error) {
953                 BT_ERR("DisconnectOtc Call Error %s[%s]",
954                                 error->message, device_address);
955                 g_error_free(error);
956                 g_object_unref(device_proxy);
957                 return BLUETOOTH_ERROR_INTERNAL;
958         }
959
960         if (device_proxy)
961                 g_object_unref(device_proxy);
962
963         return ret;
964 }