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