Handle the privilege permission error for agent methods
[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                         ret = _bt_get_error_value_from_message(err->message);
702                         g_clear_error(&err);
703                 }
704                 return ret;
705         }
706
707         g_variant_unref(reply);
708         return BLUETOOTH_ERROR_NONE;
709
710 }
711
712 BT_EXPORT_API int bluetooth_hf_terminate_call()
713 {
714         GVariant *reply = NULL;
715         GError *err = NULL;
716         int ret = BLUETOOTH_ERROR_INTERNAL;
717
718         BT_CHECK_ENABLED(return);
719
720         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
721                         "TerminateCall", &err, NULL);
722         if (!reply) {
723                 BT_ERR("Error returned in method call\n");
724                 if (err) {
725                         BT_ERR("Error = %s", err->message);
726                         g_dbus_error_strip_remote_error(err);
727                         ret = _bt_get_error_value_from_message(err->message);
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_initiate_call(char *number)
738 {
739         GVariant *reply = NULL;
740         GError *err = NULL;
741         GVariant *param = NULL;
742         int ret = BLUETOOTH_ERROR_INTERNAL;
743
744         BT_CHECK_ENABLED(return);
745
746         if (!number)
747                 number = "";
748
749         param = g_variant_new("(s)", number);
750         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
751                         "InitiateCall", &err, param);
752         if (!reply) {
753                 BT_ERR("Error returned in method call");
754                 if (err) {
755                         BT_ERR("Error = %s", err->message);
756                         g_dbus_error_strip_remote_error(err);
757                         ret = _bt_get_error_value_from_message(err->message);
758                         g_clear_error(&err);
759                 }
760                 return ret;
761         }
762
763         g_variant_unref(reply);
764         return BLUETOOTH_ERROR_NONE;
765 }
766
767 BT_EXPORT_API int bluetooth_hf_voice_recognition(unsigned int status)
768 {
769         GVariant *reply = NULL;
770         GError *err = NULL;
771         GVariant *param = NULL;
772         int ret = BLUETOOTH_ERROR_INTERNAL;
773
774         BT_CHECK_ENABLED(return);
775
776         param = g_variant_new("(i)", status);
777         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
778                         "VoiceRecognition", &err, param);
779         if (!reply) {
780                 BT_ERR("Error returned in method call\n");
781                 if (err) {
782                         BT_ERR("Error = %s", err->message);
783                         g_dbus_error_strip_remote_error(err);
784                         ret = _bt_get_error_value_from_message(err->message);
785                         g_clear_error(&err);
786                 }
787                 return ret;
788         }
789
790         g_variant_unref(reply);
791         return BLUETOOTH_ERROR_NONE;
792 }
793
794 BT_EXPORT_API int bluetooth_hf_audio_disconnect(void)
795 {
796         GVariant *reply = NULL;
797         GError *err = NULL;
798         int ret = BLUETOOTH_ERROR_INTERNAL;
799
800         BT_CHECK_ENABLED(return);
801
802         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
803                         "ScoDisconnect", &err, NULL);
804         if (!reply) {
805                 BT_ERR("Error returned in method call\n");
806                 if (err) {
807                         BT_ERR("Error = %s", err->message);
808                         g_dbus_error_strip_remote_error(err);
809                         ret = _bt_get_error_value_from_message(err->message);
810                         g_clear_error(&err);
811                 }
812                 return ret;
813         }
814
815         g_variant_unref(reply);
816         return BLUETOOTH_ERROR_NONE;
817 }
818
819 BT_EXPORT_API int bluetooth_hf_set_speaker_gain(unsigned int speaker_gain)
820 {
821         GVariant *reply = NULL;
822         GError *err = NULL;
823         GVariant *param = NULL;
824         int ret = BLUETOOTH_ERROR_INTERNAL;
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_dbus_error_strip_remote_error(err);
836                         ret = _bt_get_error_value_from_message(err->message);
837                         g_clear_error(&err);
838                 }
839                 return ret;
840         }
841
842         g_variant_unref(reply);
843         return BLUETOOTH_ERROR_NONE;
844 }
845
846 BT_EXPORT_API int bluetooth_hf_send_dtmf(char *dtmf)
847 {
848         GVariant *reply = NULL;
849         GError *err = NULL;
850         GVariant *param = NULL;
851         int ret = BLUETOOTH_ERROR_INTERNAL;
852
853         BT_CHECK_ENABLED(return);
854
855         param = g_variant_new("(s)", dtmf);
856         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
857                         "SendDtmf", &err, param);
858         if (!reply) {
859                 BT_ERR("Error returned in method call\n");
860                 if (err) {
861                         BT_ERR("Error = %s", err->message);
862                         g_dbus_error_strip_remote_error(err);
863                         ret = _bt_get_error_value_from_message(err->message);
864                         g_clear_error(&err);
865                 }
866                 return ret;
867         }
868
869         g_variant_unref(reply);
870         return BLUETOOTH_ERROR_NONE;
871 }
872
873 BT_EXPORT_API int bluetooth_hf_send_xsat_cmd(int app_id, char *xsat_cmd)
874 {
875         GVariant *reply = NULL;
876         GError *err = NULL;
877         GVariant *param = NULL;
878         char buffer[200] = {0,};
879         char *ptr = buffer;
880         int ret = BLUETOOTH_ERROR_INTERNAL;
881
882         BT_CHECK_ENABLED(return);
883
884         strncpy(buffer, "AT+XSAT=\0", 200);
885         snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
886                 "%d,", app_id);
887         strncat(buffer, xsat_cmd, (sizeof(buffer) - 1) - strlen(buffer));
888         BT_DBG("Xsat cmd received = %s", buffer);
889
890         param = g_variant_new("(s)", ptr);
891
892         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
893                                         "SendAtCmd", &err, param);
894         if (!reply) {
895                 BT_ERR("Error returned in method call\n");
896                 if (err) {
897                         BT_ERR("Error = %s", err->message);
898                         g_dbus_error_strip_remote_error(err);
899                         ret = _bt_get_error_value_from_message(err->message);
900                         g_clear_error(&err);
901                 }
902                 return ret;
903         }
904
905         g_variant_unref(reply);
906         return BLUETOOTH_ERROR_NONE;
907 }
908
909 BT_EXPORT_API int bluetooth_hf_release_and_accept(void)
910 {
911         GVariant *reply = NULL;
912         GError *err = NULL;
913         int ret = BLUETOOTH_ERROR_INTERNAL;
914
915         BT_CHECK_ENABLED(return);
916
917         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
918                         "ReleaseAndAccept", &err, NULL);
919         if (!reply) {
920                 BT_ERR("Error returned in method call\n");
921                 if (err) {
922                         BT_ERR("Error = %s", err->message);
923                         g_dbus_error_strip_remote_error(err);
924                         ret = _bt_get_error_value_from_message(err->message);
925                         g_clear_error(&err);
926                 }
927                 return ret;
928         }
929
930         g_variant_unref(reply);
931         return BLUETOOTH_ERROR_NONE;
932 }
933
934 BT_EXPORT_API int bluetooth_hf_swap_call(void)
935 {
936         GVariant *reply = NULL;
937         GError *err = NULL;
938         int ret = BLUETOOTH_ERROR_INTERNAL;
939
940         BT_CHECK_ENABLED(return);
941
942         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
943                         "CallSwap", &err, NULL);
944         if (!reply) {
945                 BT_ERR("Error returned in method call\n");
946                 if (err) {
947                         BT_ERR("Error = %s", err->message);
948                         g_dbus_error_strip_remote_error(err);
949                         ret = _bt_get_error_value_from_message(err->message);
950                         g_clear_error(&err);
951                 }
952                 return ret;
953         }
954
955         g_variant_unref(reply);
956         return BLUETOOTH_ERROR_NONE;
957 }
958
959 BT_EXPORT_API int bluetooth_hf_release_all_call(void)
960 {
961         GVariant *reply = NULL;
962         GError *err = NULL;
963         int ret = BLUETOOTH_ERROR_INTERNAL;
964
965         BT_CHECK_ENABLED(return);
966
967         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
968                         "ReleaseAllCall", &err, NULL);
969         if (!reply) {
970                 BT_ERR("Error returned in method call\n");
971                 if (err) {
972                         BT_ERR("Error = %s", err->message);
973                         g_dbus_error_strip_remote_error(err);
974                         ret = _bt_get_error_value_from_message(err->message);
975                         g_clear_error(&err);
976                 }
977                 return ret;
978         }
979
980         g_variant_unref(reply);
981         return BLUETOOTH_ERROR_NONE;
982 }
983
984 BT_EXPORT_API int bluetooth_hf_join_call(void)
985 {
986         GVariant *reply = NULL;
987         GError *err = NULL;
988         int ret = BLUETOOTH_ERROR_INTERNAL;
989
990         BT_CHECK_ENABLED(return);
991
992         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
993                         "JoinCall", &err, NULL);
994         if (!reply) {
995                 BT_ERR("Error returned in method call\n");
996                 if (err) {
997                         BT_ERR("Error = %s", err->message);
998                         g_dbus_error_strip_remote_error(err);
999                         ret = _bt_get_error_value_from_message(err->message);
1000                         g_clear_error(&err);
1001                 }
1002                 return ret;
1003         }
1004
1005         g_variant_unref(reply);
1006         return BLUETOOTH_ERROR_NONE;
1007 }
1008
1009 BT_EXPORT_API int bluetooth_hf_get_call_list(void *call_list,
1010                                                                 bt_hf_call_status_info_t **call_status)
1011 {
1012         int i;
1013         GList *list = call_list;
1014         int call_count;
1015         bt_hf_call_status_info_t * call_info;
1016
1017         BT_CHECK_ENABLED(return);
1018         retv_if(list == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
1019         retv_if(call_status == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
1020
1021         call_count = g_list_length(list);
1022
1023         BT_DBG(" call_count = [%d]", call_count);
1024
1025         for (i = 0; i < call_count; i++) {
1026                 call_info = g_list_nth_data(list, i);
1027                 BT_DBG(" direction = [%d]", call_info->direction);
1028                 BT_DBG(" status = [%d]", call_info->status);
1029                 BT_DBG(" mpart = [%d]", call_info->mpart);
1030                 BT_DBG(" number = [%s]", call_info->number);
1031                 BT_DBG(" idx = [%d]", call_info->idx);
1032                 call_status[i] = call_info;
1033         }
1034
1035         return BLUETOOTH_ERROR_NONE;
1036 }
1037
1038 BT_EXPORT_API int bluetooth_hf_free_call_list(bt_hf_call_list_s *call_list)
1039 {
1040         bt_hf_call_list_s *handle;
1041         bt_hf_call_status_info_t *call_status;
1042
1043         retv_if(call_list == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
1044
1045         handle = (bt_hf_call_list_s *)call_list;
1046         do  {
1047                 call_status = (bt_hf_call_status_info_t *)g_list_nth_data(
1048                                                         handle->list, 0);
1049                 if (call_status == NULL)
1050                         break;
1051                 handle->list = g_list_remove(handle->list, call_status);
1052                 g_free(call_status->number);
1053                 g_free(call_status);
1054         } while (1);
1055         g_free(handle);
1056         return BLUETOOTH_ERROR_NONE;
1057 }
1058
1059 BT_EXPORT_API int bluetooth_hf_request_call_list(
1060                                         bt_hf_call_list_s **call_list)
1061 {
1062         GVariant *reply = NULL;
1063         GError *err = NULL;
1064
1065         BT_CHECK_ENABLED(return);
1066
1067         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1068                         "RequestCallList", &err, NULL);
1069         if (!reply) {
1070                 BT_ERR("dbus Error or call list is null\n");
1071                 if (err) {
1072                         BT_ERR("Error = %s", err->message);
1073                         g_clear_error(&err);
1074                 }
1075                 *call_list = NULL;
1076                 return BLUETOOTH_ERROR_INTERNAL;
1077         }
1078         __bt_hf_agent_read_call_list(reply, call_list);
1079
1080         g_variant_unref(reply);
1081         return BLUETOOTH_ERROR_NONE;
1082 }
1083
1084 BT_EXPORT_API int bluetooth_hf_get_codec(unsigned int *codec_id)
1085 {
1086         GVariant *reply = NULL;
1087         GError *err = NULL;
1088         int32_t current_codec;
1089
1090         BT_CHECK_ENABLED(return);
1091
1092         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1093                         "GetCurrentCodec", &err, NULL);
1094         if (!reply) {
1095                 BT_ERR("Error returned in method call\n");
1096                 if (err) {
1097                         BT_ERR("Error = %s", err->message);
1098                         g_clear_error(&err);
1099                 }
1100                 return BLUETOOTH_ERROR_INTERNAL;
1101         }
1102
1103         g_variant_get(reply, "(i)", &current_codec);
1104         *codec_id = current_codec;
1105         BT_DBG(" Codec ID is : %d", *codec_id);
1106
1107         g_variant_unref(reply);
1108         return BLUETOOTH_ERROR_NONE;
1109 }
1110
1111 BT_EXPORT_API int bluetooth_hf_get_audio_connected(unsigned int *audio_connected)
1112 {
1113         GVariant *reply = NULL;
1114         GError *err = NULL;
1115         int32_t sco_audio_connected_from_bt_agent;
1116
1117         BT_CHECK_ENABLED(return);
1118
1119         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1120                         "GetAudioConnected", &err, NULL);
1121         if (!reply) {
1122                 BT_ERR("Error returned in method call\n");
1123                 if (err) {
1124                         BT_ERR("Error = %s", err->message);
1125                         g_clear_error(&err);
1126                 }
1127                 return BLUETOOTH_ERROR_INTERNAL;
1128         }
1129
1130         g_variant_get(reply, "(i)", &sco_audio_connected_from_bt_agent);
1131         *audio_connected = sco_audio_connected_from_bt_agent;
1132
1133         if (*audio_connected == BLUETOOTH_HF_AUDIO_CONNECTED)
1134                 BT_DBG("SCO Audio is Connected");
1135         else
1136                 BT_DBG("SCO Audio is Disconnected");
1137
1138         g_variant_unref(reply);
1139         return BLUETOOTH_ERROR_NONE;
1140 }
1141
1142 BT_EXPORT_API int bluetooth_hf_is_connected(gboolean *hf_connected)
1143 {
1144         GVariant *reply = NULL;
1145         GError *err = NULL;
1146         gboolean hf_connected_from_bt_agent;
1147
1148         BT_CHECK_ENABLED(return);
1149
1150         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1151                         "IsHfConnected", &err, NULL);
1152         if (!reply) {
1153                 BT_ERR("Error returned in method call\n");
1154                 if (err) {
1155                         BT_ERR("Error = %s", err->message);
1156                         g_clear_error(&err);
1157                 }
1158                 return BLUETOOTH_ERROR_INTERNAL;
1159         }
1160
1161         g_variant_get(reply, "(b)", &hf_connected_from_bt_agent);
1162         *hf_connected = hf_connected_from_bt_agent;
1163
1164         BT_DBG("%s", *hf_connected ? "Connected" : "Disconnected");
1165
1166         g_variant_unref(reply);
1167         return BLUETOOTH_ERROR_NONE;
1168 }
1169
1170 BT_EXPORT_API int bluetooth_hf_is_ibr_supported(gboolean *ibr_supported)
1171 {
1172         GVariant *reply = NULL;
1173         GError *err = NULL;
1174         gboolean is_supported;
1175         int ret = BLUETOOTH_ERROR_NONE;
1176
1177         BT_CHECK_ENABLED(return);
1178
1179         reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE,
1180                         "IsInbandRingtoneSupported", &err, NULL);
1181         if (!reply) {
1182                 BT_ERR("Error returned in method call");
1183                 if (err) {
1184                         g_dbus_error_strip_remote_error(err);
1185                         ret = __bluetooth_hf_get_error(err->message);
1186                         g_error_free(err);
1187                         return ret;
1188                 }
1189                 return BLUETOOTH_ERROR_INTERNAL;
1190         }
1191
1192         g_variant_get(reply, "(b)", &is_supported);
1193         *ibr_supported = is_supported;
1194
1195         BT_DBG("%s", *ibr_supported ? "Supported" : "Not Supported");
1196
1197         g_variant_unref(reply);
1198         return ret;
1199 }