4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <dbus/dbus.h>
29 #include "bluetooth-api.h"
30 #include "bt-common.h"
31 #include "bt-internal-types.h"
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"
38 gboolean interface_exist = FALSE;
41 char *obj_channel_path;
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
57 static int privilege_token;
60 /**********************************************************************
61 * Static Functions declaration *
62 ***********************************************************************/
63 static int __bt_hdp_internal_create_application(unsigned int data_type,
65 bt_hdp_qos_type_t channel_type,
68 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
72 static void __bt_hdp_internal_handle_connect(DBusMessage *msg);
74 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg);
76 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg);
78 static int __bt_hdp_internal_add_filter(void);
80 static int __bt_hdp_internal_acquire_fd(const char *path);
82 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path);
84 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
88 static int __bt_hdp_internal_destroy_application(const char *app_handle);
90 static void __bt_hdp_internal_remove_filter(void);
92 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle);
94 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd);
96 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path);
99 static DBusConnection *g_hdp_dus_conn;
101 static GSList *g_app_list = NULL;
103 /**********************************************************************
104 * Health device APIs (HDP) *
105 ***********************************************************************/
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,
112 int result = BLUETOOTH_ERROR_NONE;
116 BT_CHECK_ENABLED(return);
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;
124 result = __bt_hdp_internal_create_application(data_type, role,
125 channel_type, app_handle);
130 static void __bt_hdp_obj_info_free(hdp_obj_info_t *info)
133 g_source_remove(info->watch_id);
135 g_free(info->obj_channel_path);
140 static int __bt_hdp_internal_create_application(unsigned int data_type,
142 bt_hdp_qos_type_t channel_type,
148 const char *key_type;
150 hdp_app_list_t *list;
152 DBusMessageIter iter;
153 DBusMessageIter array_iter;
154 DBusMessageIter entry;
155 DBusMessageIter variant;
157 DBusConnection *conn;
158 int ret = BLUETOOTH_ERROR_NONE;
162 conn = _bt_get_system_conn();
163 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
165 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
166 BLUEZ_HDP_MANAGER_INTERFACE,
167 "CreateApplication");
169 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
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,
177 key_type = "DataType";
178 value = (guint16) data_type;
179 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_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);
191 svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
192 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_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);
201 key_type = "Description";
202 svalue = "Health Device";
203 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_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);
212 if (role == HDP_ROLE_SOURCE) {
213 key_type = "ChannelType";
214 if (channel_type == HDP_QOS_RELIABLE)
216 else if (channel_type == HDP_QOS_STREAMING)
217 svalue = "streaming";
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,
223 dbus_message_iter_open_container(&entry,
224 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING,
226 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
228 dbus_message_iter_close_container(&entry, &variant);
229 dbus_message_iter_close_container(&array_iter, &entry);
232 dbus_message_iter_close_container(&iter, &array_iter);
234 dbus_error_init(&err);
236 reply = dbus_connection_send_with_reply_and_block(
239 dbus_message_unref(msg);
242 BT_ERR(" HDP:dbus Can't create application");
244 if (dbus_error_is_set(&err)) {
245 BT_ERR("%s", err.message);
247 if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
248 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
250 ret = BLUETOOTH_ERROR_INTERNAL;
252 dbus_error_free(&err);
257 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
258 &app_path, DBUS_TYPE_INVALID)) {
260 BT_ERR(" HDP: Can't get reply arguments from Dbus");
262 if (dbus_error_is_set(&err)) {
263 BT_ERR("Error: %s", err.message);
264 dbus_error_free(&err);
267 dbus_message_unref(reply);
268 return BLUETOOTH_ERROR_INTERNAL;
271 dbus_message_unref(reply);
273 BT_DBG("Created health application: %s", (char *)app_path);
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);
280 BT_DBG("app_handle: %s", (char *)list->app_handle);
282 ret = __bt_hdp_internal_add_filter();
284 if (ret != BLUETOOTH_ERROR_NONE) {
285 BT_ERR("Funtion failed");
289 return BLUETOOTH_ERROR_NONE;
292 static int __bt_hdp_internal_add_filter(void)
294 DBusError dbus_error;
298 /*Single process only one signal registration is required */
299 if (g_hdp_dus_conn) {
300 BT_ERR("g_hdp_dus_conn already exist");
304 /* Add the filter for HDP client functions */
305 dbus_error_init(&dbus_error);
307 g_hdp_dus_conn = _bt_get_system_conn();
308 retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
310 dbus_connection_add_filter(g_hdp_dus_conn,
311 __bt_hdp_internal_event_filter, NULL, NULL);
313 dbus_bus_add_match(g_hdp_dus_conn,
314 "type='signal',interface=" BLUEZ_HDP_DEVICE_INTERFACE,
317 dbus_bus_add_match(g_hdp_dus_conn,
318 "type='signal',interface=" BT_MANAGER_INTERFACE,
321 dbus_bus_add_match(g_hdp_dus_conn,
322 "type='signal',interface=" BT_PROPERTIES_INTERFACE,
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;
334 return BLUETOOTH_ERROR_NONE;
338 static void __bt_hdp_internal_handle_connected(DBusMessage *msg);
341 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
342 DBusMessage *msg, void *data)
344 const char *path = dbus_message_get_path(msg);
346 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
347 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
349 BT_DBG("Path = %s\n", path);
351 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
353 if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
355 __bt_hdp_internal_handle_connect(msg);
356 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
358 __bt_hdp_internal_handle_disconnect(msg);
359 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
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");
375 __bt_hdp_internal_handle_connected(msg);
378 return DBUS_HANDLER_RESULT_HANDLED;
381 static void __bt_hdp_internal_handle_connected(DBusMessage *msg)
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;
389 if (dbus_message_iter_init(msg, &iter) == FALSE)
392 dbus_message_iter_get_basic(&iter, &path);
394 BT_DBG("object path: %s", path);
396 if(!g_strcmp0(path, "org.bluez.HealthDevice1")) {
397 dbus_message_iter_next(&iter);
399 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
402 dbus_message_iter_recurse(&iter, &dict);
403 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
404 const char *interface;
406 dbus_message_iter_recurse(&dict, &entry);
408 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
411 dbus_message_iter_get_basic(&entry, &interface);
412 dbus_message_iter_next(&entry);
413 dbus_message_iter_recurse(&entry, &var);
415 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_OBJECT_PATH)
418 dbus_message_iter_get_basic(&var, &obj_channel_path);
420 BT_DBG("interface: %s", interface);
421 BT_DBG("object_path: %s", obj_channel_path);
423 dbus_message_iter_next(&dict);
426 BT_INFO("Channel connected, Path = %s", obj_channel_path);
428 user_info = _bt_get_user_data(BT_COMMON);
429 if (user_info == NULL || user_info->cb == NULL)
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);
441 static void __bt_hdp_internal_handle_connect(DBusMessage *msg)
443 const char *path = dbus_message_get_path(msg);
444 const char *obj_channel_path;
445 bt_user_info_t *user_info;
448 BT_INFO("+********Signal - ChannelConnected******\n\n");
449 BT_DBG("Path = %s", path);
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");
457 BT_INFO("Channel connected, Path = %s", obj_channel_path);
459 user_info = _bt_get_user_data(BT_COMMON);
460 if (user_info == NULL || user_info->cb == NULL)
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);
469 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
470 BLUETOOTH_ERROR_NONE, NULL,
471 user_info->cb, user_info->user_data);
477 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg)
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;
487 BT_INFO("+********Signal - ChannelDeleted ******\n\n");
488 BT_DBG("Path = %s", path);
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");
496 BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
498 info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
500 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
504 /*Since bluetoothd is not sending the ChannelDeleted signal */
505 _bt_device_path_to_address(path, address);
507 _bt_convert_addr_string_to_type(device_addr.addr, address);
509 dis_ind.channel_id = info->fd;
510 dis_ind.device_address = device_addr;
512 user_info = _bt_get_user_data(BT_COMMON);
515 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
516 BLUETOOTH_ERROR_NONE, &dis_ind,
517 user_info->cb, user_info->user_data);
520 BT_DBG(" Removed connection from list\n");
522 __bt_hdp_obj_info_free(info);
526 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg)
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;
534 BT_DBG("+*******Signal - PropertyChanged*******\n");
535 BT_DBG("Path = %s", path);
537 dbus_message_iter_init(msg, &item_iter);
539 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
540 BT_ERR("This is bad format dbus");
544 dbus_message_iter_get_basic(&item_iter, &property);
546 ret_if(property == NULL);
548 BT_DBG("Property (%s)\n", property);
550 if (0 == g_strcmp0(property, "MainChannel")) {
551 BT_INFO("Property MainChannel received");
553 dbus_message_iter_next(&item_iter);
555 dbus_message_iter_recurse(&item_iter, &value_iter);
557 dbus_message_iter_get_basic(&value_iter,
558 &obj_main_channel_path);
559 BT_DBG("Path = %s", path);
561 BT_DBG("Main Channel Path = %s", obj_main_channel_path);
563 BT_DBG("-*************\n");
566 static int __bt_hdp_internal_acquire_fd(const char *path)
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;;
579 DBusConnection *conn;
580 bt_hdp_connected_t conn_ind;
583 bt_user_info_t *user_info;
588 conn = _bt_get_system_conn();
589 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
591 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
592 BLUEZ_HDP_CHANNEL_INTERFACE,
595 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
597 dbus_error_init(&err);
599 reply = dbus_connection_send_with_reply_and_block(conn, msg,
602 dbus_message_unref(msg);
605 BT_ERR(" HDP:****** dbus Can't create application ****");
607 if (dbus_error_is_set(&err)) {
608 BT_ERR("%s", err.message);
609 dbus_error_free(&err);
612 return BLUETOOTH_ERROR_INTERNAL;
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");
619 if (dbus_error_is_set(&err)) {
620 BT_ERR("%s", err.message);
621 dbus_error_free(&err);
626 dbus_message_unref(reply);
628 BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
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,
637 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
639 dbus_error_init(&err);
641 reply = dbus_connection_send_with_reply_and_block(conn, msg,
644 dbus_message_unref(msg);
647 BT_ERR(" HDP:dbus Can't get the reply");
649 if (dbus_error_is_set(&err)) {
650 BT_ERR("%s", err.message);
651 dbus_error_free(&err);
654 return BLUETOOTH_ERROR_INTERNAL;
656 dbus_message_iter_init(reply, &reply_iter);
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");
663 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
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);
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) !=
680 dbus_message_iter_get_basic(&dict_entry_val, &type_qos);
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)
689 dbus_message_iter_get_basic(&dict_entry_val, &device);
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)
698 dbus_message_iter_get_basic(&dict_entry_val,
701 dbus_message_iter_next(&reply_iter_entry);
704 BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
705 type_qos, device, app_handle);
707 if (NULL == type_qos || NULL == app_handle) {
708 BT_ERR("Pasing failed\n");
712 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
714 /*Only process register with app handle receive the Connected event */
716 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
720 hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
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);
726 _bt_device_path_to_address(path, address);
728 _bt_convert_addr_string_to_type(device_addr.addr, address);
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;
736 BT_DBG("Going to give callback\n");
738 user_info = _bt_get_user_data(BT_COMMON);
741 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
742 BLUETOOTH_ERROR_NONE, &conn_ind,
743 user_info->cb, user_info->user_data);
746 dbus_message_unref(reply);
748 BT_DBG("Updated fd in the list*\n");
751 return BLUETOOTH_ERROR_NONE;
753 dbus_message_unref(reply);
754 return BLUETOOTH_ERROR_INTERNAL;
757 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
764 gio = g_io_channel_unix_new(file_desc);
766 g_io_channel_set_close_on_unref(gio, TRUE);
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);
775 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
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;
783 BT_INFO("******** Socket Error ******\n");
785 info = __bt_hdp_internal_gslist_obj_find_using_path(path);
786 ret_if(info == NULL);
788 /*Since bluetoothd is not sending the ChannelDeleted signal */
789 _bt_device_path_to_address(path, address);
791 _bt_convert_addr_string_to_type(device_addr.addr, address);
793 dis_ind.channel_id = sk;
794 dis_ind.device_address = device_addr;
796 user_info = _bt_get_user_data(BT_COMMON);
799 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
800 BLUETOOTH_ERROR_NONE, &dis_ind,
801 user_info->cb, user_info->user_data);
804 BT_DBG(" Removed connection from list\n");
806 __bt_hdp_obj_info_free(info);
809 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
810 GIOCondition cond, gpointer data)
812 char buff[HDP_BUFFER_SIZE] = { 0, };
815 bt_hdp_data_ind_t data_ind = { 0, };
816 const char *path = (const char *)data;
817 bt_user_info_t *user_info;
821 sk = g_io_channel_unix_get_fd(gio);
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);
829 act_read = recv(sk, (void *)buff, sizeof(buff), 0);
832 BT_DBG("Received data of %d\n", act_read);
834 BT_ERR("Read failed.....\n");
835 __bt_hdp_internal_handle_disconnect_cb(sk, path);
839 data_ind.channel_id = sk;
840 data_ind.buffer = buff;
841 data_ind.size = act_read;
843 user_info = _bt_get_user_data(BT_COMMON);
846 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
847 BLUETOOTH_ERROR_NONE, &data_ind,
848 user_info->cb, user_info->user_data);
856 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
860 BT_CHECK_ENABLED(return);
861 BT_CHECK_PARAMETER(app_handle, return);
863 return __bt_hdp_internal_destroy_application(app_handle);
866 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
870 retv_if(g_app_list == NULL, NULL);
872 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
874 for (l = g_app_list; l != NULL; l = l->next) {
875 hdp_app_list_t *list = l->data;
878 BT_DBG("found app_handle=%s\n", (char *)list->app_handle);
879 if (0 == g_strcmp0((char *)list->app_handle,
887 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
892 retv_if(g_app_list == NULL, NULL);
894 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
896 for (l = g_app_list; l != NULL; l = l->next) {
897 hdp_app_list_t *list = l->data;
901 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
902 hdp_obj_info_t *info = iter->data;
913 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
917 hdp_obj_info_t *info = NULL;
919 retv_if(g_app_list == NULL, NULL);
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;
927 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
932 if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
933 list->obj_info = g_slist_remove(list->obj_info, info);
941 static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data)
943 const char *app_handle;
944 hdp_app_list_t *list = NULL;
945 app_handle = (const char *)data;
949 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
951 BT_ERR("**** list not found for %s ******\n", app_handle);
955 g_app_list = g_slist_remove(g_app_list, list);
957 g_free(list->app_handle);
958 g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
961 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
963 if (0 == g_slist_length(g_app_list))
964 __bt_hdp_internal_remove_filter();
969 static int __bt_hdp_internal_destroy_application(const char *app_handle)
974 DBusConnection *conn;
975 int result = BLUETOOTH_ERROR_NONE;
977 conn = _bt_get_system_conn();
978 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
980 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
981 BLUEZ_HDP_MANAGER_INTERFACE, "DestroyApplication");
983 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
985 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &app_handle,
988 dbus_error_init(&err);
990 reply = dbus_connection_send_with_reply_and_block(conn, msg,
992 dbus_message_unref(msg);
994 BT_ERR(" HDP:dbus Can't Destroy application");
996 if (dbus_error_is_set(&err)) {
997 BT_ERR("%s", err.message);
999 if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
1000 result = BLUETOOTH_ERROR_ACCESS_DENIED;
1002 result = BLUETOOTH_ERROR_INTERNAL;
1004 dbus_error_free(&err);
1010 dbus_message_unref(reply);
1012 BT_DBG("Destroyed health application: %s", (char *)app_handle);
1014 g_idle_add(__bt_hdp_internal_destroy_application_cb,
1015 (gpointer)app_handle);
1017 return BLUETOOTH_ERROR_NONE;
1020 static void __bt_hdp_internal_remove_filter(void)
1024 ret_if(g_hdp_dus_conn == NULL);
1026 dbus_connection_remove_filter(g_hdp_dus_conn,
1027 __bt_hdp_internal_event_filter, NULL);
1029 g_hdp_dus_conn = NULL; /*should not unref here, bcz no ++reff */
1034 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
1044 BT_CHECK_ENABLED(return);
1046 if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
1047 BT_ERR("Invalid arguments..\n");
1048 return BLUETOOTH_ERROR_INVALID_PARAM;
1051 switch (privilege_token) {
1053 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
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;
1062 /* Just break - It is not related with permission error */
1066 /* Already have a privilege */
1069 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1071 /* Invalid privilge token value */
1072 return BLUETOOTH_ERROR_INTERNAL;
1075 while (wbytes < size) {
1076 written = write(channel_id, buffer + wbytes, size - wbytes);
1078 BT_ERR("write failed..\n");
1079 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1084 return BLUETOOTH_ERROR_NONE;
1087 static void __bt_hdp_connect_request_cb(GDBusProxy *hdp_proxy,
1088 GAsyncResult *res, gpointer user_data)
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;
1097 reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1099 g_object_unref(hdp_proxy);
1103 BT_ERR("HDP connection Dbus Call Error: %s\n", err->message);
1104 g_clear_error(&err);
1107 user_info = _bt_get_user_data(BT_COMMON);
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);
1115 g_variant_get(reply, "(&o)", &obj_connect_path);
1117 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
1118 user_info = _bt_get_user_data(BT_COMMON);
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);
1129 g_variant_unref(reply);
1131 g_free((void *)conn_ind->app_handle);
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)
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;
1151 BT_CHECK_ENABLED(return);
1152 BT_CHECK_PARAMETER(app_handle, return);
1153 BT_CHECK_PARAMETER(device_address, return);
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;
1161 if (channel_type == HDP_QOS_RELIABLE) {
1163 } else if (channel_type == HDP_QOS_STREAMING) {
1165 } else if (channel_type == HDP_QOS_ANY) {
1168 BT_ERR("Invalid channel_type %d", channel_type);
1169 return BLUETOOTH_ERROR_ACCESS_DENIED;
1172 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1175 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1176 g_clear_error(&err);
1177 return BLUETOOTH_ERROR_INTERNAL;
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;
1188 _bt_convert_addr_type_to_string(address,
1189 (unsigned char *)device_address->addr);
1191 BT_DBG("create conection to %s", address);
1193 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1195 if (dev_path == NULL) {
1196 g_object_unref(conn);
1197 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1200 g_strdelimit(dev_path, ":", '_');
1202 BT_DBG("path: %s", dev_path);
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,
1208 g_object_unref(conn);
1210 if (hdp_proxy == NULL) {
1211 BT_ERR("Failed to get the HDP server proxy\n");
1213 return BLUETOOTH_ERROR_NOT_PAIRED;
1216 BT_DBG("app path %s\n", app_handle);
1218 param = g_new0(bt_hdp_connected_t, 1);
1219 param->app_handle = g_strdup(app_handle);
1220 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1221 param->type = channel_type;
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,
1231 return BLUETOOTH_ERROR_NONE;
1235 static void __bt_hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
1236 GAsyncResult *res, gpointer user_data)
1239 bt_hdp_disconnected_t *disconn_ind = user_data;
1240 bt_user_info_t *user_info;
1241 GVariant *reply = NULL;
1243 reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1244 g_object_unref(hdp_proxy);
1246 user_info = _bt_get_user_data(BT_COMMON);
1247 if (user_info == NULL || user_info->cb == NULL) {
1248 g_free(disconn_ind);
1250 g_clear_error(&err);
1253 g_variant_unref(reply);
1259 BT_ERR("HDP disconnection Dbus Call Error: %s\n",
1261 g_clear_error(&err);
1264 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1265 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1266 user_info->cb, user_info->user_data);
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);
1275 g_free(disconn_ind);
1279 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1280 const bluetooth_device_address_t *device_address)
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;
1292 BT_CHECK_ENABLED(return);
1293 BT_CHECK_PARAMETER(device_address, return);
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;
1301 hdp_obj_info_t *info =
1302 __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1304 BT_ERR("*** Could not locate the list for %d*****\n",
1306 return BLUETOOTH_ERROR_INVALID_PARAM;
1309 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1312 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1313 g_clear_error(&err);
1314 return BLUETOOTH_ERROR_INTERNAL;
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;
1325 _bt_convert_addr_type_to_string(address,
1326 (unsigned char *)device_address->addr);
1328 BT_DBG("create conection to %s\n", address);
1330 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1332 if (dev_path == NULL) {
1333 g_object_unref(conn);
1334 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1337 g_strdelimit(dev_path, ":", '_');
1339 BT_DBG("path %s\n", dev_path);
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,
1346 g_object_unref(conn);
1348 if (hdp_proxy == NULL) {
1349 BT_ERR("Failed to get the HDP proxy\n");
1351 return BLUETOOTH_ERROR_NOT_PAIRED;
1354 param = g_new0(bt_hdp_disconnected_t, 1);
1355 param->channel_id = channel_id;
1356 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
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,
1366 return BLUETOOTH_ERROR_NONE;