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