ec9e9ab02ab8467d1e398f098eb0cb69b6fb39c8
[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 <gio/gio.h>
25 #include <glib.h>
26 #include <dlog.h>
27 #include <string.h>
28 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
29 #include <syspopup_caller.h>
30 #endif
31
32 #include "bluetooth-api.h"
33 #include "bt-internal-types.h"
34
35 #include "bt-service-audio.h"
36 #include "bt-service-adapter.h"
37 #include "bt-service-common.h"
38 #include "bt-service-device.h"
39 #include "bt-service-event.h"
40 #include "bt-service-util.h"
41
42 #include "bt-service-headset-connection.h"
43
44 #ifdef TIZEN_SUPPORT_DUAL_HF
45 #ifdef TIZEN_WEARABLE
46 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
47 #endif
48 #endif
49
50 typedef struct {
51         unsigned int type;
52         int device_state;
53         char device_address[BT_ADDRESS_STRING_SIZE + 1];
54 } bt_connected_headset_data_t;
55
56 static GList *g_connected_list;
57
58 static bt_headset_wait_t *g_wait_data;
59
60 static bt_audio_function_data_t *pdata;
61
62 static void __bt_remove_device_from_wait_list();
63
64 static void __bt_free_wait_data();
65
66 static gboolean __bt_device_support_uuid(char *remote_address,
67                                 bt_audio_type_t type);
68
69 static void __bt_hf_request_cb(GDBusProxy *proxy, GAsyncResult *res,
70                                     gpointer user_data)
71 {
72         GError *g_error = NULL;
73         GVariant *out_param1 = NULL;
74         GVariant *reply = NULL;
75         int result = BLUETOOTH_ERROR_NONE;
76         bt_function_data_t *func_data;
77         request_info_t *req_info;
78
79         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
80         g_object_unref(proxy);
81
82         func_data = user_data;
83
84         if (func_data == NULL) {
85                 /* Send reply */
86                 BT_ERR("func_data == NULL");
87                 goto done;
88         }
89
90         req_info = _bt_get_request_info(func_data->req_id);
91         if (req_info == NULL) {
92                 BT_ERR("req_info == NULL");
93                 goto done;
94         }
95
96         if (reply == NULL) {
97                 BT_ERR("HF Connect Dbus Call Error");
98                 if (g_error) {
99                         BT_ERR("Error: %s\n", g_error->message);
100                         g_clear_error(&g_error);
101                 }
102                 result = BLUETOOTH_ERROR_INTERNAL;
103         } else {
104                 g_variant_unref(reply);
105         }
106
107         if (req_info->context == NULL)
108                 goto done;
109
110         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
111                 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
112
113         g_dbus_method_invocation_return_value(req_info->context,
114                         g_variant_new("(iv)", result, out_param1));
115
116         _bt_delete_request_list(req_info->req_id);
117
118 done:
119         if (func_data) {
120                 g_free(func_data->address);
121                 g_free(func_data);
122         }
123 }
124
125 void _bt_audio_check_pending_connect()
126 {
127         BT_DBG("+");
128         bluetooth_device_address_t device_address;
129
130         if (pdata == NULL)
131                 return;
132
133         if (pdata->pending == BT_PENDING_CONNECT) {
134
135                 _bt_convert_addr_string_to_type(device_address.addr,
136                                 pdata->address);
137                 _bt_audio_connect(pdata->req_id,
138                                 BT_AUDIO_A2DP,
139                                 &device_address,
140                                 pdata->out_param);
141
142                 g_free(pdata->address);
143                 g_free(pdata);
144                 pdata = NULL;
145         }
146
147         BT_DBG("-");
148         return;
149 }
150
151 static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
152                                     gpointer user_data)
153 {
154         GError *g_error = NULL;
155         GVariant *out_param1 = NULL;
156         GVariant *reply = NULL;
157         int result = BLUETOOTH_ERROR_NONE;
158         bt_audio_function_data_t *func_data;
159         request_info_t *req_info;
160
161         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
162         g_object_unref(proxy);
163         g_variant_unref(reply);
164
165         func_data = user_data;
166
167         if (func_data == NULL) {
168                 /* Send reply */
169                 BT_ERR("func_data == NULL");
170                 goto done;
171         }
172
173         if (func_data->pending != BT_PENDING_NONE && g_error == NULL) {
174
175                 bluetooth_device_address_t device_address;
176                 _bt_convert_addr_string_to_type(device_address.addr,
177                                         func_data->address);
178
179                 if (func_data->pending == BT_PENDING_CONNECT) {
180
181                         if (__bt_device_support_uuid(func_data->address,
182                                                         BT_AUDIO_A2DP)) {
183
184                                 pdata = g_new0(bt_audio_function_data_t, 1);
185                                 pdata->req_id = func_data->req_id;
186                                 pdata->out_param = func_data->out_param;
187                                 pdata->address = strdup(func_data->address);
188                                 pdata->pending = func_data->pending;
189                         } else
190                                 goto check_req_info;
191
192                 } else {
193
194                         if (_bt_is_service_connected(func_data->address
195                                                         , BT_AUDIO_A2DP)) {
196                                 _bt_audio_disconnect(func_data->req_id,
197                                         BT_AUDIO_A2DP,
198                                         &device_address,
199                                         func_data->out_param);
200                         } else
201                                 goto check_req_info;
202                 }
203
204                 goto done;
205         }
206
207 check_req_info:
208         req_info = _bt_get_request_info(func_data->req_id);
209         if (req_info == NULL) {
210                 BT_ERR("req_info == NULL");
211                 goto done;
212         }
213
214         if (g_error == NULL)
215                 goto dbus_return;
216
217         BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
218
219         result = BLUETOOTH_ERROR_INTERNAL;
220
221         /* Remove the device from the list */
222         _bt_remove_headset_from_list(func_data->type, func_data->address);
223
224         /* Error, check if any waiting device is there */
225         if (g_wait_data == NULL)
226                 goto dbus_return;
227
228         if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
229                 bluetooth_device_address_t device_address;
230                 _bt_convert_addr_string_to_type(device_address.addr,
231                                 g_wait_data->address);
232                 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
233                                 &device_address, g_wait_data->out_param1);
234         }
235
236         /* Event will be sent by the event reciever */
237 dbus_return:
238         if (req_info->context == NULL) {
239                 BT_DBG("req_info->context is NULL");
240                 goto done;
241         }
242
243         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
244                 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
245
246         g_dbus_method_invocation_return_value(req_info->context,
247                         g_variant_new("(iv)", result, out_param1));
248
249         _bt_delete_request_list(req_info->req_id);
250 done:
251         g_clear_error(&g_error);
252
253         if (func_data) {
254                 g_free(func_data->address);
255                 g_free(func_data);
256         }
257 }
258
259 static void __bt_free_wait_data()
260 {
261         if (g_wait_data != NULL) {
262                 g_free(g_wait_data->address);
263                 g_free(g_wait_data);
264                 g_wait_data = NULL;
265         }
266 }
267
268 static void __bt_remove_device_from_wait_list()
269 {
270         /* Before deleting the request update the UI */
271         GVariant *out_param_1 = NULL;
272         int result = BLUETOOTH_ERROR_INTERNAL;
273         request_info_t *req_info;
274
275         req_info = _bt_get_request_info(g_wait_data->req_id);
276         if (req_info == NULL) {
277                 BT_ERR("req_info == NULL");
278                 return;
279         }
280
281         out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
282                 g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
283
284         g_dbus_method_invocation_return_value(req_info->context,
285                         g_variant_new("(iv)", result, out_param_1));
286
287         _bt_delete_request_list(g_wait_data->req_id);
288 }
289
290 static void __bt_set_headset_disconnection_type(const char *address)
291 {
292         bt_connected_headset_data_t *connected_device;
293         GList *node;
294
295         node = g_list_first(g_connected_list);
296         while (node != NULL) {
297                 connected_device = node->data;
298                 if (g_strcmp0(connected_device->device_address, address) == 0) {
299                         g_wait_data->disconnection_type = connected_device->type;
300                         return;
301                 }
302                 node = g_list_next(node);
303         }
304 }
305
306 gboolean _bt_is_headset_type_connected(int type, char *address)
307 {
308         GList *node;
309
310         node = g_list_first(g_connected_list);
311         while (node != NULL) {
312                 bt_connected_headset_data_t *connected_device = node->data;
313
314                 if (connected_device->type & type) {
315                         if (address != NULL)
316                                 g_strlcpy(address, connected_device->device_address,
317                                                 BT_ADDRESS_STRING_SIZE + 1);
318                         return TRUE;
319                 }
320
321                 node = g_list_next(node);
322         }
323         return FALSE;
324 }
325
326 #ifdef TIZEN_SUPPORT_DUAL_HF
327 gboolean __bt_is_companion_device(const char *addr)
328 {
329 #ifdef TIZEN_WEARABLE
330         char *host_device_address = NULL;
331         host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
332
333         if (!host_device_address) {
334                 BT_INFO("Failed to get a companion device address");
335                 return FALSE;
336         }
337
338         if (g_strcmp0(host_device_address, addr) == 0) {
339                 BT_INFO("addr[%s] is companion device", addr);
340                 return TRUE;
341         }
342
343         return FALSE;
344 #else
345         /* TODO : Need to add companion device check condition for Phone models */
346         return FALSE;
347 #endif
348 }
349 #endif
350
351 static int __bt_is_headset_connected(int type, int req_id,
352                                 const char *address, GArray **out_param1)
353 {
354         gboolean connected = FALSE;
355         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
356         bluetooth_device_address_t device_address;
357         bt_connected_headset_data_t *connected_device = NULL;
358 #ifdef TIZEN_SUPPORT_DUAL_HF
359         gboolean is_companion_device = FALSE;
360 #endif
361
362         /* Check if any other headset is connected */
363         GList *node = NULL;;
364
365         node = g_list_first(g_connected_list);
366         while (node != NULL) {
367                 connected_device = node->data;
368                 if ((connected_device->type & type) == type) {
369                         g_strlcpy(connected_address, connected_device->device_address,
370                                         BT_ADDRESS_STRING_SIZE + 1);
371 #ifdef TIZEN_SUPPORT_DUAL_HF
372                         is_companion_device = __bt_is_companion_device(connected_address);
373                         BT_INFO(" is_companion_device[%d]", is_companion_device);
374
375                         if (!is_companion_device) {
376                                 connected = TRUE;
377                                 break;
378                         }
379 #else
380                         connected = TRUE;
381                         break;
382 #endif
383                 }
384                 node = g_list_next(node);
385         }
386
387         if (!connected)
388                 return BLUETOOTH_ERROR_NOT_CONNECTED;
389
390         BT_DBG("connected headset %s", connected_address);
391
392         if (g_strcmp0(connected_address, address) == 0)
393                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
394 #ifdef TIZEN_SUPPORT_DUAL_HF
395         else if (TRUE == __bt_is_companion_device(address))
396                 return BLUETOOTH_ERROR_NOT_CONNECTED;
397 #endif
398
399         /* If already one device is waiting, remove current waiting device and add new */
400         if (g_wait_data != NULL) {
401                 if (g_strcmp0(g_wait_data->address, address) != 0) {
402                         __bt_remove_device_from_wait_list();
403                         __bt_free_wait_data();
404                 }
405         }
406
407         if (g_wait_data == NULL) {
408                 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
409                 g_wait_data->address = g_strdup(address);
410                 g_wait_data->req_id = req_id;
411                 g_wait_data->type = type;
412                 g_wait_data->ag_flag = FALSE;
413                 g_wait_data->out_param1 = out_param1;
414
415                 /* Set disconnection type */
416                 __bt_set_headset_disconnection_type(connected_address);
417         }
418
419         /* Convert BD adress from string type */
420         _bt_convert_addr_string_to_type(device_address.addr, connected_address);
421         _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
422         return BLUETOOTH_ERROR_NONE;
423 }
424
425 void _bt_set_audio_wait_data_flag(gboolean flag)
426 {
427         BT_DBG("_bt_set_audio_wait_data_flag \n");
428         g_wait_data->ag_flag = flag;
429 }
430
431 bt_headset_wait_t *_bt_get_audio_wait_data(void)
432 {
433         BT_DBG("_bt_get_audio_wait_data \n");
434         return g_wait_data;
435 }
436
437 void _bt_rel_wait_data(void)
438 {
439         BT_DBG("_bt_rel_wait_data \n");
440         __bt_free_wait_data();
441 }
442
443 void _bt_add_headset_to_list(int type, int status, const char *address)
444 {
445         bt_connected_headset_data_t *connected_device;
446         bt_connected_headset_data_t *device;
447         GList *node;
448
449         BT_DBG("_bt_add_headset_to_list \n");
450
451         node = g_list_first(g_connected_list);
452         while (node != NULL) {
453                 device = (bt_connected_headset_data_t *)node->data;
454
455                 if (g_strcmp0(device->device_address, address) == 0) {
456                         BT_DBG("Address match, update connection type \n");
457                         if (status == BT_STATE_CONNECTED)
458                                 device->type |= type;
459                         device->device_state = status;
460                         return;
461                 }
462                 node = g_list_next(node);
463         }
464
465         connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
466         /* Fix : NULL_RETURNS */
467         if (connected_device == NULL) {
468                 BT_ERR("No memory allocated");
469                 return;
470         }
471
472         connected_device->device_state = status;
473         if (status == BT_STATE_CONNECTED)
474                 connected_device->type |= type;
475         g_strlcpy(connected_device->device_address, address,
476                         sizeof(connected_device->device_address));
477         g_connected_list = g_list_append(g_connected_list, connected_device);
478 }
479
480 int _bt_get_device_state_from_list(int type, const char *address)
481 {
482         GList *node;
483         bt_connected_headset_data_t *device;
484
485         BT_DBG("+");
486         node = g_list_first(g_connected_list);
487         while (node != NULL) {
488                 device = (bt_connected_headset_data_t *)node->data;
489                 if (g_strcmp0(device->device_address, address) == 0) {
490                         BT_DBG("Device found");
491                         return device->device_state;
492                 }
493                 node = g_list_next(node);
494         }
495
496         BT_DBG("Device not found");
497         return BLUETOOTH_ERROR_INTERNAL;
498 }
499
500 void _bt_remove_headset_from_list(int type, const char *address)
501 {
502         GList *node;
503
504         BT_DBG("_bt_remove_headset_from_list \n");
505
506         node = g_list_first(g_connected_list);
507         while (node != NULL) {
508                 bt_connected_headset_data_t *connected_device = node->data;
509
510                 if (g_strcmp0(connected_device->device_address, address) != 0) {
511                         node = g_list_next(node);
512                         continue;
513                 }
514
515                 BT_DBG("Address match \n");
516
517                 BT_DBG("Connection type = %x\n", connected_device->type);
518
519                 switch (type) {
520                 case BT_AUDIO_A2DP:
521                         if (connected_device->type & BT_AUDIO_A2DP)
522                                 connected_device->type &= ~(BT_AUDIO_A2DP);
523                         break;
524                 case BT_AUDIO_HSP:
525                         if (connected_device->type & BT_AUDIO_HSP)
526                                 connected_device->type &= ~(BT_AUDIO_HSP);
527                         break;
528                 case BT_AUDIO_ALL:
529                         if (connected_device->type & BT_AUDIO_ALL)
530                                 connected_device->type &= ~(BT_AUDIO_ALL);
531                         break;
532                 case BT_AVRCP:
533                         if (connected_device->type & BT_AVRCP)
534                                 connected_device->type &= ~(BT_AVRCP);
535                         break;
536                 }
537
538                 BT_DBG("Connection type = %x\n", connected_device->type);
539
540                 if (connected_device->type == 0x00) {
541                         g_connected_list = g_list_remove(g_connected_list, connected_device);
542                         g_free(connected_device);
543                 }
544
545                 node = g_list_next(node);
546         }
547 }
548
549 static gboolean __bt_device_support_uuid(char *remote_address,
550                                 bt_audio_type_t type)
551 {
552         GArray *dev_list = NULL;
553         int size,i,j;
554         bluetooth_device_info_t info;
555         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
556         gboolean ret = FALSE;
557
558         BT_DBG("+");
559
560         dev_list = g_array_new (FALSE, FALSE, sizeof(gchar));
561
562         _bt_get_bonded_devices(&dev_list);
563         size = (dev_list->len) / sizeof(bluetooth_device_info_t);
564
565         for (i=0; i < size; i++) {
566                 info = g_array_index(dev_list, bluetooth_device_info_t, i);
567                 _bt_convert_addr_type_to_string(bond_address,
568                                 info.device_address.addr);
569                 if (strcmp(bond_address, remote_address) != 0)
570                         continue;
571
572                 BT_INFO("Device address Matched");
573                 j = 0;
574                 while (j != info.service_index) {
575                         if (type == BT_AUDIO_HSP) {
576                                 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
577                                         BT_INFO("HFP HS UUID exists");
578                                         ret = TRUE;
579                                         goto end;
580                                 }
581                         } else if (type == BT_AUDIO_A2DP) {
582                                 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
583                                         BT_INFO("A2DP SINK UUID exists");
584                                         ret = TRUE;
585                                         goto end;
586                                 }
587                         }
588                         j++;
589                 }
590         }
591 end:
592         g_array_free(dev_list, TRUE);
593         BT_DBG("-");
594         return ret;
595 }
596
597 gboolean _bt_is_service_connected(char* address, int type)
598 {
599         GList *node;
600
601         node = g_list_first(g_connected_list);
602         while (node != NULL) {
603                 bt_connected_headset_data_t *conn_device = node->data;
604
605                 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
606                         (conn_device->type & type)) {
607                                 BT_INFO("Service connected");
608                                 return TRUE;
609                 }
610
611                 node = g_list_next(node);
612         }
613         BT_INFO("Service not connected");
614         return FALSE;
615 }
616
617 int _bt_audio_connect(int request_id, int type,
618                 bluetooth_device_address_t *device_address,
619                 GArray **out_param1)
620 {
621         int result = BLUETOOTH_ERROR_NONE;
622         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
623         GDBusProxy *adapter_proxy;
624         GDBusConnection *g_conn;
625         int ret;
626         char *uuid;
627         int value = BLUETOOTH_ERROR_NONE;
628         bt_audio_function_data_t *func_data;
629
630         BT_CHECK_PARAMETER(device_address, return);
631
632         adapter_proxy = _bt_get_adapter_proxy();
633         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
634
635         g_conn = _bt_get_system_gconn();
636         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
637
638         _bt_convert_addr_type_to_string(address, device_address->addr);
639
640         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
641         /* Fix : NULL_RETURNS */
642         if (func_data == NULL) {
643                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
644                 goto fail;
645         }
646
647         func_data->address = g_strdup(address);
648         func_data->req_id = request_id;
649         func_data->type = type;
650         func_data->pending = BT_PENDING_NONE;
651         func_data->out_param = out_param1;
652
653         switch (type) {
654         case BT_AUDIO_HSP:
655                 uuid = HFP_HS_UUID;
656                 break;
657         case BT_AUDIO_A2DP:
658                 uuid = A2DP_SINK_UUID;
659                 break;
660         case BT_AVRCP:
661                 uuid = AVRCP_TARGET_UUID;
662                 break;
663         case BT_AUDIO_A2DP_SOURCE:
664                 uuid = A2DP_SOURCE_UUID;
665                 break;
666         case BT_AUDIO_ALL:
667                 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
668                         uuid = HFP_HS_UUID;
669                         func_data->pending = BT_PENDING_CONNECT;
670                 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
671                         uuid = A2DP_SINK_UUID;
672                 } else {
673                         BT_ERR("No audio role supported");
674                         result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
675                         goto fail;
676                 }
677                 break;
678         default:
679                 BT_ERR("Unknown role");
680                 result = BLUETOOTH_ERROR_INTERNAL;
681                 goto fail;
682         }
683         BT_INFO("Connecting to service %s", uuid);
684
685         value = __bt_is_headset_connected(type, request_id, address, out_param1);
686
687         if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
688                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
689         } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
690                 _bt_headset_set_local_connection(TRUE);
691                 ret = _bt_connect_profile(address, uuid,
692                                 __bt_audio_request_cb, func_data);
693
694                 if (ret != BLUETOOTH_ERROR_NONE) {
695                         BT_ERR("_bt_connect_profile Error");
696                         _bt_headset_set_local_connection(FALSE);
697                         g_free(func_data->address);
698                         g_free(func_data);
699                         return ret;
700                 }
701
702                 /* Add data to the connected list */
703                 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
704         }
705
706         return BLUETOOTH_ERROR_NONE;
707 fail:
708         g_array_append_vals(*out_param1, address,
709                         BT_ADDRESS_STR_LEN);
710
711         return result;
712 }
713
714 int _bt_audio_disconnect(int request_id, int type,
715                 bluetooth_device_address_t *device_address,
716                 GArray **out_param1)
717 {
718         int result = BLUETOOTH_ERROR_NONE;
719         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
720         bt_audio_function_data_t *func_data;
721         GDBusProxy *adapter_proxy;
722         GDBusConnection *g_conn;
723         GList *node;
724         int ret;
725         char *uuid;
726
727         BT_CHECK_PARAMETER(device_address, return);
728
729         adapter_proxy = _bt_get_adapter_proxy();
730         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
731
732         g_conn = _bt_get_system_gconn();
733         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
734
735         _bt_convert_addr_type_to_string(address, device_address->addr);
736
737         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
738         retv_if(func_data == NULL, BLUETOOTH_ERROR_INTERNAL);
739
740         func_data->address = g_strdup(address);
741         func_data->req_id = request_id;
742         func_data->pending = BT_PENDING_NONE;
743         func_data->out_param = out_param1;
744         func_data->type = type;
745
746         switch (type) {
747         case BT_AUDIO_HSP:
748                 uuid = HFP_HS_UUID;
749                 break;
750         case BT_AUDIO_A2DP:
751                 uuid = A2DP_SINK_UUID;
752                 break;
753         case BT_AVRCP:
754                 uuid = AVRCP_TARGET_UUID;
755                 break;
756         case BT_AUDIO_A2DP_SOURCE:
757                 uuid = A2DP_SOURCE_UUID;
758                 break;
759         case BT_AUDIO_ALL:
760                 if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
761                         uuid = HFP_HS_UUID;
762                         func_data->pending = BT_PENDING_DISCONNECT;
763                 } else if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
764                         uuid = A2DP_SINK_UUID;
765                 } else {
766                         BT_ERR("No audio service connected");
767                         result = BLUETOOTH_ERROR_NOT_CONNECTED;
768                         goto fail;
769                 }
770                 break;
771         default:
772                 BT_ERR("Unknown role");
773                 result = BLUETOOTH_ERROR_INTERNAL;
774                 goto fail;
775         }
776
777         BT_INFO("Disconnecting service %s", uuid);
778         ret = _bt_disconnect_profile(address, uuid,
779                         __bt_audio_request_cb, func_data);
780
781         if (ret != BLUETOOTH_ERROR_NONE) {
782                 BT_ERR("_bt_disconnect_profile Error");
783                 g_free(func_data->address);
784                 g_free(func_data);
785                 return ret;
786         }
787
788         /*
789          *      This logic is added for dual HF mode issue.
790          */
791         node = g_list_first(g_connected_list);
792         while (node != NULL) {
793                 bt_connected_headset_data_t *connected_device = node->data;
794
795                 if (g_strcmp0(connected_device->device_address, address) == 0) {
796                         BT_DBG("Connection type update");
797                         type = connected_device->type;
798                         break;
799                 }
800                 node = g_list_next(node);
801         }
802         _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
803
804         return BLUETOOTH_ERROR_NONE;
805 fail:
806         if (out_param1 != NULL)
807                 g_array_append_vals(*out_param1, address,
808                                 BT_ADDRESS_STR_LEN);
809
810         return result;
811 }
812
813 void _bt_remove_from_connected_list(const char *address)
814 {
815         bt_connected_headset_data_t *connected_device;
816         GList *node;
817
818         node = g_list_first(g_connected_list);
819         while (node != NULL) {
820                 connected_device = node->data;
821                 if (connected_device != NULL &&
822                 g_strcmp0(connected_device->device_address, address) == 0) {
823                         BT_ERR("Device is removed from the list");
824                         g_connected_list = g_list_remove(g_connected_list, connected_device);
825                         g_free(connected_device);
826                         return;
827                 }
828                 node = g_list_next(node);
829         }
830 }
831
832 int _bt_hf_connect(int request_id,
833                 bluetooth_device_address_t *device_address,
834                 GArray **out_param1)
835 {
836         int result = BLUETOOTH_ERROR_NONE;
837         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
838         bt_function_data_t *func_data;
839         GDBusProxy *adapter_proxy;
840         GDBusConnection *g_conn;
841         int ret;
842         char *uuid;
843
844         BT_CHECK_PARAMETER(device_address, return);
845
846         _bt_convert_addr_type_to_string(address, device_address->addr);
847
848         adapter_proxy = _bt_get_adapter_proxy();
849         if (adapter_proxy == NULL) {
850                 result = BLUETOOTH_ERROR_INTERNAL;
851                 goto fail;
852         }
853
854         g_conn = _bt_get_system_gconn();
855         if (g_conn == NULL) {
856                 result = BLUETOOTH_ERROR_INTERNAL;
857                 goto fail;
858         }
859
860         func_data = g_malloc0(sizeof(bt_function_data_t));
861         /* Fix : NULL_RETURNS */
862         if (func_data == NULL) {
863                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
864                 goto fail;
865         }
866
867         func_data->address = g_strdup(address);
868         func_data->req_id = request_id;
869         uuid = g_strdup(HFP_AG_UUID);
870
871         BT_DBG("Connecting to service %s", uuid);
872
873         ret = _bt_connect_profile(address, uuid,
874                         __bt_hf_request_cb, func_data);
875
876         if (ret != BLUETOOTH_ERROR_NONE) {
877                 BT_ERR("_bt_connect_profile Error");
878                 g_free(func_data->address);
879                 g_free(func_data);
880                 g_free(uuid);
881                 return ret;
882         }
883         g_free(uuid);
884         return BLUETOOTH_ERROR_NONE;
885 fail:
886         if (out_param1 != NULL)
887                 g_array_append_vals(*out_param1, address,
888                                 BT_ADDRESS_STR_LEN);
889
890         return result;
891 }
892
893 int _bt_hf_disconnect(int request_id,
894                 bluetooth_device_address_t *device_address,
895                 GArray **out_param1)
896 {
897         int result = BLUETOOTH_ERROR_NONE;
898         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
899         bt_function_data_t *func_data;
900         GDBusProxy *adapter_proxy;
901         GDBusConnection *g_conn;
902
903         int ret;
904         char *uuid;
905
906         BT_CHECK_PARAMETER(device_address, return);
907
908         _bt_convert_addr_type_to_string(address, device_address->addr);
909
910         adapter_proxy = _bt_get_adapter_proxy();
911         if (adapter_proxy == NULL) {
912                 result = BLUETOOTH_ERROR_INTERNAL;
913                 goto fail;
914         }
915
916         g_conn = _bt_get_system_gconn();
917         if (g_conn == NULL) {
918                 result = BLUETOOTH_ERROR_INTERNAL;
919                 goto fail;
920         }
921
922         func_data = g_malloc0(sizeof(bt_function_data_t));
923         /* Fix : NULL_RETURNS */
924         if (func_data == NULL) {
925                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
926                 goto fail;
927         }
928
929         func_data->address = g_strdup(address);
930         func_data->req_id = request_id;
931         uuid = g_strdup(HFP_AG_UUID);
932
933         BT_DBG("Disconnecting service %s", uuid);
934         ret = _bt_disconnect_profile(address, uuid,
935                         __bt_hf_request_cb, func_data);
936
937         if (ret != BLUETOOTH_ERROR_NONE) {
938                 BT_ERR("_bt_disconnect_profile Error");
939                 g_free(func_data->address);
940                 g_free(func_data);
941                 g_free(uuid);
942                 return ret;
943         }
944         g_free(uuid);
945         return BLUETOOTH_ERROR_NONE;
946 fail:
947         if (out_param1 != NULL)
948                 g_array_append_vals(*out_param1, address,
949                                 BT_ADDRESS_STR_LEN);
950
951         return result;
952 }
953
954 int _bt_audio_set_content_protect(gboolean status)
955 {
956         GDBusConnection *conn;
957         GError *error = NULL;
958
959         BT_DBG("+\n");
960
961         conn = _bt_get_system_gconn();
962         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
963
964         BT_DBG("Content Protection status = [%d]", status);
965
966         g_dbus_connection_emit_signal(conn,
967                         NULL, BT_CONTENT_PROTECTION_PATH,
968                         BT_CONTENT_PROTECTION_INTERFACE,
969                         "ProtectionRequired",
970                         g_variant_new("(b)", status),
971                         &error);
972
973         if (error) {
974                 /* dBUS gives error cause */
975                 ERR("Could not Emit Signal: errCode[%x], message[%s]",
976                         error->code, error->message);
977                 g_clear_error(&error);
978                 return BLUETOOTH_ERROR_INTERNAL;
979         }
980
981         BT_DBG("Emit Signal done = [ProtectionRequired]");
982         return BLUETOOTH_ERROR_NONE;
983 }