Fix the coding style errors (bt-api)
[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
32 BT_EXPORT_API int bluetooth_audio_init(bt_audio_func_ptr cb, void *user_data)
33 {
34         int ret;
35
36         if (cb == NULL) {
37                 BT_ERR("callback is NULL");
38                 return BLUETOOTH_ERROR_INVALID_PARAM;
39         }
40         ret = _bt_init_event_handler();
41
42         if (ret != BLUETOOTH_ERROR_NONE &&
43              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
44                 BT_ERR("Fail to init the event handler");
45                 return ret;
46         }
47
48         _bt_set_user_data(BT_AUDIO, (void *)cb, user_data);
49
50         /* Register All events */
51         ret = _bt_register_event(BT_HEADSET_EVENT, (void *)cb, user_data);
52         if (ret != BLUETOOTH_ERROR_NONE &&
53             ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
54                 _bt_deinit_event_handler();
55                 return ret;
56         }
57
58         ret = _bt_register_event(BT_A2DP_SOURCE_EVENT, (void *)cb, user_data);
59         if (ret != BLUETOOTH_ERROR_NONE &&
60                         ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
61                 _bt_deinit_event_handler();
62                 return ret;
63         }
64
65         return BLUETOOTH_ERROR_NONE;
66 }
67
68 BT_EXPORT_API int bluetooth_audio_deinit(void)
69 {
70         _bt_unregister_event(BT_HEADSET_EVENT);
71         _bt_unregister_event(BT_A2DP_SOURCE_EVENT);
72         _bt_set_user_data(BT_AUDIO, NULL, NULL);
73
74         return BLUETOOTH_ERROR_NONE;
75 }
76
77 BT_EXPORT_API int bluetooth_audio_connect(bluetooth_device_address_t *remote_address)
78 {
79         int service_function = BT_AUDIO_CONNECT;
80         int result;
81         bt_user_info_t *user_info;
82
83         BT_CHECK_PARAMETER(remote_address, return);
84         BT_CHECK_ENABLED(return);
85
86         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AUDIO_CONNECT)
87              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
88                 BT_ERR("Don't have a privilege to use this API");
89                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
90         }
91
92 #ifdef TIZEN_DPM_ENABLE
93         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_address) == BT_DPM_RESTRICTED) {
94                 BT_ERR("Blacklist device");
95                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
96         }
97
98         if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED &&
99                  _bt_check_dpm(BT_DPM_A2DP, NULL) == BT_DPM_RESTRICTED) {
100                 BT_ERR("Not allow to use HSP / A2DP profile");
101                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
102         } else if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED) {
103                 BT_ERR("Not allow to use HSP profile");
104                 service_function = BT_AV_CONNECT;
105         } else if (_bt_check_dpm(BT_DPM_A2DP, NULL) == BT_DPM_RESTRICTED) {
106                 BT_ERR("Not allow to use A2DP profile");
107                 service_function = BT_AG_CONNECT;
108         }
109
110         if (_bt_check_dpm(BT_DPM_DESKTOP, NULL) == BT_DPM_RESTRICTED) {
111                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
112                 bluetooth_device_class_t dev_class;
113
114                 _bt_convert_addr_type_to_string(address, remote_address->addr);
115                 _bt_get_cod_by_address(address, &dev_class);
116
117                 if (dev_class.major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_COMPUTER) {
118                         BT_ERR("Reject a authorization due to MDM Policy");
119                         return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
120                 }
121         }
122 #endif
123
124         user_info = _bt_get_user_data(BT_AUDIO);
125         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
126
127         BT_INIT_PARAMS();
128         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
129
130         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
131
132         result = _bt_send_request_async(BT_BLUEZ_SERVICE, service_function,
133                 in_param1, in_param2, in_param3, in_param4,
134                 user_info->cb, user_info->user_data);
135
136         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
137
138         return result;
139 }
140
141 BT_EXPORT_API int bluetooth_audio_disconnect(bluetooth_device_address_t *remote_address)
142 {
143         int result;
144         bt_user_info_t *user_info;
145
146         BT_CHECK_PARAMETER(remote_address, return);
147         BT_CHECK_ENABLED(return);
148
149         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AUDIO_DISCONNECT)
150              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
151                 BT_ERR("Don't have a privilege to use this API");
152                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
153         }
154
155         user_info = _bt_get_user_data(BT_AUDIO);
156         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
157
158         BT_INIT_PARAMS();
159         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
160
161         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
162
163         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AUDIO_DISCONNECT,
164                 in_param1, in_param2, in_param3, in_param4,
165                 user_info->cb, user_info->user_data);
166
167         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
168
169         return result;
170 }
171
172 BT_EXPORT_API int bluetooth_ag_connect(bluetooth_device_address_t *remote_address)
173 {
174         int result;
175         bt_user_info_t *user_info;
176
177         BT_CHECK_PARAMETER(remote_address, return);
178         BT_CHECK_ENABLED(return);
179
180         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AG_CONNECT)
181              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
182                 BT_ERR("Don't have a privilege to use this API");
183                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
184         }
185
186 #ifdef TIZEN_DPM_ENABLE
187         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_address) == BT_DPM_RESTRICTED) {
188                 BT_ERR("Blacklist device");
189                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
190         }
191
192         if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED) {
193                 BT_ERR("Not allow to use HSP profile");
194                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
195         }
196
197         if (_bt_check_dpm(BT_DPM_DESKTOP, NULL) == BT_DPM_RESTRICTED) {
198                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
199                 bluetooth_device_class_t dev_class;
200
201                 _bt_convert_addr_type_to_string(address, remote_address->addr);
202                 _bt_get_cod_by_address(address, &dev_class);
203
204                 if (dev_class.major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_COMPUTER) {
205                         BT_ERR("Reject a authorization due to MDM Policy");
206                         return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
207                 }
208         }
209 #endif
210
211         user_info = _bt_get_user_data(BT_AUDIO);
212         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
213
214         BT_INIT_PARAMS();
215         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
216
217         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
218
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_ag_get_headset_volume(unsigned int *speaker_gain)
421 {
422         int result;
423
424         BT_CHECK_PARAMETER(speaker_gain, return);
425         BT_CHECK_ENABLED(return);
426
427         BT_INIT_PARAMS();
428         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
429
430         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_SPEAKER_GAIN,
431                 in_param1, in_param2, in_param3, in_param4, &out_param);
432
433         if (result == BLUETOOTH_ERROR_NONE) {
434                 *speaker_gain = g_array_index(out_param,
435                                 unsigned int, 0);
436         }
437
438         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
439
440         return result;
441 }
442
443 BT_EXPORT_API int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain)
444 {
445         int result;
446
447         BT_CHECK_ENABLED(return);
448
449 #ifdef TIZEN_DPM_ENABLE
450         if (_bt_check_dpm(BT_DPM_HSP, NULL) == BT_DPM_RESTRICTED) {
451                 BT_ERR("Not allow to use HSP profile");
452                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
453         }
454 #endif
455
456         BT_INIT_PARAMS();
457         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
458
459         g_array_append_vals(in_param1, &speaker_gain, sizeof(unsigned int));
460
461         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_SPEAKER_GAIN,
462                 in_param1, in_param2, in_param3, in_param4, &out_param);
463
464         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
465
466         return result;
467 }
468
469 #define BT_HF_SERVICE_NAME "org.bluez.hf_agent"
470 #define BT_HF_OBJECT_PATH "/org/bluez/handsfree_agent"
471 #define BT_HF_INTERFACE "org.tizen.HfApp"
472
473
474 static GVariant* __bt_hf_agent_dbus_send(const char *path, const char *interface,
475                                 const char *method, GError **err, GVariant *parameters)
476 {
477         GVariant *reply = NULL;
478         GDBusProxy *proxy = NULL;
479         GDBusConnection *conn = NULL;
480
481         conn = _bt_gdbus_get_system_gconn();
482         retv_if(conn == NULL, NULL);
483
484         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
485                 NULL, BT_HF_SERVICE_NAME, path, interface, NULL, err);
486         if (proxy == NULL) {
487                 BT_ERR("Unable to allocate new proxy");
488                 return NULL;
489         }
490
491         reply = g_dbus_proxy_call_sync(proxy, method, parameters,
492                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
493
494         g_object_unref(proxy);
495         return reply;
496 }
497
498 static int __bt_hf_agent_read_call_list(GVariant *reply,
499                                 bt_hf_call_list_s **call_list) {
500
501         GVariantIter iter;
502         GVariant *var_temp = NULL;
503         int32_t call_count;
504         gchar *num = NULL;
505         int dir, status, mpart, idx;
506
507         BT_DBG("+");
508
509         g_variant_get(reply, "(i@a(siiii))", &call_count, &var_temp);
510
511         if (call_count <= 0) {
512                 *call_list = NULL;
513                 return BLUETOOTH_ERROR_NOT_FOUND;
514         }
515         BT_DBG("Call count = %d", call_count);
516
517         *call_list = g_malloc0(sizeof(bt_hf_call_list_s));
518         /* Fix : NULL_RETURNS */
519         retv_if(*call_list == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
520
521         (*call_list)->count = call_count;
522
523         g_variant_iter_init(&iter, var_temp);
524         while (g_variant_iter_loop(&iter, "(siiii)", &num, &dir, &status, &mpart, &idx)) {
525                 bt_hf_call_status_info_t *call_info;
526
527                 call_info = g_malloc0(sizeof(bt_hf_call_status_info_t));
528                 /* Fix : NULL_RETURNS */
529                 retv_if(call_info == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
530
531                 call_info->number = g_strdup(num);
532                 call_info->direction = dir;
533                 call_info->status = status;
534                 call_info->mpart = mpart;
535                 call_info->idx = idx;
536
537                 (*call_list)->list = g_list_append((*call_list)->list,
538                                                         (gpointer)call_info);
539         }
540         BT_DBG("-");
541         return BLUETOOTH_ERROR_NONE;
542 }
543
544 BT_EXPORT_API int bluetooth_hf_init(bt_hf_func_ptr cb, void *user_data)
545 {
546         int ret;
547
548         if (cb == NULL) {
549                 BT_ERR("callback is NULL");
550                 return BLUETOOTH_ERROR_INVALID_PARAM;
551         }
552
553         ret = _bt_init_event_handler();
554
555         if (ret != BLUETOOTH_ERROR_NONE &&
556              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
557                 BT_ERR("Fail to init the event handler");
558                 return ret;
559         }
560
561         _bt_set_user_data(BT_HF, (void *)cb, user_data);
562
563         /* Register All events */
564         ret = _bt_register_event(BT_HF_AGENT_EVENT, (void *)cb, user_data);
565         if (ret != BLUETOOTH_ERROR_NONE &&
566              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
567                 _bt_deinit_event_handler();
568                 return ret;
569         }
570
571         return BLUETOOTH_ERROR_NONE;
572 }
573
574 BT_EXPORT_API int bluetooth_hf_deinit(void)
575 {
576         int ret;
577
578         ret = _bt_unregister_event(BT_HF_AGENT_EVENT);
579         if (ret != BLUETOOTH_ERROR_NONE)
580                 BT_ERR("_bt_unregister_event failed");
581
582         _bt_set_user_data(BT_HF, NULL, NULL);
583
584         return BLUETOOTH_ERROR_NONE;
585 }
586
587 BT_EXPORT_API int bluetooth_hf_connect(bluetooth_device_address_t *remote_address)
588 {
589         int result;
590         bt_user_info_t *user_info;
591
592         BT_CHECK_ENABLED(return);
593         BT_CHECK_PARAMETER(remote_address, return);
594
595         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HF_CONNECT)
596              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
597                 BT_ERR("Don't have a privilege to use this API");
598                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
599         }
600
601         user_info = _bt_get_user_data(BT_HF);
602         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
603
604         BT_INIT_PARAMS();
605         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
606
607         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
608
609         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HF_CONNECT,
610                 in_param1, in_param2, in_param3, in_param4,
611                 user_info->cb, user_info->user_data);
612
613         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
614
615         return result;
616 }
617
618 BT_EXPORT_API int bluetooth_hf_disconnect(bluetooth_device_address_t *remote_address)
619 {
620         int result;
621         bt_user_info_t *user_info;
622
623         BT_CHECK_PARAMETER(remote_address, return);
624         BT_CHECK_ENABLED(return);
625
626         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HF_DISCONNECT)
627              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
628                 BT_ERR("Don't have a privilege to use this API");
629                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
630         }
631
632         user_info = _bt_get_user_data(BT_HF);
633         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
634
635         BT_INIT_PARAMS();
636         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
637
638         g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t));
639
640         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HF_DISCONNECT,
641                 in_param1, in_param2, in_param3, in_param4,
642                 user_info->cb, user_info->user_data);
643
644         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
645
646         return result;
647 }
648
649 BT_EXPORT_API int bluetooth_hf_answer_call()
650 {
651         GVariant *reply = NULL;
652         GError *err = NULL;
653         int ret = BLUETOOTH_ERROR_INTERNAL;
654
655         BT_CHECK_ENABLED(return);
656
657         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
658                         "AnswerCall", &err, NULL);
659         if (!reply) {
660                 BT_ERR("Error returned in method call\n");
661                 if (err) {
662                         BT_ERR("Error = %s", err->message);
663                         g_dbus_error_strip_remote_error(err);
664                         if (strcmp(err->message, "Operation not supported") == 0)
665                                 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
666                         else if (strcmp(err->message, "Operation not allowed") == 0)
667                                 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
668                         else
669                                 ret = BLUETOOTH_ERROR_INTERNAL;
670                         g_clear_error(&err);
671                 }
672                 return ret;
673         }
674
675         g_variant_unref(reply);
676         return BLUETOOTH_ERROR_NONE;
677
678 }
679
680 BT_EXPORT_API int bluetooth_hf_terminate_call()
681 {
682         GVariant *reply = NULL;
683         GError *err = NULL;
684
685         BT_CHECK_ENABLED(return);
686
687         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
688                         "TerminateCall", &err, NULL);
689         if (!reply) {
690                 BT_ERR("Error returned in method call\n");
691                 if (err) {
692                         BT_ERR("Error = %s", err->message);
693                         g_clear_error(&err);
694                 }
695                 return BLUETOOTH_ERROR_INTERNAL;
696         }
697
698         g_variant_unref(reply);
699         return BLUETOOTH_ERROR_NONE;
700 }
701
702 BT_EXPORT_API int bluetooth_hf_initiate_call(char *number)
703 {
704         GVariant *reply = NULL;
705         GError *err = NULL;
706         GVariant *param = NULL;
707         int ret = BLUETOOTH_ERROR_INTERNAL;
708
709         BT_CHECK_ENABLED(return);
710
711         if (!number)
712                 number = "";
713
714         param = g_variant_new("(s)", number);
715         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
716                         "InitiateCall", &err, param);
717         if (!reply) {
718                 BT_ERR("Error returned in method call");
719                 if (err) {
720                         BT_ERR("Error = %s", err->message);
721                         g_dbus_error_strip_remote_error(err);
722                         if (strcmp(err->message, "NotConnected") == 0)
723                                 ret = BLUETOOTH_ERROR_NOT_CONNECTED;
724                         else if (strcmp(err->message, "Operation not allowed") == 0)
725                                 ret = BLUETOOTH_ERROR_IN_PROGRESS;
726                         else
727                                 ret = BLUETOOTH_ERROR_INTERNAL;
728                         g_clear_error(&err);
729                 }
730                 return ret;
731         }
732
733         g_variant_unref(reply);
734         return BLUETOOTH_ERROR_NONE;
735 }
736
737 BT_EXPORT_API int bluetooth_hf_voice_recognition(unsigned int status)
738 {
739         GVariant *reply = NULL;
740         GError *err = NULL;
741         GVariant *param = NULL;
742
743         BT_CHECK_ENABLED(return);
744
745         param = g_variant_new("(i)", status);
746         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
747                         "VoiceRecognition", &err, param);
748         if (!reply) {
749                 BT_ERR("Error returned in method call\n");
750                 if (err) {
751                         BT_ERR("Error = %s", err->message);
752                         g_clear_error(&err);
753                 }
754                 return BLUETOOTH_ERROR_INTERNAL;
755         }
756
757         g_variant_unref(reply);
758         return BLUETOOTH_ERROR_NONE;
759 }
760
761 BT_EXPORT_API int bluetooth_hf_audio_disconnect(void)
762 {
763         GVariant *reply = NULL;
764         GError *err = NULL;
765
766         BT_CHECK_ENABLED(return);
767
768         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
769                         "ScoDisconnect", &err, NULL);
770         if (!reply) {
771                 BT_ERR("Error returned in method call\n");
772                 if (err) {
773                         BT_ERR("Error = %s", err->message);
774                         g_clear_error(&err);
775                 }
776                 return BLUETOOTH_ERROR_INTERNAL;
777         }
778
779         g_variant_unref(reply);
780         return BLUETOOTH_ERROR_NONE;
781 }
782
783 BT_EXPORT_API int bluetooth_hf_set_speaker_gain(unsigned int speaker_gain)
784 {
785         GVariant *reply = NULL;
786         GError *err = NULL;
787         GVariant *param = NULL;
788
789         BT_CHECK_ENABLED(return);
790
791         param = g_variant_new("(u)", speaker_gain);
792         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
793                         "SpeakerGain", &err, param);
794         if (!reply) {
795                 BT_ERR("Error returned in method call\n");
796                 if (err) {
797                         BT_ERR("Error = %s", err->message);
798                         g_clear_error(&err);
799                 }
800                 return BLUETOOTH_ERROR_INTERNAL;
801         }
802
803         g_variant_unref(reply);
804         return BLUETOOTH_ERROR_NONE;
805 }
806
807 BT_EXPORT_API int bluetooth_hf_send_dtmf(char *dtmf)
808 {
809         GVariant *reply = NULL;
810         GError *err = NULL;
811         GVariant *param = NULL;
812
813         BT_CHECK_ENABLED(return);
814
815         param = g_variant_new("(s)", dtmf);
816         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
817                         "SendDtmf", &err, param);
818         if (!reply) {
819                 BT_ERR("Error returned in method call\n");
820                 if (err) {
821                         BT_ERR("Error = %s", err->message);
822                         g_clear_error(&err);
823                 }
824                 return BLUETOOTH_ERROR_INTERNAL;
825         }
826
827         g_variant_unref(reply);
828         return BLUETOOTH_ERROR_NONE;
829 }
830
831 BT_EXPORT_API int bluetooth_hf_send_xsat_cmd(int app_id, char *xsat_cmd)
832 {
833         GVariant *reply = NULL;
834         GError *err = NULL;
835         GVariant *param = NULL;
836         char buffer[200] = {0,};
837         char *ptr = buffer;
838
839         BT_CHECK_ENABLED(return);
840
841         strncpy(buffer, "AT+XSAT=", strlen("AT+XSAT="));
842         snprintf(buffer + strlen(buffer), sizeof(buffer), "%d,", app_id);
843         strncat(buffer, xsat_cmd, (sizeof(buffer) - 1) - strlen(buffer));
844         BT_DBG("Xsat cmd received = %s", buffer);
845
846         param = g_variant_new("(s)", ptr);
847
848         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
849                                         "SendAtCmd", &err, param);
850         if (!reply) {
851                 BT_ERR("Error returned in method call\n");
852                 if (err) {
853                         BT_ERR("Error = %s", err->message);
854                         g_clear_error(&err);
855                 }
856                 return BLUETOOTH_ERROR_INTERNAL;
857         }
858
859         g_variant_unref(reply);
860         return BLUETOOTH_ERROR_NONE;
861 }
862
863 BT_EXPORT_API int bluetooth_hf_release_and_accept(void)
864 {
865         GVariant *reply = NULL;
866         GError *err = NULL;
867
868         BT_CHECK_ENABLED(return);
869
870         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
871                         "ReleaseAndAccept", &err, NULL);
872         if (!reply) {
873                 BT_ERR("Error returned in method call\n");
874                 if (err) {
875                         BT_ERR("Error = %s", err->message);
876                         g_clear_error(&err);
877                 }
878                 return BLUETOOTH_ERROR_INTERNAL;
879         }
880
881         g_variant_unref(reply);
882         return BLUETOOTH_ERROR_NONE;
883 }
884
885 BT_EXPORT_API int bluetooth_hf_swap_call(void)
886 {
887         GVariant *reply = NULL;
888         GError *err = NULL;
889
890         BT_CHECK_ENABLED(return);
891
892         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
893                         "CallSwap", &err, NULL);
894         if (!reply) {
895                 BT_ERR("Error returned in method call\n");
896                 if (err) {
897                         BT_ERR("Error = %s", err->message);
898                         g_clear_error(&err);
899                 }
900                 return BLUETOOTH_ERROR_INTERNAL;
901         }
902
903         g_variant_unref(reply);
904         return BLUETOOTH_ERROR_NONE;
905 }
906
907 BT_EXPORT_API int bluetooth_hf_release_all_call(void)
908 {
909         GVariant *reply = NULL;
910         GError *err = NULL;
911
912         BT_CHECK_ENABLED(return);
913
914         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
915                         "ReleaseAllCall", &err, NULL);
916         if (!reply) {
917                 BT_ERR("Error returned in method call\n");
918                 if (err) {
919                         BT_ERR("Error = %s", err->message);
920                         g_clear_error(&err);
921                 }
922                 return BLUETOOTH_ERROR_INTERNAL;
923         }
924
925         g_variant_unref(reply);
926         return BLUETOOTH_ERROR_NONE;
927 }
928
929 BT_EXPORT_API int bluetooth_hf_join_call(void)
930 {
931         GVariant *reply = NULL;
932         GError *err = NULL;
933
934         BT_CHECK_ENABLED(return);
935
936         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
937                         "JoinCall", &err, NULL);
938         if (!reply) {
939                 BT_ERR("Error returned in method call\n");
940                 if (err) {
941                         BT_ERR("Error = %s", err->message);
942                         g_clear_error(&err);
943                 }
944                 return BLUETOOTH_ERROR_INTERNAL;
945         }
946
947         g_variant_unref(reply);
948         return BLUETOOTH_ERROR_NONE;
949 }
950
951 BT_EXPORT_API int bluetooth_hf_get_call_list(void *call_list,
952                                                                 bt_hf_call_status_info_t **call_status)
953 {
954         int i;
955         GList *list = call_list;
956         int call_count;
957         bt_hf_call_status_info_t * call_info;
958
959         BT_CHECK_ENABLED(return);
960         retv_if(list == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
961         retv_if(call_status == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
962
963         call_count = g_list_length(list);
964
965         BT_DBG(" call_count = [%d]", call_count);
966
967         for (i = 0; i < call_count; i++) {
968                 call_info = g_list_nth_data(list, i);
969                 BT_DBG(" direction = [%d]", call_info->direction);
970                 BT_DBG(" status = [%d]", call_info->status);
971                 BT_DBG(" mpart = [%d]", call_info->mpart);
972                 BT_DBG(" number = [%s]", call_info->number);
973                 BT_DBG(" idx = [%d]", call_info->idx);
974                 call_status[i] = call_info;
975         }
976
977         return BLUETOOTH_ERROR_NONE;
978 }
979
980 BT_EXPORT_API int bluetooth_hf_free_call_list(bt_hf_call_list_s *call_list)
981 {
982         bt_hf_call_list_s *handle;
983         bt_hf_call_status_info_t *call_status;
984
985         retv_if(call_list == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
986
987         handle = (bt_hf_call_list_s *)call_list;
988         do  {
989                 call_status = (bt_hf_call_status_info_t *)g_list_nth_data(
990                                                         handle->list, 0);
991                 if (call_status == NULL)
992                         break;
993                 handle->list = g_list_remove(handle->list, call_status);
994                 g_free(call_status->number);
995                 g_free(call_status);
996         } while (1);
997         g_free(handle);
998         return BLUETOOTH_ERROR_NONE;
999 }
1000
1001 BT_EXPORT_API int bluetooth_hf_request_call_list(
1002                                         bt_hf_call_list_s **call_list)
1003 {
1004         GVariant *reply = NULL;
1005         GError *err = NULL;
1006
1007         BT_CHECK_ENABLED(return);
1008
1009         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1010                         "RequestCallList", &err, NULL);
1011         if (!reply) {
1012                 BT_ERR("dbus Error or call list is null\n");
1013                 if (err) {
1014                         BT_ERR("Error = %s", err->message);
1015                         g_clear_error(&err);
1016                 }
1017                 *call_list = NULL;
1018                 return BLUETOOTH_ERROR_INTERNAL;
1019         }
1020         __bt_hf_agent_read_call_list(reply, call_list);
1021
1022         g_variant_unref(reply);
1023         return BLUETOOTH_ERROR_NONE;
1024 }
1025
1026 BT_EXPORT_API int bluetooth_hf_get_codec(unsigned int *codec_id)
1027 {
1028         GVariant *reply = NULL;
1029         GError *err = NULL;
1030         int32_t current_codec;
1031
1032         BT_CHECK_ENABLED(return);
1033
1034         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1035                         "GetCurrentCodec", &err, NULL);
1036         if (!reply) {
1037                 BT_ERR("Error returned in method call\n");
1038                 if (err) {
1039                         BT_ERR("Error = %s", err->message);
1040                         g_clear_error(&err);
1041                 }
1042                 return BLUETOOTH_ERROR_INTERNAL;
1043         }
1044
1045         g_variant_get(reply, "(i)", &current_codec);
1046         *codec_id = current_codec;
1047         BT_DBG(" Codec ID is : %d", *codec_id);
1048
1049         g_variant_unref(reply);
1050         return BLUETOOTH_ERROR_NONE;
1051 }
1052
1053 BT_EXPORT_API int bluetooth_hf_get_audio_connected(unsigned int *audio_connected)
1054 {
1055         GVariant *reply = NULL;
1056         GError *err = NULL;
1057         int32_t sco_audio_connected_from_bt_agent;
1058
1059         BT_CHECK_ENABLED(return);
1060
1061         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1062                         "GetAudioConnected", &err, NULL);
1063         if (!reply) {
1064                 BT_ERR("Error returned in method call\n");
1065                 if (err) {
1066                         BT_ERR("Error = %s", err->message);
1067                         g_clear_error(&err);
1068                 }
1069                 return BLUETOOTH_ERROR_INTERNAL;
1070         }
1071
1072         g_variant_get(reply, "(i)", &sco_audio_connected_from_bt_agent);
1073         *audio_connected = sco_audio_connected_from_bt_agent;
1074
1075         if (*audio_connected == BLUETOOTH_HF_AUDIO_CONNECTED) {
1076                 BT_DBG("SCO Audio is Connected");
1077         } else {
1078                 BT_DBG("SCO Audio is Disconnected");
1079         }
1080
1081         g_variant_unref(reply);
1082         return BLUETOOTH_ERROR_NONE;
1083 }
1084
1085 BT_EXPORT_API int bluetooth_hf_is_connected(gboolean *hf_connected)
1086 {
1087         GVariant *reply = NULL;
1088         GError *err = NULL;
1089         gboolean hf_connected_from_bt_agent;
1090
1091         BT_CHECK_ENABLED(return);
1092
1093         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1094                         "IsHfConnected", &err, NULL);
1095         if (!reply) {
1096                 BT_ERR("Error returned in method call\n");
1097                 if (err) {
1098                         BT_ERR("Error = %s", err->message);
1099                         g_clear_error(&err);
1100                 }
1101                 return BLUETOOTH_ERROR_INTERNAL;
1102         }
1103
1104         g_variant_get(reply, "(b)", &hf_connected_from_bt_agent);
1105         *hf_connected = hf_connected_from_bt_agent;
1106
1107         BT_DBG("%s", *hf_connected ? "Connected" : "Disconnected");
1108
1109         g_variant_unref(reply);
1110         return BLUETOOTH_ERROR_NONE;
1111 }
1112