[FRWK]Added run time audio role select Feature
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-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 <stdio.h>
19
20 #include "bluetooth-api.h"
21 #include "bluetooth-audio-api.h"
22 #include "bt-internal-types.h"
23
24 #include "bt-common.h"
25 #include "bt-request-sender.h"
26 #include "bt-event-handler.h"
27 #ifdef TIZEN_DPM_ENABLE
28 #include "bt-dpm.h"
29 #endif
30
31 BT_EXPORT_API int bluetooth_audio_init(bt_audio_func_ptr cb, void *user_data)
32 {
33         int ret;
34
35         if (cb == NULL) {
36                 BT_ERR("callback is NULL");
37                 return BLUETOOTH_ERROR_INVALID_PARAM;
38         }
39         ret = _bt_init_event_handler();
40
41         if (ret != BLUETOOTH_ERROR_NONE &&
42              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
43                 BT_ERR("Fail to init the event handler");
44                 return ret;
45         }
46
47         _bt_set_user_data(BT_AUDIO, (void *)cb, user_data);
48
49         /* Register All events */
50         ret = _bt_register_event(BT_HEADSET_EVENT, (void *)cb, user_data);
51         if (ret != BLUETOOTH_ERROR_NONE &&
52             ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
53                 _bt_deinit_event_handler();
54                 return ret;
55         }
56
57         ret = _bt_register_event(BT_A2DP_SOURCE_EVENT, (void *)cb, user_data);
58         if (ret != BLUETOOTH_ERROR_NONE &&
59                         ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
60                 _bt_deinit_event_handler();
61                 return ret;
62         }
63
64         return BLUETOOTH_ERROR_NONE;
65 }
66
67 BT_EXPORT_API int bluetooth_audio_deinit(void)
68 {
69         _bt_unregister_event(BT_HEADSET_EVENT);
70         _bt_unregister_event(BT_A2DP_SOURCE_EVENT);
71         _bt_set_user_data(BT_AUDIO, NULL, NULL);
72
73         return BLUETOOTH_ERROR_NONE;
74 }
75
76 BT_EXPORT_API int bluetooth_audio_connect(bluetooth_device_address_t *remote_address)
77 {
78         int service_function = BT_AUDIO_CONNECT;
79         int result;
80         bt_user_info_t *user_info;
81
82         BT_CHECK_PARAMETER(remote_address, return);
83         BT_CHECK_ENABLED(return);
84
85         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AUDIO_CONNECT)
86              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
87                 BT_ERR("Don't have a privilege to use this API");
88                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
89         }
90
91 #ifdef TIZEN_DPM_ENABLE
92         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_address) == BT_DPM_RESTRICTED) {
93                 BT_ERR("Blacklist device");
94                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
95         }
96
97         if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED &&
98                  _bt_check_dpm(BT_DPM_A2DP, NULL) == BT_DPM_RESTRICTED) {
99                 BT_ERR("Not allow to use HSP / A2DP profile");
100                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
101         } else if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED) {
102                 BT_ERR("Not allow to use HSP profile");
103                 service_function = BT_AV_CONNECT;
104         } else if (_bt_check_dpm(BT_DPM_A2DP, NULL) == BT_DPM_RESTRICTED) {
105                 BT_ERR("Not allow to use A2DP profile");
106                 service_function = BT_AG_CONNECT;
107         }
108
109         if (_bt_check_dpm(BT_DPM_DESKTOP, NULL) == BT_DPM_RESTRICTED) {
110                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
111                 bluetooth_device_class_t dev_class;
112
113                 _bt_convert_addr_type_to_string(address, remote_address->addr);
114                 _bt_get_cod_by_address(address, &dev_class);
115
116                 if (dev_class.major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_COMPUTER) {
117                         BT_ERR("Reject a authorization due to MDM Policy");
118                         return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
119                 }
120         }
121 #endif
122
123         user_info = _bt_get_user_data(BT_AUDIO);
124         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
125
126         BT_INIT_PARAMS();
127         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
128
129         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
130
131         result = _bt_send_request_async(BT_BLUEZ_SERVICE, service_function,
132                 in_param1, in_param2, in_param3, in_param4,
133                 user_info->cb, user_info->user_data);
134
135         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
136
137         return result;
138 }
139
140 BT_EXPORT_API int bluetooth_audio_disconnect(bluetooth_device_address_t *remote_address)
141 {
142         int result;
143         bt_user_info_t *user_info;
144
145         BT_CHECK_PARAMETER(remote_address, return);
146         BT_CHECK_ENABLED(return);
147
148         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AUDIO_DISCONNECT)
149              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
150                 BT_ERR("Don't have a privilege to use this API");
151                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
152         }
153
154         user_info = _bt_get_user_data(BT_AUDIO);
155         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
156
157         BT_INIT_PARAMS();
158         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
159
160         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
161
162         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AUDIO_DISCONNECT,
163                 in_param1, in_param2, in_param3, in_param4,
164                 user_info->cb, user_info->user_data);
165
166         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
167
168         return result;
169 }
170
171 BT_EXPORT_API int bluetooth_ag_connect(bluetooth_device_address_t *remote_address)
172 {
173         int result;
174         bt_user_info_t *user_info;
175
176         BT_CHECK_PARAMETER(remote_address, return);
177         BT_CHECK_ENABLED(return);
178
179         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AG_CONNECT)
180              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
181                 BT_ERR("Don't have a privilege to use this API");
182                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
183         }
184
185 #ifdef TIZEN_DPM_ENABLE
186         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_address) == BT_DPM_RESTRICTED) {
187                 BT_ERR("Blacklist device");
188                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
189         }
190
191         if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED) {
192                 BT_ERR("Not allow to use HSP profile");
193                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
194         }
195
196         if (_bt_check_dpm(BT_DPM_DESKTOP, NULL) == BT_DPM_RESTRICTED) {
197                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
198                 bluetooth_device_class_t dev_class;
199
200                 _bt_convert_addr_type_to_string(address, remote_address->addr);
201                 _bt_get_cod_by_address(address, &dev_class);
202
203                 if (dev_class.major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_COMPUTER) {
204                         BT_ERR("Reject a authorization due to MDM Policy");
205                         return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
206                 }
207         }
208 #endif
209
210         user_info = _bt_get_user_data(BT_AUDIO);
211         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
212
213         BT_INIT_PARAMS();
214         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
215
216         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
217
218         BT_INFO_C("### Connect AG");
219         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AG_CONNECT,
220                 in_param1, in_param2, in_param3, in_param4,
221                 user_info->cb, user_info->user_data);
222
223         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
224
225         return result;
226 }
227
228 BT_EXPORT_API int bluetooth_ag_disconnect(bluetooth_device_address_t *remote_address)
229 {
230         int result;
231         bt_user_info_t *user_info;
232
233         BT_CHECK_PARAMETER(remote_address, return);
234         BT_CHECK_ENABLED(return);
235
236         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AG_DISCONNECT)
237              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
238                 BT_ERR("Don't have a privilege to use this API");
239                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
240         }
241
242         user_info = _bt_get_user_data(BT_AUDIO);
243         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
244
245         BT_INIT_PARAMS();
246         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
247
248         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
249
250         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AG_DISCONNECT,
251                 in_param1, in_param2, in_param3, in_param4,
252                 user_info->cb, user_info->user_data);
253
254         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
255
256         return result;
257 }
258
259 BT_EXPORT_API int bluetooth_av_connect(bluetooth_device_address_t *remote_address)
260 {
261         int result;
262         bt_user_info_t *user_info;
263
264         BT_CHECK_PARAMETER(remote_address, return);
265         BT_CHECK_ENABLED(return);
266
267         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AV_CONNECT)
268              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
269                 BT_ERR("Don't have a privilege to use this API");
270                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
271         }
272
273 #ifdef TIZEN_DPM_ENABLE
274         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_address) == BT_DPM_RESTRICTED) {
275                 BT_ERR("Blacklist device");
276                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
277         }
278
279         if (_bt_check_dpm(BT_DPM_A2DP, NULL) == BT_DPM_RESTRICTED) {
280                 BT_ERR("Not allow to use A2DP profile");
281                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
282         }
283
284         if (_bt_check_dpm(BT_DPM_DESKTOP, NULL) == BT_DPM_RESTRICTED) {
285                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
286                 bluetooth_device_class_t dev_class;
287
288                 _bt_convert_addr_type_to_string(address, remote_address->addr);
289                 _bt_get_cod_by_address(address, &dev_class);
290
291                 if (dev_class.major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_COMPUTER) {
292                         BT_ERR("Reject a authorization due to MDM Policy");
293                         return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
294                 }
295         }
296 #endif
297
298         user_info = _bt_get_user_data(BT_AUDIO);
299         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
300
301         BT_INIT_PARAMS();
302         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
303
304         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
305
306         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AV_CONNECT,
307                 in_param1, in_param2, in_param3, in_param4,
308                 user_info->cb, user_info->user_data);
309
310         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
311
312         return result;
313 }
314
315 BT_EXPORT_API int bluetooth_av_source_connect(bluetooth_device_address_t *remote_address)
316 {
317         int result;
318         bt_user_info_t *user_info;
319
320         BT_CHECK_PARAMETER(remote_address, return);
321         BT_CHECK_ENABLED(return);
322
323         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AV_SOURCE_CONNECT)
324                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
325                 BT_ERR("Don't have a privilege to use this API");
326                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
327         }
328
329 #ifdef TIZEN_DPM_ENABLE
330         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_address) == BT_DPM_RESTRICTED) {
331                 BT_ERR("Blacklist device");
332                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
333         }
334
335         if (_bt_check_dpm(BT_DPM_A2DP, NULL) == BT_DPM_RESTRICTED) {
336                 BT_ERR("Not allow to use A2DP profile");
337                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
338         }
339 #endif
340
341         user_info = _bt_get_user_data(BT_AUDIO);
342         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
343
344         BT_INIT_PARAMS();
345         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
346
347         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
348
349         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AV_SOURCE_CONNECT,
350                 in_param1, in_param2, in_param3, in_param4,
351                 user_info->cb, user_info->user_data);
352
353         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
354
355         return result;
356 }
357
358 BT_EXPORT_API int bluetooth_av_disconnect(bluetooth_device_address_t *remote_address)
359 {
360         int result;
361         bt_user_info_t *user_info;
362
363         BT_CHECK_PARAMETER(remote_address, return);
364         BT_CHECK_ENABLED(return);
365
366         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AV_DISCONNECT)
367              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
368                 BT_ERR("Don't have a privilege to use this API");
369                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
370         }
371
372         user_info = _bt_get_user_data(BT_AUDIO);
373         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
374
375         BT_INIT_PARAMS();
376         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
377
378         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
379
380         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AV_DISCONNECT,
381                 in_param1, in_param2, in_param3, in_param4,
382                 user_info->cb, user_info->user_data);
383
384         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
385
386         return result;
387 }
388
389 BT_EXPORT_API int bluetooth_av_source_disconnect(bluetooth_device_address_t *remote_address)
390 {
391         int result;
392         bt_user_info_t *user_info;
393
394         BT_CHECK_PARAMETER(remote_address, return);
395         BT_CHECK_ENABLED(return);
396
397         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AV_SOURCE_DISCONNECT)
398              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
399                 BT_ERR("Don't have a privilege to use this API");
400                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
401         }
402
403         user_info = _bt_get_user_data(BT_AUDIO);
404         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
405
406         BT_INIT_PARAMS();
407         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
408
409         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
410
411         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AV_SOURCE_DISCONNECT,
412                 in_param1, in_param2, in_param3, in_param4,
413                 user_info->cb, user_info->user_data);
414
415         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
416
417         return result;
418 }
419
420 BT_EXPORT_API int bluetooth_audio_select_role(bluetooth_audio_role_t role)
421 {
422         int result;
423
424         BT_CHECK_ENABLED(return);
425
426         BT_INIT_PARAMS();
427         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
428
429         g_array_append_vals(in_param1, &role, sizeof(bluetooth_audio_role_t));
430
431         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AUDIO_SELECT_ROLE,
432                 in_param1, in_param2, in_param3, in_param4, &out_param);
433
434         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
435         return result;
436 }
437
438 BT_EXPORT_API int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain)
439 {
440         int result;
441
442         BT_CHECK_PARAMETER(speaker_gain, return);
443         BT_CHECK_ENABLED(return);
444
445         BT_INIT_PARAMS();
446         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
447
448         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_SPEAKER_GAIN,
449                 in_param1, in_param2, in_param3, in_param4, &out_param);
450
451         if (result == BLUETOOTH_ERROR_NONE) {
452                 *speaker_gain = g_array_index(out_param,
453                                 unsigned int, 0);
454         }
455
456         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
457
458         return result;
459 }
460
461 BT_EXPORT_API int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain)
462 {
463         int result;
464
465         BT_CHECK_ENABLED(return);
466
467 #ifdef TIZEN_DPM_ENABLE
468         if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED) {
469                 BT_ERR("Not allow to use HSP profile");
470                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
471         }
472 #endif
473
474         BT_INIT_PARAMS();
475         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
476
477         g_array_append_vals(in_param1, &speaker_gain, sizeof(unsigned int));
478
479         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_SPEAKER_GAIN,
480                 in_param1, in_param2, in_param3, in_param4, &out_param);
481
482         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
483
484         return result;
485 }
486
487 #define BT_HF_SERVICE_NAME "org.bluez.hf_agent"
488 #define BT_HF_OBJECT_PATH "/org/bluez/handsfree_agent"
489 #define BT_HF_INTERFACE "org.tizen.HfApp"
490
491
492 static GVariant* __bt_hf_agent_dbus_send(const char *path, const char *interface,
493                                 const char *method, GError **err, GVariant *parameters)
494 {
495         GVariant *reply = NULL;
496         GDBusProxy *proxy = NULL;
497         GDBusConnection *conn = NULL;
498
499         conn = _bt_gdbus_get_system_gconn();
500         retv_if(conn == NULL, NULL);
501
502         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
503                 NULL, BT_HF_SERVICE_NAME, path, interface, NULL, err);
504         if (proxy == NULL) {
505                 BT_ERR("Unable to allocate new proxy");
506                 return NULL;
507         }
508
509         reply = g_dbus_proxy_call_sync(proxy, method, parameters,
510                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
511
512         g_object_unref(proxy);
513         return reply;
514 }
515
516 static int __bt_hf_agent_read_call_list(GVariant *reply,
517                                 bt_hf_call_list_s **call_list) {
518
519         GVariantIter iter;
520         GVariant *var_temp = NULL;
521         int32_t call_count;
522         gchar *num = NULL;
523         int dir, status, mpart, idx;
524
525         BT_DBG("+");
526
527         g_variant_get(reply, "(i@a(siiii))", &call_count, &var_temp);
528
529         if (call_count <= 0) {
530                 *call_list = NULL;
531                 return BLUETOOTH_ERROR_NOT_FOUND;
532         }
533         BT_DBG("Call count = %d", call_count);
534
535         *call_list = g_malloc0(sizeof(bt_hf_call_list_s));
536         /* Fix : NULL_RETURNS */
537         retv_if(*call_list == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
538
539         (*call_list)->count = call_count;
540
541         g_variant_iter_init(&iter, var_temp);
542         while (g_variant_iter_loop(&iter, "(siiii)", &num, &dir, &status, &mpart, &idx)) {
543                 bt_hf_call_status_info_t *call_info;
544
545                 call_info = g_malloc0(sizeof(bt_hf_call_status_info_t));
546                 /* Fix : NULL_RETURNS */
547                 retv_if(call_info == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
548
549                 call_info->number = g_strdup(num);
550                 call_info->direction = dir;
551                 call_info->status = status;
552                 call_info->mpart = mpart;
553                 call_info->idx = idx;
554
555                 (*call_list)->list = g_list_append((*call_list)->list,
556                                                         (gpointer)call_info);
557         }
558         BT_DBG("-");
559         return BLUETOOTH_ERROR_NONE;
560 }
561
562 static int __bluetooth_hf_get_error(const char *error_message)
563 {
564         if (error_message == NULL) {
565                 BT_ERR("Error message NULL");
566                 return BLUETOOTH_ERROR_INTERNAL;
567         }
568
569         BT_ERR("Error message = %s", error_message);
570
571         if (g_strcmp0(error_message, "NotConnected") == 0)
572                 return BLUETOOTH_ERROR_NOT_CONNECTED;
573         else
574                 return BLUETOOTH_ERROR_INTERNAL;
575 }
576
577 BT_EXPORT_API int bluetooth_hf_init(bt_hf_func_ptr cb, void *user_data)
578 {
579         int ret;
580
581         if (cb == NULL) {
582                 BT_ERR("callback is NULL");
583                 return BLUETOOTH_ERROR_INVALID_PARAM;
584         }
585
586         ret = _bt_init_event_handler();
587
588         if (ret != BLUETOOTH_ERROR_NONE &&
589              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
590                 BT_ERR("Fail to init the event handler");
591                 return ret;
592         }
593
594         _bt_set_user_data(BT_HF, (void *)cb, user_data);
595
596         /* Register All events */
597         ret = _bt_register_event(BT_HF_AGENT_EVENT, (void *)cb, user_data);
598         if (ret != BLUETOOTH_ERROR_NONE &&
599              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
600                 _bt_deinit_event_handler();
601                 return ret;
602         }
603
604         return BLUETOOTH_ERROR_NONE;
605 }
606
607 BT_EXPORT_API int bluetooth_hf_deinit(void)
608 {
609         int ret;
610
611         ret = _bt_unregister_event(BT_HF_AGENT_EVENT);
612         if (ret != BLUETOOTH_ERROR_NONE)
613                 BT_ERR("_bt_unregister_event failed");
614
615         _bt_set_user_data(BT_HF, NULL, NULL);
616
617         return BLUETOOTH_ERROR_NONE;
618 }
619
620 BT_EXPORT_API int bluetooth_hf_connect(bluetooth_device_address_t *remote_address)
621 {
622         int result;
623         bt_user_info_t *user_info;
624
625         BT_CHECK_ENABLED(return);
626         BT_CHECK_PARAMETER(remote_address, return);
627
628         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HF_CONNECT)
629              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
630                 BT_ERR("Don't have a privilege to use this API");
631                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
632         }
633
634         user_info = _bt_get_user_data(BT_HF);
635         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
636
637         BT_INIT_PARAMS();
638         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
639
640         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
641
642         BT_INFO_C("### Connect HF");
643         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HF_CONNECT,
644                 in_param1, in_param2, in_param3, in_param4,
645                 user_info->cb, user_info->user_data);
646
647         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
648
649         return result;
650 }
651
652 BT_EXPORT_API int bluetooth_hf_disconnect(bluetooth_device_address_t *remote_address)
653 {
654         int result;
655         bt_user_info_t *user_info;
656
657         BT_CHECK_PARAMETER(remote_address, return);
658         BT_CHECK_ENABLED(return);
659
660         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HF_DISCONNECT)
661              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
662                 BT_ERR("Don't have a privilege to use this API");
663                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
664         }
665
666         user_info = _bt_get_user_data(BT_HF);
667         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
668
669         BT_INIT_PARAMS();
670         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
671
672         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
673
674         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HF_DISCONNECT,
675                 in_param1, in_param2, in_param3, in_param4,
676                 user_info->cb, user_info->user_data);
677
678         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
679
680         return result;
681 }
682
683 BT_EXPORT_API int bluetooth_hf_answer_call()
684 {
685         GVariant *reply = NULL;
686         GError *err = NULL;
687         int ret = BLUETOOTH_ERROR_INTERNAL;
688
689         BT_CHECK_ENABLED(return);
690
691         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
692                         "AnswerCall", &err, NULL);
693         if (!reply) {
694                 BT_ERR("Error returned in method call\n");
695                 if (err) {
696                         BT_ERR("Error = %s", err->message);
697                         g_dbus_error_strip_remote_error(err);
698                         if (strcmp(err->message, "Operation not supported") == 0)
699                                 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
700                         else if (strcmp(err->message, "Operation not allowed") == 0)
701                                 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
702                         else
703                                 ret = BLUETOOTH_ERROR_INTERNAL;
704                         g_clear_error(&err);
705                 }
706                 return ret;
707         }
708
709         g_variant_unref(reply);
710         return BLUETOOTH_ERROR_NONE;
711
712 }
713
714 BT_EXPORT_API int bluetooth_hf_terminate_call()
715 {
716         GVariant *reply = NULL;
717         GError *err = NULL;
718
719         BT_CHECK_ENABLED(return);
720
721         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
722                         "TerminateCall", &err, NULL);
723         if (!reply) {
724                 BT_ERR("Error returned in method call\n");
725                 if (err) {
726                         BT_ERR("Error = %s", err->message);
727                         g_clear_error(&err);
728                 }
729                 return BLUETOOTH_ERROR_INTERNAL;
730         }
731
732         g_variant_unref(reply);
733         return BLUETOOTH_ERROR_NONE;
734 }
735
736 BT_EXPORT_API int bluetooth_hf_initiate_call(const char *number)
737 {
738         GVariant *reply = NULL;
739         GError *err = NULL;
740         GVariant *param = NULL;
741         int ret = BLUETOOTH_ERROR_INTERNAL;
742
743         BT_CHECK_ENABLED(return);
744
745         if (!number)
746                 number = "";
747
748         param = g_variant_new("(s)", number);
749         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
750                         "InitiateCall", &err, param);
751         if (!reply) {
752                 BT_ERR("Error returned in method call");
753                 if (err) {
754                         BT_ERR("Error = %s", err->message);
755                         g_dbus_error_strip_remote_error(err);
756                         if (strcmp(err->message, "NotConnected") == 0)
757                                 ret = BLUETOOTH_ERROR_NOT_CONNECTED;
758                         else if (strcmp(err->message, "Operation not allowed") == 0)
759                                 ret = BLUETOOTH_ERROR_IN_PROGRESS;
760                         else
761                                 ret = BLUETOOTH_ERROR_INTERNAL;
762                         g_clear_error(&err);
763                 }
764                 return ret;
765         }
766
767         g_variant_unref(reply);
768         return BLUETOOTH_ERROR_NONE;
769 }
770
771 BT_EXPORT_API int bluetooth_hf_voice_recognition(unsigned int status)
772 {
773         GVariant *reply = NULL;
774         GError *err = NULL;
775         GVariant *param = NULL;
776
777         BT_CHECK_ENABLED(return);
778
779         param = g_variant_new("(i)", status);
780         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
781                         "VoiceRecognition", &err, param);
782         if (!reply) {
783                 BT_ERR("Error returned in method call\n");
784                 if (err) {
785                         BT_ERR("Error = %s", err->message);
786                         g_clear_error(&err);
787                 }
788                 return BLUETOOTH_ERROR_INTERNAL;
789         }
790
791         g_variant_unref(reply);
792         return BLUETOOTH_ERROR_NONE;
793 }
794
795 BT_EXPORT_API int bluetooth_hf_audio_disconnect(void)
796 {
797         GVariant *reply = NULL;
798         GError *err = NULL;
799
800         BT_CHECK_ENABLED(return);
801
802         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
803                         "ScoDisconnect", &err, NULL);
804         if (!reply) {
805                 BT_ERR("Error returned in method call\n");
806                 if (err) {
807                         BT_ERR("Error = %s", err->message);
808                         g_clear_error(&err);
809                 }
810                 return BLUETOOTH_ERROR_INTERNAL;
811         }
812
813         g_variant_unref(reply);
814         return BLUETOOTH_ERROR_NONE;
815 }
816
817 BT_EXPORT_API int bluetooth_hf_set_speaker_gain(unsigned int speaker_gain)
818 {
819         GVariant *reply = NULL;
820         GError *err = NULL;
821         GVariant *param = NULL;
822
823         BT_CHECK_ENABLED(return);
824
825         param = g_variant_new("(u)", speaker_gain);
826         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
827                         "SpeakerGain", &err, param);
828         if (!reply) {
829                 BT_ERR("Error returned in method call\n");
830                 if (err) {
831                         BT_ERR("Error = %s", err->message);
832                         g_clear_error(&err);
833                 }
834                 return BLUETOOTH_ERROR_INTERNAL;
835         }
836
837         g_variant_unref(reply);
838         return BLUETOOTH_ERROR_NONE;
839 }
840
841 BT_EXPORT_API int bluetooth_hf_send_dtmf(char *dtmf)
842 {
843         GVariant *reply = NULL;
844         GError *err = NULL;
845         GVariant *param = NULL;
846
847         BT_CHECK_ENABLED(return);
848
849         param = g_variant_new("(s)", dtmf);
850         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
851                         "SendDtmf", &err, param);
852         if (!reply) {
853                 BT_ERR("Error returned in method call\n");
854                 if (err) {
855                         BT_ERR("Error = %s", err->message);
856                         g_clear_error(&err);
857                 }
858                 return BLUETOOTH_ERROR_INTERNAL;
859         }
860
861         g_variant_unref(reply);
862         return BLUETOOTH_ERROR_NONE;
863 }
864
865 BT_EXPORT_API int bluetooth_hf_send_xsat_cmd(int app_id, char *xsat_cmd)
866 {
867         GVariant *reply = NULL;
868         GError *err = NULL;
869         GVariant *param = NULL;
870         char buffer[200] = {0,};
871         char *ptr = buffer;
872
873         BT_CHECK_ENABLED(return);
874
875         strncpy(buffer, "AT+XSAT=\0", 200);
876         snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
877                 "%d,", app_id);
878         strncat(buffer, xsat_cmd, (sizeof(buffer) - 1) - strlen(buffer));
879         BT_DBG("Xsat cmd received = %s", buffer);
880
881         param = g_variant_new("(s)", ptr);
882
883         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
884                                         "SendAtCmd", &err, param);
885         if (!reply) {
886                 BT_ERR("Error returned in method call\n");
887                 if (err) {
888                         BT_ERR("Error = %s", err->message);
889                         g_clear_error(&err);
890                 }
891                 return BLUETOOTH_ERROR_INTERNAL;
892         }
893
894         g_variant_unref(reply);
895         return BLUETOOTH_ERROR_NONE;
896 }
897
898 BT_EXPORT_API int bluetooth_hf_release_and_accept(void)
899 {
900         GVariant *reply = NULL;
901         GError *err = NULL;
902
903         BT_CHECK_ENABLED(return);
904
905         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
906                         "ReleaseAndAccept", &err, NULL);
907         if (!reply) {
908                 BT_ERR("Error returned in method call\n");
909                 if (err) {
910                         BT_ERR("Error = %s", err->message);
911                         g_clear_error(&err);
912                 }
913                 return BLUETOOTH_ERROR_INTERNAL;
914         }
915
916         g_variant_unref(reply);
917         return BLUETOOTH_ERROR_NONE;
918 }
919
920 BT_EXPORT_API int bluetooth_hf_swap_call(void)
921 {
922         GVariant *reply = NULL;
923         GError *err = NULL;
924
925         BT_CHECK_ENABLED(return);
926
927         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
928                         "CallSwap", &err, NULL);
929         if (!reply) {
930                 BT_ERR("Error returned in method call\n");
931                 if (err) {
932                         BT_ERR("Error = %s", err->message);
933                         g_clear_error(&err);
934                 }
935                 return BLUETOOTH_ERROR_INTERNAL;
936         }
937
938         g_variant_unref(reply);
939         return BLUETOOTH_ERROR_NONE;
940 }
941
942 BT_EXPORT_API int bluetooth_hf_release_all_call(void)
943 {
944         GVariant *reply = NULL;
945         GError *err = NULL;
946
947         BT_CHECK_ENABLED(return);
948
949         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
950                         "ReleaseAllCall", &err, NULL);
951         if (!reply) {
952                 BT_ERR("Error returned in method call\n");
953                 if (err) {
954                         BT_ERR("Error = %s", err->message);
955                         g_clear_error(&err);
956                 }
957                 return BLUETOOTH_ERROR_INTERNAL;
958         }
959
960         g_variant_unref(reply);
961         return BLUETOOTH_ERROR_NONE;
962 }
963
964 BT_EXPORT_API int bluetooth_hf_join_call(void)
965 {
966         GVariant *reply = NULL;
967         GError *err = NULL;
968
969         BT_CHECK_ENABLED(return);
970
971         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
972                         "JoinCall", &err, NULL);
973         if (!reply) {
974                 BT_ERR("Error returned in method call\n");
975                 if (err) {
976                         BT_ERR("Error = %s", err->message);
977                         g_clear_error(&err);
978                 }
979                 return BLUETOOTH_ERROR_INTERNAL;
980         }
981
982         g_variant_unref(reply);
983         return BLUETOOTH_ERROR_NONE;
984 }
985
986 BT_EXPORT_API int bluetooth_hf_get_call_list(void *call_list,
987                                                                 bt_hf_call_status_info_t **call_status)
988 {
989         int i;
990         GList *list = call_list;
991         int call_count;
992         bt_hf_call_status_info_t * call_info;
993
994         BT_CHECK_ENABLED(return);
995         retv_if(list == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
996         retv_if(call_status == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
997
998         call_count = g_list_length(list);
999
1000         BT_DBG(" call_count = [%d]", call_count);
1001
1002         for (i = 0; i < call_count; i++) {
1003                 call_info = g_list_nth_data(list, i);
1004                 BT_DBG(" direction = [%d]", call_info->direction);
1005                 BT_DBG(" status = [%d]", call_info->status);
1006                 BT_DBG(" mpart = [%d]", call_info->mpart);
1007                 BT_DBG(" number = [%s]", call_info->number);
1008                 BT_DBG(" idx = [%d]", call_info->idx);
1009                 call_status[i] = call_info;
1010         }
1011
1012         return BLUETOOTH_ERROR_NONE;
1013 }
1014
1015 BT_EXPORT_API int bluetooth_hf_free_call_list(bt_hf_call_list_s *call_list)
1016 {
1017         bt_hf_call_list_s *handle;
1018         bt_hf_call_status_info_t *call_status;
1019
1020         retv_if(call_list == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
1021
1022         handle = (bt_hf_call_list_s *)call_list;
1023         do  {
1024                 call_status = (bt_hf_call_status_info_t *)g_list_nth_data(
1025                                                         handle->list, 0);
1026                 if (call_status == NULL)
1027                         break;
1028                 handle->list = g_list_remove(handle->list, call_status);
1029                 g_free(call_status->number);
1030                 g_free(call_status);
1031         } while (1);
1032         g_free(handle);
1033         return BLUETOOTH_ERROR_NONE;
1034 }
1035
1036 BT_EXPORT_API int bluetooth_hf_request_call_list(
1037                                         bt_hf_call_list_s **call_list)
1038 {
1039         GVariant *reply = NULL;
1040         GError *err = NULL;
1041
1042         BT_CHECK_ENABLED(return);
1043
1044         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1045                         "RequestCallList", &err, NULL);
1046         if (!reply) {
1047                 BT_ERR("dbus Error or call list is null\n");
1048                 if (err) {
1049                         BT_ERR("Error = %s", err->message);
1050                         g_clear_error(&err);
1051                 }
1052                 *call_list = NULL;
1053                 return BLUETOOTH_ERROR_INTERNAL;
1054         }
1055         __bt_hf_agent_read_call_list(reply, call_list);
1056
1057         g_variant_unref(reply);
1058         return BLUETOOTH_ERROR_NONE;
1059 }
1060
1061 BT_EXPORT_API int bluetooth_hf_get_codec(unsigned int *codec_id)
1062 {
1063         GVariant *reply = NULL;
1064         GError *err = NULL;
1065         int32_t current_codec;
1066
1067         BT_CHECK_ENABLED(return);
1068
1069         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1070                         "GetCurrentCodec", &err, NULL);
1071         if (!reply) {
1072                 BT_ERR("Error returned in method call\n");
1073                 if (err) {
1074                         BT_ERR("Error = %s", err->message);
1075                         g_clear_error(&err);
1076                 }
1077                 return BLUETOOTH_ERROR_INTERNAL;
1078         }
1079
1080         g_variant_get(reply, "(i)", &current_codec);
1081         *codec_id = current_codec;
1082         BT_DBG(" Codec ID is : %d", *codec_id);
1083
1084         g_variant_unref(reply);
1085         return BLUETOOTH_ERROR_NONE;
1086 }
1087
1088 BT_EXPORT_API int bluetooth_hf_get_audio_connected(unsigned int *audio_connected)
1089 {
1090         GVariant *reply = NULL;
1091         GError *err = NULL;
1092         int32_t sco_audio_connected_from_bt_agent;
1093
1094         BT_CHECK_ENABLED(return);
1095
1096         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1097                         "GetAudioConnected", &err, NULL);
1098         if (!reply) {
1099                 BT_ERR("Error returned in method call\n");
1100                 if (err) {
1101                         BT_ERR("Error = %s", err->message);
1102                         g_clear_error(&err);
1103                 }
1104                 return BLUETOOTH_ERROR_INTERNAL;
1105         }
1106
1107         g_variant_get(reply, "(i)", &sco_audio_connected_from_bt_agent);
1108         *audio_connected = sco_audio_connected_from_bt_agent;
1109
1110         if (*audio_connected == BLUETOOTH_HF_AUDIO_CONNECTED)
1111                 BT_DBG("SCO Audio is Connected");
1112         else
1113                 BT_DBG("SCO Audio is Disconnected");
1114
1115         g_variant_unref(reply);
1116         return BLUETOOTH_ERROR_NONE;
1117 }
1118
1119 BT_EXPORT_API int bluetooth_hf_is_connected(gboolean *hf_connected)
1120 {
1121         GVariant *reply = NULL;
1122         GError *err = NULL;
1123         gboolean hf_connected_from_bt_agent;
1124
1125         BT_CHECK_ENABLED(return);
1126
1127         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1128                         "IsHfConnected", &err, NULL);
1129         if (!reply) {
1130                 BT_ERR("Error returned in method call\n");
1131                 if (err) {
1132                         BT_ERR("Error = %s", err->message);
1133                         g_clear_error(&err);
1134                 }
1135                 return BLUETOOTH_ERROR_INTERNAL;
1136         }
1137
1138         g_variant_get(reply, "(b)", &hf_connected_from_bt_agent);
1139         *hf_connected = hf_connected_from_bt_agent;
1140
1141         BT_DBG("%s", *hf_connected ? "Connected" : "Disconnected");
1142
1143         g_variant_unref(reply);
1144         return BLUETOOTH_ERROR_NONE;
1145 }
1146
1147 BT_EXPORT_API int bluetooth_hf_is_ibr_supported(gboolean *ibr_supported)
1148 {
1149         GVariant *reply = NULL;
1150         GError *err = NULL;
1151         gboolean is_supported;
1152         int ret = BLUETOOTH_ERROR_NONE;
1153
1154         BT_CHECK_ENABLED(return);
1155
1156         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1157                         "IsInbandRingtoneSupported", &err, NULL);
1158         if (!reply) {
1159                 BT_ERR("Error returned in method call");
1160                 if (err) {
1161                         g_dbus_error_strip_remote_error(err);
1162                         ret = __bluetooth_hf_get_error(err->message);
1163                         g_error_free(err);
1164                         return ret;
1165                 }
1166                 return BLUETOOTH_ERROR_INTERNAL;
1167         }
1168
1169         g_variant_get(reply, "(b)", &is_supported);
1170         *ibr_supported = is_supported;
1171
1172         BT_DBG("%s", *ibr_supported ? "Supported" : "Not Supported");
1173
1174         g_variant_unref(reply);
1175         return ret;
1176 }