4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <dbus/dbus.h>
25 #include "bluetooth-api.h"
26 #include "bt-common.h"
27 #include "bt-internal-types.h"
29 #define HDP_BUFFER_SIZE 1024
30 #define BLUEZ_HDP_MANAGER_INTERFACE "org.bluez.HealthManager"
31 #define BLUEZ_HDP_DEVICE_INTERFACE "org.bluez.HealthDevice"
32 #define BLUEZ_HDP_CHANNEL_INTERFACE "org.bluez.HealthChannel"
35 char *obj_channel_path;
45 /**********************************************************************
46 * Static Functions declaration *
47 ***********************************************************************/
48 static int __bt_hdp_internal_create_application(unsigned int data_type,
50 bt_hdp_qos_type_t channel_type,
53 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
57 static void __bt_hdp_internal_handle_connect(DBusMessage *msg);
59 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg);
61 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg);
63 static int __bt_hdp_internal_add_filter(void);
65 static int __bt_hdp_internal_acquire_fd(const char *path);
67 static void __bt_hdp_internal_watch_fd(int file_desc, const char *path);
69 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
73 static int __bt_hdp_internal_destroy_application(const char *app_handle);
75 static void __bt_hdp_internal_remove_filter(void);
77 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle);
79 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd);
81 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path);
84 static DBusConnection *g_hdp_dus_conn;
86 static GSList *g_app_list = NULL;
88 /**********************************************************************
89 * Health device APIs (HDP) *
90 ***********************************************************************/
92 BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type,
93 bt_hdp_role_type_t role,
94 bt_hdp_qos_type_t channel_type,
97 int result = BLUETOOTH_ERROR_NONE;
103 /*For source role is mandatory */
104 if (role == HDP_ROLE_SOURCE && channel_type == HDP_QOS_ANY) {
105 BT_DBG("For source, type is mandatory - Reliable/Streaming");
106 return BLUETOOTH_ERROR_INVALID_PARAM;
109 result = __bt_hdp_internal_create_application(data_type, role,
110 channel_type, app_handle);
115 static void __bt_hdp_obj_info_free(hdp_obj_info_t *info)
119 g_free(info->obj_channel_path);
124 static int __bt_hdp_internal_create_application(unsigned int data_type,
126 bt_hdp_qos_type_t channel_type,
132 const char *key_type;
134 hdp_app_list_t *list;
136 DBusMessageIter iter;
137 DBusMessageIter array_iter;
138 DBusMessageIter entry;
139 DBusMessageIter variant;
141 DBusConnection *conn;
142 int ret = BLUETOOTH_ERROR_NONE;
146 conn = _bt_get_system_conn();
147 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
149 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
150 BLUEZ_HDP_MANAGER_INTERFACE,
151 "CreateApplication");
153 retv_if(msg == NULL, BLUETOOTH_ERROR_NO_RESOURCES);
155 dbus_message_iter_init_append(msg, &iter);
156 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
157 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING
158 DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
161 key_type = "DataType";
162 value = (guint16) data_type;
163 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
165 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
166 dbus_message_iter_open_container(&entry,
167 DBUS_TYPE_VARIANT, DBUS_TYPE_UINT16_AS_STRING, &variant);
168 dbus_message_iter_append_basic(&variant, DBUS_TYPE_UINT16, &value);
169 dbus_message_iter_close_container(&entry, &variant);
170 dbus_message_iter_close_container(&array_iter, &entry);
175 svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
176 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
178 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
179 dbus_message_iter_open_container(&entry,
180 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
181 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue);
182 dbus_message_iter_close_container(&entry, &variant);
183 dbus_message_iter_close_container(&array_iter, &entry);
185 key_type = "Description";
186 svalue = "Health Device";
187 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
189 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
190 dbus_message_iter_open_container(&entry,
191 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
192 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue);
193 dbus_message_iter_close_container(&entry, &variant);
194 dbus_message_iter_close_container(&array_iter, &entry);
196 if (role == HDP_ROLE_SOURCE) {
197 key_type = "ChannelType";
198 if (channel_type == HDP_QOS_RELIABLE)
200 else if (channel_type == HDP_QOS_STREAMING)
201 svalue = "Streaming";
203 dbus_message_iter_open_container(&array_iter,
204 DBUS_TYPE_DICT_ENTRY, NULL, &entry);
205 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
207 dbus_message_iter_open_container(&entry,
208 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING,
210 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
212 dbus_message_iter_close_container(&entry, &variant);
213 dbus_message_iter_close_container(&array_iter, &entry);
216 dbus_message_iter_close_container(&iter, &array_iter);
218 dbus_error_init(&err);
220 reply = dbus_connection_send_with_reply_and_block(
223 dbus_message_unref(msg);
226 BT_ERR(" HDP:dbus Can't create application");
228 if (dbus_error_is_set(&err)) {
229 BT_ERR("%s", err.message);
230 dbus_error_free(&err);
232 return BLUETOOTH_ERROR_INTERNAL;
235 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
236 &app_path, DBUS_TYPE_INVALID)) {
238 BT_ERR(" HDP: Can't get reply arguments from Dbus");
240 if (dbus_error_is_set(&err)) {
241 BT_ERR("Error: %s", err.message);
242 dbus_error_free(&err);
245 dbus_message_unref(reply);
246 return BLUETOOTH_ERROR_INTERNAL;
249 dbus_message_unref(reply);
251 BT_DBG("Created health application: %s", (char *)app_path);
253 ret = __bt_hdp_internal_add_filter();
255 if (ret != BLUETOOTH_ERROR_NONE) {
256 BT_ERR("Funtion failed");
260 list = g_new0(hdp_app_list_t, 1);
261 list->app_handle = (void *)g_strdup(app_path);
262 *app_handle = list->app_handle;
264 g_app_list = g_slist_append(g_app_list, list);
266 return BLUETOOTH_ERROR_NONE;
269 static int __bt_hdp_internal_add_filter(void)
271 DBusError dbus_error;
275 /*Single process only one signal registration is required */
276 if (g_hdp_dus_conn) {
277 BT_ERR("g_hdp_dus_conn already exist");
281 /* Add the filter for HDP client functions */
282 dbus_error_init(&dbus_error);
284 g_hdp_dus_conn = _bt_get_system_conn();
285 retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
287 dbus_connection_add_filter(g_hdp_dus_conn,
288 __bt_hdp_internal_event_filter, NULL, NULL);
290 dbus_bus_add_match(g_hdp_dus_conn,
291 "type='signal',interface=" BLUEZ_HDP_DEVICE_INTERFACE,
294 if (dbus_error_is_set(&dbus_error)) {
295 BT_ERR("Fail to add dbus filter signal\n");
296 dbus_error_free(&dbus_error);
297 g_hdp_dus_conn = NULL;
298 return BLUETOOTH_ERROR_INTERNAL;
303 return BLUETOOTH_ERROR_NONE;
307 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
308 DBusMessage *msg, void *data)
310 const char *path = dbus_message_get_path(msg);
312 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
313 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
315 BT_DBG("Path = %s\n", path);
316 if (path == NULL || g_strcmp0(path, "/") == 0)
317 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
319 if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
321 __bt_hdp_internal_handle_connect(msg);
323 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
325 __bt_hdp_internal_handle_disconnect(msg);
327 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
329 __bt_hdp_internal_handle_property_changed(msg);
331 return DBUS_HANDLER_RESULT_HANDLED;
334 static void __bt_hdp_internal_handle_connect(DBusMessage *msg)
336 const char *path = dbus_message_get_path(msg);
337 const char *obj_channel_path;
338 bt_user_info_t *user_info;
339 bt_hdp_connected_t conn_ind;
342 BT_DBG("+********Signal - ChannelConnected******\n\n");
343 BT_DBG("Path = %s", path);
345 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
346 &obj_channel_path, DBUS_TYPE_INVALID)) {
347 BT_ERR("Unexpected parameters in ChannelConnected signal");
351 BT_DBG("Channel connected, Path = %s", obj_channel_path);
353 ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
354 if (ret != BLUETOOTH_ERROR_NONE) {
355 user_info = _bt_get_user_data(BT_COMMON);
357 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
358 BLUETOOTH_ERROR_CONNECTION_ERROR, &conn_ind,
359 user_info->cb, user_info->user_data);
366 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg)
368 const char *path = dbus_message_get_path(msg);
369 const char *obj_channel_path;
370 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
371 bluetooth_device_address_t device_addr = { {0} };
372 bt_hdp_disconnected_t dis_ind;
373 hdp_obj_info_t *info;
374 bt_user_info_t *user_info;
376 BT_DBG("+********Signal - ChannelDeleted ******\n\n");
377 BT_DBG("Path = %s", path);
379 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
380 &obj_channel_path, DBUS_TYPE_INVALID)) {
381 BT_ERR("Unexpected parameters in ChannelDeleted signal");
385 BT_DBG("Channel Deleted, Path = %s", obj_channel_path);
387 info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
389 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
393 /*Since bluetoothd is not sending the ChannelDeleted signal */
394 _bt_device_path_to_address(path, address);
396 _bt_convert_addr_string_to_type(device_addr.addr, address);
398 dis_ind.channel_id = info->fd;
399 dis_ind.device_address = device_addr;
401 user_info = _bt_get_user_data(BT_COMMON);
404 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
405 BLUETOOTH_ERROR_NONE, &dis_ind,
406 user_info->cb, user_info->user_data);
409 BT_DBG(" Removed connection from list\n");
411 __bt_hdp_obj_info_free(info);
415 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg)
417 const char *path = dbus_message_get_path(msg);
418 DBusMessageIter item_iter;
419 DBusMessageIter value_iter;
420 const char *property;
421 const char *obj_main_channel_path;
423 BT_DBG("+*******Signal - PropertyChanged*******\n");
424 BT_DBG("Path = %s", path);
426 dbus_message_iter_init(msg, &item_iter);
428 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
429 BT_DBG("This is bad format dbus");
433 dbus_message_iter_get_basic(&item_iter, &property);
435 ret_if(property == NULL);
437 BT_DBG("Property (%s)\n", property);
439 if (0 == g_strcmp0(property, "MainChannel")) {
440 BT_DBG("Property MainChannel received");
442 dbus_message_iter_next(&item_iter);
444 dbus_message_iter_recurse(&item_iter, &value_iter);
446 dbus_message_iter_get_basic(&value_iter,
447 &obj_main_channel_path);
448 BT_DBG("Path = %s", path);
450 BT_DBG("Main Channel Path = %s", obj_main_channel_path);
452 BT_DBG("-*************\n");
455 static int __bt_hdp_internal_acquire_fd(const char *path)
457 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
458 bluetooth_device_address_t device_addr = { {0} };
459 DBusMessageIter reply_iter;
460 DBusMessageIter reply_iter_entry;
461 const char *property;
462 char *type_qos = NULL;
463 char *device = NULL;;
464 char *app_handle = NULL;;
465 hdp_app_list_t *list = NULL;;
468 DBusConnection *conn;
469 bt_hdp_connected_t conn_ind;
472 bt_user_info_t *user_info;
476 conn = _bt_get_system_conn();
477 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
479 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
480 BLUEZ_HDP_CHANNEL_INTERFACE,
483 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
485 dbus_error_init(&err);
487 reply = dbus_connection_send_with_reply_and_block(conn, msg,
490 dbus_message_unref(msg);
493 BT_ERR(" HDP:****** dbus Can't create application ****");
495 if (dbus_error_is_set(&err)) {
496 BT_ERR("%s", err.message);
497 dbus_error_free(&err);
500 return BLUETOOTH_ERROR_INTERNAL;
503 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd,
504 DBUS_TYPE_INVALID)) {
505 BT_ERR(" HDP:dbus Can't get reply arguments");
507 if (dbus_error_is_set(&err)) {
508 BT_ERR("%s", err.message);
509 dbus_error_free(&err);
514 dbus_message_unref(reply);
516 BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
518 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
519 BLUEZ_HDP_CHANNEL_INTERFACE, "GetProperties");
521 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
523 dbus_error_init(&err);
525 reply = dbus_connection_send_with_reply_and_block(conn, msg,
528 dbus_message_unref(msg);
531 BT_ERR(" HDP:dbus Can't get the reply");
533 if (dbus_error_is_set(&err)) {
534 BT_ERR("%s", err.message);
535 dbus_error_free(&err);
538 return BLUETOOTH_ERROR_INTERNAL;
540 dbus_message_iter_init(reply, &reply_iter);
542 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
543 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
547 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
550 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
551 DBUS_TYPE_DICT_ENTRY) {
552 DBusMessageIter dict_entry, dict_entry_val;
553 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
554 dbus_message_iter_get_basic(&dict_entry, &property);
555 BT_DBG("String received = %s\n", property);
557 if (g_strcmp0("Type", property) == 0) {
558 dbus_message_iter_next(&dict_entry);
559 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
560 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
564 dbus_message_iter_get_basic(&dict_entry_val, &type_qos);
566 } else if (g_strcmp0("Device", property) == 0) {
567 dbus_message_iter_next(&dict_entry);
568 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
569 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
570 DBUS_TYPE_OBJECT_PATH)
573 dbus_message_iter_get_basic(&dict_entry_val, &device);
575 } else if (g_strcmp0("Application", property) == 0) {
576 dbus_message_iter_next(&dict_entry);
577 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
578 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
579 DBUS_TYPE_OBJECT_PATH)
582 dbus_message_iter_get_basic(&dict_entry_val,
585 dbus_message_iter_next(&reply_iter_entry);
588 BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
589 type_qos, device, app_handle);
591 if (NULL == type_qos || NULL == app_handle) {
592 BT_ERR("Pasing failed\n");
596 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
598 /*Only process register with app handle receive the Connected event */
600 BT_DBG("**** Could not locate the list for %s*****\n", app_handle);
604 hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
606 info->obj_channel_path = g_strdup(path);
607 list->obj_info = g_slist_append(list->obj_info, info);
609 __bt_hdp_internal_watch_fd(fd, info->obj_channel_path);
611 _bt_device_path_to_address(path, address);
613 _bt_convert_addr_string_to_type(device_addr.addr, address);
615 conn_ind.app_handle = app_handle;
616 conn_ind.channel_id = fd;
617 conn_ind.device_address = device_addr;
618 conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ?
619 HDP_QOS_RELIABLE : HDP_QOS_STREAMING;
621 BT_DBG("Going to give callback\n");
623 user_info = _bt_get_user_data(BT_COMMON);
626 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
627 BLUETOOTH_ERROR_NONE, &conn_ind,
628 user_info->cb, user_info->user_data);
631 dbus_message_unref(reply);
633 BT_DBG("Updated fd in the list*\n");
636 return BLUETOOTH_ERROR_NONE;
638 dbus_message_unref(reply);
639 return BLUETOOTH_ERROR_INTERNAL;
642 static void __bt_hdp_internal_watch_fd(int file_desc, const char *path)
648 gio = g_io_channel_unix_new(file_desc);
650 g_io_channel_set_close_on_unref(gio, TRUE);
652 g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
653 __bt_hdp_internal_data_received, (void *)path);
658 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
660 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
661 bluetooth_device_address_t device_addr = { {0} };
662 bt_hdp_disconnected_t dis_ind;
663 hdp_obj_info_t *info;
664 bt_user_info_t *user_info;
666 BT_DBG("******** Socket Error ******\n");
668 info = __bt_hdp_internal_gslist_obj_find_using_path(path);
669 ret_if(info == NULL);
671 /*Since bluetoothd is not sending the ChannelDeleted signal */
672 _bt_device_path_to_address(path, address);
674 _bt_convert_addr_string_to_type(device_addr.addr, address);
676 dis_ind.channel_id = sk;
677 dis_ind.device_address = device_addr;
679 user_info = _bt_get_user_data(BT_COMMON);
682 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
683 BLUETOOTH_ERROR_NONE, &dis_ind,
684 user_info->cb, user_info->user_data);
687 BT_DBG(" Removed connection from list\n");
689 __bt_hdp_obj_info_free(info);
692 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
693 GIOCondition cond, gpointer data)
695 char buff[HDP_BUFFER_SIZE] = { 0, };
698 bt_hdp_data_ind_t data_ind = { 0, };
699 const char *path = (const char *)data;
700 bt_user_info_t *user_info;
704 sk = g_io_channel_unix_get_fd(gio);
706 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
707 BT_DBG("GIOCondition %d.............path = %s\n", cond, path);
708 __bt_hdp_internal_handle_disconnect_cb(sk, path);
712 act_read = recv(sk, (void *)buff, sizeof(buff), 0);
715 BT_DBG("Received data of %d\n", act_read);
717 BT_DBG("Read failed.....\n");
721 data_ind.channel_id = sk;
722 data_ind.buffer = buff;
723 data_ind.size = act_read;
725 user_info = _bt_get_user_data(BT_COMMON);
728 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
729 BLUETOOTH_ERROR_NONE, &data_ind,
730 user_info->cb, user_info->user_data);
738 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
743 BT_CHECK_PARAMETER(app_handle);
745 return __bt_hdp_internal_destroy_application(app_handle);
748 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
752 retv_if(g_app_list == NULL, NULL);
754 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
756 for (l = g_app_list; l != NULL; l = l->next) {
757 hdp_app_list_t *list = l->data;
760 if (0 == g_strcmp0((char *)list->app_handle,
768 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
773 retv_if(g_app_list == NULL, NULL);
775 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
777 for (l = g_app_list; l != NULL; l = l->next) {
778 hdp_app_list_t *list = l->data;
782 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
783 hdp_obj_info_t *info = iter->data;
794 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
798 hdp_obj_info_t *info = NULL;
800 retv_if(g_app_list == NULL, NULL);
802 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
803 for (l = g_app_list; l != NULL; l = l->next) {
804 hdp_app_list_t *list = l->data;
808 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
813 if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
814 list->obj_info = g_slist_remove(list->obj_info, info);
822 static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data)
824 const char *app_handle;
825 hdp_app_list_t *list = NULL;
826 app_handle = (const char *)data;
830 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
832 BT_DBG("**** list not found for %s ******\n", app_handle);
836 g_app_list = g_slist_remove(g_app_list, list);
838 g_free(list->app_handle);
839 g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
842 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
844 if (0 == g_slist_length(g_app_list))
845 __bt_hdp_internal_remove_filter();
850 static int __bt_hdp_internal_destroy_application(const char *app_handle)
855 DBusConnection *conn;
857 conn = _bt_get_system_conn();
858 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
860 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
861 BLUEZ_HDP_MANAGER_INTERFACE, "DestroyApplication");
863 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
865 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &app_handle,
868 dbus_error_init(&err);
870 reply = dbus_connection_send_with_reply_and_block(conn, msg,
872 dbus_message_unref(msg);
874 BT_ERR(" HDP:dbus Can't Destroy application");
876 if (dbus_error_is_set(&err)) {
877 BT_ERR("%s", err.message);
878 dbus_error_free(&err);
881 return BLUETOOTH_ERROR_INTERNAL;
884 dbus_message_unref(reply);
886 BT_DBG("Destroyed health application: %s", (char *)app_handle);
888 g_idle_add(__bt_hdp_internal_destroy_application_cb,
889 (gpointer)app_handle);
891 return BLUETOOTH_ERROR_NONE;
894 static void __bt_hdp_internal_remove_filter(void)
898 ret_if(g_hdp_dus_conn == NULL);
900 dbus_connection_remove_filter(g_hdp_dus_conn,
901 __bt_hdp_internal_event_filter, NULL);
903 g_hdp_dus_conn = NULL; /*should not unref here, bcz no ++reff */
908 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
919 if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
920 BT_DBG("Invalid arguments..\n");
921 return BLUETOOTH_ERROR_INVALID_PARAM;
923 while (wbytes < size) {
924 written = write(channel_id, buffer + wbytes, size - wbytes);
926 BT_DBG("write failed..\n");
927 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
933 return BLUETOOTH_ERROR_NONE;
937 static void __bt_hdp_connect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *call,
940 GError *g_error = NULL;
941 char *obj_connect_path = NULL;
942 bt_hdp_connected_t *conn_ind = user_data;
943 bt_user_info_t *user_info;
945 dbus_g_proxy_end_call(hdp_proxy, call, &g_error,
946 DBUS_TYPE_G_OBJECT_PATH, &obj_connect_path, G_TYPE_INVALID);
948 g_object_unref(hdp_proxy);
950 if (g_error != NULL) {
951 BT_ERR("HDP connection Dbus Call Error: %s\n", g_error->message);
952 g_error_free(g_error);
954 user_info = _bt_get_user_data(BT_COMMON);
957 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
958 BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind,
959 user_info->cb, user_info->user_data);
962 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
963 g_free(obj_connect_path);
965 g_free((void *)conn_ind->app_handle);
970 BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle,
971 bt_hdp_qos_type_t channel_type,
972 const bluetooth_device_address_t *device_address)
975 DBusGConnection *conn = NULL;
976 DBusGProxy *hdp_proxy = NULL;
977 bt_hdp_connected_t *param;
978 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
979 char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
980 char *dev_path = NULL;
986 BT_CHECK_PARAMETER(app_handle);
987 BT_CHECK_PARAMETER(device_address);
989 if (channel_type == HDP_QOS_RELIABLE) {
991 } else if (channel_type == HDP_QOS_STREAMING) {
993 } else if (channel_type == HDP_QOS_ANY) {
996 BT_ERR("Invalid channel_type %d", channel_type);
997 return BLUETOOTH_ERROR_ACCESS_DENIED;
1000 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
1003 BT_DBG("ERROR: Can't get on system bus [%s]", err->message);
1005 return BLUETOOTH_ERROR_INTERNAL;
1008 /* If the adapter path is wrong, we can think the BT is not enabled. */
1009 if (_bt_get_adapter_path(conn, default_adapter_path) < 0) {
1010 BT_ERR("Could not get adapter path\n");
1011 dbus_g_connection_unref(conn);
1012 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1015 _bt_convert_addr_type_to_string(address,
1016 (unsigned char *)device_address->addr);
1018 BT_DBG("create conection to %s", address);
1020 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1022 if (dev_path == NULL) {
1023 dbus_g_connection_unref(conn);
1024 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1027 g_strdelimit(dev_path, ":", '_');
1029 BT_DBG("path: %s", dev_path);
1031 hdp_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, dev_path,
1032 BLUEZ_HDP_DEVICE_INTERFACE);
1033 dbus_g_connection_unref(conn);
1035 if (hdp_proxy == NULL) {
1036 BT_DBG("Failed to get the HDP server proxy\n");
1038 return BLUETOOTH_ERROR_NOT_PAIRED;
1041 BT_DBG("app path %s\n", app_handle);
1043 param = g_new0(bt_hdp_connected_t, 1);
1044 param->app_handle = g_strdup(app_handle);
1045 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1046 param->type = channel_type;
1048 if (!dbus_g_proxy_begin_call(hdp_proxy, "CreateChannel",
1049 (DBusGProxyCallNotify) __bt_hdp_connect_request_cb,
1050 param, /* user_data */
1052 DBUS_TYPE_G_OBJECT_PATH, app_handle,
1053 G_TYPE_STRING, role,
1055 BT_ERR("HDP connection Dbus Call Error");
1057 g_free((void *)param->app_handle);
1059 g_object_unref(hdp_proxy);
1060 return BLUETOOTH_ERROR_INTERNAL;
1064 return BLUETOOTH_ERROR_NONE;
1067 static void __bt_hdp_disconnect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *call,
1070 GError *g_error = NULL;
1071 bt_hdp_disconnected_t *disconn_ind = user_data;
1072 bt_user_info_t *user_info;
1074 dbus_g_proxy_end_call(hdp_proxy, call, &g_error, G_TYPE_INVALID);
1076 g_object_unref(hdp_proxy);
1078 if (g_error != NULL) {
1079 BT_ERR("HDP disconnection Dbus Call Error: %s\n", g_error->message);
1080 g_error_free(g_error);
1082 user_info = _bt_get_user_data(BT_COMMON);
1085 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1086 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1087 user_info->cb, user_info->user_data);
1090 BT_DBG("HDP disconnection Dbus Call is done\n");
1093 g_free(disconn_ind);
1096 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1097 const bluetooth_device_address_t *device_address)
1100 DBusGConnection *conn = NULL;
1101 DBusGProxy *hdp_proxy = NULL;
1102 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1103 char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1104 char *dev_path = NULL;
1105 bt_hdp_disconnected_t *param;
1110 BT_CHECK_PARAMETER(device_address);
1112 hdp_obj_info_t *info = __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1114 BT_ERR("*** Could not locate the list for %d*****\n", channel_id);
1115 return BLUETOOTH_ERROR_INVALID_PARAM;
1118 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
1121 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1123 return BLUETOOTH_ERROR_INTERNAL;
1126 /* If the adapter path is wrong, we can think the BT is not enabled. */
1127 if (_bt_get_adapter_path(conn, default_adapter_path) < 0) {
1128 BT_ERR("Could not get adapter path\n");
1129 dbus_g_connection_unref(conn);
1130 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1133 _bt_convert_addr_type_to_string(address,
1134 (unsigned char *)device_address->addr);
1136 BT_DBG("create conection to %s\n", address);
1138 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1140 if (dev_path == NULL) {
1141 dbus_g_connection_unref(conn);
1142 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1145 g_strdelimit(dev_path, ":", '_');
1147 BT_DBG("path %s\n", dev_path);
1149 hdp_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, dev_path,
1150 BLUEZ_HDP_DEVICE_INTERFACE);
1152 dbus_g_connection_unref(conn);
1154 if (hdp_proxy == NULL) {
1155 BT_ERR("Failed to get the HDP proxy\n");
1157 return BLUETOOTH_ERROR_NOT_PAIRED;
1160 param = g_new0(bt_hdp_disconnected_t, 1);
1161 param->channel_id = channel_id;
1162 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1164 if (!dbus_g_proxy_begin_call(hdp_proxy, "DestroyChannel",
1165 (DBusGProxyCallNotify) __bt_hdp_disconnect_request_cb,
1166 param, /* user_data */
1168 DBUS_TYPE_G_OBJECT_PATH, info->obj_channel_path,
1170 BT_ERR("HDP connection Dbus Call Error");
1173 g_object_unref(hdp_proxy);
1174 return BLUETOOTH_ERROR_INTERNAL;
1179 return BLUETOOTH_ERROR_NONE;