Merge "DPM: Add basic code for device policy manager for BT." into tizen
[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)
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                 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
665                         uuid = A2DP_SINK_UUID;
666                 } else {
667                         BT_ERR("No audio role supported");
668                         result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
669                         goto fail;
670                 }
671                 break;
672         default:
673                 BT_ERR("Unknown role");
674                 result = BLUETOOTH_ERROR_INTERNAL;
675                 goto fail;
676         }
677         BT_INFO("Connecting to service %s", uuid);
678
679         value = __bt_is_headset_connected(type, request_id, address, out_param1);
680
681         if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
682                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
683         } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
684                 _bt_headset_set_local_connection(TRUE);
685                 ret = _bt_connect_profile(address, uuid,
686                                 __bt_audio_request_cb, func_data);
687
688                 if (ret != BLUETOOTH_ERROR_NONE) {
689                         BT_ERR("_bt_connect_profile Error");
690                         _bt_headset_set_local_connection(FALSE);
691                         g_free(func_data->address);
692                         g_free(func_data);
693                         return ret;
694                 }
695
696                 /* Add data to the connected list */
697                 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
698         }
699
700         return BLUETOOTH_ERROR_NONE;
701 fail:
702         g_array_append_vals(*out_param1, address,
703                         BT_ADDRESS_STR_LEN);
704
705         return result;
706 }
707
708 int _bt_audio_disconnect(int request_id, int type,
709                 bluetooth_device_address_t *device_address,
710                 GArray **out_param1)
711 {
712         int result = BLUETOOTH_ERROR_NONE;
713         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
714         bt_audio_function_data_t *func_data;
715         GDBusProxy *adapter_proxy;
716         GDBusConnection *g_conn;
717         GList *node;
718         int ret;
719         char *uuid;
720
721         BT_CHECK_PARAMETER(device_address, return);
722
723         adapter_proxy = _bt_get_adapter_proxy();
724         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
725
726         g_conn = _bt_get_system_gconn();
727         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
728
729         _bt_convert_addr_type_to_string(address, device_address->addr);
730
731         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
732         retv_if(func_data == NULL, BLUETOOTH_ERROR_INTERNAL);
733
734         func_data->address = g_strdup(address);
735         func_data->req_id = request_id;
736         func_data->pending = BT_PENDING_NONE;
737         func_data->out_param = out_param1;
738         func_data->type = type;
739
740         switch (type) {
741         case BT_AUDIO_HSP:
742                 uuid = HFP_HS_UUID;
743                 break;
744         case BT_AUDIO_A2DP:
745                 uuid = A2DP_SINK_UUID;
746                 break;
747         case BT_AVRCP:
748                 uuid = AVRCP_TARGET_UUID;
749                 break;
750         case BT_AUDIO_A2DP_SOURCE:
751                 uuid = A2DP_SOURCE_UUID;
752                 break;
753         case BT_AUDIO_ALL:
754                 if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
755                         uuid = HFP_HS_UUID;
756                         func_data->pending = BT_PENDING_DISCONNECT;
757                 } else if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
758                         uuid = A2DP_SINK_UUID;
759                 } else {
760                         BT_ERR("No audio service connected");
761                         result = BLUETOOTH_ERROR_NOT_CONNECTED;
762                         goto fail;
763                 }
764                 break;
765         default:
766                 BT_ERR("Unknown role");
767                 result = BLUETOOTH_ERROR_INTERNAL;
768                 goto fail;
769         }
770
771         BT_INFO("Disconnecting service %s", uuid);
772         ret = _bt_disconnect_profile(address, uuid,
773                         __bt_audio_request_cb, func_data);
774
775         if (ret != BLUETOOTH_ERROR_NONE) {
776                 BT_ERR("_bt_disconnect_profile Error");
777                 g_free(func_data->address);
778                 g_free(func_data);
779                 return ret;
780         }
781
782         /*
783          *      This logic is added for dual HF mode issue.
784          */
785         node = g_list_first(g_connected_list);
786         while (node != NULL) {
787                 bt_connected_headset_data_t *connected_device = node->data;
788
789                 if (g_strcmp0(connected_device->device_address, address) == 0) {
790                         BT_DBG("Connection type update");
791                         type = connected_device->type;
792                         break;
793                 }
794                 node = g_list_next(node);
795         }
796         _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
797
798         return BLUETOOTH_ERROR_NONE;
799 fail:
800         if (out_param1 != NULL)
801                 g_array_append_vals(*out_param1, address,
802                                 BT_ADDRESS_STR_LEN);
803
804         return result;
805 }
806
807 void _bt_remove_from_connected_list(const char *address)
808 {
809         bt_connected_headset_data_t *connected_device;
810         GList *node;
811
812         node = g_list_first(g_connected_list);
813         while (node != NULL) {
814                 connected_device = node->data;
815                 if (connected_device != NULL &&
816                 g_strcmp0(connected_device->device_address, address) == 0) {
817                         BT_ERR("Device is removed from the list");
818                         g_connected_list = g_list_remove(g_connected_list, connected_device);
819                         g_free(connected_device);
820                         return;
821                 }
822                 node = g_list_next(node);
823         }
824 }
825
826 int _bt_hf_connect(int request_id,
827                 bluetooth_device_address_t *device_address,
828                 GArray **out_param1)
829 {
830         int result = BLUETOOTH_ERROR_NONE;
831         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
832         bt_function_data_t *func_data;
833         GDBusProxy *adapter_proxy;
834         GDBusConnection *g_conn;
835         int ret;
836         char *uuid;
837
838         BT_CHECK_PARAMETER(device_address, return);
839
840         _bt_convert_addr_type_to_string(address, device_address->addr);
841
842         adapter_proxy = _bt_get_adapter_proxy();
843         if (adapter_proxy == NULL) {
844                 result = BLUETOOTH_ERROR_INTERNAL;
845                 goto fail;
846         }
847
848         g_conn = _bt_get_system_gconn();
849         if (g_conn == NULL) {
850                 result = BLUETOOTH_ERROR_INTERNAL;
851                 goto fail;
852         }
853
854         func_data = g_malloc0(sizeof(bt_function_data_t));
855         /* Fix : NULL_RETURNS */
856         if (func_data == NULL) {
857                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
858                 goto fail;
859         }
860
861         func_data->address = g_strdup(address);
862         func_data->req_id = request_id;
863         uuid = g_strdup(HFP_AG_UUID);
864
865         BT_DBG("Connecting to service %s", uuid);
866
867         ret = _bt_connect_profile(address, uuid,
868                         __bt_hf_request_cb, func_data);
869
870         if (ret != BLUETOOTH_ERROR_NONE) {
871                 BT_ERR("_bt_connect_profile Error");
872                 g_free(func_data->address);
873                 g_free(func_data);
874                 g_free(uuid);
875                 return ret;
876         }
877         g_free(uuid);
878         return BLUETOOTH_ERROR_NONE;
879 fail:
880         if (out_param1 != NULL)
881                 g_array_append_vals(*out_param1, address,
882                                 BT_ADDRESS_STR_LEN);
883
884         return result;
885 }
886
887 int _bt_hf_disconnect(int request_id,
888                 bluetooth_device_address_t *device_address,
889                 GArray **out_param1)
890 {
891         int result = BLUETOOTH_ERROR_NONE;
892         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
893         bt_function_data_t *func_data;
894         GDBusProxy *adapter_proxy;
895         GDBusConnection *g_conn;
896
897         int ret;
898         char *uuid;
899
900         BT_CHECK_PARAMETER(device_address, return);
901
902         _bt_convert_addr_type_to_string(address, device_address->addr);
903
904         adapter_proxy = _bt_get_adapter_proxy();
905         if (adapter_proxy == NULL) {
906                 result = BLUETOOTH_ERROR_INTERNAL;
907                 goto fail;
908         }
909
910         g_conn = _bt_get_system_gconn();
911         if (g_conn == NULL) {
912                 result = BLUETOOTH_ERROR_INTERNAL;
913                 goto fail;
914         }
915
916         func_data = g_malloc0(sizeof(bt_function_data_t));
917         /* Fix : NULL_RETURNS */
918         if (func_data == NULL) {
919                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
920                 goto fail;
921         }
922
923         func_data->address = g_strdup(address);
924         func_data->req_id = request_id;
925         uuid = g_strdup(HFP_AG_UUID);
926
927         BT_DBG("Disconnecting service %s", uuid);
928         ret = _bt_disconnect_profile(address, uuid,
929                         __bt_hf_request_cb, func_data);
930
931         if (ret != BLUETOOTH_ERROR_NONE) {
932                 BT_ERR("_bt_disconnect_profile Error");
933                 g_free(func_data->address);
934                 g_free(func_data);
935                 g_free(uuid);
936                 return ret;
937         }
938         g_free(uuid);
939         return BLUETOOTH_ERROR_NONE;
940 fail:
941         if (out_param1 != NULL)
942                 g_array_append_vals(*out_param1, address,
943                                 BT_ADDRESS_STR_LEN);
944
945         return result;
946 }
947
948 int _bt_audio_set_content_protect(gboolean status)
949 {
950         GDBusConnection *conn;
951         GError *error = NULL;
952
953         BT_DBG("+\n");
954
955         conn = _bt_get_system_gconn();
956         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
957
958         BT_DBG("Content Protection status = [%d]", status);
959
960         g_dbus_connection_emit_signal(conn,
961                         NULL, BT_CONTENT_PROTECTION_PATH,
962                         BT_CONTENT_PROTECTION_INTERFACE,
963                         "ProtectionRequired",
964                         g_variant_new("(b)", status),
965                         &error);
966
967         if (error) {
968                 /* dBUS gives error cause */
969                 ERR("Could not Emit Signal: errCode[%x], message[%s]",
970                         error->code, error->message);
971                 g_clear_error(&error);
972                 return BLUETOOTH_ERROR_INTERNAL;
973         }
974
975         BT_DBG("Emit Signal done = [ProtectionRequired]");
976         return BLUETOOTH_ERROR_NONE;
977 }