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