Fixes TIVI-670, Bluetooth settings app crashes occasionally
[profile/ivi/bluetooth.git] / src / bluetooth-audio.c
1 /*
2  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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 #include <dlog.h>
18 #include <stdbool.h>
19 #include <bluetooth-api.h>
20 #include <string.h>
21 #include "bluetooth.h"
22 #include "bluetooth_private.h"
23 #include "bluetooth-audio-api.h"
24 #include "bluetooth-telephony-api.h"
25
26 typedef struct _call_list_s {
27         GList *list;
28 } call_list_s;
29
30 /*The below API is just to convert the error from Telephony API's to CAPI error codes,
31 * this is temporary change and changes to proper error code will be done in
32 * subsequent check ins.*/
33 int _bt_convert_telephony_error_code(int error)
34 {
35         switch(error) {
36         case BLUETOOTH_TELEPHONY_ERROR_NONE:
37                 return BT_ERROR_NONE;
38         case BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM:
39                 return BT_ERROR_INVALID_PARAMETER;
40         case BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED:
41                 return BT_ERROR_NOT_INITIALIZED;
42         case BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED:
43                 return BT_ERROR_NOT_ENABLED;
44         case BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED:
45         case BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED:
46                 return BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED;
47         case BLUETOOTH_TELEPHONY_ERROR_BUSY:
48                 return BT_ERROR_RESOURCE_BUSY;
49         case BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY:
50                 return BT_ERROR_OUT_OF_MEMORY;
51         case BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED:
52         case BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST:
53         case BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED:
54                 return BT_ERROR_ALREADY_DONE;
55         case BLUETOOTH_TELEPHONY_ERROR_INTERNAL:
56         case BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE:
57         case BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR:
58         case BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE:
59                 return BT_ERROR_OPERATION_FAILED;
60         default:
61                 return BT_ERROR_NONE;
62         }
63 }
64
65 int bt_audio_initialize(void)
66 {
67         int error;
68
69         BT_CHECK_INIT_STATUS();
70         error = bluetooth_audio_init(_bt_audio_event_proxy, NULL);
71         error = _bt_get_error_code(error);
72         if (BT_ERROR_NONE != error) {
73                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
74                 return error;
75         }
76         error = bluetooth_telephony_init((void *)_bt_telephony_event_proxy, NULL);
77         error = _bt_convert_telephony_error_code(error);
78         error = _bt_get_error_code(error);
79         if (BT_ERROR_NONE != error) {
80                 BT_ERR("%s(0x%08x)",
81                         _bt_convert_error_to_string(error), error);
82         }
83         return error;
84 }
85
86 int bt_audio_deinitialize(void)
87 {
88         int error;
89
90         BT_CHECK_INIT_STATUS();
91         error = bluetooth_audio_deinit();
92         error = _bt_get_error_code(error);
93         if (BT_ERROR_NONE != error) {
94                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
95                 return error;
96         }
97         error = bluetooth_telephony_deinit();
98         error = _bt_convert_telephony_error_code(error);
99         error = _bt_get_error_code(error);
100         if (BT_ERROR_NONE != error) {
101                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
102         }
103         return error;
104 }
105
106 int bt_audio_connect(const char *remote_address, bt_audio_profile_type_e type)
107 {
108         int error;
109         bluetooth_device_address_t addr_hex = { {0,} };
110
111         BT_CHECK_INIT_STATUS();
112         BT_CHECK_INPUT_PARAMETER(remote_address);
113         _bt_convert_address_to_hex(&addr_hex, remote_address);
114         switch(type) {
115         case BT_AUDIO_PROFILE_TYPE_HSP_HFP:
116                 error = bluetooth_ag_connect(&addr_hex);
117                 break;
118         case BT_AUDIO_PROFILE_TYPE_A2DP:
119                 error = bluetooth_av_connect(&addr_hex);
120                 break;
121         case BT_AUDIO_PROFILE_TYPE_ALL:
122         default:
123                 error = bluetooth_audio_connect(&addr_hex);
124                 break;
125         }
126         error = _bt_get_error_code(error);
127         if (error != BT_ERROR_NONE) {
128                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
129         }
130         return error;
131 }
132
133 int bt_audio_disconnect(const char *remote_address, bt_audio_profile_type_e type)
134 {
135         int error;
136         bluetooth_device_address_t addr_hex = { {0,} };
137
138         BT_CHECK_INIT_STATUS();
139         BT_CHECK_INPUT_PARAMETER(remote_address);
140         _bt_convert_address_to_hex(&addr_hex, remote_address);
141         switch(type) {
142         case BT_AUDIO_PROFILE_TYPE_HSP_HFP:
143                 error = bluetooth_ag_disconnect(&addr_hex);
144                 break;
145         case BT_AUDIO_PROFILE_TYPE_A2DP:
146                 error = bluetooth_av_disconnect(&addr_hex);
147                 break;
148         case BT_AUDIO_PROFILE_TYPE_ALL:
149         default:
150                 error = bluetooth_audio_disconnect(&addr_hex);
151                 break;
152         }
153         error = _bt_get_error_code(error);
154         if (error != BT_ERROR_NONE) {
155                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
156         }
157         return error;
158 }
159
160 int bt_audio_set_connection_state_changed_cb(bt_audio_connection_state_changed_cb callback, void *user_data)
161 {
162         BT_CHECK_INIT_STATUS();
163         BT_CHECK_INPUT_PARAMETER(callback);
164         _bt_set_cb(BT_EVENT_AUDIO_CONNECTION_STATUS, callback, user_data);
165         return BT_ERROR_NONE;
166
167 }
168 int bt_audio_unset_connection_state_changed_cb(void)
169 {
170         BT_CHECK_INIT_STATUS();
171         if (_bt_check_cb(BT_EVENT_AUDIO_CONNECTION_STATUS) == true)
172                 _bt_unset_cb(BT_EVENT_AUDIO_CONNECTION_STATUS);
173         return BT_ERROR_NONE;
174 }
175
176 int bt_ag_notify_speaker_gain(int gain)
177 {
178         int error;
179
180         BT_CHECK_INIT_STATUS();
181         error = bluetooth_telephony_set_speaker_gain((unsigned short)gain);
182         error = _bt_get_error_code(error);
183         if (BT_ERROR_NONE != error) {
184                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
185         }
186         return error;
187 }
188
189 int bt_ag_get_speaker_gain(int *gain)
190 {
191         int error;
192
193         BT_CHECK_INIT_STATUS();
194         BT_CHECK_INPUT_PARAMETER(gain);
195         error = bluetooth_telephony_get_headset_volume((unsigned int *)gain);
196         error = _bt_get_error_code(error);
197         if (BT_ERROR_NONE != error) {
198                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
199         }
200         return error;
201 }
202
203 int bt_ag_is_nrec_enabled(bool *enabled)
204 {
205         int error;
206
207         BT_CHECK_INIT_STATUS();
208         BT_CHECK_INPUT_PARAMETER(enabled);
209
210         error = bluetooth_telephony_is_nrec_enabled((gboolean *)enabled);
211         error = _bt_get_error_code(error);
212         if (BT_ERROR_NONE != error) {
213                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
214         }
215
216         return error;
217 }
218
219 int bt_ag_set_microphone_gain_changed_cb(bt_ag_microphone_gain_changed_cb callback, void *user_data)
220 {
221         BT_CHECK_INIT_STATUS();
222         BT_CHECK_INPUT_PARAMETER(callback);
223         _bt_set_cb(BT_EVENT_AG_MICROPHONE_GAIN_CHANGE, callback, user_data);
224         return BT_ERROR_NONE;
225
226 }
227
228 int bt_ag_unset_microphone_gain_changed_cb(void)
229 {
230         BT_CHECK_INIT_STATUS();
231         if (_bt_check_cb(BT_EVENT_AG_MICROPHONE_GAIN_CHANGE) == true)
232                 _bt_unset_cb(BT_EVENT_AG_MICROPHONE_GAIN_CHANGE);
233         return BT_ERROR_NONE;
234 }
235
236 int bt_ag_set_speaker_gain_changed_cb(bt_ag_speaker_gain_changed_cb callback,
237                                         void *user_data)
238 {
239         BT_CHECK_INIT_STATUS();
240         BT_CHECK_INPUT_PARAMETER(callback);
241         _bt_set_cb(BT_EVENT_AG_SPEAKER_GAIN_CHANGE, callback, user_data);
242         return BT_ERROR_NONE;
243 }
244
245 int bt_ag_unset_speaker_gain_changed_cb(void)
246 {
247         BT_CHECK_INIT_STATUS();
248         if (_bt_check_cb(BT_EVENT_AG_SPEAKER_GAIN_CHANGE) == true)
249                 _bt_unset_cb(BT_EVENT_AG_SPEAKER_GAIN_CHANGE);
250         return BT_ERROR_NONE;
251 }
252
253 int bt_ag_open_sco(void)
254 {
255         int error;
256
257         BT_CHECK_INIT_STATUS();
258         error = bluetooth_telephony_audio_open();
259         error = _bt_convert_telephony_error_code(error);
260         error = _bt_get_error_code(error);
261         if (error != BT_ERROR_NONE) {
262                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
263         }
264         return error;
265 }
266
267 int bt_ag_close_sco(void)
268 {
269         int error;
270
271         BT_CHECK_INIT_STATUS();
272         error = bluetooth_telephony_audio_close();
273         error = _bt_convert_telephony_error_code(error);
274         error = _bt_get_error_code(error);
275         if (error != BT_ERROR_NONE) {
276                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
277         }
278         return error;
279 }
280
281 int bt_ag_is_sco_opened(bool *opened)
282 {
283         BT_CHECK_INIT_STATUS();
284         BT_CHECK_INPUT_PARAMETER(opened);
285         *opened = bluetooth_telephony_is_sco_connected();
286         return BT_ERROR_NONE;
287 }
288
289 int bt_ag_set_sco_state_changed_cb(bt_ag_sco_state_changed_cb callback,
290                                         void *user_data)
291 {
292         BT_CHECK_INIT_STATUS();
293         BT_CHECK_INPUT_PARAMETER(callback);
294         _bt_set_cb(BT_EVENT_AG_SCO_CONNECTION_STATUS, callback, user_data);
295         return BT_ERROR_NONE;
296 }
297
298 int bt_ag_unset_sco_state_changed_cb(void)
299 {
300         BT_CHECK_INIT_STATUS();
301         if (_bt_check_cb(BT_EVENT_AG_SCO_CONNECTION_STATUS) == true)
302                 _bt_unset_cb(BT_EVENT_AG_SCO_CONNECTION_STATUS);
303         return BT_ERROR_NONE;
304 }
305
306 int bt_ag_notify_call_event(bt_ag_call_event_e event, unsigned int call_id, const char *phone_number)
307 {
308         int error;
309
310         BT_CHECK_INIT_STATUS();
311         switch(event) {
312         case BT_AG_CALL_EVENT_IDLE:
313                 error = bluetooth_telephony_call_end(call_id);
314                 break;
315         case BT_AG_CALL_EVENT_ANSWERED:
316                 error = bluetooth_telephony_call_answered(call_id, FALSE);
317                 break;
318         case BT_AG_CALL_EVENT_HELD:
319                 error = bluetooth_telephony_call_held(call_id);
320                 break;
321         case BT_AG_CALL_EVENT_RETRIEVED:
322                 error = bluetooth_telephony_call_retrieved(call_id);
323                 break;
324         case BT_AG_CALL_EVENT_DIALING:
325                 BT_CHECK_INPUT_PARAMETER(phone_number);
326                 error = bluetooth_telephony_indicate_outgoing_call(
327                                         phone_number, call_id, FALSE);
328                 break;
329         case BT_AG_CALL_EVENT_ALERTING:
330                 error = bluetooth_telephony_call_remote_ringing(call_id);
331                 break;
332         case BT_AG_CALL_EVENT_INCOMING:
333                 BT_CHECK_INPUT_PARAMETER(phone_number);
334                 error = bluetooth_telephony_indicate_incoming_call(phone_number,
335                                         call_id);
336                 break;
337         default:
338                 error = BT_ERROR_INVALID_PARAMETER;
339         }
340         error = _bt_convert_telephony_error_code(error);
341         error = _bt_get_error_code(error);
342         if (error != BT_ERROR_NONE) {
343                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
344         }
345         return error;
346 }
347
348 int bt_ag_notify_call_list(bt_call_list_h list)
349 {
350         int error;
351         unsigned int call_count;
352         call_list_s *handle;
353
354         BT_CHECK_INIT_STATUS();
355         BT_CHECK_INPUT_PARAMETER(list);
356         handle = (call_list_s *)list;
357         call_count = g_list_length(handle->list);
358         error = bluetooth_telephony_set_call_status((void *)handle->list, call_count);
359         error = _bt_convert_telephony_error_code(error);
360         error = _bt_get_error_code(error);
361         if (error != BT_ERROR_NONE) {
362                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
363         }
364         return error;
365 }
366
367 int bt_ag_notify_voice_recognition_state(bool state)
368 {
369         int error;
370
371         BT_CHECK_INIT_STATUS();
372         if (state)
373                 error = bluetooth_telephony_start_voice_recognition();
374         else
375                 error = bluetooth_telephony_stop_voice_recognition();
376         error = _bt_convert_telephony_error_code(error);
377         error = _bt_get_error_code(error);
378         if (error != BT_ERROR_NONE) {
379                 BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
380         }
381         return error;
382 }
383
384 int bt_ag_set_call_handling_event_cb(bt_ag_call_handling_event_cb callback,
385                                         void *user_data)
386 {
387         BT_CHECK_INIT_STATUS();
388         BT_CHECK_INPUT_PARAMETER(callback);
389         _bt_set_cb(BT_EVENT_AG_CALL_HANDLING_EVENT, callback, user_data);
390         return BT_ERROR_NONE;
391
392 }
393
394 int bt_ag_unset_call_handling_event_cb(void)
395 {
396         BT_CHECK_INIT_STATUS();
397         if (_bt_check_cb(BT_EVENT_AG_CALL_HANDLING_EVENT) == true)
398                 _bt_unset_cb(BT_EVENT_AG_CALL_HANDLING_EVENT);
399         return BT_ERROR_NONE;
400 }
401
402 int bt_ag_set_multi_call_handling_event_cb(
403                                         bt_ag_multi_call_handling_event_cb callback,
404                                         void *user_data)
405 {
406         BT_CHECK_INIT_STATUS();
407         BT_CHECK_INPUT_PARAMETER(callback);
408         _bt_set_cb(BT_EVENT_AG_MULTI_CALL_HANDLING_EVENT, callback, user_data);
409         return BT_ERROR_NONE;
410 }
411
412 int bt_ag_unset_multi_call_handling_event_cb(void)
413 {
414         BT_CHECK_INIT_STATUS();
415         if (_bt_check_cb(BT_EVENT_AG_MULTI_CALL_HANDLING_EVENT) == true)
416                 _bt_unset_cb(BT_EVENT_AG_MULTI_CALL_HANDLING_EVENT);
417         return BT_ERROR_NONE;
418 }
419
420 int bt_ag_set_dtmf_transmitted_cb(bt_ag_dtmf_transmitted_cb callback,
421                                                 void *user_data)
422 {
423         BT_CHECK_INIT_STATUS();
424         BT_CHECK_INPUT_PARAMETER(callback);
425         _bt_set_cb(BT_EVENT_AG_DTMF_TRANSMITTED, callback, user_data);
426         return BT_ERROR_NONE;
427 }
428
429 int bt_ag_unset_dtmf_transmitted_cb(void)
430 {
431         BT_CHECK_INIT_STATUS();
432         if (_bt_check_cb(BT_EVENT_AG_DTMF_TRANSMITTED) == true)
433                 _bt_unset_cb(BT_EVENT_AG_DTMF_TRANSMITTED);
434         return BT_ERROR_NONE;
435 }
436
437 int bt_call_list_create(bt_call_list_h *list)
438 {
439         call_list_s *handle;
440
441         BT_CHECK_INIT_STATUS();
442         if (*list != NULL) {
443                 BT_ERR("BT_ERROR_ALREADY_DONE(0x%08x)", BT_ERROR_ALREADY_DONE);
444                 return BT_ERROR_ALREADY_DONE;
445         }
446         handle = g_malloc0(sizeof(call_list_s));
447         *list = handle;
448         return BT_ERROR_NONE;
449 }
450
451 int bt_call_list_destroy(bt_call_list_h list)
452 {
453         int result;
454         call_list_s *handle;
455
456         BT_CHECK_INIT_STATUS();
457         BT_CHECK_INPUT_PARAMETER(list);
458         handle = (call_list_s *)list;
459         result = bt_call_list_reset(list);
460         g_free(handle);
461         return result;
462 }
463
464 int bt_call_list_reset(bt_call_list_h list)
465 {
466         call_list_s *handle;
467         bt_telephony_call_status_info_t *call_status;
468
469         BT_CHECK_INIT_STATUS();
470         BT_CHECK_INPUT_PARAMETER(list);
471         handle = (call_list_s *)list;
472         do  {
473                 call_status = (bt_telephony_call_status_info_t *)g_list_nth_data(handle->list, 0);
474                 if (call_status == NULL)
475                         break;
476                 handle->list = g_list_remove(handle->list, call_status);
477                 g_free(call_status);
478         } while (1);
479         return BT_ERROR_NONE;
480 }
481
482 int bt_call_list_add(bt_call_list_h list, unsigned int call_id, bt_ag_call_state_e state)
483 {
484         call_list_s *handle;
485         bt_telephony_call_status_info_t *call_status;
486
487         BT_CHECK_INIT_STATUS();
488         BT_CHECK_INPUT_PARAMETER(list);
489         handle = (call_list_s *)list;
490         call_status = g_malloc0(sizeof(bt_telephony_call_status_info_t));
491         call_status->call_id = call_id;
492         call_status->call_status = state;
493         handle->list = g_list_append(handle->list, (gpointer)call_status);
494         return BT_ERROR_NONE;
495 }