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