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