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>
27 #include <dbus/dbus-glib-lowlevel.h>
30 #include "bluetooth-api.h"
31 #include "bt-common.h"
32 #include "bt-internal-types.h"
34 #define HDP_BUFFER_SIZE 1024
35 #define BLUEZ_HDP_MANAGER_INTERFACE "org.bluez.HealthManager1"
36 #define BLUEZ_HDP_DEVICE_INTERFACE "org.bluez.HealthDevice1"
37 #define BLUEZ_HDP_CHANNEL_INTERFACE "org.bluez.HealthChannel1"
40 char *obj_channel_path;
50 /* Variable for privilege, only for write API,
51 before we should reduce time to bt-service dbus calling
52 -1 : Don't have a permission to access API
53 0 : Initial value, not yet check
54 1 : Have a permission to access API
56 static int privilege_token;
59 /**********************************************************************
60 * Static Functions declaration *
61 ***********************************************************************/
62 static int __bt_hdp_internal_create_application(unsigned int data_type,
64 bt_hdp_qos_type_t channel_type,
67 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
71 static void __bt_hdp_internal_handle_connect(DBusMessage *msg);
73 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg);
75 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg);
77 static int __bt_hdp_internal_add_filter(void);
79 static int __bt_hdp_internal_acquire_fd(const char *path);
81 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path);
83 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
87 static int __bt_hdp_internal_destroy_application(const char *app_handle);
89 static void __bt_hdp_internal_remove_filter(void);
91 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle);
93 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd);
95 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path);
98 static DBusConnection *g_hdp_dus_conn;
100 static GSList *g_app_list = NULL;
102 /**********************************************************************
103 * Health device APIs (HDP) *
104 ***********************************************************************/
106 BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type,
107 bt_hdp_role_type_t role,
108 bt_hdp_qos_type_t channel_type,
111 int result = BLUETOOTH_ERROR_NONE;
115 BT_CHECK_ENABLED(return);
117 /*For source role is mandatory */
118 if (role == HDP_ROLE_SOURCE && channel_type == HDP_QOS_ANY) {
119 BT_ERR("For source, type is mandatory - Reliable/Streaming");
120 return BLUETOOTH_ERROR_INVALID_PARAM;
123 result = __bt_hdp_internal_create_application(data_type, role,
124 channel_type, app_handle);
129 static void __bt_hdp_obj_info_free(hdp_obj_info_t *info)
132 g_source_remove(info->watch_id);
134 g_free(info->obj_channel_path);
139 static int __bt_hdp_internal_create_application(unsigned int data_type,
141 bt_hdp_qos_type_t channel_type,
147 const char *key_type;
149 hdp_app_list_t *list;
151 DBusMessageIter iter;
152 DBusMessageIter array_iter;
153 DBusMessageIter entry;
154 DBusMessageIter variant;
156 DBusConnection *conn;
157 int ret = BLUETOOTH_ERROR_NONE;
161 conn = _bt_get_system_conn();
162 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
164 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
165 BLUEZ_HDP_MANAGER_INTERFACE,
166 "CreateApplication");
168 retv_if(msg == NULL, BLUETOOTH_ERROR_NO_RESOURCES);
170 dbus_message_iter_init_append(msg, &iter);
171 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
172 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING
173 DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
176 key_type = "DataType";
177 value = (guint16) data_type;
178 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
180 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
181 dbus_message_iter_open_container(&entry,
182 DBUS_TYPE_VARIANT, DBUS_TYPE_UINT16_AS_STRING, &variant);
183 dbus_message_iter_append_basic(&variant, DBUS_TYPE_UINT16, &value);
184 dbus_message_iter_close_container(&entry, &variant);
185 dbus_message_iter_close_container(&array_iter, &entry);
190 svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
191 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
193 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
194 dbus_message_iter_open_container(&entry,
195 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
196 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue);
197 dbus_message_iter_close_container(&entry, &variant);
198 dbus_message_iter_close_container(&array_iter, &entry);
200 key_type = "Description";
201 svalue = "Health Device";
202 dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY,
204 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type);
205 dbus_message_iter_open_container(&entry,
206 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
207 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue);
208 dbus_message_iter_close_container(&entry, &variant);
209 dbus_message_iter_close_container(&array_iter, &entry);
211 if (role == HDP_ROLE_SOURCE) {
212 key_type = "ChannelType";
213 if (channel_type == HDP_QOS_RELIABLE)
215 else if (channel_type == HDP_QOS_STREAMING)
216 svalue = "streaming";
218 dbus_message_iter_open_container(&array_iter,
219 DBUS_TYPE_DICT_ENTRY, NULL, &entry);
220 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
222 dbus_message_iter_open_container(&entry,
223 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING,
225 dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
227 dbus_message_iter_close_container(&entry, &variant);
228 dbus_message_iter_close_container(&array_iter, &entry);
231 dbus_message_iter_close_container(&iter, &array_iter);
233 dbus_error_init(&err);
235 reply = dbus_connection_send_with_reply_and_block(
238 dbus_message_unref(msg);
241 BT_ERR(" HDP:dbus Can't create application");
243 if (dbus_error_is_set(&err)) {
244 BT_ERR("%s", err.message);
246 if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
247 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
249 ret = BLUETOOTH_ERROR_INTERNAL;
251 dbus_error_free(&err);
256 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
257 &app_path, DBUS_TYPE_INVALID)) {
259 BT_ERR(" HDP: Can't get reply arguments from Dbus");
261 if (dbus_error_is_set(&err)) {
262 BT_ERR("Error: %s", err.message);
263 dbus_error_free(&err);
266 dbus_message_unref(reply);
267 return BLUETOOTH_ERROR_INTERNAL;
270 dbus_message_unref(reply);
272 BT_DBG("Created health application: %s", (char *)app_path);
274 ret = __bt_hdp_internal_add_filter();
276 if (ret != BLUETOOTH_ERROR_NONE) {
277 BT_ERR("Funtion failed");
281 list = g_new0(hdp_app_list_t, 1);
282 list->app_handle = (void *)g_strdup(app_path);
283 *app_handle = list->app_handle;
285 g_app_list = g_slist_append(g_app_list, list);
287 return BLUETOOTH_ERROR_NONE;
290 static int __bt_hdp_internal_add_filter(void)
292 DBusError dbus_error;
296 /*Single process only one signal registration is required */
297 if (g_hdp_dus_conn) {
298 BT_ERR("g_hdp_dus_conn already exist");
302 /* Add the filter for HDP client functions */
303 dbus_error_init(&dbus_error);
305 g_hdp_dus_conn = _bt_get_system_conn();
306 retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
308 dbus_connection_add_filter(g_hdp_dus_conn,
309 __bt_hdp_internal_event_filter, NULL, NULL);
311 dbus_bus_add_match(g_hdp_dus_conn,
312 "type='signal',interface=" BLUEZ_HDP_DEVICE_INTERFACE,
315 if (dbus_error_is_set(&dbus_error)) {
316 BT_ERR("Fail to add dbus filter signal\n");
317 dbus_error_free(&dbus_error);
318 g_hdp_dus_conn = NULL;
319 return BLUETOOTH_ERROR_INTERNAL;
324 return BLUETOOTH_ERROR_NONE;
328 static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn,
329 DBusMessage *msg, void *data)
331 const char *path = dbus_message_get_path(msg);
333 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
334 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
336 BT_DBG("Path = %s\n", path);
337 if (path == NULL || g_strcmp0(path, "/") == 0)
338 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
340 if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
342 __bt_hdp_internal_handle_connect(msg);
344 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
346 __bt_hdp_internal_handle_disconnect(msg);
348 else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE,
350 __bt_hdp_internal_handle_property_changed(msg);
352 return DBUS_HANDLER_RESULT_HANDLED;
355 static void __bt_hdp_internal_handle_connect(DBusMessage *msg)
357 const char *path = dbus_message_get_path(msg);
358 const char *obj_channel_path;
359 bt_user_info_t *user_info;
362 BT_INFO("+********Signal - ChannelConnected******\n\n");
363 BT_DBG("Path = %s", path);
365 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
366 &obj_channel_path, DBUS_TYPE_INVALID)) {
367 BT_ERR("Unexpected parameters in ChannelConnected signal");
371 BT_INFO("Channel connected, Path = %s", obj_channel_path);
373 user_info = _bt_get_user_data(BT_COMMON);
374 if (user_info == NULL || user_info->cb == NULL)
377 ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
378 if (ret != BLUETOOTH_ERROR_NONE) {
379 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
380 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
381 user_info->cb, user_info->user_data);
384 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
385 BLUETOOTH_ERROR_NONE, NULL,
386 user_info->cb, user_info->user_data);
393 static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg)
395 const char *path = dbus_message_get_path(msg);
396 const char *obj_channel_path;
397 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
398 bluetooth_device_address_t device_addr = { {0} };
399 bt_hdp_disconnected_t dis_ind;
400 hdp_obj_info_t *info;
401 bt_user_info_t *user_info;
403 BT_INFO("+********Signal - ChannelDeleted ******\n\n");
404 BT_DBG("Path = %s", path);
406 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
407 &obj_channel_path, DBUS_TYPE_INVALID)) {
408 BT_ERR("Unexpected parameters in ChannelDeleted signal");
412 BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
414 info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
416 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
420 /*Since bluetoothd is not sending the ChannelDeleted signal */
421 _bt_device_path_to_address(path, address);
423 _bt_convert_addr_string_to_type(device_addr.addr, address);
425 dis_ind.channel_id = info->fd;
426 dis_ind.device_address = device_addr;
428 user_info = _bt_get_user_data(BT_COMMON);
431 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
432 BLUETOOTH_ERROR_NONE, &dis_ind,
433 user_info->cb, user_info->user_data);
436 BT_DBG(" Removed connection from list\n");
438 __bt_hdp_obj_info_free(info);
442 static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg)
444 const char *path = dbus_message_get_path(msg);
445 DBusMessageIter item_iter;
446 DBusMessageIter value_iter;
447 const char *property;
448 const char *obj_main_channel_path;
450 BT_DBG("+*******Signal - PropertyChanged*******\n");
451 BT_DBG("Path = %s", path);
453 dbus_message_iter_init(msg, &item_iter);
455 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
456 BT_ERR("This is bad format dbus");
460 dbus_message_iter_get_basic(&item_iter, &property);
462 ret_if(property == NULL);
464 BT_DBG("Property (%s)\n", property);
466 if (0 == g_strcmp0(property, "MainChannel")) {
467 BT_INFO("Property MainChannel received");
469 dbus_message_iter_next(&item_iter);
471 dbus_message_iter_recurse(&item_iter, &value_iter);
473 dbus_message_iter_get_basic(&value_iter,
474 &obj_main_channel_path);
475 BT_DBG("Path = %s", path);
477 BT_DBG("Main Channel Path = %s", obj_main_channel_path);
479 BT_DBG("-*************\n");
482 static int __bt_hdp_internal_acquire_fd(const char *path)
484 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
485 bluetooth_device_address_t device_addr = { {0} };
486 DBusMessageIter reply_iter;
487 DBusMessageIter reply_iter_entry;
488 const char *property;
489 char *type_qos = NULL;
490 char *device = NULL;;
491 char *app_handle = NULL;;
492 hdp_app_list_t *list = NULL;;
495 DBusConnection *conn;
496 bt_hdp_connected_t conn_ind;
499 bt_user_info_t *user_info;
504 conn = _bt_get_system_conn();
505 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
507 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
508 BLUEZ_HDP_CHANNEL_INTERFACE,
511 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
513 dbus_error_init(&err);
515 reply = dbus_connection_send_with_reply_and_block(conn, msg,
518 dbus_message_unref(msg);
521 BT_ERR(" HDP:****** dbus Can't create application ****");
523 if (dbus_error_is_set(&err)) {
524 BT_ERR("%s", err.message);
525 dbus_error_free(&err);
528 return BLUETOOTH_ERROR_INTERNAL;
531 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd,
532 DBUS_TYPE_INVALID)) {
533 BT_ERR(" HDP:dbus Can't get reply arguments");
535 if (dbus_error_is_set(&err)) {
536 BT_ERR("%s", err.message);
537 dbus_error_free(&err);
542 dbus_message_unref(reply);
544 BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
546 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path,
547 BT_PROPERTIES_INTERFACE, "GetAll");
548 dev_path = g_strdup(BLUEZ_HDP_CHANNEL_INTERFACE);
549 dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_path,
553 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
555 dbus_error_init(&err);
557 reply = dbus_connection_send_with_reply_and_block(conn, msg,
560 dbus_message_unref(msg);
563 BT_ERR(" HDP:dbus Can't get the reply");
565 if (dbus_error_is_set(&err)) {
566 BT_ERR("%s", err.message);
567 dbus_error_free(&err);
570 return BLUETOOTH_ERROR_INTERNAL;
572 dbus_message_iter_init(reply, &reply_iter);
574 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
575 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
579 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
582 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
583 DBUS_TYPE_DICT_ENTRY) {
584 DBusMessageIter dict_entry, dict_entry_val;
585 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
586 dbus_message_iter_get_basic(&dict_entry, &property);
587 BT_DBG("String received = %s\n", property);
589 if (g_strcmp0("Type", property) == 0) {
590 dbus_message_iter_next(&dict_entry);
591 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
592 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
596 dbus_message_iter_get_basic(&dict_entry_val, &type_qos);
598 } else if (g_strcmp0("Device", property) == 0) {
599 dbus_message_iter_next(&dict_entry);
600 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
601 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
602 DBUS_TYPE_OBJECT_PATH)
605 dbus_message_iter_get_basic(&dict_entry_val, &device);
607 } else if (g_strcmp0("Application", property) == 0) {
608 dbus_message_iter_next(&dict_entry);
609 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
610 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
611 DBUS_TYPE_OBJECT_PATH)
614 dbus_message_iter_get_basic(&dict_entry_val,
617 dbus_message_iter_next(&reply_iter_entry);
620 BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
621 type_qos, device, app_handle);
623 if (NULL == type_qos || NULL == app_handle) {
624 BT_ERR("Pasing failed\n");
628 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
630 /*Only process register with app handle receive the Connected event */
632 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
636 hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
638 info->obj_channel_path = g_strdup(path);
639 info->watch_id = __bt_hdp_internal_watch_fd(fd, info->obj_channel_path);
640 list->obj_info = g_slist_append(list->obj_info, info);
642 _bt_device_path_to_address(path, address);
644 _bt_convert_addr_string_to_type(device_addr.addr, address);
646 conn_ind.app_handle = app_handle;
647 conn_ind.channel_id = fd;
648 conn_ind.device_address = device_addr;
649 conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ?
650 HDP_QOS_RELIABLE : HDP_QOS_STREAMING;
652 BT_DBG("Going to give callback\n");
654 user_info = _bt_get_user_data(BT_COMMON);
657 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
658 BLUETOOTH_ERROR_NONE, &conn_ind,
659 user_info->cb, user_info->user_data);
662 dbus_message_unref(reply);
664 BT_DBG("Updated fd in the list*\n");
667 return BLUETOOTH_ERROR_NONE;
669 dbus_message_unref(reply);
670 return BLUETOOTH_ERROR_INTERNAL;
673 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
680 gio = g_io_channel_unix_new(file_desc);
682 g_io_channel_set_close_on_unref(gio, TRUE);
684 id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
685 __bt_hdp_internal_data_received, (void *)path);
691 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
693 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
694 bluetooth_device_address_t device_addr = { {0} };
695 bt_hdp_disconnected_t dis_ind;
696 hdp_obj_info_t *info;
697 bt_user_info_t *user_info;
699 BT_INFO("******** Socket Error ******\n");
701 info = __bt_hdp_internal_gslist_obj_find_using_path(path);
702 ret_if(info == NULL);
704 /*Since bluetoothd is not sending the ChannelDeleted signal */
705 _bt_device_path_to_address(path, address);
707 _bt_convert_addr_string_to_type(device_addr.addr, address);
709 dis_ind.channel_id = sk;
710 dis_ind.device_address = device_addr;
712 user_info = _bt_get_user_data(BT_COMMON);
715 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
716 BLUETOOTH_ERROR_NONE, &dis_ind,
717 user_info->cb, user_info->user_data);
720 BT_DBG(" Removed connection from list\n");
722 __bt_hdp_obj_info_free(info);
725 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
726 GIOCondition cond, gpointer data)
728 char buff[HDP_BUFFER_SIZE] = { 0, };
731 bt_hdp_data_ind_t data_ind = { 0, };
732 const char *path = (const char *)data;
733 bt_user_info_t *user_info;
737 sk = g_io_channel_unix_get_fd(gio);
739 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
740 BT_DBG("GIOCondition %d.............path = %s\n", cond, path);
741 __bt_hdp_internal_handle_disconnect_cb(sk, path);
745 act_read = recv(sk, (void *)buff, sizeof(buff), 0);
748 BT_DBG("Received data of %d\n", act_read);
750 BT_ERR("Read failed.....\n");
754 data_ind.channel_id = sk;
755 data_ind.buffer = buff;
756 data_ind.size = act_read;
758 user_info = _bt_get_user_data(BT_COMMON);
761 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
762 BLUETOOTH_ERROR_NONE, &data_ind,
763 user_info->cb, user_info->user_data);
771 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
775 BT_CHECK_ENABLED(return);
776 BT_CHECK_PARAMETER(app_handle, return);
778 return __bt_hdp_internal_destroy_application(app_handle);
781 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
785 retv_if(g_app_list == NULL, NULL);
787 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
789 for (l = g_app_list; l != NULL; l = l->next) {
790 hdp_app_list_t *list = l->data;
793 if (0 == g_strcmp0((char *)list->app_handle,
801 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
806 retv_if(g_app_list == NULL, NULL);
808 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
810 for (l = g_app_list; l != NULL; l = l->next) {
811 hdp_app_list_t *list = l->data;
815 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
816 hdp_obj_info_t *info = iter->data;
827 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
831 hdp_obj_info_t *info = NULL;
833 retv_if(g_app_list == NULL, NULL);
835 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
836 for (l = g_app_list; l != NULL; l = l->next) {
837 hdp_app_list_t *list = l->data;
841 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
846 if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
847 list->obj_info = g_slist_remove(list->obj_info, info);
855 static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data)
857 const char *app_handle;
858 hdp_app_list_t *list = NULL;
859 app_handle = (const char *)data;
863 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
865 BT_ERR("**** list not found for %s ******\n", app_handle);
869 g_app_list = g_slist_remove(g_app_list, list);
871 g_free(list->app_handle);
872 g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
875 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
877 if (0 == g_slist_length(g_app_list))
878 __bt_hdp_internal_remove_filter();
883 static int __bt_hdp_internal_destroy_application(const char *app_handle)
888 DBusConnection *conn;
889 int result = BLUETOOTH_ERROR_NONE;
891 conn = _bt_get_system_conn();
892 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
894 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez",
895 BLUEZ_HDP_MANAGER_INTERFACE, "DestroyApplication");
897 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
899 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &app_handle,
902 dbus_error_init(&err);
904 reply = dbus_connection_send_with_reply_and_block(conn, msg,
906 dbus_message_unref(msg);
908 BT_ERR(" HDP:dbus Can't Destroy application");
910 if (dbus_error_is_set(&err)) {
911 BT_ERR("%s", err.message);
913 if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG))
914 result = BLUETOOTH_ERROR_ACCESS_DENIED;
916 result = BLUETOOTH_ERROR_INTERNAL;
918 dbus_error_free(&err);
924 dbus_message_unref(reply);
926 BT_DBG("Destroyed health application: %s", (char *)app_handle);
928 g_idle_add(__bt_hdp_internal_destroy_application_cb,
929 (gpointer)app_handle);
931 return BLUETOOTH_ERROR_NONE;
934 static void __bt_hdp_internal_remove_filter(void)
938 ret_if(g_hdp_dus_conn == NULL);
940 dbus_connection_remove_filter(g_hdp_dus_conn,
941 __bt_hdp_internal_event_filter, NULL);
943 g_hdp_dus_conn = NULL; /*should not unref here, bcz no ++reff */
948 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
958 BT_CHECK_ENABLED(return);
960 if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
961 BT_ERR("Invalid arguments..\n");
962 return BLUETOOTH_ERROR_INVALID_PARAM;
965 switch (privilege_token) {
967 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
969 if (result == BLUETOOTH_ERROR_NONE) {
970 privilege_token = 1; /* Have a permission */
971 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
972 BT_ERR("Don't have a privilege to use this API");
973 privilege_token = -1; /* Don't have a permission */
974 return BLUETOOTH_ERROR_PERMISSION_DEINED;
976 /* Just break - It is not related with permission error */
980 /* Already have a privilege */
983 return BLUETOOTH_ERROR_PERMISSION_DEINED;
985 /* Invalid privilge token value */
986 return BLUETOOTH_ERROR_INTERNAL;
989 while (wbytes < size) {
990 written = write(channel_id, buffer + wbytes, size - wbytes);
992 BT_ERR("write failed..\n");
993 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
998 return BLUETOOTH_ERROR_NONE;
1002 static void __bt_hdp_connect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *call,
1005 GError *g_error = NULL;
1006 char *obj_connect_path = NULL;
1007 bt_hdp_connected_t *conn_ind = user_data;
1008 bt_user_info_t *user_info;
1010 dbus_g_proxy_end_call(hdp_proxy, call, &g_error,
1011 DBUS_TYPE_G_OBJECT_PATH, &obj_connect_path, G_TYPE_INVALID);
1013 g_object_unref(hdp_proxy);
1015 if (g_error != NULL) {
1016 BT_ERR("HDP connection Dbus Call Error: %s\n", g_error->message);
1017 g_error_free(g_error);
1019 user_info = _bt_get_user_data(BT_COMMON);
1021 if (user_info->cb) {
1022 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
1023 BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind,
1024 user_info->cb, user_info->user_data);
1027 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
1028 user_info = _bt_get_user_data(BT_COMMON);
1030 if (user_info->cb) {
1031 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
1032 BLUETOOTH_ERROR_NONE, conn_ind,
1033 user_info->cb, user_info->user_data);
1035 g_free(obj_connect_path);
1037 g_free((void *)conn_ind->app_handle);
1042 BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle,
1043 bt_hdp_qos_type_t channel_type,
1044 const bluetooth_device_address_t *device_address)
1047 DBusGConnection *conn = NULL;
1048 DBusGProxy *hdp_proxy = NULL;
1049 bt_hdp_connected_t *param;
1050 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1051 char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1052 char *dev_path = NULL;
1057 BT_CHECK_ENABLED(return);
1058 BT_CHECK_PARAMETER(app_handle, return);
1059 BT_CHECK_PARAMETER(device_address, return);
1061 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_CONNECT)
1062 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1063 BT_ERR("Don't have a privilege to use this API");
1064 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1067 if (channel_type == HDP_QOS_RELIABLE) {
1069 } else if (channel_type == HDP_QOS_STREAMING) {
1071 } else if (channel_type == HDP_QOS_ANY) {
1074 BT_ERR("Invalid channel_type %d", channel_type);
1075 return BLUETOOTH_ERROR_ACCESS_DENIED;
1078 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
1081 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1083 return BLUETOOTH_ERROR_INTERNAL;
1086 /* If the adapter path is wrong, we can think the BT is not enabled. */
1087 if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1088 default_adapter_path) < 0) {
1089 BT_ERR("Could not get adapter path\n");
1090 dbus_g_connection_unref(conn);
1091 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1094 _bt_convert_addr_type_to_string(address,
1095 (unsigned char *)device_address->addr);
1097 BT_DBG("create conection to %s", address);
1099 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1101 if (dev_path == NULL) {
1102 dbus_g_connection_unref(conn);
1103 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1106 g_strdelimit(dev_path, ":", '_');
1108 BT_DBG("path: %s", dev_path);
1110 hdp_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, dev_path,
1111 BLUEZ_HDP_DEVICE_INTERFACE);
1112 dbus_g_connection_unref(conn);
1114 if (hdp_proxy == NULL) {
1115 BT_ERR("Failed to get the HDP server proxy\n");
1117 return BLUETOOTH_ERROR_NOT_PAIRED;
1120 BT_DBG("app path %s\n", app_handle);
1122 param = g_new0(bt_hdp_connected_t, 1);
1123 param->app_handle = g_strdup(app_handle);
1124 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1125 param->type = channel_type;
1127 if (!dbus_g_proxy_begin_call(hdp_proxy, "CreateChannel",
1128 (DBusGProxyCallNotify) __bt_hdp_connect_request_cb,
1129 param, /* user_data */
1131 DBUS_TYPE_G_OBJECT_PATH, app_handle,
1132 G_TYPE_STRING, role,
1134 BT_ERR("HDP connection Dbus Call Error");
1136 g_free((void *)param->app_handle);
1138 g_object_unref(hdp_proxy);
1139 return BLUETOOTH_ERROR_INTERNAL;
1143 return BLUETOOTH_ERROR_NONE;
1146 static void __bt_hdp_disconnect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *call,
1149 GError *g_error = NULL;
1150 bt_hdp_disconnected_t *disconn_ind = user_data;
1151 bt_user_info_t *user_info;
1153 dbus_g_proxy_end_call(hdp_proxy, call, &g_error, G_TYPE_INVALID);
1155 g_object_unref(hdp_proxy);
1157 user_info = _bt_get_user_data(BT_COMMON);
1158 if (user_info == NULL || user_info->cb == NULL) {
1159 g_free(disconn_ind);
1161 g_error_free(g_error);
1165 if (g_error != NULL) {
1166 BT_ERR("HDP disconnection Dbus Call Error: %s\n", g_error->message);
1167 g_error_free(g_error);
1169 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1170 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1171 user_info->cb, user_info->user_data);
1173 if (user_info->cb) {
1174 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1175 BLUETOOTH_ERROR_NONE, disconn_ind,
1176 user_info->cb, user_info->user_data);
1178 BT_INFO("HDP disconnection Dbus Call is done\n");
1181 g_free(disconn_ind);
1184 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1185 const bluetooth_device_address_t *device_address)
1188 DBusGConnection *conn = NULL;
1189 DBusGProxy *hdp_proxy = NULL;
1190 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1191 char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1192 char *dev_path = NULL;
1193 bt_hdp_disconnected_t *param;
1197 BT_CHECK_ENABLED(return);
1198 BT_CHECK_PARAMETER(device_address, return);
1200 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_DISCONNECT)
1201 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1202 BT_ERR("Don't have a privilege to use this API");
1203 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1206 hdp_obj_info_t *info = __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1208 BT_ERR("*** Could not locate the list for %d*****\n", channel_id);
1209 return BLUETOOTH_ERROR_INVALID_PARAM;
1212 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
1215 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1217 return BLUETOOTH_ERROR_INTERNAL;
1220 /* If the adapter path is wrong, we can think the BT is not enabled. */
1221 if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1222 default_adapter_path) < 0) {
1223 BT_ERR("Could not get adapter path\n");
1224 dbus_g_connection_unref(conn);
1225 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1228 _bt_convert_addr_type_to_string(address,
1229 (unsigned char *)device_address->addr);
1231 BT_DBG("create conection to %s\n", address);
1233 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1235 if (dev_path == NULL) {
1236 dbus_g_connection_unref(conn);
1237 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1240 g_strdelimit(dev_path, ":", '_');
1242 BT_DBG("path %s\n", dev_path);
1244 hdp_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, dev_path,
1245 BLUEZ_HDP_DEVICE_INTERFACE);
1247 dbus_g_connection_unref(conn);
1249 if (hdp_proxy == NULL) {
1250 BT_ERR("Failed to get the HDP proxy\n");
1252 return BLUETOOTH_ERROR_NOT_PAIRED;
1255 param = g_new0(bt_hdp_disconnected_t, 1);
1256 param->channel_id = channel_id;
1257 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1259 if (!dbus_g_proxy_begin_call(hdp_proxy, "DestroyChannel",
1260 (DBusGProxyCallNotify) __bt_hdp_disconnect_request_cb,
1261 param, /* user_data */
1263 DBUS_TYPE_G_OBJECT_PATH, info->obj_channel_path,
1265 BT_ERR("HDP connection Dbus Call Error");
1268 g_object_unref(hdp_proxy);
1269 return BLUETOOTH_ERROR_INTERNAL;
1274 return BLUETOOTH_ERROR_NONE;