[Boiler Plate] Update Boiler plate to remove unwanted information
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-hdp.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 <sys/types.h>
19 #include <sys/socket.h>
20 #include <dbus/dbus.h>
21 #include <string.h>
22
23 #include "bluetooth-api.h"
24 #include "bt-common.h"
25 #include "bt-internal-types.h"
26
27 #define HDP_BUFFER_SIZE 1024
28 #define BLUEZ_HDP_MANAGER_INTERFACE  "org.bluez.HealthManager1"
29 #define BLUEZ_HDP_DEVICE_INTERFACE  "org.bluez.HealthDevice1"
30 #define BLUEZ_HDP_CHANNEL_INTERFACE  "org.bluez.HealthChannel1"
31
32 gboolean interface_exist = FALSE;
33
34 typedef struct {
35         char *obj_channel_path;
36         int fd;
37         guint watch_id;
38 } hdp_obj_info_t;
39
40 typedef struct {
41         void *app_handle;
42         GSList *obj_info;
43 } hdp_app_list_t;
44
45 /* Variable for privilege, only for write API,
46   before we should reduce time to bt-service dbus calling
47   -1 : Don't have a permission to access API
48   0 : Initial value, not yet check
49   1 : Have a permission to access API
50 */
51 static int privilege_token;
52
53
54 /**********************************************************************
55 *               Static Functions declaration                            *
56 ***********************************************************************/
57 static int __bt_hdp_internal_create_application(unsigned int data_type,
58                                                 int role,
59                                                 bt_hdp_qos_type_t channel_type,
60                                                 char **app_handle);
61
62 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
63                                                         DBusMessage *msg,
64                                                         void *data);
65
66 static void __bt_hdp_internal_handle_connect(DBusMessage *msg);
67
68 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg);
69
70 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg);
71
72 static int __bt_hdp_internal_add_filter(void);
73
74 static int __bt_hdp_internal_acquire_fd(const char *path);
75
76 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path);
77
78 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
79                                                 GIOCondition cond,
80                                                 gpointer data);
81
82 static int __bt_hdp_internal_destroy_application(const char *app_handle);
83
84 static void __bt_hdp_internal_remove_filter(void);
85
86 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle);
87
88 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd);
89
90 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path);
91
92 /*Global Variables*/
93 static DBusConnection *g_hdp_dus_conn;
94
95 static GSList *g_app_list = NULL;
96
97 /**********************************************************************
98 *                       Health device APIs (HDP)                        *
99 ***********************************************************************/
100
101 BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type,
102                                         bt_hdp_role_type_t role,
103                                         bt_hdp_qos_type_t channel_type,
104                                         char **app_handle)
105 {
106         int result = BLUETOOTH_ERROR_NONE;
107
108         BT_DBG("+");
109
110         BT_CHECK_ENABLED(return);
111
112         /*For source role is mandatory */
113         if (role == HDP_ROLE_SOURCE && channel_type == HDP_QOS_ANY) {
114                 BT_ERR("For source, type is mandatory - Reliable/Streaming");
115                 return BLUETOOTH_ERROR_INVALID_PARAM;
116         }
117
118         result = __bt_hdp_internal_create_application(data_type, role,
119                                                 channel_type, app_handle);
120
121         return result;
122 }
123
124 static void __bt_hdp_obj_info_free(hdp_obj_info_t *info)
125 {
126         if (info) {
127                 g_source_remove(info->watch_id);
128                 close(info->fd);
129                 g_free(info->obj_channel_path);
130                 g_free(info);
131         }
132 }
133
134 static int __bt_hdp_internal_create_application(unsigned int data_type,
135                                         int role,
136                                         bt_hdp_qos_type_t channel_type,
137                                         char **app_handle)
138 {
139         DBusMessage *msg;
140         DBusMessage *reply;
141         const char *svalue;
142         const char *key_type;
143         char *app_path;
144         hdp_app_list_t *list;
145         DBusError err;
146         DBusMessageIter iter;
147         DBusMessageIter array_iter;
148         DBusMessageIter entry;
149         DBusMessageIter variant;
150         guint16 value;
151         DBusConnection *conn;
152         int ret = BLUETOOTH_ERROR_NONE;
153
154         BT_DBG("+");
155
156         conn = _bt_get_system_conn();
157         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
158
159         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
160                                           BLUEZ_HDP_MANAGER_INTERFACE,
161                                           "CreateApplication");
162
163         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
164
165         dbus_message_iter_init_append(msg, &iter);
166         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
167                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING
168                 DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
169                 &array_iter);
170
171         key_type = "DataType";
172         value = (guint16) data_type;
173         dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
174                                         NULL, &entry);
175         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
176         dbus_message_iter_open_container(&entry,
177                 DBUS_TYPE_VARIANT, DBUS_TYPE_UINT16_AS_STRING, &variant);
178         dbus_message_iter_append_basic(&variant, DBUS_TYPE_UINT16, &value);
179         dbus_message_iter_close_container(&entry, &variant);
180         dbus_message_iter_close_container(&array_iter, &entry);
181
182         key_type = "Role";
183
184         /*0-Source,1-Sink*/
185         svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
186         dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
187                                         NULL, &entry);
188         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
189         dbus_message_iter_open_container(&entry,
190                 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
191         dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue);
192         dbus_message_iter_close_container(&entry, &variant);
193         dbus_message_iter_close_container(&array_iter, &entry);
194
195         key_type = "Description";
196         svalue = "Health Device";
197         dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
198                                         NULL, &entry);
199         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
200         dbus_message_iter_open_container(&entry,
201                 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
202         dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue);
203         dbus_message_iter_close_container(&entry, &variant);
204         dbus_message_iter_close_container(&array_iter, &entry);
205
206         if (role == HDP_ROLE_SOURCE) {
207                 key_type = "ChannelType";
208                 if (channel_type == HDP_QOS_RELIABLE)
209                         svalue = "reliable";
210                 else if (channel_type == HDP_QOS_STREAMING)
211                         svalue = "streaming";
212
213                 dbus_message_iter_open_container(&array_iter,
214                         DBUS_TYPE_DICT_ENTRY, NULL, &entry);
215                 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
216                                                 &key_type);
217                 dbus_message_iter_open_container(&entry,
218                         DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING,
219                         &variant);
220                 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
221                                                 &svalue);
222                 dbus_message_iter_close_container(&entry, &variant);
223                 dbus_message_iter_close_container(&array_iter, &entry);
224         }
225
226         dbus_message_iter_close_container(&iter, &array_iter);
227
228         dbus_error_init(&err);
229
230         reply = dbus_connection_send_with_reply_and_block(
231                                         conn, msg,
232                                         -1, &err);
233         dbus_message_unref(msg);
234
235         if (!reply) {
236                 BT_ERR(" HDP:dbus Can't create application");
237
238                 if (dbus_error_is_set(&err)) {
239                         BT_ERR("%s", err.message);
240
241                         if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
242                                 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
243                         else
244                                 ret = BLUETOOTH_ERROR_INTERNAL;
245
246                         dbus_error_free(&err);
247                 }
248                 return ret;
249         }
250
251         if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
252                                 &app_path, DBUS_TYPE_INVALID)) {
253
254                 BT_ERR(" HDP: Can't get reply arguments from Dbus");
255
256                 if (dbus_error_is_set(&err)) {
257                         BT_ERR("Error: %s", err.message);
258                         dbus_error_free(&err);
259                 }
260
261                 dbus_message_unref(reply);
262                 return BLUETOOTH_ERROR_INTERNAL;
263         }
264
265         dbus_message_unref(reply);
266
267         BT_DBG("Created health application: %s", (char *)app_path);
268
269         list = g_new0(hdp_app_list_t, 1);
270         list->app_handle = (void *)g_strdup(app_path);
271         *app_handle = (char *)list->app_handle;
272         g_app_list = g_slist_append(g_app_list, list);
273
274         BT_DBG("app_handle: %s", (char *)list->app_handle);
275
276         ret = __bt_hdp_internal_add_filter();
277
278         if (ret != BLUETOOTH_ERROR_NONE) {
279                 BT_ERR("Funtion failed");
280                 return ret;
281         }
282
283         return BLUETOOTH_ERROR_NONE;
284 }
285
286 static int __bt_hdp_internal_add_filter(void)
287 {
288         DBusError dbus_error;
289
290         BT_DBG("+");
291
292         /*Single process only one signal registration is required */
293         if (g_hdp_dus_conn) {
294                 BT_ERR("g_hdp_dus_conn already exist");
295                 goto done;
296         }
297
298         /* Add the filter for HDP client functions */
299         dbus_error_init(&dbus_error);
300
301         g_hdp_dus_conn = _bt_get_system_conn();
302         retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
303
304         dbus_connection_add_filter(g_hdp_dus_conn,
305                                 __bt_hdp_internal_event_filter, NULL, NULL);
306
307         dbus_bus_add_match(g_hdp_dus_conn,
308                         "type='signal',interface=" BLUEZ_HDP_DEVICE_INTERFACE,
309                         &dbus_error);
310
311         dbus_bus_add_match(g_hdp_dus_conn,
312                         "type='signal',interface=" BT_MANAGER_INTERFACE,
313                         &dbus_error);
314
315         dbus_bus_add_match(g_hdp_dus_conn,
316                         "type='signal',interface=" BT_PROPERTIES_INTERFACE,
317                         &dbus_error);
318
319         if (dbus_error_is_set(&dbus_error)) {
320                 BT_ERR("Fail to add dbus filter signal\n");
321                 dbus_error_free(&dbus_error);
322                 g_hdp_dus_conn = NULL;
323                 return BLUETOOTH_ERROR_INTERNAL;
324         }
325
326 done:
327         BT_DBG("-\n");
328         return BLUETOOTH_ERROR_NONE;
329
330 }
331
332 static void __bt_hdp_internal_handle_connected(DBusMessage *msg);
333
334
335 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
336                                         DBusMessage *msg, void *data)
337 {
338         const char *path = dbus_message_get_path(msg);
339
340         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
341                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
342
343         BT_DBG("Path = %s\n", path);
344         if (path == NULL)
345                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
346
347         if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
348                                         "ChannelConnected"))
349                 __bt_hdp_internal_handle_connect(msg);
350         else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
351                                         "ChannelDeleted"))
352                 __bt_hdp_internal_handle_disconnect(msg);
353         else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
354                                         "PropertyChanged"))
355                 __bt_hdp_internal_handle_property_changed(msg);
356         else if (dbus_message_is_signal(msg, BT_MANAGER_INTERFACE,
357                                         "InterfacesAdded")) {
358                 interface_exist = TRUE;
359                 BT_DBG("InterfaceAdded");
360         } else if (dbus_message_is_signal(msg, BT_MANAGER_INTERFACE,
361                                         "InterfacesRemoved")) {
362                 interface_exist = FALSE;
363                 __bt_hdp_internal_handle_disconnect(msg);
364                 BT_DBG("InterfaceRemoved");
365         } else if (dbus_message_is_signal(msg, BT_PROPERTIES_INTERFACE,
366                                         "PropertiesChanged")) {
367                 BT_DBG("PropertyChanged");
368                 if(interface_exist)
369                         __bt_hdp_internal_handle_connected(msg);
370         }
371
372         return DBUS_HANDLER_RESULT_HANDLED;
373 }
374
375 static void __bt_hdp_internal_handle_connected(DBusMessage *msg)
376 {
377         DBusMessageIter iter, dict, entry, var;
378         const char *path = NULL;
379         const char *obj_channel_path = NULL;
380         bt_user_info_t *user_info;
381         int ret;
382
383         if (dbus_message_iter_init(msg, &iter) == FALSE)
384                 return;
385
386         dbus_message_iter_get_basic(&iter, &path);
387
388         BT_DBG("object path: %s", path);
389
390         if(!g_strcmp0(path, "org.bluez.HealthDevice1")) {
391                 dbus_message_iter_next(&iter);
392
393                 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
394                         return;
395
396                 dbus_message_iter_recurse(&iter, &dict);
397                 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
398                         const char *interface;
399
400                         dbus_message_iter_recurse(&dict, &entry);
401
402                         if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
403                                 break;
404
405                         dbus_message_iter_get_basic(&entry, &interface);
406                         dbus_message_iter_next(&entry);
407                         dbus_message_iter_recurse(&entry, &var);
408
409                         if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_OBJECT_PATH)
410                                 break;
411
412                         dbus_message_iter_get_basic(&var, &obj_channel_path);
413
414                         BT_DBG("interface: %s", interface);
415                         BT_DBG("object_path: %s", obj_channel_path);
416
417                         dbus_message_iter_next(&dict);
418                 }
419
420                 BT_INFO("Channel connected, Path = %s", obj_channel_path);
421
422                 user_info = _bt_get_user_data(BT_COMMON);
423                 if (user_info == NULL || user_info->cb == NULL)
424                         return;
425
426                 ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
427                 if (ret != BLUETOOTH_ERROR_NONE) {
428                         _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
429                                         BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
430                                         user_info->cb, user_info->user_data);
431                 }
432         }
433 }
434
435 static void __bt_hdp_internal_handle_connect(DBusMessage *msg)
436 {
437         const char *path = dbus_message_get_path(msg);
438         const char *obj_channel_path;
439         bt_user_info_t *user_info;
440         int ret;
441
442         BT_INFO("+********Signal - ChannelConnected******\n\n");
443         BT_DBG("Path = %s", path);
444
445         if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
446                                 &obj_channel_path, DBUS_TYPE_INVALID)) {
447                 BT_ERR("Unexpected parameters in ChannelConnected signal");
448                 return;
449         }
450
451         BT_INFO("Channel connected, Path = %s", obj_channel_path);
452
453         user_info = _bt_get_user_data(BT_COMMON);
454         if (user_info == NULL || user_info->cb == NULL)
455                 return;
456
457         ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
458         if (ret != BLUETOOTH_ERROR_NONE) {
459                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
460                                 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
461                                 user_info->cb, user_info->user_data);
462         } else {
463                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
464                                 BLUETOOTH_ERROR_NONE, NULL,
465                                 user_info->cb, user_info->user_data);
466         }
467
468         BT_DBG("-");
469 }
470
471 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg)
472 {
473         const char *path = dbus_message_get_path(msg);
474         const char *obj_channel_path;
475         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
476         bluetooth_device_address_t device_addr = { {0} };
477         bt_hdp_disconnected_t dis_ind;
478         hdp_obj_info_t *info;
479         bt_user_info_t *user_info;
480
481         BT_INFO("+********Signal - ChannelDeleted ******\n\n");
482         BT_DBG("Path = %s", path);
483
484         if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
485                                 &obj_channel_path, DBUS_TYPE_INVALID)) {
486                 BT_ERR("Unexpected parameters in ChannelDeleted signal");
487                 return;
488         }
489
490         BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
491
492         info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
493         if (!info) {
494                 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
495                 return;
496         }
497
498         /*Since bluetoothd is not sending the ChannelDeleted signal */
499         _bt_device_path_to_address(path, address);
500
501         _bt_convert_addr_string_to_type(device_addr.addr, address);
502
503         dis_ind.channel_id = info->fd;
504         dis_ind.device_address = device_addr;
505
506         user_info = _bt_get_user_data(BT_COMMON);
507
508         if (user_info->cb) {
509                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
510                                 BLUETOOTH_ERROR_NONE, &dis_ind,
511                                 user_info->cb, user_info->user_data);
512         }
513
514         BT_DBG(" Removed connection from list\n");
515
516         __bt_hdp_obj_info_free(info);
517
518 }
519
520 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg)
521 {
522         const char *path = dbus_message_get_path(msg);
523         DBusMessageIter item_iter;
524         DBusMessageIter value_iter;
525         const char *property;
526         const char *obj_main_channel_path;
527
528         BT_DBG("+*******Signal - PropertyChanged*******\n");
529         BT_DBG("Path = %s", path);
530
531         dbus_message_iter_init(msg, &item_iter);
532
533         if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
534                 BT_ERR("This is bad format dbus");
535                 return;
536         }
537
538         dbus_message_iter_get_basic(&item_iter, &property);
539
540         ret_if(property == NULL);
541
542         BT_DBG("Property (%s)\n", property);
543
544         if (0 == g_strcmp0(property, "MainChannel")) {
545                 BT_INFO("Property MainChannel received");
546
547                 dbus_message_iter_next(&item_iter);
548
549                 dbus_message_iter_recurse(&item_iter, &value_iter);
550
551                 dbus_message_iter_get_basic(&value_iter,
552                                                 &obj_main_channel_path);
553                 BT_DBG("Path = %s", path);
554
555                 BT_DBG("Main Channel  Path = %s", obj_main_channel_path);
556         }
557         BT_DBG("-*************\n");
558 }
559
560 static int __bt_hdp_internal_acquire_fd(const char *path)
561 {
562         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
563         bluetooth_device_address_t device_addr = { {0} };
564         DBusMessageIter reply_iter;
565         DBusMessageIter reply_iter_entry;
566         const char *property;
567         char *type_qos = NULL;
568         char *device = NULL;;
569         char *app_handle = NULL;;
570         hdp_app_list_t *list = NULL;;
571         DBusMessage *msg;
572         DBusMessage *reply;
573         DBusConnection *conn;
574         bt_hdp_connected_t conn_ind;
575         DBusError err;
576         int fd;
577         bt_user_info_t *user_info;
578         char *dev_path;
579
580         BT_DBG("+");
581
582         conn = _bt_get_system_conn();
583         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
584
585         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
586                                           BLUEZ_HDP_CHANNEL_INTERFACE,
587                                           "Acquire");
588
589         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
590
591         dbus_error_init(&err);
592
593         reply = dbus_connection_send_with_reply_and_block(conn, msg,
594                                                         -1, &err);
595
596         dbus_message_unref(msg);
597
598         if (!reply) {
599                 BT_ERR(" HDP:****** dbus Can't create application ****");
600
601                 if (dbus_error_is_set(&err)) {
602                         BT_ERR("%s", err.message);
603                         dbus_error_free(&err);
604                 }
605
606                 return BLUETOOTH_ERROR_INTERNAL;
607         }
608
609         if (!dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd,
610                                 DBUS_TYPE_INVALID)) {
611                 BT_ERR(" HDP:dbus Can't get reply arguments");
612
613                 if (dbus_error_is_set(&err)) {
614                         BT_ERR("%s", err.message);
615                         dbus_error_free(&err);
616                 }
617                 goto error;
618         }
619
620         dbus_message_unref(reply);
621
622         BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
623
624         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
625                         BT_PROPERTIES_INTERFACE, "GetAll");
626         dev_path = g_strdup(BLUEZ_HDP_CHANNEL_INTERFACE);
627         dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_path,
628                                         DBUS_TYPE_INVALID);
629         g_free(dev_path);
630
631         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
632
633         dbus_error_init(&err);
634
635         reply = dbus_connection_send_with_reply_and_block(conn, msg,
636                                                         -1, &err);
637
638         dbus_message_unref(msg);
639
640         if (!reply) {
641                 BT_ERR(" HDP:dbus Can't get the reply");
642
643                 if (dbus_error_is_set(&err)) {
644                         BT_ERR("%s", err.message);
645                         dbus_error_free(&err);
646                 }
647
648                 return BLUETOOTH_ERROR_INTERNAL;
649         }
650         dbus_message_iter_init(reply, &reply_iter);
651
652         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
653                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
654                 goto error;
655         }
656
657         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
658
659         /*Parse the dict */
660         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
661                                                 DBUS_TYPE_DICT_ENTRY) {
662                 DBusMessageIter dict_entry, dict_entry_val;
663                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
664                 dbus_message_iter_get_basic(&dict_entry, &property);
665                 BT_DBG("String received = %s\n", property);
666
667                 if (g_strcmp0("Type", property) == 0) {
668                         dbus_message_iter_next(&dict_entry);
669                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
670                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
671                                                 DBUS_TYPE_STRING)
672                                 continue;
673
674                         dbus_message_iter_get_basic(&dict_entry_val, &type_qos);
675
676                 } else if (g_strcmp0("Device", property) == 0) {
677                         dbus_message_iter_next(&dict_entry);
678                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
679                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
680                                                 DBUS_TYPE_OBJECT_PATH)
681                                 continue;
682
683                         dbus_message_iter_get_basic(&dict_entry_val, &device);
684
685                 } else if (g_strcmp0("Application", property) == 0) {
686                         dbus_message_iter_next(&dict_entry);
687                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
688                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
689                                                 DBUS_TYPE_OBJECT_PATH)
690                                 continue;
691
692                         dbus_message_iter_get_basic(&dict_entry_val,
693                                                         &app_handle);
694                 }
695                 dbus_message_iter_next(&reply_iter_entry);
696         }
697
698         BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
699                         type_qos, device, app_handle);
700
701         if (NULL == type_qos || NULL == app_handle) {
702                 BT_ERR("Pasing failed\n");
703                 goto error;
704         }
705
706         list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
707
708         /*Only process register with app handle receive the Connected event */
709         if (NULL == list) {
710                 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
711                 goto error;
712         }
713
714         hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
715         info->fd = fd;
716         info->obj_channel_path = g_strdup(path);
717         info->watch_id = __bt_hdp_internal_watch_fd(fd, info->obj_channel_path);
718         list->obj_info = g_slist_append(list->obj_info, info);
719
720         _bt_device_path_to_address(path, address);
721
722         _bt_convert_addr_string_to_type(device_addr.addr, address);
723
724         conn_ind.app_handle = app_handle;
725         conn_ind.channel_id = fd;
726         conn_ind.device_address = device_addr;
727         conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ?
728                         HDP_QOS_RELIABLE : HDP_QOS_STREAMING;
729
730         BT_DBG("Going to give callback\n");
731
732         user_info = _bt_get_user_data(BT_COMMON);
733
734         if (user_info->cb) {
735                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
736                                 BLUETOOTH_ERROR_NONE, &conn_ind,
737                                 user_info->cb, user_info->user_data);
738         }
739
740         dbus_message_unref(reply);
741
742         BT_DBG("Updated fd in the list*\n");
743         BT_DBG("-\n");
744
745         return BLUETOOTH_ERROR_NONE;
746  error:
747         dbus_message_unref(reply);
748         return BLUETOOTH_ERROR_INTERNAL;
749 }
750
751 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
752 {
753         GIOChannel *gio;
754         guint id;
755
756         BT_DBG("+");
757
758         gio = g_io_channel_unix_new(file_desc);
759
760         g_io_channel_set_close_on_unref(gio, TRUE);
761
762         id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
763                         __bt_hdp_internal_data_received, (void *)path);
764         BT_DBG("-");
765         return id;
766 }
767
768
769 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
770 {
771         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
772         bluetooth_device_address_t device_addr = { {0} };
773         bt_hdp_disconnected_t dis_ind;
774         hdp_obj_info_t *info;
775         bt_user_info_t *user_info;
776
777         BT_INFO("******** Socket Error  ******\n");
778
779         info = __bt_hdp_internal_gslist_obj_find_using_path(path);
780         ret_if(info == NULL);
781
782         /*Since bluetoothd is not sending the ChannelDeleted signal */
783         _bt_device_path_to_address(path, address);
784
785         _bt_convert_addr_string_to_type(device_addr.addr, address);
786
787         dis_ind.channel_id = sk;
788         dis_ind.device_address = device_addr;
789
790         user_info = _bt_get_user_data(BT_COMMON);
791
792         if (user_info->cb) {
793                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
794                                 BLUETOOTH_ERROR_NONE, &dis_ind,
795                                 user_info->cb, user_info->user_data);
796         }
797
798         BT_DBG(" Removed connection from list\n");
799
800         __bt_hdp_obj_info_free(info);
801 }
802
803 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
804                                         GIOCondition cond, gpointer data)
805 {
806         char buff[HDP_BUFFER_SIZE] = { 0, };
807         int sk;
808         int act_read;
809         bt_hdp_data_ind_t data_ind = { 0, };
810         const char *path = (const char *)data;
811         bt_user_info_t *user_info;
812
813         BT_DBG("+");
814
815         sk = g_io_channel_unix_get_fd(gio);
816
817         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
818                 BT_DBG("GIOCondition %d.............path = %s\n", cond, path);
819                  __bt_hdp_internal_handle_disconnect_cb(sk, path);
820                 return FALSE;
821         }
822
823         act_read = recv(sk, (void *)buff, sizeof(buff), 0);
824
825         if (act_read > 0) {
826                 BT_DBG("Received data of %d\n", act_read);
827         } else {
828                 BT_ERR("Read failed.....\n");
829                 __bt_hdp_internal_handle_disconnect_cb(sk, path);
830                 return FALSE;
831         }
832
833         data_ind.channel_id = sk;
834         data_ind.buffer = buff;
835         data_ind.size = act_read;
836
837         user_info = _bt_get_user_data(BT_COMMON);
838
839         if (user_info->cb) {
840                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
841                                 BLUETOOTH_ERROR_NONE, &data_ind,
842                                 user_info->cb, user_info->user_data);
843         }
844
845         BT_DBG("-\n");
846
847         return TRUE;
848 }
849
850 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
851 {
852         BT_DBG("+");
853
854         BT_CHECK_ENABLED(return);
855         BT_CHECK_PARAMETER(app_handle, return);
856
857         return __bt_hdp_internal_destroy_application(app_handle);
858 }
859
860 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
861 {
862         GSList *l;
863
864         retv_if(g_app_list == NULL, NULL);
865
866         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
867
868         for (l = g_app_list; l != NULL; l = l->next) {
869                 hdp_app_list_t *list = l->data;
870
871                 if (list) {
872                         BT_DBG("found app_handle=%s\n", (char *)list->app_handle);
873                         if (0 == g_strcmp0((char *)list->app_handle,
874                                                 (char *)app_handle))
875                                 return list;
876                 }
877         }
878         return NULL;
879 }
880
881 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
882 {
883         GSList *l;
884         GSList *iter;
885
886         retv_if(g_app_list == NULL, NULL);
887
888         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
889
890         for (l = g_app_list; l != NULL; l = l->next) {
891                 hdp_app_list_t *list = l->data;
892                 if (!list)
893                         return NULL;
894
895                 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
896                         hdp_obj_info_t *info = iter->data;
897                         if (!info)
898                                 return NULL;
899
900                         if (fd == info->fd)
901                                 return info;
902                 }
903         }
904         return NULL;
905 }
906
907 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
908 {
909         GSList *l;
910         GSList *iter;
911         hdp_obj_info_t *info = NULL;
912
913         retv_if(g_app_list == NULL, NULL);
914
915         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
916         for (l = g_app_list; l != NULL; l = l->next) {
917                 hdp_app_list_t *list = l->data;
918                 if (!list)
919                         return NULL;
920
921                 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
922                          info = iter->data;
923                         if (!info)
924                                 return NULL;
925
926                         if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
927                                 list->obj_info = g_slist_remove(list->obj_info, info);
928                                 return info;
929                         }
930                 }
931         }
932         return NULL;
933 }
934
935 static gboolean  __bt_hdp_internal_destroy_application_cb(gpointer data)
936 {
937         const char *app_handle;
938         hdp_app_list_t *list = NULL;
939         app_handle = (const char *)data;
940
941         BT_DBG("+");
942
943         list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
944         if (NULL == list) {
945                 BT_ERR("**** list not found for %s ******\n", app_handle);
946                 return FALSE;
947         }
948
949         g_app_list = g_slist_remove(g_app_list, list);
950
951         g_free(list->app_handle);
952         g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
953         g_free(list);
954
955         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
956
957         if (0 == g_slist_length(g_app_list))
958                 __bt_hdp_internal_remove_filter();
959         BT_DBG("-");
960         return FALSE;
961 }
962
963 static int __bt_hdp_internal_destroy_application(const char *app_handle)
964 {
965         DBusMessage *msg;
966         DBusMessage *reply;
967         DBusError err;
968         DBusConnection *conn;
969         int result = BLUETOOTH_ERROR_NONE;
970
971         conn = _bt_get_system_conn();
972         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
973
974         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
975                         BLUEZ_HDP_MANAGER_INTERFACE, "DestroyApplication");
976
977         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
978
979         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &app_handle,
980                                         DBUS_TYPE_INVALID);
981
982         dbus_error_init(&err);
983
984         reply = dbus_connection_send_with_reply_and_block(conn, msg,
985                                                         -1, &err);
986         dbus_message_unref(msg);
987         if (!reply) {
988                 BT_ERR(" HDP:dbus Can't Destroy application");
989
990                 if (dbus_error_is_set(&err)) {
991                         BT_ERR("%s", err.message);
992
993                         if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
994                                 result  = BLUETOOTH_ERROR_ACCESS_DENIED;
995                         else
996                                 result  = BLUETOOTH_ERROR_INTERNAL;
997
998                         dbus_error_free(&err);
999                 }
1000
1001                 return result ;
1002         }
1003
1004         dbus_message_unref(reply);
1005
1006         BT_DBG("Destroyed health application: %s", (char *)app_handle);
1007
1008         g_idle_add(__bt_hdp_internal_destroy_application_cb,
1009                         (gpointer)app_handle);
1010
1011         return BLUETOOTH_ERROR_NONE;
1012 }
1013
1014 static void __bt_hdp_internal_remove_filter(void)
1015 {
1016         BT_DBG("+");
1017
1018         ret_if(g_hdp_dus_conn == NULL);
1019
1020         dbus_connection_remove_filter(g_hdp_dus_conn,
1021                                         __bt_hdp_internal_event_filter, NULL);
1022
1023         g_hdp_dus_conn = NULL;  /*should not unref here, bcz no ++reff */
1024
1025         BT_DBG("-");
1026 }
1027
1028 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
1029                                             const char *buffer,
1030                                             unsigned int size)
1031 {
1032         int wbytes = 0;
1033         int written = 0;
1034         int result;
1035
1036         BT_DBG("+");
1037
1038         BT_CHECK_ENABLED(return);
1039
1040         if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
1041                 BT_ERR("Invalid arguments..\n");
1042                 return BLUETOOTH_ERROR_INVALID_PARAM;
1043         }
1044
1045         switch (privilege_token) {
1046         case 0:
1047                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
1048
1049                 if (result == BLUETOOTH_ERROR_NONE) {
1050                         privilege_token = 1; /* Have a permission */
1051                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1052                         BT_ERR("Don't have a privilege to use this API");
1053                         privilege_token = -1; /* Don't have a permission */
1054                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
1055                 } else {
1056                         /* Just break - It is not related with permission error */
1057                 }
1058                 break;
1059         case 1:
1060                 /* Already have a privilege */
1061                 break;
1062         case -1:
1063                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1064         default:
1065                 /* Invalid privilge token value */
1066                 return BLUETOOTH_ERROR_INTERNAL;
1067         }
1068
1069         while (wbytes < size) {
1070                 written = write(channel_id, buffer + wbytes, size - wbytes);
1071                 if (written <= 0) {
1072                         BT_ERR("write failed..\n");
1073                         return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1074                 }
1075                 wbytes += written;
1076         }
1077
1078         return BLUETOOTH_ERROR_NONE;
1079 }
1080
1081 static void __bt_hdp_connect_request_cb(GDBusProxy *hdp_proxy,
1082                                 GAsyncResult *res, gpointer user_data)
1083 {
1084         GError *err = NULL;
1085         char *obj_connect_path = NULL;
1086         bt_hdp_connected_t *conn_ind = user_data;
1087         bt_user_info_t *user_info;
1088         GVariant *reply = NULL;
1089         int ret = BLUETOOTH_ERROR_NONE;
1090
1091         reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1092
1093         g_object_unref(hdp_proxy);
1094
1095         if (!reply) {
1096                 if (err) {
1097                         BT_ERR("HDP connection  Dbus Call Error: %s\n", err->message);
1098                         g_clear_error(&err);
1099                 }
1100
1101                 user_info = _bt_get_user_data(BT_COMMON);
1102
1103                 if (user_info->cb) {
1104                         _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
1105                                         BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind,
1106                                         user_info->cb, user_info->user_data);
1107                 }
1108         } else {
1109                 g_variant_get(reply, "(&o)", &obj_connect_path);
1110
1111                 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
1112                 user_info = _bt_get_user_data(BT_COMMON);
1113
1114                 ret = __bt_hdp_internal_acquire_fd(obj_connect_path);
1115                 if (ret != BLUETOOTH_ERROR_NONE) {
1116                         user_info = _bt_get_user_data(BT_COMMON);
1117                         if (user_info->cb) {
1118                                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
1119                                                 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
1120                                                         user_info->cb, user_info->user_data);
1121                         }
1122                 }
1123                 g_variant_unref(reply);
1124         }
1125         g_free((void *)conn_ind->app_handle);
1126         g_free(conn_ind);
1127 }
1128
1129
1130 BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle,
1131                         bt_hdp_qos_type_t channel_type,
1132                         const bluetooth_device_address_t *device_address)
1133 {
1134         GError *err = NULL;
1135         GDBusConnection *conn = NULL;
1136         GDBusProxy *hdp_proxy = NULL;
1137         bt_hdp_connected_t *param;
1138         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1139         char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1140         char *dev_path = NULL;
1141         char *role;
1142
1143         BT_DBG("+");
1144
1145         BT_CHECK_ENABLED(return);
1146         BT_CHECK_PARAMETER(app_handle, return);
1147         BT_CHECK_PARAMETER(device_address, return);
1148
1149         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_CONNECT)
1150              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1151                 BT_ERR("Don't have a privilege to use this API");
1152                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1153         }
1154
1155         if (channel_type == HDP_QOS_RELIABLE) {
1156                 role = "Reliable";
1157         } else if (channel_type == HDP_QOS_STREAMING) {
1158                 role = "Streaming";
1159         } else if (channel_type == HDP_QOS_ANY) {
1160                 role = "Any";
1161         } else {
1162                 BT_ERR("Invalid channel_type %d", channel_type);
1163                 return BLUETOOTH_ERROR_ACCESS_DENIED;
1164         }
1165
1166         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1167
1168         if (err) {
1169                 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1170                 g_clear_error(&err);
1171                 return BLUETOOTH_ERROR_INTERNAL;
1172         }
1173
1174         /* If the adapter path is wrong, we can think the BT is not enabled. */
1175         if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1176                                         default_adapter_path) < 0) {
1177                 BT_ERR("Could not get adapter path\n");
1178                 g_object_unref(conn);
1179                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1180         }
1181
1182         _bt_convert_addr_type_to_string(address,
1183                                 (unsigned char *)device_address->addr);
1184
1185         BT_DBG("create conection to %s", address);
1186
1187         dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1188
1189         if (dev_path == NULL) {
1190                 g_object_unref(conn);
1191                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1192         }
1193
1194         g_strdelimit(dev_path, ":", '_');
1195
1196         BT_DBG("path: %s", dev_path);
1197
1198         hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1199                                                 NULL, BT_BLUEZ_NAME,
1200                                                 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1201                                                 NULL, NULL);
1202         g_object_unref(conn);
1203
1204         if (hdp_proxy == NULL) {
1205                 BT_ERR("Failed to get the HDP server proxy\n");
1206                 g_free(dev_path);
1207                 return BLUETOOTH_ERROR_NOT_PAIRED;
1208         }
1209
1210         BT_DBG("app path %s\n", app_handle);
1211
1212         param = g_new0(bt_hdp_connected_t, 1);
1213         param->app_handle = g_strdup(app_handle);
1214         memcpy(&param->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1215         param->type = channel_type;
1216
1217         g_dbus_proxy_call(hdp_proxy, "CreateChannel",
1218                                 g_variant_new("(os)", app_handle, role),
1219                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1220                                 (GAsyncReadyCallback)__bt_hdp_connect_request_cb,
1221                                 param);
1222
1223         g_free(dev_path);
1224
1225         return BLUETOOTH_ERROR_NONE;
1226
1227 }
1228
1229 static void __bt_hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
1230                         GAsyncResult *res, gpointer user_data)
1231 {
1232         GError *err = NULL;
1233         bt_hdp_disconnected_t *disconn_ind = user_data;
1234         bt_user_info_t *user_info;
1235         GVariant *reply = NULL;
1236
1237         reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1238         g_object_unref(hdp_proxy);
1239
1240         user_info = _bt_get_user_data(BT_COMMON);
1241         if (user_info == NULL || user_info->cb == NULL) {
1242                 g_free(disconn_ind);
1243                 if (err) {
1244                                 g_clear_error(&err);
1245                         return;
1246                 }
1247                 g_variant_unref(reply);
1248                 return;
1249         }
1250
1251         if (!reply) {
1252                 if (err) {
1253                         BT_ERR("HDP disconnection Dbus Call Error: %s\n",
1254                                                         err->message);
1255                         g_clear_error(&err);
1256                 }
1257
1258                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1259                                 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1260                                 user_info->cb, user_info->user_data);
1261         } else {
1262                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1263                                 BLUETOOTH_ERROR_NONE, disconn_ind,
1264                                 user_info->cb, user_info->user_data);
1265                 BT_INFO("HDP disconnection Dbus Call is done\n");
1266                 g_variant_unref(reply);
1267         }
1268
1269         g_free(disconn_ind);
1270
1271 }
1272
1273 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1274                         const bluetooth_device_address_t *device_address)
1275 {
1276         GError *err = NULL;
1277         GDBusConnection *conn = NULL;
1278         GDBusProxy *hdp_proxy = NULL;
1279         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1280         char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1281         char *dev_path = NULL;
1282         bt_hdp_disconnected_t *param;
1283
1284         BT_DBG("+\n");
1285
1286         BT_CHECK_ENABLED(return);
1287         BT_CHECK_PARAMETER(device_address, return);
1288
1289         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_DISCONNECT)
1290              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1291                 BT_ERR("Don't have a privilege to use this API");
1292                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1293         }
1294
1295         hdp_obj_info_t *info =
1296                 __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1297         if (NULL == info) {
1298                 BT_ERR("*** Could not locate the list for %d*****\n",
1299                                                         channel_id);
1300                 return BLUETOOTH_ERROR_INVALID_PARAM;
1301         }
1302
1303         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1304
1305         if (err) {
1306                 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1307                 g_clear_error(&err);
1308                 return BLUETOOTH_ERROR_INTERNAL;
1309         }
1310
1311         /* If the adapter path is wrong, we can think the BT is not enabled. */
1312         if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1313                                         default_adapter_path) < 0) {
1314                 BT_ERR("Could not get adapter path\n");
1315                 g_object_unref(conn);
1316                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1317         }
1318
1319         _bt_convert_addr_type_to_string(address,
1320                                 (unsigned char *)device_address->addr);
1321
1322         BT_DBG("create conection to  %s\n", address);
1323
1324         dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1325
1326         if (dev_path == NULL) {
1327                 g_object_unref(conn);
1328                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1329         }
1330
1331         g_strdelimit(dev_path, ":", '_');
1332
1333         BT_DBG("path  %s\n", dev_path);
1334
1335         hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1336                                                 NULL, BT_BLUEZ_NAME,
1337                                                 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1338                                                 NULL, NULL);
1339
1340         g_object_unref(conn);
1341
1342         if (hdp_proxy == NULL) {
1343                 BT_ERR("Failed to get the HDP proxy\n");
1344                 g_free(dev_path);
1345                 return BLUETOOTH_ERROR_NOT_PAIRED;
1346         }
1347
1348         param = g_new0(bt_hdp_disconnected_t, 1);
1349         param->channel_id = channel_id;
1350         memcpy(&param->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1351
1352         g_dbus_proxy_call(hdp_proxy, "DestroyChannel",
1353                                 g_variant_new("o", info->obj_channel_path),
1354                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1355                                 (GAsyncReadyCallback)__bt_hdp_disconnect_request_cb,
1356                                 param);
1357
1358         g_free(dev_path);
1359
1360         return BLUETOOTH_ERROR_NONE;
1361
1362 }