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>
23 #include <gio/gunixfdlist.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.HealthManager1"
31 #define BLUEZ_HDP_DEVICE_INTERFACE "org.bluez.HealthDevice1"
32 #define BLUEZ_HDP_CHANNEL_INTERFACE "org.bluez.HealthChannel1"
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 void __bt_hdp_internal_event_filter(GDBusConnection *connection,
63 const gchar *sender_name,
64 const gchar *object_path,
65 const gchar *interface_name,
66 const gchar *signal_name,
70 static void __bt_hdp_internal_handle_connect(GVariant *parameters);
72 static void __bt_hdp_internal_handle_disconnect(GVariant *parameters,
73 const gchar *object_path);
75 static void __bt_hdp_internal_handle_property_changed(GVariant *parameters);
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 GDBusConnection *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,
144 GDBusProxy *proxy = NULL;
145 GVariant *reply = NULL;
146 GVariantBuilder *builder;
148 const char *key_type;
150 hdp_app_list_t *list;
153 GDBusConnection *conn;
154 int ret = BLUETOOTH_ERROR_NONE;
158 conn = _bt_gdbus_get_system_gconn();
159 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
161 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
165 BLUEZ_HDP_MANAGER_INTERFACE,
169 BT_ERR("Unable to create proxy: %s", err->message);
171 return BLUETOOTH_ERROR_INTERNAL;
174 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
176 key_type = "DataType";
177 value = (guint16) data_type;
178 g_variant_builder_add(builder, "{sv}",
179 key_type, g_variant_new("q",
184 svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
185 g_variant_builder_add(builder, "{sv}",
186 key_type, g_variant_new("s",
189 key_type = "Description";
190 svalue = "Health Device";
191 g_variant_builder_add(builder, "{sv}",
192 key_type, g_variant_new("s",
195 if (role == HDP_ROLE_SOURCE) {
196 key_type = "ChannelType";
197 if (channel_type == HDP_QOS_RELIABLE)
199 else if (channel_type == HDP_QOS_STREAMING)
200 svalue = "streaming";
202 g_variant_builder_add(builder, "{sv}",
203 key_type, g_variant_new("s",
207 reply = g_dbus_proxy_call_sync(proxy, "CreateApplication",
208 g_variant_new("(a{sv})", builder),
209 G_DBUS_CALL_FLAGS_NONE, -1,
212 g_variant_builder_unref(builder);
213 g_object_unref(proxy);
216 BT_ERR(" HDP:dbus Can't create application");
218 BT_ERR("%s", err->message);
219 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
220 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
222 ret = BLUETOOTH_ERROR_INTERNAL;
228 g_variant_get(reply, "(&o)", &app_path);
229 BT_DBG("Created health application: %s", (char *)app_path);
231 ret = __bt_hdp_internal_add_filter();
233 if (ret != BLUETOOTH_ERROR_NONE) {
234 BT_ERR("Funtion failed");
238 list = g_new0(hdp_app_list_t, 1);
239 list->app_handle = (void *)g_strdup(app_path);
240 *app_handle = list->app_handle;
242 g_app_list = g_slist_append(g_app_list, list);
244 g_variant_unref(reply);
245 return BLUETOOTH_ERROR_NONE;
248 static int __bt_hdp_add_filter_subscribe_signal(GDBusConnection *conn,
251 static guint subs_add_filter_id = 0;
254 return BLUETOOTH_ERROR_INVALID_PARAM;
257 if (subs_add_filter_id == 0) {
258 subs_add_filter_id = g_dbus_connection_signal_subscribe(
259 conn, NULL, BLUEZ_HDP_DEVICE_INTERFACE,
261 __bt_hdp_internal_event_filter, NULL, NULL);
264 if (subs_add_filter_id > 0) {
265 g_dbus_connection_signal_unsubscribe(conn,
267 subs_add_filter_id = 0;
270 return BLUETOOTH_ERROR_NONE;
273 static int __bt_hdp_internal_add_filter(void)
277 /*Single process only one signal registration is required */
278 if (g_hdp_dus_conn) {
279 BT_ERR("g_hdp_dus_conn already exist");
280 return BLUETOOTH_ERROR_NONE;
283 g_hdp_dus_conn = _bt_gdbus_get_system_gconn();
284 retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
287 return __bt_hdp_add_filter_subscribe_signal(g_hdp_dus_conn, TRUE);
292 static void __bt_hdp_internal_event_filter(GDBusConnection *connection,
293 const gchar *sender_name,
294 const gchar *object_path,
295 const gchar *interface_name,
296 const gchar *signal_name,
297 GVariant *parameters,
300 BT_DBG("Path = %s\n", object_path);
301 if (object_path == NULL || g_strcmp0(object_path, "/") == 0)
304 if (signal_name == NULL)
307 if (strcasecmp(signal_name, "ChannelConnected") == 0)
308 __bt_hdp_internal_handle_connect(parameters);
310 else if (strcasecmp(signal_name, "ChannelDeleted") == 0)
311 __bt_hdp_internal_handle_disconnect(parameters, object_path);
313 else if (strcasecmp(signal_name, "PropertyChanged") == 0)
314 __bt_hdp_internal_handle_property_changed(parameters);
319 static void __bt_hdp_internal_handle_connect(GVariant *parameters)
321 const char *obj_channel_path;
322 bt_user_info_t *user_info;
325 BT_INFO("+********Signal - ChannelConnected******\n\n");
326 g_variant_get(parameters, "(&o)", &obj_channel_path);
328 BT_INFO("Channel connected, Path = %s", obj_channel_path);
330 user_info = _bt_get_user_data(BT_COMMON);
331 if (user_info == NULL || user_info->cb == NULL)
334 ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
335 if (ret != BLUETOOTH_ERROR_NONE) {
336 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
337 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
338 user_info->cb, user_info->user_data);
340 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
341 BLUETOOTH_ERROR_NONE, NULL,
342 user_info->cb, user_info->user_data);
348 static void __bt_hdp_internal_handle_disconnect(GVariant *parameters,
349 const gchar *object_path)
351 const char *obj_channel_path;
352 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
353 bluetooth_device_address_t device_addr = { {0} };
354 bt_hdp_disconnected_t dis_ind;
355 hdp_obj_info_t *info;
356 bt_user_info_t *user_info;
358 BT_INFO("+********Signal - ChannelDeleted ******\n\n");
359 BT_DBG("Path = %s", object_path);
361 g_variant_get(parameters, "(&o)", &obj_channel_path);
363 BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
365 info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
367 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
371 /*Since bluetoothd is not sending the ChannelDeleted signal */
372 _bt_convert_device_path_to_address(object_path, address);
374 _bt_convert_addr_string_to_type(device_addr.addr, address);
376 dis_ind.channel_id = info->fd;
377 dis_ind.device_address = device_addr;
379 user_info = _bt_get_user_data(BT_COMMON);
382 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
383 BLUETOOTH_ERROR_NONE, &dis_ind,
384 user_info->cb, user_info->user_data);
387 BT_DBG(" Removed connection from list\n");
389 __bt_hdp_obj_info_free(info);
393 static void __bt_hdp_internal_handle_property_changed(GVariant *parameters)
395 char *property = NULL;
396 GVariant *value = NULL;
398 char *obj_main_channel_path = NULL;
399 GVariantIter *property_iter;
401 BT_DBG("+*******Signal - PropertyChanged*******\n");
403 g_variant_get (parameters, "(a{sv})", &property_iter);
405 while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
406 if (g_strcmp0("MainChannel", property) == 0) {
407 BT_INFO("Property MainChannel received");
408 obj_main_channel_path = g_variant_dup_string (value, &len);
409 BT_DBG("Main Channel Path = %s", obj_main_channel_path);
414 g_variant_unref(value);
415 g_free(obj_main_channel_path);
416 BT_DBG("-*************\n");
419 static int __bt_hdp_internal_acquire_fd(const char *path)
421 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
422 bluetooth_device_address_t device_addr = { {0} };
423 const char *property;
424 GVariant *value = NULL;
425 char *type_qos = NULL;
427 char *app_handle = NULL;
428 hdp_app_list_t *list = NULL;
429 GDBusProxy *proxy = NULL;
430 GVariant *reply = NULL;
431 GDBusConnection *conn;
432 bt_hdp_connected_t conn_ind;
435 bt_user_info_t *user_info;
437 GUnixFDList *out_fd_list;
439 GVariantIter *property_iter;
444 conn = _bt_gdbus_get_system_gconn();
445 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
447 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
451 BLUEZ_HDP_CHANNEL_INTERFACE,
455 BT_ERR("Unable to create proxy: %s", err->message);
457 return BLUETOOTH_ERROR_INTERNAL;
460 reply = g_dbus_proxy_call_with_unix_fd_list_sync (proxy,
463 G_DBUS_CALL_FLAGS_NONE,
470 g_object_unref(proxy);
473 BT_ERR(" HDP:****** dbus Can't create application ****");
476 BT_ERR("%s", err->message);;
480 return BLUETOOTH_ERROR_INTERNAL;
483 g_variant_get (reply, "(h)", &index);
484 fd = g_unix_fd_list_get(out_fd_list, index, NULL);
486 g_variant_unref(reply);
488 BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
490 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
494 BT_PROPERTIES_INTERFACE,
498 BT_ERR("Unable to create proxy: %s", err->message);
500 return BLUETOOTH_ERROR_INTERNAL;
503 dev_path = g_strdup(BLUEZ_HDP_CHANNEL_INTERFACE);
505 reply = g_dbus_proxy_call_sync(proxy, "GetAll",
506 g_variant_new("(s)", dev_path),
507 G_DBUS_CALL_FLAGS_NONE,
513 g_object_unref(proxy);
516 BT_ERR(" HDP:dbus Can't get the reply");
519 BT_ERR("%s", err->message);;
523 return BLUETOOTH_ERROR_INTERNAL;
526 g_variant_get (reply, "(a{sv})", &property_iter);
528 while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
529 BT_DBG("String received = %s\n", property);
531 if (g_strcmp0("Type", property) == 0) {
532 type_qos = g_variant_dup_string (value, &len);
533 } else if (g_strcmp0("Device", property) == 0) {
534 device = g_variant_dup_string (value, &len);
535 } else if (g_strcmp0("Application", property) == 0) {
536 app_handle = g_variant_dup_string (value, &len);
540 g_variant_unref(reply);
541 BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
542 type_qos, device, app_handle);
544 if (NULL == type_qos || NULL == app_handle) {
545 BT_ERR("Pasing failed\n");
549 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
551 /*Only process register with app handle receive the Connected event */
553 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
557 hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
559 info->obj_channel_path = g_strdup(path);
560 info->watch_id = __bt_hdp_internal_watch_fd(fd, info->obj_channel_path);
561 list->obj_info = g_slist_append(list->obj_info, info);
563 _bt_convert_device_path_to_address(path, address);
565 _bt_convert_addr_string_to_type(device_addr.addr, address);
567 conn_ind.app_handle = app_handle;
568 conn_ind.channel_id = fd;
569 conn_ind.device_address = device_addr;
570 conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ?
571 HDP_QOS_RELIABLE : HDP_QOS_STREAMING;
573 BT_DBG("Going to give callback\n");
575 user_info = _bt_get_user_data(BT_COMMON);
578 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
579 BLUETOOTH_ERROR_NONE, &conn_ind,
580 user_info->cb, user_info->user_data);
583 BT_DBG("Updated fd in the list*\n");
589 return BLUETOOTH_ERROR_NONE;
594 return BLUETOOTH_ERROR_INTERNAL;
597 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
604 gio = g_io_channel_unix_new(file_desc);
606 g_io_channel_set_close_on_unref(gio, TRUE);
608 id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
609 __bt_hdp_internal_data_received, (void *)path);
615 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
617 char address[BT_ADDRESS_STRING_SIZE] = { 0, };
618 bluetooth_device_address_t device_addr = { {0} };
619 bt_hdp_disconnected_t dis_ind;
620 hdp_obj_info_t *info;
621 bt_user_info_t *user_info;
623 BT_INFO("******** Socket Error ******\n");
625 info = __bt_hdp_internal_gslist_obj_find_using_path(path);
626 ret_if(info == NULL);
628 /*Since bluetoothd is not sending the ChannelDeleted signal */
629 _bt_convert_device_path_to_address(path, address);
631 _bt_convert_addr_string_to_type(device_addr.addr, address);
633 dis_ind.channel_id = sk;
634 dis_ind.device_address = device_addr;
636 user_info = _bt_get_user_data(BT_COMMON);
639 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
640 BLUETOOTH_ERROR_NONE, &dis_ind,
641 user_info->cb, user_info->user_data);
644 BT_DBG(" Removed connection from list\n");
646 __bt_hdp_obj_info_free(info);
649 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
650 GIOCondition cond, gpointer data)
652 char buff[HDP_BUFFER_SIZE] = { 0, };
655 bt_hdp_data_ind_t data_ind = { 0, };
656 const char *path = (const char *)data;
657 bt_user_info_t *user_info;
661 sk = g_io_channel_unix_get_fd(gio);
663 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
664 BT_DBG("GIOCondition %d.............path = %s\n", cond, path);
665 g_io_channel_shutdown(gio, TRUE, NULL);
666 g_io_channel_unref(gio);
667 __bt_hdp_internal_handle_disconnect_cb(sk, path);
671 act_read = recv(sk, (void *)buff, sizeof(buff), 0);
674 BT_DBG("Received data of %d\n", act_read);
676 BT_ERR("Read failed.....\n");
680 data_ind.channel_id = sk;
681 data_ind.buffer = buff;
682 data_ind.size = act_read;
684 user_info = _bt_get_user_data(BT_COMMON);
687 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
688 BLUETOOTH_ERROR_NONE, &data_ind,
689 user_info->cb, user_info->user_data);
697 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
701 BT_CHECK_ENABLED(return);
702 BT_CHECK_PARAMETER(app_handle, return);
704 return __bt_hdp_internal_destroy_application(app_handle);
707 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
711 retv_if(g_app_list == NULL, NULL);
713 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
715 for (l = g_app_list; l != NULL; l = l->next) {
716 hdp_app_list_t *list = l->data;
719 if (0 == g_strcmp0((char *)list->app_handle,
727 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
732 retv_if(g_app_list == NULL, NULL);
734 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
736 for (l = g_app_list; l != NULL; l = l->next) {
737 hdp_app_list_t *list = l->data;
741 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
742 hdp_obj_info_t *info = iter->data;
753 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
757 hdp_obj_info_t *info = NULL;
759 retv_if(g_app_list == NULL, NULL);
761 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
762 for (l = g_app_list; l != NULL; l = l->next) {
763 hdp_app_list_t *list = l->data;
767 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
772 if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
773 list->obj_info = g_slist_remove(list->obj_info, info);
781 static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data)
783 const char *app_handle;
784 hdp_app_list_t *list = NULL;
785 app_handle = (const char *)data;
789 list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
791 BT_ERR("**** list not found for %s ******\n", app_handle);
795 g_app_list = g_slist_remove(g_app_list, list);
797 g_free(list->app_handle);
798 g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
801 BT_DBG("List length = %d\n", g_slist_length(g_app_list));
803 if (0 == g_slist_length(g_app_list))
804 __bt_hdp_internal_remove_filter();
809 static int __bt_hdp_internal_destroy_application(const char *app_handle)
811 GDBusProxy *proxy = NULL;
812 GVariant *reply = NULL;
814 GDBusConnection *conn;
815 int result = BLUETOOTH_ERROR_NONE;
817 conn = _bt_gdbus_get_system_gconn();
818 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
820 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
824 BLUEZ_HDP_MANAGER_INTERFACE,
828 BT_ERR("Unable to create proxy: %s", err->message);
830 return BLUETOOTH_ERROR_INTERNAL;
833 reply = g_dbus_proxy_call_sync(proxy, "DestroyApplication",
834 g_variant_new("o", app_handle),
835 G_DBUS_CALL_FLAGS_NONE,
840 g_object_unref(proxy);
842 BT_ERR(" HDP:dbus Can't Destroy application");
845 BT_ERR("%s", err->message);
846 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
847 result = BLUETOOTH_ERROR_ACCESS_DENIED;
849 result = BLUETOOTH_ERROR_INTERNAL;
855 g_variant_unref(reply);
857 BT_DBG("Destroyed health application: %s", (char *)app_handle);
859 g_idle_add(__bt_hdp_internal_destroy_application_cb,
860 (gpointer)app_handle);
862 return BLUETOOTH_ERROR_NONE;
865 static void __bt_hdp_internal_remove_filter(void)
869 ret_if(g_hdp_dus_conn == NULL);
871 __bt_hdp_add_filter_subscribe_signal(g_hdp_dus_conn, FALSE);
873 g_hdp_dus_conn = NULL; /*should not unref here, bcz no ++reff */
878 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
888 BT_CHECK_ENABLED(return);
890 if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
891 BT_ERR("Invalid arguments..\n");
892 return BLUETOOTH_ERROR_INVALID_PARAM;
895 switch (privilege_token) {
897 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
899 if (result == BLUETOOTH_ERROR_NONE) {
900 privilege_token = 1; /* Have a permission */
901 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
902 BT_ERR("Don't have a privilege to use this API");
903 privilege_token = -1; /* Don't have a permission */
904 return BLUETOOTH_ERROR_PERMISSION_DEINED;
906 /* Just break - It is not related with permission error */
910 /* Already have a privilege */
913 return BLUETOOTH_ERROR_PERMISSION_DEINED;
915 /* Invalid privilge token value */
916 return BLUETOOTH_ERROR_INTERNAL;
919 while (wbytes < size) {
920 written = write(channel_id, buffer + wbytes, size - wbytes);
922 BT_ERR("write failed..\n");
923 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
928 return BLUETOOTH_ERROR_NONE;
931 static void __bt_hdp_connect_request_cb(GDBusProxy *hdp_proxy,
932 GAsyncResult *res, gpointer user_data)
935 char *obj_connect_path = NULL;
936 bt_hdp_connected_t *conn_ind = user_data;
937 bt_user_info_t *user_info;
938 GVariant *reply = NULL;
939 int ret = BLUETOOTH_ERROR_NONE;
941 reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
943 g_object_unref(hdp_proxy);
947 BT_ERR("HDP connection Dbus Call Error: %s\n", err->message);
951 user_info = _bt_get_user_data(BT_COMMON);
954 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
955 BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind,
956 user_info->cb, user_info->user_data);
959 g_variant_get(reply, "(&o)", &obj_connect_path);
961 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
962 user_info = _bt_get_user_data(BT_COMMON);
964 ret = __bt_hdp_internal_acquire_fd(obj_connect_path);
965 if (ret != BLUETOOTH_ERROR_NONE) {
966 user_info = _bt_get_user_data(BT_COMMON);
968 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
969 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
970 user_info->cb, user_info->user_data);
973 g_variant_unref(reply);
975 g_free((void *)conn_ind->app_handle);
980 BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle,
981 bt_hdp_qos_type_t channel_type,
982 const bluetooth_device_address_t *device_address)
985 GDBusConnection *conn = NULL;
986 GDBusProxy *hdp_proxy = NULL;
987 bt_hdp_connected_t *param;
988 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
989 char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
990 char *dev_path = NULL;
995 BT_CHECK_ENABLED(return);
996 BT_CHECK_PARAMETER(app_handle, return);
997 BT_CHECK_PARAMETER(device_address, return);
999 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_CONNECT)
1000 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1001 BT_ERR("Don't have a privilege to use this API");
1002 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1005 if (channel_type == HDP_QOS_RELIABLE) {
1007 } else if (channel_type == HDP_QOS_STREAMING) {
1009 } else if (channel_type == HDP_QOS_ANY) {
1012 BT_ERR("Invalid channel_type %d", channel_type);
1013 return BLUETOOTH_ERROR_ACCESS_DENIED;
1016 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1019 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1020 g_clear_error(&err);
1021 return BLUETOOTH_ERROR_INTERNAL;
1024 /* If the adapter path is wrong, we can think the BT is not enabled. */
1025 if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1026 default_adapter_path) < 0) {
1027 BT_ERR("Could not get adapter path\n");
1028 g_object_unref(conn);
1029 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1032 _bt_convert_addr_type_to_string(address,
1033 (unsigned char *)device_address->addr);
1035 BT_DBG("create conection to %s", address);
1037 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1039 if (dev_path == NULL) {
1040 g_object_unref(conn);
1041 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1044 g_strdelimit(dev_path, ":", '_');
1046 BT_DBG("path: %s", dev_path);
1048 hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1049 NULL, BT_BLUEZ_NAME,
1050 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1052 g_object_unref(conn);
1054 if (hdp_proxy == NULL) {
1055 BT_ERR("Failed to get the HDP server proxy\n");
1057 return BLUETOOTH_ERROR_NOT_PAIRED;
1060 BT_DBG("app path %s\n", app_handle);
1062 param = g_new0(bt_hdp_connected_t, 1);
1063 param->app_handle = g_strdup(app_handle);
1064 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1065 param->type = channel_type;
1067 g_dbus_proxy_call(hdp_proxy, "CreateChannel",
1068 g_variant_new("(os)", app_handle, role),
1069 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1070 (GAsyncReadyCallback)__bt_hdp_connect_request_cb,
1074 g_free((void *)param->app_handle);
1076 g_object_unref(hdp_proxy);
1078 return BLUETOOTH_ERROR_NONE;
1081 static void __bt_hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
1082 GAsyncResult *res, gpointer user_data)
1085 bt_hdp_disconnected_t *disconn_ind = user_data;
1086 bt_user_info_t *user_info;
1087 GVariant *reply = NULL;
1089 reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1090 g_object_unref(hdp_proxy);
1092 user_info = _bt_get_user_data(BT_COMMON);
1093 if (user_info == NULL || user_info->cb == NULL) {
1094 g_free(disconn_ind);
1096 g_clear_error(&err);
1099 g_variant_unref(reply);
1105 BT_ERR("HDP disconnection Dbus Call Error: %s\n",
1107 g_clear_error(&err);
1110 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1111 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1112 user_info->cb, user_info->user_data);
1114 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1115 BLUETOOTH_ERROR_NONE, disconn_ind,
1116 user_info->cb, user_info->user_data);
1117 BT_INFO("HDP disconnection Dbus Call is done\n");
1118 g_variant_unref(reply);
1121 g_free(disconn_ind);
1124 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1125 const bluetooth_device_address_t *device_address)
1128 GDBusConnection *conn = NULL;
1129 GDBusProxy *hdp_proxy = NULL;
1130 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1131 char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1132 char *dev_path = NULL;
1133 bt_hdp_disconnected_t *param;
1137 BT_CHECK_ENABLED(return);
1138 BT_CHECK_PARAMETER(device_address, return);
1140 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_DISCONNECT)
1141 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1142 BT_ERR("Don't have a privilege to use this API");
1143 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1146 hdp_obj_info_t *info =
1147 __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1149 BT_ERR("*** Could not locate the list for %d*****\n",
1151 return BLUETOOTH_ERROR_INVALID_PARAM;
1154 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1157 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1158 g_clear_error(&err);
1159 return BLUETOOTH_ERROR_INTERNAL;
1162 /* If the adapter path is wrong, we can think the BT is not enabled. */
1163 if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1164 default_adapter_path) < 0) {
1165 BT_ERR("Could not get adapter path\n");
1166 g_object_unref(conn);
1167 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1170 _bt_convert_addr_type_to_string(address,
1171 (unsigned char *)device_address->addr);
1173 BT_DBG("create conection to %s\n", address);
1175 dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1177 if (dev_path == NULL) {
1178 g_object_unref(conn);
1179 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1182 g_strdelimit(dev_path, ":", '_');
1184 BT_DBG("path %s\n", dev_path);
1186 hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1187 NULL, BT_BLUEZ_NAME,
1188 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1191 g_object_unref(conn);
1193 if (hdp_proxy == NULL) {
1194 BT_ERR("Failed to get the HDP proxy\n");
1196 return BLUETOOTH_ERROR_NOT_PAIRED;
1199 param = g_new0(bt_hdp_disconnected_t, 1);
1200 param->channel_id = channel_id;
1201 memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1203 g_dbus_proxy_call(hdp_proxy, "DestroyChannel",
1204 g_variant_new("o", info->obj_channel_path),
1205 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1206 (GAsyncReadyCallback)__bt_hdp_disconnect_request_cb,
1211 g_object_unref(hdp_proxy);
1213 return BLUETOOTH_ERROR_NONE;