a85d4ed30424c2c286fb5434a737b03914085c9a
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-audio.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *
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
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
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.
21  *
22  */
23
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus.h>
26 #include <glib.h>
27 #include <dlog.h>
28 #include <string.h>
29 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
30 #include <syspopup_caller.h>
31 #endif
32
33 #include "bluetooth-api.h"
34 #include "bt-internal-types.h"
35
36 #include "bt-service-audio.h"
37 #include "bt-service-adapter.h"
38 #include "bt-service-common.h"
39 #include "bt-service-device.h"
40 #include "bt-service-event.h"
41 #include "bt-service-util.h"
42
43 #include "bt-service-headset-connection.h"
44
45 #ifdef TIZEN_SUPPORT_DUAL_HF
46 #ifdef TIZEN_WEARABLE
47 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
48 #endif
49 #endif
50
51 typedef struct {
52         unsigned int type;
53         int device_state;
54         char device_address[BT_ADDRESS_STRING_SIZE + 1];
55 } bt_connected_headset_data_t;
56
57 static GList *g_connected_list;
58
59 static bt_headset_wait_t *g_wait_data;
60
61 static bt_audio_function_data_t *pdata;
62
63 static void __bt_remove_device_from_wait_list();
64
65 static void __bt_free_wait_data();
66
67 static gboolean __bt_device_support_uuid(char *remote_address,
68                                 bt_audio_type_t type);
69
70 static void __bt_hf_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
71                                     gpointer user_data)
72 {
73         GError *g_error = NULL;
74         GArray *out_param1 = NULL;
75         GArray *out_param2 = NULL;
76         int result = BLUETOOTH_ERROR_NONE;
77         bt_function_data_t *func_data;
78         request_info_t *req_info;
79
80         dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID);
81
82         g_object_unref(proxy);
83
84         func_data = user_data;
85
86         if (func_data == NULL) {
87                 /* Send reply */
88                 BT_ERR("func_data == NULL");
89                 goto done;
90         }
91
92         req_info = _bt_get_request_info(func_data->req_id);
93         if (req_info == NULL) {
94                 BT_ERR("req_info == NULL");
95                 goto done;
96         }
97
98         if (g_error == NULL)
99                 goto dbus_return;
100
101         BT_ERR("HFG request Dbus Call Error: %s\n", g_error->message);
102
103         result = BLUETOOTH_ERROR_INTERNAL;
104
105 dbus_return:
106         if (req_info->context == NULL)
107                 goto done;
108
109         out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
110         out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
111
112         g_array_append_vals(out_param1, func_data->address,
113                                 BT_ADDRESS_STR_LEN);
114         g_array_append_vals(out_param2, &result, sizeof(int));
115
116         dbus_g_method_return(req_info->context, out_param1, out_param2);
117
118         g_array_free(out_param1, TRUE);
119         g_array_free(out_param2, TRUE);
120
121         _bt_delete_request_list(req_info->req_id);
122 done:
123         if (g_error)
124                 g_error_free(g_error);
125
126         if (func_data) {
127                 g_free(func_data->address);
128                 g_free(func_data);
129         }
130 }
131
132 void _bt_audio_check_pending_connect()
133 {
134         BT_DBG("+");
135         bluetooth_device_address_t device_address;
136
137         if (pdata == NULL)
138                 return;
139
140         if (pdata->pending == BT_PENDING_CONNECT) {
141
142                 _bt_convert_addr_string_to_type(device_address.addr,
143                                 pdata->address);
144
145                 _bt_audio_connect(pdata->req_id,
146                                 BT_AUDIO_A2DP,
147                                 &device_address,
148                                 pdata->out_param);
149
150                 g_free(pdata->address);
151                 g_free(pdata);
152                 pdata = NULL;
153         }
154
155         BT_DBG("-");
156         return;
157 }
158
159 static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
160                                     gpointer user_data)
161 {
162         GError *g_error = NULL;
163         GArray *out_param1 = NULL;
164         GArray *out_param2 = NULL;
165         int result = BLUETOOTH_ERROR_NONE;
166
167         bt_audio_function_data_t *func_data;
168
169         request_info_t *req_info;
170
171         dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID);
172
173         g_object_unref(proxy);
174
175         func_data = user_data;
176
177         if (func_data == NULL) {
178                 /* Send reply */
179                 BT_ERR("func_data == NULL");
180                 goto done;
181         }
182
183         if (func_data->pending != BT_PENDING_NONE && g_error == NULL) {
184
185                 bluetooth_device_address_t device_address;
186                 _bt_convert_addr_string_to_type(device_address.addr,
187                                         func_data->address);
188
189                 if (func_data->pending == BT_PENDING_CONNECT) {
190
191                         if (__bt_device_support_uuid(func_data->address,
192                                                         BT_AUDIO_A2DP)) {
193
194                                 pdata = g_new0(bt_audio_function_data_t, 1);
195                                 pdata->req_id = func_data->req_id;
196                                 pdata->out_param = func_data->out_param;
197                                 pdata->address = strdup(func_data->address);
198                                 pdata->pending = func_data->pending;
199                         } else
200                                 goto check_req_info;
201
202                 } else {
203
204                         if (_bt_is_service_connected(func_data->address
205                                                         , BT_AUDIO_A2DP)) {
206                                 _bt_audio_disconnect(func_data->req_id,
207                                         BT_AUDIO_A2DP,
208                                         &device_address,
209                                         func_data->out_param);
210                         } else
211                                 goto check_req_info;
212                 }
213
214                 goto done;
215         }
216
217 check_req_info:
218         req_info = _bt_get_request_info(func_data->req_id);
219         if (req_info == NULL) {
220                 BT_ERR("req_info == NULL");
221                 goto done;
222         }
223
224         if (g_error == NULL)
225                 goto dbus_return;
226
227         BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
228
229         result = BLUETOOTH_ERROR_INTERNAL;
230
231         /* Remove the device from the list */
232         _bt_remove_headset_from_list(func_data->type, func_data->address);
233
234         /* Error, check if any waiting device is there */
235         if (g_wait_data == NULL)
236                 goto dbus_return;
237
238         if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
239                 bluetooth_device_address_t device_address;
240                 _bt_convert_addr_string_to_type(device_address.addr,
241                                 g_wait_data->address);
242                 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
243                                 &device_address, g_wait_data->out_param1);
244         }
245
246         /* Event will be sent by the event reciever */
247 dbus_return:
248         if (req_info->context == NULL) {
249                 BT_DBG("req_info->context is NULL");
250                 goto done;
251         }
252
253         out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
254         out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
255
256         g_array_append_vals(out_param1, func_data->address,
257                         BT_ADDRESS_STR_LEN);
258         g_array_append_vals(out_param2, &result, sizeof(int));
259
260         dbus_g_method_return(req_info->context, out_param1, out_param2);
261
262         g_array_free(out_param1, TRUE);
263         g_array_free(out_param2, TRUE);
264
265         _bt_delete_request_list(req_info->req_id);
266 done:
267         if (g_error)
268                 g_error_free(g_error);
269
270         if (func_data) {
271                 g_free(func_data->address);
272                 g_free(func_data);
273         }
274 }
275
276 static char *__bt_get_audio_path(bluetooth_device_address_t *address)
277 {
278
279         char *object_path = NULL;
280         char addr_str[BT_ADDRESS_STRING_SIZE + 1] = { 0 };
281         DBusGProxy *audio_proxy;
282         DBusGProxy *adapter_proxy;
283         DBusGConnection *g_conn;
284
285         retv_if(address == NULL, NULL);
286
287         g_conn = _bt_get_system_gconn();
288         retv_if(g_conn == NULL, NULL);
289
290         adapter_proxy = _bt_get_adapter_proxy();
291         retv_if(adapter_proxy == NULL, NULL);
292
293         _bt_convert_addr_type_to_string(addr_str, address->addr);
294
295         object_path = _bt_get_device_object_path(addr_str);
296
297         retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
298
299         audio_proxy = dbus_g_proxy_new_for_name(g_conn,
300                                         BT_BLUEZ_NAME,
301                                         object_path,
302                                         BT_HFP_AGENT_INTERFACE);
303
304         retv_if(audio_proxy == NULL, NULL);
305
306         g_object_unref(audio_proxy);
307
308         return object_path;
309 }
310
311 static char *__bt_get_connected_audio_path(void)
312 {
313         int i;
314         guint size;
315         char *audio_path = NULL;
316         GArray *device_list;
317         bluetooth_device_info_t info;
318
319         /* allocate the g_pointer_array */
320         device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
321
322         if (_bt_get_bonded_devices(&device_list)
323                         != BLUETOOTH_ERROR_NONE) {
324                 g_array_free(device_list, TRUE);
325                 return NULL;
326         }
327
328         size = device_list->len;
329         size = (device_list->len) / sizeof(bluetooth_device_info_t);
330
331         for (i = 0; i < size; i++) {
332
333                 info = g_array_index(device_list,
334                                 bluetooth_device_info_t, i);
335
336                 if (info.connected == TRUE) {
337                         audio_path = __bt_get_audio_path(&info.device_address);
338                         if (audio_path)
339                                 break;
340                 }
341         }
342
343         g_array_free(device_list, TRUE);
344
345         return audio_path;
346 }
347
348 static void __bt_free_wait_data()
349 {
350         if (g_wait_data != NULL) {
351                 g_free(g_wait_data->address);
352                 g_free(g_wait_data);
353                 g_wait_data = NULL;
354         }
355 }
356
357 static void __bt_remove_device_from_wait_list()
358 {
359         /* Before deleting the request update the UI */
360         GArray *out_param_1 = NULL;
361         GArray *out_param_2 = NULL;
362         int result = BLUETOOTH_ERROR_INTERNAL;
363         request_info_t *req_info;
364
365         req_info = _bt_get_request_info(g_wait_data->req_id);
366         if (req_info == NULL) {
367                 BT_ERR("req_info == NULL");
368                 return;
369         }
370
371         out_param_1 = g_array_new(FALSE, FALSE, sizeof(gchar));
372         out_param_2 = g_array_new(FALSE, FALSE, sizeof(gchar));
373         g_array_append_vals(out_param_1, g_wait_data->address,
374                         BT_ADDRESS_STR_LEN);
375         g_array_append_vals(out_param_2, &result, sizeof(int));
376         dbus_g_method_return(req_info->context,
377                         out_param_1, out_param_2);
378         g_array_free(out_param_1, TRUE);
379         g_array_free(out_param_2, TRUE);
380         _bt_delete_request_list(g_wait_data->req_id);
381 }
382
383 static void __bt_set_headset_disconnection_type(const char *address)
384 {
385         bt_connected_headset_data_t *connected_device;
386         GList *node;
387
388         node = g_list_first(g_connected_list);
389         while (node != NULL) {
390                 connected_device = node->data;
391                 if (g_strcmp0(connected_device->device_address, address) == 0) {
392                         g_wait_data->disconnection_type = connected_device->type;
393                         return;
394                 }
395                 node = g_list_next(node);
396         }
397 }
398
399 gboolean _bt_is_headset_type_connected(int type, char *address)
400 {
401         GList *node;
402
403         node = g_list_first(g_connected_list);
404         while (node != NULL) {
405                 bt_connected_headset_data_t *connected_device = node->data;
406
407                 if (connected_device->type & type) {
408                         if (address != NULL)
409                                 g_strlcpy(address, connected_device->device_address,
410                                                 BT_ADDRESS_STRING_SIZE + 1);
411                         return TRUE;
412                 }
413
414                 node = g_list_next(node);
415         }
416         return FALSE;
417 }
418
419 #ifdef TIZEN_SUPPORT_DUAL_HF
420 gboolean __bt_is_companion_device(const char *addr)
421 {
422 #ifdef TIZEN_WEARABLE
423         char *host_device_address = NULL;
424         host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
425
426         if (!host_device_address) {
427                 BT_INFO("Failed to get a companion device address");
428                 return FALSE;
429         }
430
431         if (g_strcmp0(host_device_address, addr) == 0) {
432                 BT_INFO("addr[%s] is companion device", addr);
433                 return TRUE;
434         }
435
436         return FALSE;
437 #else
438         /* TODO : Need to add companion device check condition for Phone models */
439         return FALSE;
440 #endif
441 }
442 #endif
443
444 static int __bt_is_headset_connected(int type, int req_id,
445                                 const char *address, GArray **out_param1)
446 {
447         gboolean connected = FALSE;
448         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
449         bluetooth_device_address_t device_address;
450         bt_connected_headset_data_t *connected_device = NULL;
451 #ifdef TIZEN_SUPPORT_DUAL_HF
452         gboolean is_companion_device = FALSE;
453 #endif
454
455         /* Check if any other headset is connected */
456         GList *node = NULL;;
457
458         node = g_list_first(g_connected_list);
459         while (node != NULL) {
460                 connected_device = node->data;
461                 if ((connected_device->type & type) == type) {
462                         g_strlcpy(connected_address, connected_device->device_address,
463                                         BT_ADDRESS_STRING_SIZE + 1);
464 #ifdef TIZEN_SUPPORT_DUAL_HF
465                         is_companion_device = __bt_is_companion_device(connected_address);
466                         BT_INFO(" is_companion_device[%d]", is_companion_device);
467
468                         if (!is_companion_device) {
469                                 connected = TRUE;
470                                 break;
471                         }
472 #else
473                         connected = TRUE;
474                         break;
475 #endif
476                 }
477                 node = g_list_next(node);
478         }
479
480         if (!connected)
481                 return BLUETOOTH_ERROR_NOT_CONNECTED;
482
483         BT_DBG("connected headset %s", connected_address);
484
485         if (g_strcmp0(connected_address, address) == 0)
486                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
487 #ifdef TIZEN_SUPPORT_DUAL_HF
488         else if (TRUE == __bt_is_companion_device(address))
489                 return BLUETOOTH_ERROR_NOT_CONNECTED;
490 #endif
491
492         /* If already one device is waiting, remove current waiting device and add new */
493         if (g_wait_data != NULL) {
494                 if (g_strcmp0(g_wait_data->address, address) != 0) {
495                         __bt_remove_device_from_wait_list();
496                         __bt_free_wait_data();
497                 }
498         }
499
500         if (g_wait_data == NULL) {
501                 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
502                 g_wait_data->address = g_strdup(address);
503                 g_wait_data->req_id = req_id;
504                 g_wait_data->type = type;
505                 g_wait_data->ag_flag = FALSE;
506                 g_wait_data->out_param1 = out_param1;
507
508                 /* Set disconnection type */
509                 __bt_set_headset_disconnection_type(connected_address);
510         }
511
512         /* Convert BD adress from string type */
513         _bt_convert_addr_string_to_type(device_address.addr, connected_address);
514         _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
515         return BLUETOOTH_ERROR_NONE;
516 }
517
518 void _bt_set_audio_wait_data_flag(gboolean flag)
519 {
520         BT_DBG("_bt_set_audio_wait_data_flag \n");
521         g_wait_data->ag_flag = flag;
522 }
523
524 bt_headset_wait_t *_bt_get_audio_wait_data(void)
525 {
526         BT_DBG("_bt_get_audio_wait_data \n");
527         return g_wait_data;
528 }
529
530 void _bt_rel_wait_data(void)
531 {
532         BT_DBG("_bt_rel_wait_data \n");
533         __bt_free_wait_data();
534 }
535
536 void _bt_add_headset_to_list(int type, int status, const char *address)
537 {
538         bt_connected_headset_data_t *connected_device;
539         bt_connected_headset_data_t *device;
540         GList *node;
541
542         BT_DBG("_bt_add_headset_to_list \n");
543
544         node = g_list_first(g_connected_list);
545         while (node != NULL) {
546                 device = (bt_connected_headset_data_t *)node->data;
547
548                 if (g_strcmp0(device->device_address, address) == 0) {
549                         BT_DBG("Address match, update connection type \n");
550                         if (status == BT_STATE_CONNECTED)
551                                 device->type |= type;
552                         device->device_state = status;
553                         return;
554                 }
555                 node = g_list_next(node);
556         }
557
558         connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
559         connected_device->device_state = status;
560         if (status == BT_STATE_CONNECTED)
561                 connected_device->type |= type;
562         g_strlcpy(connected_device->device_address, address,
563                         sizeof(connected_device->device_address));
564         g_connected_list = g_list_append(g_connected_list, connected_device);
565 }
566
567 int _bt_get_device_state_from_list(int type, const char *address)
568 {
569         GList *node;
570         bt_connected_headset_data_t *device;
571
572         BT_DBG("+");
573         node = g_list_first(g_connected_list);
574         while (node != NULL) {
575                 device = (bt_connected_headset_data_t *)node->data;
576                 if (g_strcmp0(device->device_address, address) == 0) {
577                         BT_DBG("Device found");
578                         return device->device_state;
579                 }
580                 node = g_list_next(node);
581         }
582
583         BT_DBG("Device not found");
584         return BLUETOOTH_ERROR_INTERNAL;
585 }
586
587 void _bt_remove_headset_from_list(int type, const char *address)
588 {
589         GList *node;
590
591         BT_DBG("_bt_remove_headset_from_list \n");
592
593         node = g_list_first(g_connected_list);
594         while (node != NULL) {
595                 bt_connected_headset_data_t *connected_device = node->data;
596
597                 if (g_strcmp0(connected_device->device_address, address) != 0) {
598                         node = g_list_next(node);
599                         continue;
600                 }
601
602                 BT_DBG("Address match \n");
603
604                 BT_DBG("Connection type = %x\n", connected_device->type);
605
606                 switch (type) {
607                 case BT_AUDIO_A2DP:
608                         if (connected_device->type & BT_AUDIO_A2DP)
609                                 connected_device->type &= ~(BT_AUDIO_A2DP);
610                         break;
611                 case BT_AUDIO_HSP:
612                         if (connected_device->type & BT_AUDIO_HSP)
613                                 connected_device->type &= ~(BT_AUDIO_HSP);
614                         break;
615                 case BT_AUDIO_ALL:
616                         if (connected_device->type & BT_AUDIO_ALL)
617                                 connected_device->type &= ~(BT_AUDIO_ALL);
618                         break;
619                 case BT_AVRCP:
620                         if (connected_device->type & BT_AVRCP)
621                                 connected_device->type &= ~(BT_AVRCP);
622                         break;
623                 }
624
625                 BT_DBG("Connection type = %x\n", connected_device->type);
626
627                 if (connected_device->type == 0x00) {
628                         g_connected_list = g_list_remove(g_connected_list, connected_device);
629                         g_free(connected_device);
630                 }
631
632                 node = g_list_next(node);
633         }
634 }
635
636 static gboolean __bt_device_support_uuid(char *remote_address,
637                                 bt_audio_type_t type)
638 {
639         GArray *dev_list = NULL;
640         int size,i,j;
641         bluetooth_device_info_t info;
642         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
643         gboolean ret = FALSE;
644
645         BT_DBG("+");
646
647         dev_list = g_array_new (FALSE, FALSE, sizeof(gchar));
648
649         _bt_get_bonded_devices(&dev_list);
650         size = (dev_list->len) / sizeof(bluetooth_device_info_t);
651
652         for (i=0; i < size; i++) {
653                 info = g_array_index(dev_list, bluetooth_device_info_t, i);
654                 _bt_convert_addr_type_to_string(bond_address,
655                                 info.device_address.addr);
656                 if (strcmp(bond_address, remote_address) != 0)
657                         continue;
658
659                 BT_INFO("Device address Matched");
660                 j = 0;
661                 while (j != info.service_index) {
662                         if (type == BT_AUDIO_HSP) {
663                                 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
664                                         BT_INFO("HFP HS UUID exists");
665                                         ret = TRUE;
666                                         goto end;
667                                 }
668                         } else if (type == BT_AUDIO_A2DP) {
669                                 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
670                                         BT_INFO("A2DP SINK UUID exists");
671                                         ret = TRUE;
672                                         goto end;
673                                 }
674                         }
675                         j++;
676                 }
677         }
678 end:
679         g_array_free(dev_list, TRUE);
680         BT_DBG("-");
681         return ret;
682 }
683
684 gboolean _bt_is_service_connected(char* address, int type)
685 {
686         GList *node;
687
688         node = g_list_first(g_connected_list);
689         while (node != NULL) {
690                 bt_connected_headset_data_t *conn_device = node->data;
691
692                 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
693                         (conn_device->type & type)) {
694                                 BT_INFO("Service connected");
695                                 return TRUE;
696                 }
697
698                 node = g_list_next(node);
699         }
700         BT_INFO("Service not connected");
701         return FALSE;
702 }
703
704 int _bt_audio_connect(int request_id, int type,
705                 bluetooth_device_address_t *device_address,
706                 GArray **out_param1)
707 {
708         int result = BLUETOOTH_ERROR_NONE;
709         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
710         DBusGProxy *adapter_proxy;
711         DBusGConnection *g_conn;
712         int ret;
713         char *uuid;
714         int value = BLUETOOTH_ERROR_NONE;
715         bt_audio_function_data_t *func_data;
716
717         BT_CHECK_PARAMETER(device_address, return);
718
719         adapter_proxy = _bt_get_adapter_proxy();
720         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
721
722         g_conn = _bt_get_system_gconn();
723         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
724
725         _bt_convert_addr_type_to_string(address, device_address->addr);
726
727         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
728
729         func_data->address = g_strdup(address);
730         func_data->req_id = request_id;
731         func_data->type = type;
732         func_data->pending = BT_PENDING_NONE;
733         func_data->out_param = out_param1;
734
735         switch (type) {
736         case BT_AUDIO_HSP:
737                 uuid = HFP_HS_UUID;
738                 break;
739         case BT_AUDIO_A2DP:
740                 uuid = A2DP_SINK_UUID;
741                 break;
742         case BT_AVRCP:
743                 uuid = AVRCP_TARGET_UUID;
744                 break;
745         case BT_AUDIO_ALL:
746                 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
747                         uuid = HFP_HS_UUID;
748                         func_data->pending = BT_PENDING_CONNECT;
749                 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
750                         uuid = A2DP_SINK_UUID;
751                 } else {
752                         BT_ERR("No audio role supported");
753                         result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
754                         goto fail;
755                 }
756                 break;
757         default:
758                 BT_ERR("Unknown role");
759                 result = BLUETOOTH_ERROR_INTERNAL;
760                 goto fail;
761         }
762         BT_INFO("Connecting to service %s", uuid);
763
764         value = __bt_is_headset_connected(type, request_id, address, out_param1);
765
766         if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
767                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
768         } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
769                 _bt_headset_set_local_connection(TRUE);
770                 ret = _bt_connect_profile(address, uuid,
771                                 __bt_audio_request_cb, func_data);
772
773                 if (ret != BLUETOOTH_ERROR_NONE) {
774                         BT_ERR("_bt_connect_profile Error");
775                         _bt_headset_set_local_connection(FALSE);
776                         g_free(func_data->address);
777                         g_free(func_data);
778                         return ret;
779                 }
780
781                 /* Add data to the connected list */
782                 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
783         }
784
785         return BLUETOOTH_ERROR_NONE;
786 fail:
787         g_array_append_vals(*out_param1, address,
788                         BT_ADDRESS_STR_LEN);
789
790         return result;
791 }
792
793 int _bt_audio_disconnect(int request_id, int type,
794                 bluetooth_device_address_t *device_address,
795                 GArray **out_param1)
796 {
797         int result = BLUETOOTH_ERROR_NONE;
798         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
799         bt_audio_function_data_t *func_data;
800         DBusGProxy *adapter_proxy;
801         DBusGConnection *g_conn;
802         GList *node;
803         int ret;
804         char *uuid;
805
806         BT_CHECK_PARAMETER(device_address, return);
807
808         adapter_proxy = _bt_get_adapter_proxy();
809         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
810
811         g_conn = _bt_get_system_gconn();
812         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
813
814         _bt_convert_addr_type_to_string(address, device_address->addr);
815
816         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
817
818         func_data->address = g_strdup(address);
819         func_data->req_id = request_id;
820         func_data->pending = BT_PENDING_NONE;
821         func_data->out_param = out_param1;
822         func_data->type = type;
823
824         switch (type) {
825         case BT_AUDIO_HSP:
826                 uuid = HFP_HS_UUID;
827                 break;
828         case BT_AUDIO_A2DP:
829                 uuid = A2DP_SINK_UUID;
830                 break;
831         case BT_AVRCP:
832                 uuid = AVRCP_TARGET_UUID;
833                 break;
834         case BT_AUDIO_ALL:
835                 if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
836                         uuid = HFP_HS_UUID;
837                         func_data->pending = BT_PENDING_DISCONNECT;
838                 } else if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
839                         uuid = A2DP_SINK_UUID;
840                 } else {
841                         BT_ERR("No audio service connected");
842                         result = BLUETOOTH_ERROR_NOT_CONNECTED;
843                         goto fail;
844                 }
845                 break;
846         default:
847                 BT_ERR("Unknown role");
848                 result = BLUETOOTH_ERROR_INTERNAL;
849                 goto fail;
850         }
851
852         BT_INFO("Disconnecting service %s", uuid);
853         ret = _bt_disconnect_profile(address, uuid,
854                         __bt_audio_request_cb, func_data);
855
856         if (ret != BLUETOOTH_ERROR_NONE) {
857                 BT_ERR("_bt_disconnect_profile Error");
858                 g_free(func_data->address);
859                 g_free(func_data);
860                 return ret;
861         }
862
863         /*
864          *      This logic is added for dual HF mode issue.
865          */
866         node = g_list_first(g_connected_list);
867         while (node != NULL) {
868                 bt_connected_headset_data_t *connected_device = node->data;
869
870                 if (g_strcmp0(connected_device->device_address, address) == 0) {
871                         BT_DBG("Connection type update");
872                         type = connected_device->type;
873                         break;
874                 }
875                 node = g_list_next(node);
876         }
877         _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
878
879         return BLUETOOTH_ERROR_NONE;
880 fail:
881         if (out_param1 != NULL)
882                 g_array_append_vals(*out_param1, address,
883                                 BT_ADDRESS_STR_LEN);
884
885         return result;
886 }
887
888 void _bt_remove_from_connected_list(const char *address)
889 {
890         bt_connected_headset_data_t *connected_device;
891         GList *node;
892
893         node = g_list_first(g_connected_list);
894         while (node != NULL) {
895                 connected_device = node->data;
896                 if (connected_device != NULL &&
897                 g_strcmp0(connected_device->device_address, address) == 0) {
898                         BT_ERR("Device is removed from the list");
899                         g_connected_list = g_list_remove(g_connected_list, connected_device);
900                         g_free(connected_device);
901                         return;
902                 }
903                 node = g_list_next(node);
904         }
905 }
906
907 int _bt_hf_connect(int request_id,
908                 bluetooth_device_address_t *device_address,
909                 GArray **out_param1)
910 {
911         int result = BLUETOOTH_ERROR_NONE;
912         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
913         bt_function_data_t *func_data;
914         DBusGProxy *adapter_proxy;
915         DBusGConnection *g_conn;
916
917         int ret;
918         char *uuid;
919
920
921         BT_CHECK_PARAMETER(device_address, return);
922
923         _bt_convert_addr_type_to_string(address, device_address->addr);
924
925         adapter_proxy = _bt_get_adapter_proxy();
926         if (adapter_proxy == NULL) {
927                 result = BLUETOOTH_ERROR_INTERNAL;
928                 goto fail;
929         }
930
931         g_conn = _bt_get_system_gconn();
932         if (g_conn == NULL) {
933                 result = BLUETOOTH_ERROR_INTERNAL;
934                 goto fail;
935         }
936
937         func_data = g_malloc0(sizeof(bt_function_data_t));
938
939         func_data->address = g_strdup(address);
940         func_data->req_id = request_id;
941         uuid = g_strdup(HFP_AG_UUID);
942
943         BT_DBG("Connecting to service %s", uuid);
944
945         ret = _bt_connect_profile(address, uuid,
946                         __bt_hf_request_cb, func_data);
947
948         if (ret != BLUETOOTH_ERROR_NONE) {
949                 BT_ERR("_bt_connect_profile Error");
950                 g_free(func_data->address);
951                 g_free(func_data);
952                 g_free(uuid);
953                 return ret;
954         }
955         g_free(uuid);
956         return BLUETOOTH_ERROR_NONE;
957 fail:
958         if (out_param1 != NULL)
959                 g_array_append_vals(*out_param1, address,
960                                 BT_ADDRESS_STR_LEN);
961
962         return result;
963 }
964
965 int _bt_hf_disconnect(int request_id,
966                 bluetooth_device_address_t *device_address,
967                 GArray **out_param1)
968 {
969         int result = BLUETOOTH_ERROR_NONE;
970         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
971         bt_function_data_t *func_data;
972         DBusGProxy *adapter_proxy;
973         DBusGConnection *g_conn;
974
975         int ret;
976         char *uuid;
977
978         BT_CHECK_PARAMETER(device_address, return);
979
980         _bt_convert_addr_type_to_string(address, device_address->addr);
981
982         adapter_proxy = _bt_get_adapter_proxy();
983         if (adapter_proxy == NULL) {
984                 result = BLUETOOTH_ERROR_INTERNAL;
985                 goto fail;
986         }
987
988         g_conn = _bt_get_system_gconn();
989         if (g_conn == NULL) {
990                 result = BLUETOOTH_ERROR_INTERNAL;
991                 goto fail;
992         }
993
994         func_data = g_malloc0(sizeof(bt_function_data_t));
995
996         func_data->address = g_strdup(address);
997         func_data->req_id = request_id;
998         uuid = g_strdup(HFP_AG_UUID);
999
1000         BT_DBG("Disconnecting service %s", uuid);
1001         ret = _bt_disconnect_profile(address, uuid,
1002                         __bt_hf_request_cb, func_data);
1003
1004         if (ret != BLUETOOTH_ERROR_NONE) {
1005                 BT_ERR("_bt_disconnect_profile Error");
1006                 g_free(func_data->address);
1007                 g_free(func_data);
1008                 g_free(uuid);
1009                 return ret;
1010         }
1011         g_free(uuid);
1012         return BLUETOOTH_ERROR_NONE;
1013 fail:
1014         if (out_param1 != NULL)
1015                 g_array_append_vals(*out_param1, address,
1016                                 BT_ADDRESS_STR_LEN);
1017
1018         return result;
1019 }
1020
1021 int _bt_audio_get_speaker_gain(unsigned int *gain)
1022 {
1023         char *device_path = NULL;
1024         DBusGProxy *adapter_proxy;
1025         DBusGProxy *profile_proxy;
1026         DBusGConnection *g_conn;
1027         GHashTable *hash = NULL;
1028         GValue *value;
1029
1030         adapter_proxy = _bt_get_adapter_proxy();
1031         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1032
1033         g_conn = _bt_get_system_gconn();
1034         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1035
1036         device_path = __bt_get_connected_audio_path();
1037         retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1038
1039         profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
1040                                       device_path, BT_HEADSET_INTERFACE);
1041
1042         g_free(device_path);
1043
1044         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1045
1046         dbus_g_proxy_call(profile_proxy, "GetProperties", NULL,
1047                         G_TYPE_INVALID,
1048                         dbus_g_type_get_map("GHashTable",
1049                         G_TYPE_STRING, G_TYPE_VALUE),
1050                         &hash, G_TYPE_INVALID);
1051
1052         g_object_unref(profile_proxy);
1053
1054         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
1055
1056         value = g_hash_table_lookup(hash, "SpeakerGain");
1057         *gain = value ? g_value_get_uint(value) : 0;
1058         g_hash_table_destroy(hash);
1059         return BLUETOOTH_ERROR_NONE;
1060 }
1061
1062 int _bt_audio_set_speaker_gain(unsigned int gain)
1063 {
1064         char *device_path = NULL;
1065         char *gain_str = "SpeakerGain";
1066         char sig[2] = {DBUS_TYPE_UINT16, '\0'};
1067         int ret = BLUETOOTH_ERROR_NONE;
1068         DBusMessage *msg;
1069         DBusMessageIter iter;
1070         DBusMessageIter value;
1071         DBusConnection *conn;
1072
1073         conn = _bt_get_system_conn();
1074         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1075
1076         device_path = __bt_get_connected_audio_path();
1077         retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1078
1079         msg = dbus_message_new_method_call(BT_BLUEZ_NAME,
1080                         device_path, BT_HEADSET_INTERFACE,
1081                         "SetProperty");
1082
1083         g_free(device_path);
1084
1085         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
1086
1087         dbus_message_iter_init_append(msg, &iter);
1088         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1089                         &gain_str);
1090         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1091                         sig, &value);
1092         dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
1093                         &gain);
1094         dbus_message_iter_close_container(&iter, &value);
1095
1096         if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1097                 dbus_message_set_no_reply(msg, TRUE);
1098
1099         if (!dbus_connection_send(conn, msg, NULL)) {
1100                 BT_ERR("Dbus sending failed\n");
1101                 ret = BLUETOOTH_ERROR_INTERNAL;
1102         }
1103         dbus_message_unref(msg);
1104
1105         return ret;
1106 }
1107
1108 int _bt_audio_set_content_protect(gboolean status)
1109 {
1110         DBusConnection *conn;
1111         DBusMessage *signal;
1112
1113         BT_DBG("+\n");
1114
1115         conn = _bt_get_system_conn();
1116         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1117
1118         BT_DBG("Content Protection status = [%d] \n", status);
1119
1120         /*Emit Content protection Status change signal with value*/
1121         signal = dbus_message_new_signal(BT_CONTENT_PROTECTION_PATH,
1122                                         BT_CONTENT_PROTECTION_INTERFACE,
1123                                         "ProtectionRequired");
1124         if (!signal)
1125                 goto err;
1126
1127         if (!dbus_message_append_args(signal,
1128                                 DBUS_TYPE_BOOLEAN, &status,
1129                                 DBUS_TYPE_INVALID)) {
1130                 BT_ERR("Signal appending failed\n");
1131                 dbus_message_unref(signal);
1132                 goto err;
1133         }
1134
1135         dbus_connection_send(conn, signal, NULL);
1136         dbus_message_unref(signal);
1137
1138         BT_DBG("-\n");
1139         return BLUETOOTH_ERROR_NONE;
1140
1141 err:
1142         return BLUETOOTH_ERROR_INTERNAL;
1143 }