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