2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <dbus/dbus.h>
23 #include "bluetooth-api.h"
24 #include "bt-common.h"
25 #include "bt-internal-types.h"
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"
32 gboolean interface_exist = FALSE;
35 char *obj_channel_path;
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
51 static int privilege_token;
54 /**********************************************************************
55 * Static Functions declaration *
56 ***********************************************************************/
57 static int __bt_hdp_internal_create_application(unsigned int data_type,
59 bt_hdp_qos_type_t channel_type,
62 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
66 static void __bt_hdp_internal_handle_connect(DBusMessage *msg);
68 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg);
70 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg);
72 static int __bt_hdp_internal_add_filter(void);
74 static int __bt_hdp_internal_acquire_fd(const char *path);
76 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path);
78 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
82 static int __bt_hdp_internal_destroy_application(const char *app_handle);
84 static void __bt_hdp_internal_remove_filter(void);
86 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle);
88 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd);
90 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path);
93 static DBusConnection *g_hdp_dus_conn;
95 static GSList *g_app_list = NULL;
97 /**********************************************************************
98 * Health device APIs (HDP) *
99 ***********************************************************************/
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,
106 int result = BLUETOOTH_ERROR_NONE;
110 BT_CHECK_ENABLED(return);
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;
118 result = __bt_hdp_internal_create_application(data_type, role,
119 channel_type, app_handle);
124 static void __bt_hdp_obj_info_free(hdp_obj_info_t *info)
127 g_source_remove(info->watch_id);
129 g_free(info->obj_channel_path);
134 static int __bt_hdp_internal_create_application(unsigned int data_type,
136 bt_hdp_qos_type_t channel_type,
142 const char *key_type;
144 hdp_app_list_t *list;
146 DBusMessageIter iter;
147 DBusMessageIter array_iter;
148 DBusMessageIter entry;
149 DBusMessageIter variant;
151 DBusConnection *conn;
152 int ret = BLUETOOTH_ERROR_NONE;
156 conn = _bt_get_system_conn();
157 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
159 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
160 BLUEZ_HDP_MANAGER_INTERFACE,
161 "CreateApplication");
163 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
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,
171 key_type = "DataType";
172 value = (guint16) data_type;
173 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_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);
185 svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
186 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_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);
195 key_type = "Description";
196 svalue = "Health Device";
197 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_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);
206 if (role == HDP_ROLE_SOURCE) {
207 key_type = "ChannelType";
208 if (channel_type == HDP_QOS_RELIABLE)
210 else if (channel_type == HDP_QOS_STREAMING)
211 svalue = "streaming";
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,
217 dbus_message_iter_open_container(&entry,
218 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING,
220 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
222 dbus_message_iter_close_container(&entry, &variant);
223 dbus_message_iter_close_container(&array_iter, &entry);
226 dbus_message_iter_close_container(&iter, &array_iter);
228 dbus_error_init(&err);
230 reply = dbus_connection_send_with_reply_and_block(
233 dbus_message_unref(msg);
236 BT_ERR(" HDP:dbus Can't create application");
238 if (dbus_error_is_set(&err)) {
239 BT_ERR("%s", err.message);
241 if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
242 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
244 ret = BLUETOOTH_ERROR_INTERNAL;
246 dbus_error_free(&err);
251 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
252 &app_path, DBUS_TYPE_INVALID)) {
254 BT_ERR(" HDP: Can't get reply arguments from Dbus");
256 if (dbus_error_is_set(&err)) {
257 BT_ERR("Error: %s", err.message);
258 dbus_error_free(&err);
261 dbus_message_unref(reply);
262 return BLUETOOTH_ERROR_INTERNAL;
265 dbus_message_unref(reply);
267 BT_DBG("Created health application: %s", (char *)app_path);
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);
274 BT_DBG("app_handle: %s", (char *)list->app_handle);
276 ret = __bt_hdp_internal_add_filter();
278 if (ret != BLUETOOTH_ERROR_NONE) {
279 BT_ERR("Funtion failed");
283 return BLUETOOTH_ERROR_NONE;
286 static int __bt_hdp_internal_add_filter(void)
288 DBusError dbus_error;
292 /*Single process only one signal registration is required */
293 if (g_hdp_dus_conn) {
294 BT_ERR("g_hdp_dus_conn already exist");
298 /* Add the filter for HDP client functions */
299 dbus_error_init(&dbus_error);
301 g_hdp_dus_conn = _bt_get_system_conn();
302 retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
304 dbus_connection_add_filter(g_hdp_dus_conn,
305 __bt_hdp_internal_event_filter, NULL, NULL);
307 dbus_bus_add_match(g_hdp_dus_conn,
308 "type='signal',interface=" BLUEZ_HDP_DEVICE_INTERFACE,
311 dbus_bus_add_match(g_hdp_dus_conn,
312 "type='signal',interface=" BT_MANAGER_INTERFACE,
315 dbus_bus_add_match(g_hdp_dus_conn,
316 "type='signal',interface=" BT_PROPERTIES_INTERFACE,
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;
328 return BLUETOOTH_ERROR_NONE;
332 static void __bt_hdp_internal_handle_connected(DBusMessage *msg);
335 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
336 DBusMessage *msg, void *data)
338 const char *path = dbus_message_get_path(msg);
340 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
341 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
343 BT_DBG("Path = %s\n", path);
345 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
347 if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
349 __bt_hdp_internal_handle_connect(msg);
350 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
352 __bt_hdp_internal_handle_disconnect(msg);
353 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
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");
369 __bt_hdp_internal_handle_connected(msg);
372 return DBUS_HANDLER_RESULT_HANDLED;
375 static void __bt_hdp_internal_handle_connected(DBusMessage *msg)
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;
383 if (dbus_message_iter_init(msg, &iter) == FALSE)
386 dbus_message_iter_get_basic(&iter, &path);
388 BT_DBG("object path: %s", path);
390 if(!g_strcmp0(path, "org.bluez.HealthDevice1")) {
391 dbus_message_iter_next(&iter);
393 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
396 dbus_message_iter_recurse(&iter, &dict);
397 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
398 const char *interface;
400 dbus_message_iter_recurse(&dict, &entry);
402 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
405 dbus_message_iter_get_basic(&entry, &interface);
406 dbus_message_iter_next(&entry);
407 dbus_message_iter_recurse(&entry, &var);
409 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_OBJECT_PATH)
412 dbus_message_iter_get_basic(&var, &obj_channel_path);
414 BT_DBG("interface: %s", interface);
415 BT_DBG("object_path: %s", obj_channel_path);
417 dbus_message_iter_next(&dict);
420 BT_INFO("Channel connected, Path = %s", obj_channel_path);
422 user_info = _bt_get_user_data(BT_COMMON);
423 if (user_info == NULL || user_info->cb == NULL)
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);
435 static void __bt_hdp_internal_handle_connect(DBusMessage *msg)
437 const char *path = dbus_message_get_path(msg);
438 const char *obj_channel_path;
439 bt_user_info_t *user_info;
442 BT_INFO("+********Signal - ChannelConnected******\n\n");
443 BT_DBG("Path = %s", path);
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");
451 BT_INFO("Channel connected, Path = %s", obj_channel_path);
453 user_info = _bt_get_user_data(BT_COMMON);
454 if (user_info == NULL || user_info->cb == NULL)
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);
463 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
464 BLUETOOTH_ERROR_NONE, NULL,
465 user_info->cb, user_info->user_data);
471 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg)
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;
481 BT_INFO("+********Signal - ChannelDeleted ******\n\n");
482 BT_DBG("Path = %s", path);
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");
490 BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
492 info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
494 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
498 /*Since bluetoothd is not sending the ChannelDeleted signal */
499 _bt_device_path_to_address(path, address);
501 _bt_convert_addr_string_to_type(device_addr.addr, address);
503 dis_ind.channel_id = info->fd;
504 dis_ind.device_address = device_addr;
506 user_info = _bt_get_user_data(BT_COMMON);
509 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
510 BLUETOOTH_ERROR_NONE, &dis_ind,
511 user_info->cb, user_info->user_data);
514 BT_DBG(" Removed connection from list\n");
516 __bt_hdp_obj_info_free(info);
520 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg)
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;
528 BT_DBG("+*******Signal - PropertyChanged*******\n");
529 BT_DBG("Path = %s", path);
531 dbus_message_iter_init(msg, &item_iter);
533 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
534 BT_ERR("This is bad format dbus");
538 dbus_message_iter_get_basic(&item_iter, &property);
540 ret_if(property == NULL);
542 BT_DBG("Property (%s)\n", property);
544 if (0 == g_strcmp0(property, "MainChannel")) {
545 BT_INFO("Property MainChannel received");
547 dbus_message_iter_next(&item_iter);
549 dbus_message_iter_recurse(&item_iter, &value_iter);
551 dbus_message_iter_get_basic(&value_iter,
552 &obj_main_channel_path);
553 BT_DBG("Path = %s", path);
555 BT_DBG("Main Channel Path = %s", obj_main_channel_path);
557 BT_DBG("-*************\n");
560 static int __bt_hdp_internal_acquire_fd(const char *path)
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;;
573 DBusConnection *conn;
574 bt_hdp_connected_t conn_ind;
577 bt_user_info_t *user_info;
582 conn = _bt_get_system_conn();
583 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
585 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
586 BLUEZ_HDP_CHANNEL_INTERFACE,
589 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
591 dbus_error_init(&err);
593 reply = dbus_connection_send_with_reply_and_block(conn, msg,
596 dbus_message_unref(msg);
599 BT_ERR(" HDP:****** dbus Can't create application ****");
601 if (dbus_error_is_set(&err)) {
602 BT_ERR("%s", err.message);
603 dbus_error_free(&err);
606 return BLUETOOTH_ERROR_INTERNAL;
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");
613 if (dbus_error_is_set(&err)) {
614 BT_ERR("%s", err.message);
615 dbus_error_free(&err);
620 dbus_message_unref(reply);
622 BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
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,
631 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
633 dbus_error_init(&err);
635 reply = dbus_connection_send_with_reply_and_block(conn, msg,
638 dbus_message_unref(msg);
641 BT_ERR(" HDP:dbus Can't get the reply");
643 if (dbus_error_is_set(&err)) {
644 BT_ERR("%s", err.message);
645 dbus_error_free(&err);
648 return BLUETOOTH_ERROR_INTERNAL;
650 dbus_message_iter_init(reply, &reply_iter);
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");
657 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
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);
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) !=
674 dbus_message_iter_get_basic(&dict_entry_val, &type_qos);
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)
683 dbus_message_iter_get_basic(&dict_entry_val, &device);
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)
692 dbus_message_iter_get_basic(&dict_entry_val,
695 dbus_message_iter_next(&reply_iter_entry);
698 BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
699 type_qos, device, app_handle);
701 if (NULL == type_qos || NULL == app_handle) {
702 BT_ERR("Pasing failed\n");
706 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
708 /*Only process register with app handle receive the Connected event */
710 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
714 hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
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);
720 _bt_device_path_to_address(path, address);
722 _bt_convert_addr_string_to_type(device_addr.addr, address);
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;
730 BT_DBG("Going to give callback\n");
732 user_info = _bt_get_user_data(BT_COMMON);
735 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
736 BLUETOOTH_ERROR_NONE, &conn_ind,
737 user_info->cb, user_info->user_data);
740 dbus_message_unref(reply);
742 BT_DBG("Updated fd in the list*\n");
745 return BLUETOOTH_ERROR_NONE;
747 dbus_message_unref(reply);
748 return BLUETOOTH_ERROR_INTERNAL;
751 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
758 gio = g_io_channel_unix_new(file_desc);
760 g_io_channel_set_close_on_unref(gio, TRUE);
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);
769 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
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;
777 BT_INFO("******** Socket Error ******\n");
779 info = __bt_hdp_internal_gslist_obj_find_using_path(path);
780 ret_if(info == NULL);
782 /*Since bluetoothd is not sending the ChannelDeleted signal */
783 _bt_device_path_to_address(path, address);
785 _bt_convert_addr_string_to_type(device_addr.addr, address);
787 dis_ind.channel_id = sk;
788 dis_ind.device_address = device_addr;
790 user_info = _bt_get_user_data(BT_COMMON);
793 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
794 BLUETOOTH_ERROR_NONE, &dis_ind,
795 user_info->cb, user_info->user_data);
798 BT_DBG(" Removed connection from list\n");
800 __bt_hdp_obj_info_free(info);
803 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
804 GIOCondition cond, gpointer data)
806 char buff[HDP_BUFFER_SIZE] = { 0, };
809 bt_hdp_data_ind_t data_ind = { 0, };
810 const char *path = (const char *)data;
811 bt_user_info_t *user_info;
815 sk = g_io_channel_unix_get_fd(gio);
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);
823 act_read = recv(sk, (void *)buff, sizeof(buff), 0);
826 BT_DBG("Received data of %d\n", act_read);
828 BT_ERR("Read failed.....\n");
829 __bt_hdp_internal_handle_disconnect_cb(sk, path);
833 data_ind.channel_id = sk;
834 data_ind.buffer = buff;
835 data_ind.size = act_read;
837 user_info = _bt_get_user_data(BT_COMMON);
840 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
841 BLUETOOTH_ERROR_NONE, &data_ind,
842 user_info->cb, user_info->user_data);
850 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
854 BT_CHECK_ENABLED(return);
855 BT_CHECK_PARAMETER(app_handle, return);
857 return __bt_hdp_internal_destroy_application(app_handle);
860 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
864 retv_if(g_app_list == NULL, NULL);
866 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
868 for (l = g_app_list; l != NULL; l = l->next) {
869 hdp_app_list_t *list = l->data;
872 BT_DBG("found app_handle=%s\n", (char *)list->app_handle);
873 if (0 == g_strcmp0((char *)list->app_handle,
881 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
886 retv_if(g_app_list == NULL, NULL);
888 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
890 for (l = g_app_list; l != NULL; l = l->next) {
891 hdp_app_list_t *list = l->data;
895 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
896 hdp_obj_info_t *info = iter->data;
907 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
911 hdp_obj_info_t *info = NULL;
913 retv_if(g_app_list == NULL, NULL);
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;
921 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
926 if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
927 list->obj_info = g_slist_remove(list->obj_info, info);
935 static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data)
937 const char *app_handle;
938 hdp_app_list_t *list = NULL;
939 app_handle = (const char *)data;
943 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
945 BT_ERR("**** list not found for %s ******\n", app_handle);
949 g_app_list = g_slist_remove(g_app_list, list);
951 g_free(list->app_handle);
952 g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
955 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
957 if (0 == g_slist_length(g_app_list))
958 __bt_hdp_internal_remove_filter();
963 static int __bt_hdp_internal_destroy_application(const char *app_handle)
968 DBusConnection *conn;
969 int result = BLUETOOTH_ERROR_NONE;
971 conn = _bt_get_system_conn();
972 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
974 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
975 BLUEZ_HDP_MANAGER_INTERFACE, "DestroyApplication");
977 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
979 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &app_handle,
982 dbus_error_init(&err);
984 reply = dbus_connection_send_with_reply_and_block(conn, msg,
986 dbus_message_unref(msg);
988 BT_ERR(" HDP:dbus Can't Destroy application");
990 if (dbus_error_is_set(&err)) {
991 BT_ERR("%s", err.message);
993 if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
994 result = BLUETOOTH_ERROR_ACCESS_DENIED;
996 result = BLUETOOTH_ERROR_INTERNAL;
998 dbus_error_free(&err);
1004 dbus_message_unref(reply);
1006 BT_DBG("Destroyed health application: %s", (char *)app_handle);
1008 g_idle_add(__bt_hdp_internal_destroy_application_cb,
1009 (gpointer)app_handle);
1011 return BLUETOOTH_ERROR_NONE;
1014 static void __bt_hdp_internal_remove_filter(void)
1018 ret_if(g_hdp_dus_conn == NULL);
1020 dbus_connection_remove_filter(g_hdp_dus_conn,
1021 __bt_hdp_internal_event_filter, NULL);
1023 g_hdp_dus_conn = NULL; /*should not unref here, bcz no ++reff */
1028 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
1038 BT_CHECK_ENABLED(return);
1040 if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
1041 BT_ERR("Invalid arguments..\n");
1042 return BLUETOOTH_ERROR_INVALID_PARAM;
1045 switch (privilege_token) {
1047 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
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;
1056 /* Just break - It is not related with permission error */
1060 /* Already have a privilege */
1063 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1065 /* Invalid privilge token value */
1066 return BLUETOOTH_ERROR_INTERNAL;
1069 while (wbytes < size) {
1070 written = write(channel_id, buffer + wbytes, size - wbytes);
1072 BT_ERR("write failed..\n");
1073 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1078 return BLUETOOTH_ERROR_NONE;
1081 static void __bt_hdp_connect_request_cb(GDBusProxy *hdp_proxy,
1082 GAsyncResult *res, gpointer user_data)
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;
1091 reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1093 g_object_unref(hdp_proxy);
1097 BT_ERR("HDP connection Dbus Call Error: %s\n", err->message);
1098 g_clear_error(&err);
1101 user_info = _bt_get_user_data(BT_COMMON);
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);
1109 g_variant_get(reply, "(&o)", &obj_connect_path);
1111 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
1112 user_info = _bt_get_user_data(BT_COMMON);
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);
1123 g_variant_unref(reply);
1125 g_free((void *)conn_ind->app_handle);
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)
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;
1145 BT_CHECK_ENABLED(return);
1146 BT_CHECK_PARAMETER(app_handle, return);
1147 BT_CHECK_PARAMETER(device_address, return);
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;
1155 if (channel_type == HDP_QOS_RELIABLE) {
1157 } else if (channel_type == HDP_QOS_STREAMING) {
1159 } else if (channel_type == HDP_QOS_ANY) {
1162 BT_ERR("Invalid channel_type %d", channel_type);
1163 return BLUETOOTH_ERROR_ACCESS_DENIED;
1166 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1169 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1170 g_clear_error(&err);
1171 return BLUETOOTH_ERROR_INTERNAL;
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;
1182 _bt_convert_addr_type_to_string(address,
1183 (unsigned char *)device_address->addr);
1185 BT_DBG("create conection to %s", address);
1187 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1189 if (dev_path == NULL) {
1190 g_object_unref(conn);
1191 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1194 g_strdelimit(dev_path, ":", '_');
1196 BT_DBG("path: %s", dev_path);
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,
1202 g_object_unref(conn);
1204 if (hdp_proxy == NULL) {
1205 BT_ERR("Failed to get the HDP server proxy\n");
1207 return BLUETOOTH_ERROR_NOT_PAIRED;
1210 BT_DBG("app path %s\n", app_handle);
1212 param = g_new0(bt_hdp_connected_t, 1);
1213 param->app_handle = g_strdup(app_handle);
1214 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1215 param->type = channel_type;
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,
1225 return BLUETOOTH_ERROR_NONE;
1229 static void __bt_hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
1230 GAsyncResult *res, gpointer user_data)
1233 bt_hdp_disconnected_t *disconn_ind = user_data;
1234 bt_user_info_t *user_info;
1235 GVariant *reply = NULL;
1237 reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1238 g_object_unref(hdp_proxy);
1240 user_info = _bt_get_user_data(BT_COMMON);
1241 if (user_info == NULL || user_info->cb == NULL) {
1242 g_free(disconn_ind);
1244 g_clear_error(&err);
1247 g_variant_unref(reply);
1253 BT_ERR("HDP disconnection Dbus Call Error: %s\n",
1255 g_clear_error(&err);
1258 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1259 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1260 user_info->cb, user_info->user_data);
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);
1269 g_free(disconn_ind);
1273 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1274 const bluetooth_device_address_t *device_address)
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;
1286 BT_CHECK_ENABLED(return);
1287 BT_CHECK_PARAMETER(device_address, return);
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;
1295 hdp_obj_info_t *info =
1296 __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1298 BT_ERR("*** Could not locate the list for %d*****\n",
1300 return BLUETOOTH_ERROR_INVALID_PARAM;
1303 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1306 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1307 g_clear_error(&err);
1308 return BLUETOOTH_ERROR_INTERNAL;
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;
1319 _bt_convert_addr_type_to_string(address,
1320 (unsigned char *)device_address->addr);
1322 BT_DBG("create conection to %s\n", address);
1324 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1326 if (dev_path == NULL) {
1327 g_object_unref(conn);
1328 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1331 g_strdelimit(dev_path, ":", '_');
1333 BT_DBG("path %s\n", dev_path);
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,
1340 g_object_unref(conn);
1342 if (hdp_proxy == NULL) {
1343 BT_ERR("Failed to get the HDP proxy\n");
1345 return BLUETOOTH_ERROR_NOT_PAIRED;
1348 param = g_new0(bt_hdp_disconnected_t, 1);
1349 param->channel_id = channel_id;
1350 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
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,
1360 return BLUETOOTH_ERROR_NONE;