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