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 <dbus/dbus-glib.h>
21 #include <dbus/dbus.h>
25 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
26 #include <syspopup_caller.h>
29 #include "bluetooth-api.h"
30 #include "bt-internal-types.h"
32 #include "bt-service-audio.h"
33 #include "bt-service-adapter.h"
34 #include "bt-service-common.h"
35 #include "bt-service-event.h"
36 #include "bt-service-util.h"
41 char device_address[BT_ADDRESS_STRING_SIZE + 1];
42 } bt_connected_headset_data_t;
44 static GList *g_connected_list;
46 static bt_headset_wait_t *g_wait_data;
48 static void __bt_remove_device_from_wait_list();
50 static void __bt_free_wait_data();
52 static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
55 GError *g_error = NULL;
56 GArray *out_param1 = NULL;
57 GArray *out_param2 = NULL;
58 int result = BLUETOOTH_ERROR_NONE;
59 bt_function_data_t *func_data;
60 request_info_t *req_info;
62 dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID);
64 g_object_unref(proxy);
66 func_data = user_data;
68 if (func_data == NULL) {
70 BT_ERR("func_data == NULL");
74 req_info = _bt_get_request_info(func_data->req_id);
75 if (req_info == NULL) {
76 BT_ERR("req_info == NULL");
83 BT_ERR("Audio Connect Dbus Call Error: %s\n", g_error->message);
85 result = BLUETOOTH_ERROR_INTERNAL;
87 /* Remove the device from the list */
88 _bt_remove_headset_from_list(BT_AUDIO_ALL, func_data->address);
90 /* Error, check if any waiting device is there */
91 if (g_wait_data == NULL)
94 if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
95 bluetooth_device_address_t device_address;
96 _bt_convert_addr_string_to_type(device_address.addr,
97 g_wait_data->address);
98 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
99 &device_address, g_wait_data->out_param1);
102 /* Event will be sent by the event reciever */
104 if (req_info->context == NULL)
107 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
108 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
110 g_array_append_vals(out_param1, func_data->address,
112 g_array_append_vals(out_param2, &result, sizeof(int));
114 dbus_g_method_return(req_info->context, out_param1, out_param2);
116 g_array_free(out_param1, TRUE);
117 g_array_free(out_param2, TRUE);
119 _bt_delete_request_list(req_info->req_id);
122 g_error_free(g_error);
125 g_free(func_data->address);
130 static char *__bt_get_audio_path(bluetooth_device_address_t *address)
133 char *object_path = NULL;
134 char addr_str[BT_ADDRESS_STRING_SIZE + 1] = { 0 };
135 DBusGProxy *audio_proxy;
136 DBusGProxy *adapter_proxy;
137 DBusGConnection *g_conn;
139 retv_if(address == NULL, NULL);
141 g_conn = _bt_get_system_gconn();
142 retv_if(g_conn == NULL, NULL);
144 adapter_proxy = _bt_get_adapter_proxy();
145 retv_if(adapter_proxy == NULL, NULL);
147 _bt_convert_addr_type_to_string(addr_str, address->addr);
149 object_path = _bt_get_device_object_path(addr_str);
151 retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
153 audio_proxy = dbus_g_proxy_new_for_name(g_conn,
156 BT_HFP_AGENT_INTERFACE);
158 retv_if(audio_proxy == NULL, NULL);
160 g_object_unref(audio_proxy);
165 static char *__bt_get_connected_audio_path(void)
169 char *audio_path = NULL;
171 bluetooth_device_info_t info;
173 /* allocate the g_pointer_array */
174 device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
176 if (_bt_get_bonded_devices(&device_list)
177 != BLUETOOTH_ERROR_NONE) {
178 g_array_free(device_list, TRUE);
182 size = (device_list->len) / sizeof(bluetooth_device_info_t);
184 for (i = 0; i < size; i++) {
186 info = g_array_index(device_list,
187 bluetooth_device_info_t, i);
189 if (info.connected == TRUE) {
190 audio_path = __bt_get_audio_path(&info.device_address);
196 g_array_free(device_list, TRUE);
201 static void __bt_free_wait_data()
203 if (g_wait_data != NULL) {
204 g_free(g_wait_data->address);
210 static void __bt_remove_device_from_wait_list()
212 /* Before deleting the request update the UI */
213 GArray *out_param_1 = NULL;
214 GArray *out_param_2 = NULL;
215 int result = BLUETOOTH_ERROR_INTERNAL;
216 request_info_t *req_info;
218 req_info = _bt_get_request_info(g_wait_data->req_id);
219 if (req_info == NULL) {
220 BT_ERR("req_info == NULL");
224 out_param_1 = g_array_new(FALSE, FALSE, sizeof(gchar));
225 out_param_2 = g_array_new(FALSE, FALSE, sizeof(gchar));
226 g_array_append_vals(out_param_1, g_wait_data->address,
228 g_array_append_vals(out_param_2, &result, sizeof(int));
229 dbus_g_method_return(req_info->context,
230 out_param_1, out_param_2);
231 g_array_free(out_param_1, TRUE);
232 g_array_free(out_param_2, TRUE);
233 _bt_delete_request_list(g_wait_data->req_id);
236 static void __bt_set_headset_disconnection_type(const char *address)
238 bt_connected_headset_data_t *connected_device;
241 BT_DBG("__bt_set_headset_disconnection_type \n");
243 node = g_list_first(g_connected_list);
244 while (node != NULL) {
245 connected_device = node->data;
246 if (g_strcmp0(connected_device->device_address, address) == 0) {
247 g_wait_data->disconnection_type = connected_device->type;
250 node = g_list_next(node);
254 gboolean _bt_is_headset_type_connected(int type, char *address)
258 BT_DBG("_bt_is_headset_type_connected \n");
260 node = g_list_first(g_connected_list);
261 while (node != NULL) {
262 bt_connected_headset_data_t *connected_device = node->data;
264 if (connected_device->type & type) {
266 g_strlcpy(address, connected_device->device_address,
267 BT_ADDRESS_STRING_SIZE + 1);
271 node = g_list_next(node);
276 static gboolean __bt_is_headset_connected(int type, int req_id,
277 const char *address, GArray **out_param1)
280 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
281 bluetooth_device_address_t device_address;
283 BT_DBG("__bt_is_headset_connected \n");
285 /* Check if any other headset is connected */
286 connected = _bt_is_headset_type_connected(type, connected_address);
291 /* If already one device is waiting, remove current waiting device and add new */
292 if (g_wait_data != NULL) {
293 if (g_strcmp0(g_wait_data->address, address) != 0) {
294 __bt_remove_device_from_wait_list();
295 __bt_free_wait_data();
299 if (g_wait_data == NULL) {
300 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
301 g_wait_data->address = g_strdup(address);
302 g_wait_data->req_id = req_id;
303 g_wait_data->type = type;
304 g_wait_data->ag_flag = FALSE;
305 g_wait_data->out_param1 = out_param1;
307 /* Set disconnection type */
308 __bt_set_headset_disconnection_type(connected_address);
311 /* Convert BD adress from string type */
312 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
313 _bt_audio_disconnect(0, type, &device_address, NULL);
317 void _bt_set_audio_wait_data_flag(gboolean flag)
319 BT_DBG("_bt_set_audio_wait_data_flag \n");
320 g_wait_data->ag_flag = flag;
323 bt_headset_wait_t *_bt_get_audio_wait_data(void)
325 BT_DBG("_bt_get_audio_wait_data \n");
329 void _bt_add_headset_to_list(int type, int status, const char *address)
331 bt_connected_headset_data_t *connected_device;
332 bt_connected_headset_data_t *device;
335 BT_DBG("_bt_add_headset_to_list \n");
337 node = g_list_first(g_connected_list);
338 while (node != NULL) {
339 device = (bt_connected_headset_data_t *)node->data;
341 if (g_strcmp0(device->device_address, address) == 0) {
342 BT_DBG("Address match, update connection type \n");
343 device->type |= type;
344 device->device_state = status;
347 node = g_list_next(node);
350 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
351 connected_device->type |= type;
352 connected_device->device_state = status;
353 g_strlcpy(connected_device->device_address, address,
354 sizeof(connected_device->device_address));
355 g_connected_list = g_list_append(g_connected_list, connected_device);
358 void _bt_remove_headset_from_list(int type, const char *address)
362 BT_DBG("_bt_remove_headset_from_list \n");
364 node = g_list_first(g_connected_list);
365 while (node != NULL) {
366 bt_connected_headset_data_t *connected_device = node->data;
368 if (g_strcmp0(connected_device->device_address, address) != 0) {
369 node = g_list_next(node);
373 BT_DBG("Address match \n");
375 BT_DBG("Connection type = %x\n", connected_device->type);
379 if (connected_device->type & BT_AUDIO_A2DP)
380 connected_device->type &= ~(BT_AUDIO_A2DP);
383 if (connected_device->type & BT_AUDIO_HSP)
384 connected_device->type &= ~(BT_AUDIO_HSP);
387 if (connected_device->type & BT_AUDIO_ALL)
388 connected_device->type &= ~(BT_AUDIO_ALL);
392 BT_DBG("Connection type = %x\n", connected_device->type);
394 if (connected_device->type == 0x00) {
395 g_connected_list = g_list_remove(g_connected_list, connected_device);
396 g_free(connected_device);
399 node = g_list_next(node);
403 int _bt_audio_connect(int request_id, int type,
404 bluetooth_device_address_t *device_address,
407 int result = BLUETOOTH_ERROR_NONE;
408 gchar *device_path = NULL;
410 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
411 bt_function_data_t *func_data;
412 DBusGProxy *adapter_proxy;
413 DBusGProxy *profile_proxy;
414 DBusGConnection *g_conn;
416 BT_CHECK_PARAMETER(device_address, return);
418 _bt_convert_addr_type_to_string(address, device_address->addr);
425 uuid = A2DP_SINK_UUID;
428 uuid = GENERIC_AUDIO_UUID;
431 BT_ERR("Unknown role");
432 result = BLUETOOTH_ERROR_INTERNAL;
436 if (__bt_is_headset_connected(type, request_id, address, out_param1))
437 return BLUETOOTH_ERROR_NONE;
439 adapter_proxy = _bt_get_adapter_proxy();
440 if (adapter_proxy == NULL) {
441 result = BLUETOOTH_ERROR_INTERNAL;
445 device_path = _bt_get_device_object_path(address);
446 if (device_path == NULL) {
447 result = BLUETOOTH_ERROR_INTERNAL;
451 g_conn = _bt_get_system_gconn();
452 if (g_conn == NULL) {
453 result = BLUETOOTH_ERROR_INTERNAL;
457 profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
458 device_path, BT_DEVICE_INTERFACE);
462 if (profile_proxy == NULL) {
463 result = BLUETOOTH_ERROR_INTERNAL;
467 func_data = g_malloc0(sizeof(bt_function_data_t));
468 func_data->address = g_strdup(address);
469 func_data->req_id = request_id;
471 if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){
472 if (!dbus_g_proxy_begin_call(profile_proxy, "Connect",
473 (DBusGProxyCallNotify)__bt_audio_request_cb,
476 BT_ERR("Audio connect Dbus Call Error");
477 g_object_unref(profile_proxy);
479 g_free(func_data->address);
482 result = BLUETOOTH_ERROR_INTERNAL;
486 if (!dbus_g_proxy_begin_call(profile_proxy, "ConnectProfile",
487 (DBusGProxyCallNotify)__bt_audio_request_cb,
491 BT_ERR("Audio connect Dbus Call Error");
492 g_object_unref(profile_proxy);
494 g_free(func_data->address);
497 result = BLUETOOTH_ERROR_INTERNAL;
501 /* Add data to the connected list */
502 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
503 __bt_free_wait_data();
505 return BLUETOOTH_ERROR_NONE;
507 g_array_append_vals(*out_param1, address,
513 int _bt_audio_disconnect(int request_id, int type,
514 bluetooth_device_address_t *device_address,
517 int result = BLUETOOTH_ERROR_NONE;
518 gchar *device_path = NULL;
520 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
521 bt_function_data_t *func_data;
522 DBusGProxy *adapter_proxy;
523 DBusGProxy *profile_proxy;
524 DBusGConnection *g_conn;
526 BT_CHECK_PARAMETER(device_address, return);
528 _bt_convert_addr_type_to_string(address, device_address->addr);
535 uuid = A2DP_SINK_UUID;
538 uuid = GENERIC_AUDIO_UUID;
541 BT_ERR("Unknown role");
542 return BLUETOOTH_ERROR_INTERNAL;
545 adapter_proxy = _bt_get_adapter_proxy();
546 if (adapter_proxy == NULL) {
547 result = BLUETOOTH_ERROR_INTERNAL;
551 device_path = _bt_get_device_object_path(address);
552 if (device_path == NULL) {
553 result = BLUETOOTH_ERROR_INTERNAL;
557 g_conn = _bt_get_system_gconn();
558 if (g_conn == NULL) {
559 result = BLUETOOTH_ERROR_INTERNAL;
563 profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
564 device_path, BT_DEVICE_INTERFACE);
568 if (profile_proxy == NULL) {
569 result = BLUETOOTH_ERROR_INTERNAL;
573 if (g_wait_data != NULL) {
574 if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){
575 if (!dbus_g_proxy_begin_call(profile_proxy,
576 "Disconnect",NULL, NULL, NULL,
578 BT_ERR("Audio disconnect Dbus Call Error");
579 g_object_unref(profile_proxy);
580 return BLUETOOTH_ERROR_INTERNAL;
583 if (!dbus_g_proxy_begin_call(profile_proxy,
584 "DisconnectProfile",NULL, NULL, NULL,
587 BT_ERR("Audio disconnect Dbus Call Error");
588 g_object_unref(profile_proxy);
589 return BLUETOOTH_ERROR_INTERNAL;
593 func_data = g_malloc0(sizeof(bt_function_data_t));
594 func_data->address = g_strdup(address);
595 func_data->req_id = request_id;
596 if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){
597 if (!dbus_g_proxy_begin_call(profile_proxy,
599 (DBusGProxyCallNotify)__bt_audio_request_cb,
602 BT_ERR("Audio disconnect Dbus Call Error");
603 g_object_unref(profile_proxy);
605 g_free(func_data->address);
608 result = BLUETOOTH_ERROR_INTERNAL;
612 if (!dbus_g_proxy_begin_call(profile_proxy,
614 (DBusGProxyCallNotify)__bt_audio_request_cb,
618 BT_ERR("Audio disconnect Dbus Call Error");
619 g_object_unref(profile_proxy);
621 g_free(func_data->address);
624 result = BLUETOOTH_ERROR_INTERNAL;
630 return BLUETOOTH_ERROR_NONE;
632 g_array_append_vals(*out_param1, address,
638 int _bt_audio_get_speaker_gain(unsigned int *gain)
640 char *device_path = NULL;
641 DBusGProxy *adapter_proxy;
642 DBusGProxy *profile_proxy;
643 DBusGConnection *g_conn;
644 GHashTable *hash = NULL;
647 adapter_proxy = _bt_get_adapter_proxy();
648 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
650 g_conn = _bt_get_system_gconn();
651 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
653 device_path = __bt_get_connected_audio_path();
654 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
656 profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
657 device_path, BT_HFP_AGENT_INTERFACE);
661 retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
663 dbus_g_proxy_call(profile_proxy, "GetProperties", NULL,
665 dbus_g_type_get_map("GHashTable",
666 G_TYPE_STRING, G_TYPE_VALUE),
667 &hash, G_TYPE_INVALID);
669 g_object_unref(profile_proxy);
671 retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
673 value = g_hash_table_lookup(hash, "SpeakerGain");
674 *gain = value ? g_value_get_uint(value) : 0;
675 g_hash_table_destroy(hash);
676 return BLUETOOTH_ERROR_NONE;
679 int _bt_audio_set_speaker_gain(unsigned int gain)
681 char *device_path = NULL;
682 char *gain_str = "SpeakerGain";
683 char sig[2] = {DBUS_TYPE_UINT16, '\0'};
684 int ret = BLUETOOTH_ERROR_NONE;
686 DBusMessageIter iter;
687 DBusMessageIter value;
688 DBusConnection *conn;
690 conn = _bt_get_system_conn();
691 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
693 device_path = __bt_get_connected_audio_path();
694 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
696 msg = dbus_message_new_method_call(BT_BLUEZ_NAME,
697 device_path, BT_HFP_AGENT_INTERFACE,
702 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
704 dbus_message_iter_init_append(msg, &iter);
705 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
707 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
709 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
711 dbus_message_iter_close_container(&iter, &value);
713 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
714 dbus_message_set_no_reply(msg, TRUE);
716 if (!dbus_connection_send(conn, msg, NULL)) {
717 BT_ERR("Dbus sending failed\n");
718 ret = BLUETOOTH_ERROR_INTERNAL;
720 dbus_message_unref(msg);