Fix the coding style errors (bt-service)
[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;
548         int i;
549         int j;
550         bluetooth_device_info_t info;
551         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
552         gboolean ret = FALSE;
553
554         BT_DBG("+");
555
556         dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
557
558         _bt_get_bonded_devices(&dev_list);
559         size = (dev_list->len) / sizeof(bluetooth_device_info_t);
560
561         for (i = 0; i < size; i++) {
562                 info = g_array_index(dev_list, bluetooth_device_info_t, i);
563                 _bt_convert_addr_type_to_string(bond_address,
564                                 info.device_address.addr);
565                 if (strcmp(bond_address, remote_address) != 0)
566                         continue;
567
568                 BT_INFO("Device address Matched");
569                 j = 0;
570                 while (j != info.service_index) {
571                         if (type == BT_AUDIO_HSP) {
572                                 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
573                                         BT_INFO("HFP HS UUID exists");
574                                         ret = TRUE;
575                                         goto end;
576                                 }
577                         } else if (type == BT_AUDIO_A2DP) {
578                                 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
579                                         BT_INFO("A2DP SINK UUID exists");
580                                         ret = TRUE;
581                                         goto end;
582                                 }
583                         }
584                         j++;
585                 }
586         }
587 end:
588         g_array_free(dev_list, TRUE);
589         BT_DBG("-");
590         return ret;
591 }
592
593 gboolean _bt_is_service_connected(char* address, int type)
594 {
595         GList *node;
596
597         node = g_list_first(g_connected_list);
598         while (node != NULL) {
599                 bt_connected_headset_data_t *conn_device = node->data;
600
601                 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
602                         (conn_device->type & type)) {
603                                 BT_INFO("Service connected");
604                                 return TRUE;
605                 }
606
607                 node = g_list_next(node);
608         }
609         BT_INFO("Service not connected");
610         return FALSE;
611 }
612
613 int _bt_audio_connect(int request_id, int type,
614                 bluetooth_device_address_t *device_address,
615                 GArray **out_param1)
616 {
617         int result = BLUETOOTH_ERROR_NONE;
618         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
619         GDBusProxy *adapter_proxy;
620         GDBusConnection *g_conn;
621         int ret;
622         char *uuid;
623         int value = BLUETOOTH_ERROR_NONE;
624         bt_audio_function_data_t *func_data;
625
626         BT_CHECK_PARAMETER(device_address, return);
627
628         adapter_proxy = _bt_get_adapter_proxy();
629         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
630
631         g_conn = _bt_get_system_gconn();
632         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
633
634         _bt_convert_addr_type_to_string(address, device_address->addr);
635
636         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
637         /* Fix : NULL_RETURNS */
638         if (func_data == NULL) {
639                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
640                 goto fail;
641         }
642
643         func_data->address = g_strdup(address);
644         func_data->req_id = request_id;
645         func_data->type = type;
646         func_data->pending = BT_PENDING_NONE;
647         func_data->out_param = out_param1;
648
649         switch (type) {
650         case BT_AUDIO_HSP:
651                 uuid = HFP_HS_UUID;
652                 break;
653         case BT_AUDIO_A2DP:
654                 uuid = A2DP_SINK_UUID;
655                 break;
656         case BT_AVRCP:
657                 uuid = AVRCP_TARGET_UUID;
658                 break;
659         case BT_AUDIO_A2DP_SOURCE:
660                 uuid = A2DP_SOURCE_UUID;
661                 break;
662         case BT_AUDIO_ALL:
663                 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
664                         uuid = HFP_HS_UUID;
665                         func_data->pending = BT_PENDING_CONNECT;
666                         type = BT_AUDIO_HSP;
667                 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
668                         uuid = A2DP_SINK_UUID;
669                         type = BT_AUDIO_A2DP;
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         retv_if(func_data == NULL, BLUETOOTH_ERROR_INTERNAL);
737
738         func_data->address = g_strdup(address);
739         func_data->req_id = request_id;
740         func_data->pending = BT_PENDING_NONE;
741         func_data->out_param = out_param1;
742         func_data->type = type;
743
744         switch (type) {
745         case BT_AUDIO_HSP:
746                 uuid = HFP_HS_UUID;
747                 break;
748         case BT_AUDIO_A2DP:
749                 uuid = A2DP_SINK_UUID;
750                 break;
751         case BT_AVRCP:
752                 uuid = AVRCP_TARGET_UUID;
753                 break;
754         case BT_AUDIO_A2DP_SOURCE:
755                 uuid = A2DP_SOURCE_UUID;
756                 break;
757         case BT_AUDIO_ALL:
758                 if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
759                         uuid = HFP_HS_UUID;
760                         func_data->pending = BT_PENDING_DISCONNECT;
761                 } else if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
762                         uuid = A2DP_SINK_UUID;
763                 } else {
764                         BT_ERR("No audio service connected");
765                         result = BLUETOOTH_ERROR_NOT_CONNECTED;
766                         goto fail;
767                 }
768                 break;
769         default:
770                 BT_ERR("Unknown role");
771                 result = BLUETOOTH_ERROR_INTERNAL;
772                 goto fail;
773         }
774
775         BT_INFO("Disconnecting service %s", uuid);
776         ret = _bt_disconnect_profile(address, uuid,
777                         __bt_audio_request_cb, func_data);
778
779         if (ret != BLUETOOTH_ERROR_NONE) {
780                 BT_ERR("_bt_disconnect_profile Error");
781                 g_free(func_data->address);
782                 g_free(func_data);
783                 return ret;
784         }
785
786         /*
787          *      This logic is added for dual HF mode issue.
788          */
789         node = g_list_first(g_connected_list);
790         while (node != NULL) {
791                 bt_connected_headset_data_t *connected_device = node->data;
792
793                 if (g_strcmp0(connected_device->device_address, address) == 0) {
794                         BT_DBG("Connection type update");
795                         type = connected_device->type;
796                         break;
797                 }
798                 node = g_list_next(node);
799         }
800         _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
801
802         return BLUETOOTH_ERROR_NONE;
803 fail:
804         if (out_param1 != NULL)
805                 g_array_append_vals(*out_param1, address,
806                                 BT_ADDRESS_STR_LEN);
807
808         return result;
809 }
810
811 void _bt_remove_from_connected_list(const char *address)
812 {
813         bt_connected_headset_data_t *connected_device;
814         GList *node;
815
816         node = g_list_first(g_connected_list);
817         while (node != NULL) {
818                 connected_device = node->data;
819                 if (connected_device != NULL &&
820                 g_strcmp0(connected_device->device_address, address) == 0) {
821                         BT_ERR("Device is removed from the list");
822                         g_connected_list = g_list_remove(g_connected_list, connected_device);
823                         g_free(connected_device);
824                         return;
825                 }
826                 node = g_list_next(node);
827         }
828 }
829
830 int _bt_hf_connect(int request_id,
831                 bluetooth_device_address_t *device_address,
832                 GArray **out_param1)
833 {
834         int result = BLUETOOTH_ERROR_NONE;
835         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
836         bt_function_data_t *func_data;
837         GDBusProxy *adapter_proxy;
838         GDBusConnection *g_conn;
839         int ret;
840         char *uuid;
841
842         BT_CHECK_PARAMETER(device_address, return);
843
844         _bt_convert_addr_type_to_string(address, device_address->addr);
845
846         adapter_proxy = _bt_get_adapter_proxy();
847         if (adapter_proxy == NULL) {
848                 result = BLUETOOTH_ERROR_INTERNAL;
849                 goto fail;
850         }
851
852         g_conn = _bt_get_system_gconn();
853         if (g_conn == NULL) {
854                 result = BLUETOOTH_ERROR_INTERNAL;
855                 goto fail;
856         }
857
858         func_data = g_malloc0(sizeof(bt_function_data_t));
859         /* Fix : NULL_RETURNS */
860         if (func_data == NULL) {
861                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
862                 goto fail;
863         }
864
865         func_data->address = g_strdup(address);
866         func_data->req_id = request_id;
867         uuid = g_strdup(HFP_AG_UUID);
868
869         BT_DBG("Connecting to service %s", uuid);
870
871         ret = _bt_connect_profile(address, uuid,
872                         __bt_hf_request_cb, func_data);
873
874         if (ret != BLUETOOTH_ERROR_NONE) {
875                 BT_ERR("_bt_connect_profile Error");
876                 g_free(func_data->address);
877                 g_free(func_data);
878                 g_free(uuid);
879                 return ret;
880         }
881         g_free(uuid);
882         return BLUETOOTH_ERROR_NONE;
883 fail:
884         if (out_param1 != NULL)
885                 g_array_append_vals(*out_param1, address,
886                                 BT_ADDRESS_STR_LEN);
887
888         return result;
889 }
890
891 int _bt_hf_disconnect(int request_id,
892                 bluetooth_device_address_t *device_address,
893                 GArray **out_param1)
894 {
895         int result = BLUETOOTH_ERROR_NONE;
896         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
897         bt_function_data_t *func_data;
898         GDBusProxy *adapter_proxy;
899         GDBusConnection *g_conn;
900
901         int ret;
902         char *uuid;
903
904         BT_CHECK_PARAMETER(device_address, return);
905
906         _bt_convert_addr_type_to_string(address, device_address->addr);
907
908         adapter_proxy = _bt_get_adapter_proxy();
909         if (adapter_proxy == NULL) {
910                 result = BLUETOOTH_ERROR_INTERNAL;
911                 goto fail;
912         }
913
914         g_conn = _bt_get_system_gconn();
915         if (g_conn == NULL) {
916                 result = BLUETOOTH_ERROR_INTERNAL;
917                 goto fail;
918         }
919
920         func_data = g_malloc0(sizeof(bt_function_data_t));
921         /* Fix : NULL_RETURNS */
922         if (func_data == NULL) {
923                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
924                 goto fail;
925         }
926
927         func_data->address = g_strdup(address);
928         func_data->req_id = request_id;
929         uuid = g_strdup(HFP_AG_UUID);
930
931         BT_DBG("Disconnecting service %s", uuid);
932         ret = _bt_disconnect_profile(address, uuid,
933                         __bt_hf_request_cb, func_data);
934
935         if (ret != BLUETOOTH_ERROR_NONE) {
936                 BT_ERR("_bt_disconnect_profile Error");
937                 g_free(func_data->address);
938                 g_free(func_data);
939                 g_free(uuid);
940                 return ret;
941         }
942         g_free(uuid);
943         return BLUETOOTH_ERROR_NONE;
944 fail:
945         if (out_param1 != NULL)
946                 g_array_append_vals(*out_param1, address,
947                                 BT_ADDRESS_STR_LEN);
948
949         return result;
950 }
951
952 int _bt_audio_set_content_protect(gboolean status)
953 {
954         GDBusConnection *conn;
955         GError *error = NULL;
956
957         BT_DBG("+\n");
958
959         conn = _bt_get_system_gconn();
960         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
961
962         BT_DBG("Content Protection status = [%d]", status);
963
964         g_dbus_connection_emit_signal(conn,
965                         NULL, BT_CONTENT_PROTECTION_PATH,
966                         BT_CONTENT_PROTECTION_INTERFACE,
967                         "ProtectionRequired",
968                         g_variant_new("(b)", status),
969                         &error);
970
971         if (error) {
972                 /* dBUS gives error cause */
973                 ERR("Could not Emit Signal: errCode[%x], message[%s]",
974                         error->code, error->message);
975                 g_clear_error(&error);
976                 return BLUETOOTH_ERROR_INTERNAL;
977         }
978
979         BT_DBG("Emit Signal done = [ProtectionRequired]");
980         return BLUETOOTH_ERROR_NONE;
981 }