2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.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
8 * http://www.tizenopensource.org/license
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.
18 #include "vc-core-util.h"
19 #include "vc-core-engine-status.h"
20 #include "vc-core-engine-group.h"
21 #include "voice-call-core.h"
22 #include "voice-call-sound.h"
23 #include "voice-call-bt.h"
25 #include "vconf-keys.h"
26 #include "voice-call-dbus.h"
27 #include "voice-call-engine-msg.h"
29 /* For Debug Information, name string constant */
31 static char *gszbt_res_event[BT_AG_RES_CALL_SWAPPED + 1] = {
32 "BT_AG_RES_CALL_ORIG",
33 "BT_AG_RES_CALL_INCOM",
34 "BT_AG_RES_CALL_CONNECT",
36 "BT_AG_RES_CALL_HOLD",
37 "BT_AG_RES_CALL_RETRIEVE",
38 "BT_AG_RES_CALL_JOINED",
41 "BT_AG_RES_CALL_REMOTE_RINGING",
42 "BT_AG_RES_SWITCH_TO_HEADSET",
43 "BT_AG_RES_SWITCH_TO_PHONE",
44 "BT_AG_RES_CALL_STATUS",
45 "BT_AG_RES_HEADSET_VOL",
46 "BT_AG_RES_CALL_SWAPPED"
50 static char *gszbt_req_event[BT_AG_REQ_CALL_STATUS + 1] = {
52 "BT_AG_REQ_CONNECT_ERROR",
53 "BT_AG_REQ_DISCONNECT",
56 "BT_AG_REQ_CALL_ACCEPTED",
57 "BT_AG_REQ_CALL_REJECT",
59 "BT_AG_REQ_CALL_HOLD",
60 "BT_AG_REQ_CALL_RETRIEVE",
61 "BT_AG_REQ_BUTTON_PRESSED",
62 "BT_AG_REQ_CALL_REDIAL",
63 "BT_AG_REQ_CALL_2_SEND",
64 "BT_AG_REQ_CALL_3_SEND",
65 "BT_AG_REQ_CALL_0_SEND",
66 "BT_AG_REQ_CALL_1_SEND",
67 "BT_AG_REQ_HEADSET_VOL",
68 "BT_AG_REQ_SWITCH_TO_HEADSET",
69 "BT_AG_REQ_SWITCH_TO_PHONE",
71 "BT_AG_REQ_CALL_STATUS"
75 static gboolean b_user_rqst_path_change = FALSE;
77 static int __vc_bt_converted_bt_vol_to_voice_vol(int bt_vol_level);
78 static void __vc_bt_handle_connectivity_event(call_vc_core_state_t *pcall_core, gboolean bt_headset_connect_status);
80 static int __vc_bt_converted_bt_vol_to_voice_vol(int bt_vol_level)
82 int converted_vol_level = -1;
84 if (bt_vol_level <= 0) {
85 converted_vol_level = 1;
86 } else if (bt_vol_level > 15) {
87 converted_vol_level = 15;
89 converted_vol_level = bt_vol_level;
91 return converted_vol_level;
94 static void __vc_bt_handle_connectivity_event(call_vc_core_state_t *pcall_core, gboolean bt_headset_connect_status)
96 VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
98 voicecall_engine_t *pcall_engine = pcall_core->pcall_engine;
100 CALL_ENG_DEBUG(ENG_DEBUG, "bt_headset_connect_status = %d \n", bt_headset_connect_status);
101 if (FALSE == bt_headset_connect_status) {
102 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING, FALSE);
105 if (bt_headset_connect_status == pcall_core->bt_connected) {
106 CALL_ENG_DEBUG(ENG_DEBUG, "No change in state, Ignoring Event \n");
107 CALL_ENG_DEBUG(ENG_DEBUG, "bt_headset_connect_status = %d \n", bt_headset_connect_status);
110 pcall_core->bt_connected = bt_headset_connect_status;
112 if (TRUE == pcall_core->bt_connected) {
113 /*Check the Call Status and Send Response event to the Bluetooth */
114 int call_handle = -1;
116 CALL_ENG_DEBUG(ENG_DEBUG, "BT connected, Not changing the sound status \n");
117 /* Headset is connected, Set the Sound Status to Headset
118 and change the path only incase of mocall and connected call */
120 _vc_core_engine_status_get_call_handle_bytype(pcall_engine, VC_INCOMING_CALL, &call_handle);
121 if (call_handle != -1) {
122 call_vc_call_objectinfo_t callobject_info;
124 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming Call Exists, call handle = %d \n", call_handle);
126 voicecall_core_get_call_object(pcall_engine, call_handle, &callobject_info);
128 /*Incoming Call Exists */
129 _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_INCOM, call_handle, callobject_info.tel_number);
133 _vc_core_engine_status_get_call_handle_bytype(pcall_engine, VC_OUTGOING_CALL, &call_handle);
134 if (call_handle != -1) {
135 int io_state = VC_INOUT_STATE_NONE;
137 CALL_ENG_DEBUG(ENG_DEBUG, "Outgoing Call Exists, call handle = %d \n", call_handle);
138 _vc_core_engine_status_get_engine_iostate(pcall_engine, &io_state);
141 case VC_INOUT_STATE_OUTGOING_WAIT_ORIG:
142 case VC_INOUT_STATE_OUTGOING_WAIT_ALERT: /*Fall Through */
144 call_vc_call_objectinfo_t callobject_info;
146 voicecall_core_get_call_object(pcall_engine, call_handle, &callobject_info);
148 _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_ORIG, call_handle, callobject_info.tel_number);
151 case VC_INOUT_STATE_OUTGOING_WAIT_CONNECTED:
153 _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_REMOTE_RINGING, call_handle, NULL);
155 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_BT);
156 _vc_bt_request_switch_headset_path(pcall_core, TRUE);
162 CALL_ENG_DEBUG(ENG_DEBUG, "Engine not in desired IO State, Current IO State: %d \n", io_state);
171 _vc_core_engine_status_get_call_handle_bytype(pcall_engine, VC_CONNECTED_CALL, &call_handle);
172 if (call_handle != -1) {
173 CALL_ENG_DEBUG(ENG_DEBUG, "Connected Call Exists, call handle = %d \n", call_handle);
175 CALL_ENG_DEBUG(ENG_DEBUG, "BT connected, Not changing the path in bt connect event\n");
177 _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_CONNECT, call_handle, NULL);
181 vc_engine_headset_status_type event_data;
184 if (voicecall_snd_get_path_status(pcall_core->papp_snd) == VOICE_CALL_SND_PATH_BT) {
185 if (_voicecall_dvc_get_earjack_connected() == TRUE) {
186 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_EARJACK);
188 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_RECEIVER);
191 /* Headset is disconnected, so voice sound path should be changed to phone. */
192 voicecall_snd_set_status(pcall_core->papp_snd, VOICE_CALL_AUDIO_HEADSET, FALSE);
193 if (voicecall_core_is_incoming_call_exists(pcall_engine)) {
194 if (pcall_core->papp_snd->bmute_play == TRUE) {
195 voicecall_snd_change_mm_path(pcall_core->papp_snd, VOICE_CALL_MM_MUTE_PLAY);
197 voicecall_snd_change_mm_path(pcall_core->papp_snd, VOICE_CALL_MM_RING_TONE);
200 if (voicecall_core_is_outgoing_call_exists(pcall_engine) || (voicecall_core_is_connected_call_exist(pcall_engine))) {
201 voicecall_snd_change_path(pcall_core->papp_snd);
203 CALL_ENG_DEBUG(ENG_ERR, "No valid calls, not changing the path \n");
207 CALL_ENG_DEBUG(ENG_ERR, "BT disconnected when path is not on BT. Do NOT change path. only update UI");
210 memset(&event_data, 0, sizeof(event_data));
211 event_data.bstatus = FALSE;
212 vcall_engine_send_event_to_client(VC_ENGINE_MSG_HEADSET_STATUS_TO_UI, (void *)&event_data);
214 memset(&event_data, 0, sizeof(event_data));
215 event_data.bstatus = FALSE;
216 vcall_engine_send_event_to_client(VC_ENGINE_MSG_HEADSET_STATUS_TO_UI, (void *)&event_data);
218 /* Headset is disconnected, so voice sound path should be changed to phone. */
219 voicecall_snd_set_status(pcall_core->papp_snd, VOICE_CALL_AUDIO_HEADSET, FALSE);
220 if (voicecall_core_is_incoming_call_exists(pcall_engine)) {
221 if (pcall_core->papp_snd->bmute_play == TRUE) {
222 voicecall_snd_change_mm_path(pcall_core->papp_snd, VOICE_CALL_MM_MUTE_PLAY);
224 voicecall_snd_change_mm_path(pcall_core->papp_snd, VOICE_CALL_MM_RING_TONE);
227 if (voicecall_core_is_outgoing_call_exists(pcall_engine) || (voicecall_core_is_connected_call_exist(pcall_engine))) {
228 voicecall_snd_change_path(pcall_core->papp_snd);
230 CALL_ENG_DEBUG(ENG_ERR, "No valid calls, not changing the path \n");
238 gboolean _vc_bt_switch_headset_path(call_vc_core_state_t *pcall_core, gboolean bheadset, gboolean bsend_bt_response)
240 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
242 connectivity_bt_ag_res_t bt_event = BT_AG_RES_SWITCH_TO_PHONE;
243 voicecall_snd_mgr_t *papp_snd = pcall_core->papp_snd;
244 voicecall_engine_t *pcall_engine = pcall_core->pcall_engine;
246 CALL_ENG_DEBUG(ENG_DEBUG, "bheadset = %d,bsend_bt_response = %d \n", bheadset, bsend_bt_response);
249 CALL_ENG_DEBUG(ENG_DEBUG, "b_user_rqst_path_change(%d)", b_user_rqst_path_change);
250 if (b_user_rqst_path_change == FALSE) {
251 if (TRUE == bheadset) {
252 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_BT);
255 int earjack_status = -1;
256 if (!vconf_get_int(VCONFKEY_SYSMAN_EARJACK, &earjack_status)) {
257 CALL_ENG_DEBUG(ENG_DEBUG, "earjack_status:[%d]\n", earjack_status);
258 if (earjack_status == VCONFKEY_SYSMAN_EARJACK_REMOVED) {
259 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_RECEIVER);
261 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_EARJACK);
264 CALL_ENG_DEBUG(ENG_ERR, "vconf_get_int fail");
265 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_RECEIVER);
269 CALL_ENG_DEBUG(ENG_DEBUG, "Don't set path_status.. rqst from User. Already setted.");
272 /*TODO Check whehter the follwing check and set status to be done inside if((TRUE == bconnected_call_exists) || (TRUE == bmo_call_exists)) */
273 /*If Loud Speaker is ON, Change to Normal when Bluetooth Headset is switched ON */
274 if ((TRUE == bheadset) && (TRUE == voicecall_snd_get_status(papp_snd, VOICE_CALL_AUDIO_SPEAKER))) {
275 voicecall_snd_set_status(papp_snd, VOICE_CALL_AUDIO_SPEAKER, FALSE);
277 voicecall_snd_set_status(papp_snd, VOICE_CALL_AUDIO_HEADSET, bheadset);
280 /*Donot change the path for MT Call. Change the Audio Path only for MO and Connected calls */
281 if ((TRUE == voicecall_core_is_connected_call_exist(pcall_engine)) || (TRUE == voicecall_core_is_outgoing_call_exists(pcall_engine))) {
282 CALL_ENG_DEBUG(ENG_DEBUG, "Changing the Path on BT Request \n");
283 voicecall_snd_change_path_real(papp_snd);
285 /*Send Response to BT only if the path is changed */
286 if (TRUE == bsend_bt_response) {
287 bt_event = (TRUE == bheadset) ? BT_AG_RES_SWITCH_TO_HEADSET : BT_AG_RES_SWITCH_TO_PHONE;
288 CALL_ENG_DEBUG(ENG_DEBUG, "Sending BT Response bt_event: %d \n", bt_event);
289 _vc_bt_send_response_to_bt(pcall_core, bt_event, -1, NULL);
298 * This function sends event to BT for switch to Headset/Phone
301 * @param[in] pcall_core Handle to voicecall core
302 * @param[in] bheadset TRUE if sound type is Audio Headset, FALSE otherwise
304 void _vc_bt_request_switch_headset_path(call_vc_core_state_t *pcall_core, gboolean bheadset)
306 VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
308 connectivity_bt_ag_res_t bt_event = BT_AG_RES_SWITCH_TO_PHONE;
309 voicecall_engine_t *pcall_engine = pcall_core->pcall_engine;
311 CALL_ENG_DEBUG(ENG_DEBUG, "..\n");
313 /*Donot change the path for MT Call. Change the Audio Path only for MO and Connected calls */
314 if ((TRUE == voicecall_core_is_connected_call_exist(pcall_engine)) || (TRUE == voicecall_core_is_outgoing_call_exists(pcall_engine))) {
315 bt_event = (TRUE == bheadset) ? BT_AG_RES_SWITCH_TO_HEADSET : BT_AG_RES_SWITCH_TO_PHONE;
316 CALL_ENG_DEBUG(ENG_DEBUG, "Sending BT Response bt_event: %d \n", bt_event);
317 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING, TRUE);
319 _vc_bt_send_response_to_bt(pcall_core, bt_event, -1, NULL);
321 CALL_ENG_DEBUG(ENG_ERR, "No Valid calls to switch path \n");
326 * This function handles the bluetooth notifications sent by blue tooth application
328 * @return TRUE -if event is handled, FALSE otherwise
329 * @param[in] pcall_core Handle to voicecall core
330 * @param[in] pbt_info bt notification details
332 gboolean _vc_bt_handle_bt_events(call_vc_core_state_t *pcall_core, connectivity_bt_ag_param_info_t * pbt_info)
334 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
335 VOICECALL_RETURN_FALSE_IF_FAIL(pbt_info != NULL);
337 CALL_ENG_DEBUG(ENG_DEBUG, "Event: %s(%d) \n", gszbt_req_event[pbt_info->param1], pbt_info->param1);
339 /*HS Connection not required for sending response to BT_AG_REQ_CALL_STATUS */
340 if ((FALSE == pcall_core->bt_connected) && (BT_AG_REQ_CALL_STATUS != pbt_info->param1)) {
341 CALL_ENG_DEBUG(ENG_ERR, "BT not connected, Ignoring BT Events, BT Event= %d \n", pbt_info->param1);
345 switch (pbt_info->param1) {
346 case BT_AG_REQ_CALL_STATUS:
348 /*Send the Current Call status to BT */
349 _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_STATUS, -1, NULL);
353 case BT_AG_REQ_SPK_GAIN:
355 int bt_vol_level = pbt_info->param2;
356 int converted_vol_level;
357 vc_engine_vol_set_from_bt_type event_data;
359 CALL_ENG_DEBUG(ENG_DEBUG, "Speaker Gain Value : %d\n", bt_vol_level);
362 if (voicecall_snd_get_path_status(pcall_core->papp_snd) != VOICE_CALL_SND_PATH_BT) {
363 CALL_ENG_DEBUG(ENG_DEBUG, "Headset not switched on, Ignoring Speaker Gain Event \n");
367 if (FALSE == voicecall_snd_get_status(pcall_core->papp_snd, VOICE_CALL_AUDIO_HEADSET)) {
368 CALL_ENG_DEBUG(ENG_DEBUG, "Headset not switched on, Ignoring Speaker Gain Event \n");
372 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_VOL_CHNGD_BYBT, TRUE);
374 converted_vol_level = __vc_bt_converted_bt_vol_to_voice_vol(bt_vol_level);
376 CALL_ENG_DEBUG(ENG_DEBUG, "converted Speaker Gain Value : %d\n", converted_vol_level);
378 memset(&event_data, 0, sizeof(event_data));
379 event_data.vol_level = converted_vol_level;
380 vcall_engine_send_event_to_client(VC_ENGINE_MSG_SET_VOLUME_FROM_BT_TO_UI, (void *)&event_data);
383 case BT_AG_REQ_CALL_ACCEPTED:
385 if (voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
386 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming call Accept by BT \n");
387 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, TRUE);
388 if(_vc_core_util_phonelock_status() == FALSE)
389 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
391 voicecall_snd_set_path_status(pcall_core->papp_snd,VOICE_CALL_SND_PATH_BT);
393 if (TRUE == voicecall_core_answer_call(pcall_core, FALSE)) {
394 CALL_ENG_DEBUG(ENG_DEBUG, "voicecall_core_answer_call success \n");
397 CALL_ENG_DEBUG(ENG_ERR, "No Incoming call, skipping BT request \n");
401 case BT_AG_REQ_CALL_REJECT:
403 if (TRUE == voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
404 if (FALSE == voicecall_core_reject_mt(pcall_core, TRUE)) {
405 CALL_ENG_DEBUG(ENG_ERR, "voicecall_core_reject_mt returned FALSE!\n");
407 /*Call rejected, reset the accept by flag */
408 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, FALSE);
409 } else if (TRUE == voicecall_core_is_outgoing_call_exists(pcall_core->pcall_engine)) {
410 /*To retrieve the held call automatically once the mo call is ended, if held is call is available */
411 _vc_core_engine_status_set_end_flag(pcall_core->pcall_engine, VC_RETREIVE_CALL_ON_MOCALL_END);
413 voicecall_core_end_mo_call(pcall_core->pcall_engine);
415 CALL_ENG_DEBUG(ENG_ERR, "No Incoming/Outgoing calls, skipping BT request \n");
419 case BT_AG_REQ_BUTTON_PRESSED:
421 if (voicecall_core_is_connected_call_exist(pcall_core->pcall_engine)) {
422 return voicecall_core_process_hold_call(pcall_core);
424 CALL_ENG_DEBUG(ENG_ERR, "No connected calls, skipping BT request \n");
429 case BT_AG_REQ_CALL_END:
431 voicecall_core_end_call(pcall_core);
434 case BT_AG_REQ_CONNECT_ERROR:
436 /*To change path , reset flags and to update UI, if this is conisdered as Bt disconnect */
437 __vc_bt_handle_connectivity_event(pcall_core, FALSE);
440 case BT_AG_REQ_CALL_0_SEND:
442 if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
443 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_0);
447 case BT_AG_REQ_CALL_1_SEND:
449 if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
450 if (TRUE == voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
451 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming call Accept by BT \n");
452 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, TRUE);
454 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_1);
458 case BT_AG_REQ_CALL_2_SEND:
460 if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
461 gboolean bactive_calls = FALSE;
462 gboolean bheld_calls = FALSE;
464 if (TRUE == voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
465 voicecall_core_is_call_exists(pcall_core->pcall_engine, &bactive_calls, &bheld_calls);
466 if (!((TRUE == bactive_calls) && (TRUE == bheld_calls))) {
467 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming call Accept by BT \n");
468 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, TRUE);
471 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_2);
475 case BT_AG_REQ_CALL_3_SEND:
477 if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
478 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_3);
482 case BT_AG_REQ_HEADSET_VOL:
484 int bt_vol_level = pbt_info->param2;
485 int converted_vol_level;
487 CALL_ENG_DEBUG(ENG_DEBUG, "BT volume Level: %d \n", bt_vol_level);
489 if (voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
490 vc_engine_vol_resp_type event_data;
492 converted_vol_level = __vc_bt_converted_bt_vol_to_voice_vol(bt_vol_level);
494 memset(&event_data, 0, sizeof(event_data));
495 event_data.vol_alert_type = VOICE_CALL_VOL_TYPE_HEADSET;
496 event_data.vol_level = converted_vol_level;
497 vcall_engine_send_event_to_client(VC_ENGINE_MSG_GET_VOLUME_RESP_TO_UI, (void *)&event_data);
499 CALL_ENG_DEBUG(ENG_ERR, "NO Calls, Skipping BT Response \n");
503 case BT_AG_REQ_SWITCH_TO_HEADSET:
504 case BT_AG_REQ_SWITCH_TO_PHONE:
506 gboolean bswitch_to_headset = FALSE;
507 int bt_error = pbt_info->param2;
510 if(voicecall_core_get_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING) == TRUE) {
511 b_user_rqst_path_change = TRUE;
513 b_user_rqst_path_change = FALSE;
517 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING, FALSE);
519 /*Switch to response is received from BT, BT decision is fina, so reset the accept by BT */
520 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, FALSE);
522 CALL_ENG_DEBUG(ENG_DEBUG, "BT Error :%d \n", bt_error);
524 /*Audio Connection/Disconnection Success case */
525 bswitch_to_headset = (BT_AG_REQ_SWITCH_TO_HEADSET == pbt_info->param1) ? TRUE : FALSE;
527 /*Audio Connection/Disconnection Error Case */
528 if (BT_AG_RES_AUDIO_CONNECTION_ERROR == bt_error) {
529 /*Connection Error, switch to phone */
530 bswitch_to_headset = FALSE;
531 } else if (BT_AG_RES_AUDIO_DISCONNECTION_ERROR == bt_error) {
532 /*Disconnection Error, switch to headset */
533 bswitch_to_headset = TRUE;
535 CALL_ENG_DEBUG(ENG_ERR, "Invalid BT Error: %d \n", bt_error);
540 CALL_ENG_DEBUG(ENG_DEBUG, "bswitch_to_headset = %d \n", bswitch_to_headset);
542 if ((TRUE == voicecall_core_is_connected_call_exist(pcall_core->pcall_engine)) || (TRUE == voicecall_core_is_outgoing_call_exists(pcall_core->pcall_engine))) {
543 gboolean bupdate = FALSE;
546 /*Connection/Diconnection is sucess, don't send response to BT */
547 bupdate = _vc_bt_switch_headset_path(pcall_core, bswitch_to_headset, FALSE);
548 CALL_ENG_DEBUG(ENG_DEBUG, "bupdate = %d, bswitch_to_headset = %d \n", bupdate, bswitch_to_headset);
550 vc_engine_headset_status_type event_data;
551 memset(&event_data, 0, sizeof(event_data));
552 event_data.bstatus = bswitch_to_headset;
553 vcall_engine_send_event_to_client(VC_ENGINE_MSG_HEADSET_STATUS_TO_UI, (void *)&event_data);
555 /*Connection/Diconnection is NOT sucess, change path and send response to BT */
556 bupdate = _vc_bt_switch_headset_path(pcall_core, bswitch_to_headset, TRUE);
560 CALL_ENG_DEBUG(ENG_ERR, "No connected/outgoing calls, Skipping BT Request \n");
566 gboolean active_calls = FALSE;
567 gboolean held_calls = FALSE;
569 CALL_ENG_DEBUG(ENG_DEBUG, "Send DTMF(%s)\n", pbt_info->param4);
570 if ((voicecall_core_is_call_exists(pcall_core->pcall_engine, &active_calls, &held_calls)) && (TRUE == active_calls)) {
571 voicecall_core_send_dtmf(pcall_core, pbt_info->param4);
576 case BT_AG_REQ_CALL_REDIAL:
578 CALL_ENG_DEBUG(ENG_DEBUG, "Action not defined for bt event: %d\n", pbt_info->param1);
588 * This function sends response back to the bt application
591 * @param[in] pcall_core Handle to voicecall core
592 * @param[in] bt_event bluetooth event type
593 * @param[in] param1 user param1
594 * @param[in] param2 user param2
596 void _vc_bt_send_response_to_bt(call_vc_core_state_t *pcall_core, int bt_event, int param1, gpointer param2)
598 VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
600 connectivity_bt_ag_param_info_t bt_response_info;
601 CALL_ENG_DEBUG(ENG_DEBUG, "Event: %s(%d), param1=[%d] \n", gszbt_res_event[bt_event], bt_event, param1);
603 /*Skip events, if Bluetooth is not connected */
604 /* if((FALSE == pcall_core->bt_connected) && (BT_AG_RES_CALL_STATUS != bt_event))
606 CALL_ENG_DEBUG(ENG_DEBUG,"Bluetooth not connected , Not sending any responses to BT\n");
610 /*Make BT Response Info */
611 memset(&bt_response_info, 0, sizeof(connectivity_bt_ag_param_info_t));
613 bt_response_info.param1 = bt_event;
616 case BT_AG_RES_CALL_STATUS:
617 case BT_AG_RES_CALL_SWAPPED:
619 connectivity_bt_ag_call_status_info_t call_status_info[10];
620 int mt_call_handle = -1;
621 int mo_call_handle = -1;
622 int connected_call_handle = -1;
623 int active_group_member_num = 0;
624 int held_group_member_num = 0;
627 char temp_str[10] = { 0, };
628 char result_str[256] = { 0, };
631 _vc_core_engine_status_get_call_handle_bytype(pcall_core->pcall_engine, VC_INCOMING_CALL, &mt_call_handle);
632 if (mt_call_handle != -1) {
633 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming Call Exists, call handle = %d \n", mt_call_handle);
635 call_status_info[index].call_id = mt_call_handle;
636 call_status_info[index].call_status = BT_AG_CALL_STATUS_INCOMING;
638 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after mt= %d \n", index);
642 _vc_core_engine_status_get_call_handle_bytype(pcall_core->pcall_engine, VC_OUTGOING_CALL, &mo_call_handle);
643 if (mo_call_handle != -1) {
644 voicecall_call_state_t call_state;
645 gboolean bvalid_call = TRUE;
647 _vc_core_engine_status_get_call_state_byhandle(pcall_core->pcall_engine, mo_call_handle, &call_state);
648 CALL_ENG_DEBUG(ENG_DEBUG, "call state: %d \n", call_state);
650 switch (call_state) {
651 case VC_CALL_STATE_OUTGOING_ALERT:
653 call_status_info[index].call_status = BT_AG_CALL_STATUS_ALERTING;
656 case VC_CALL_STATE_PREPARE_OUTGOING:
657 case VC_CALL_STATE_OUTGOING:
658 case VC_CALL_STATE_OUTGOING_ORIG:
660 call_status_info[index].call_status = BT_AG_CALL_STATUS_DIALLING;
663 default: /*All Other states , donot consider for mocall */
664 CALL_ENG_DEBUG(ENG_DEBUG, "mo call state: %d \n", call_state);
668 if (TRUE == bvalid_call) {
669 call_status_info[index].call_id = mo_call_handle;
671 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after mo= %d \n", index);
677 int act_grp_index = -1;
678 int held_grp_index = -1;
680 _vc_core_engine_group_get_group_indices(pcall_core->pcall_engine, &act_grp_index, &held_grp_index);
682 CALL_ENG_DEBUG(ENG_DEBUG, "act_grp_index = %d, held_grp_index = %d\n", act_grp_index, held_grp_index);
683 /*Active Connected Call */
684 if (act_grp_index != -1) {
685 _vc_core_engine_group_get_connected_member_count(pcall_core->pcall_engine, act_grp_index, &active_group_member_num);
686 CALL_ENG_DEBUG(ENG_DEBUG, "active_group_connected_member_num = %d \n", active_group_member_num);
687 for (i = 0; i < active_group_member_num; i++) {
688 _vc_core_engine_group_get_call_handle_byposition(pcall_core->pcall_engine, act_grp_index, i, &connected_call_handle);
689 if (connected_call_handle != -1) {
690 call_status_info[index].call_id = connected_call_handle;
691 call_status_info[index].call_status = BT_AG_CALL_STATUS_CONNECTED;
695 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after active calls= %d \n", index);
698 /*Held Connected Call */
699 if (held_grp_index != -1) {
700 _vc_core_engine_group_get_connected_member_count(pcall_core->pcall_engine, held_grp_index, &held_group_member_num);
702 CALL_ENG_DEBUG(ENG_DEBUG, "held_group_member_num = %d \n", held_group_member_num);
703 for (i = 0; i < held_group_member_num; i++) {
704 _vc_core_engine_group_get_call_handle_byposition(pcall_core->pcall_engine, held_grp_index, i, &connected_call_handle);
705 CALL_ENG_DEBUG(ENG_DEBUG, "Call Handle[%d] = %d \n", i, connected_call_handle);
706 if (connected_call_handle != -1) {
707 call_status_info[index].call_id = connected_call_handle;
708 call_status_info[index].call_status = BT_AG_CALL_STATUS_HELD;
712 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after held calls= %d \n", index);
715 CALL_ENG_DEBUG(ENG_DEBUG, "Total Calls = %d \n", index);
716 bt_response_info.param2 = index;
718 memset(result_str, 0x00, sizeof(result_str));
719 for (i = 0; i < index; i++) {
720 memset(temp_str, 0x00, sizeof(temp_str));
721 snprintf(temp_str, sizeof(temp_str), "%d.%d/", call_status_info[i].call_id, call_status_info[i].call_status);
722 strncat(result_str, temp_str, sizeof(temp_str) - 1);
724 CALL_ENG_DEBUG(ENG_DEBUG, "The resultant string is %s\n", result_str);
726 _vc_core_util_strcpy(bt_response_info.param4, sizeof(bt_response_info.param4), result_str);
728 CALL_ENG_DEBUG(ENG_DEBUG, "Actual Data Passed is %s \n", bt_response_info.param4);
729 CALL_ENG_DEBUG(ENG_DEBUG, "Actual Data Passed to BT \n");
730 for (i = 0; i < index; i++) {
731 CALL_ENG_DEBUG(ENG_DEBUG, "call id = %d \n", call_status_info[i].call_id);
732 CALL_ENG_DEBUG(ENG_DEBUG, "call status= %d \n", call_status_info[i].call_status);
735 CALL_ENG_DEBUG(ENG_DEBUG, "Verification of BT data being sent\n");
739 case BT_AG_RES_CALL_INCOM:
741 /*Length of Incoming Call Number */
742 if (NULL != param2) {
743 CALL_ENG_DEBUG(ENG_DEBUG, "phone number=%s\n", (char *)param2);
744 bt_response_info.param2 = strlen(param2);
745 bt_response_info.param3 = param1;
746 _vc_core_util_strcpy(bt_response_info.param4, VC_PHONE_NUMBER_LENGTH_MAX, param2);
750 case BT_AG_RES_CALL_ORIG:
752 if (NULL != param2) {
753 CALL_ENG_DEBUG(ENG_DEBUG, "phone number=%s\n", (char *)param2);
755 switch (voicecall_snd_get_path_status(pcall_core->papp_snd)) {
756 case VOICE_CALL_SND_PATH_RECEIVER:
757 case VOICE_CALL_SND_PATH_SPEAKER:
758 case VOICE_CALL_SND_PATH_EARJACK:
759 bt_response_info.param2 = FALSE;
761 case VOICE_CALL_SND_PATH_BT:
762 bt_response_info.param2 = TRUE;
766 bt_response_info.param2 = strlen(param2);
768 bt_response_info.param3 = param1;
769 _vc_core_util_strcpy(bt_response_info.param4, VC_PHONE_NUMBER_LENGTH_MAX, param2);
773 case BT_AG_RES_CALL_REMOTE_RINGING:
775 /*Assign Call Handle */
776 bt_response_info.param3 = param1;
779 case BT_AG_RES_CALL_CONNECT:
780 case BT_AG_RES_CALL_END:
783 switch (voicecall_snd_get_path_status(pcall_core->papp_snd)) {
784 case VOICE_CALL_SND_PATH_RECEIVER:
785 case VOICE_CALL_SND_PATH_SPEAKER:
786 case VOICE_CALL_SND_PATH_EARJACK:
787 bt_response_info.param2 = FALSE;
789 case VOICE_CALL_SND_PATH_BT:
790 bt_response_info.param2 = TRUE;
794 /*Assign Call Handle */
795 bt_response_info.param3 = param1;
798 case BT_AG_RES_SPK_GAIN:
800 bt_response_info.param2 = param1;
802 case BT_AG_RES_HEADSET_VOL: /*Request For Current BT Volume Level */
804 CALL_ENG_DEBUG(ENG_DEBUG, "Requesting for Current BT Volume Level \n");
807 case BT_AG_RES_SWITCH_TO_HEADSET:
808 case BT_AG_RES_SWITCH_TO_PHONE:
810 case BT_AG_RES_CALL_HOLD:
811 case BT_AG_RES_CALL_RETRIEVE: /*Fall Through */
812 bt_response_info.param3 = param1;
814 case BT_AG_RES_CALL_JOINED: /*Fall Through */
819 vc_engine_on_dbus_send_response_to_bt(bt_response_info);
821 CALL_ENG_DEBUG(ENG_DEBUG, "bt response ended.\n");
826 * This function register bt callback.
828 * @return TRUE if bt status is registered, FALSE otherwise
831 gboolean _vc_bt_status_init(call_vc_core_state_t *pcall_core)
833 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
835 gboolean ret = FALSE;
838 bstatus = _vc_bt_get_bt_status();
839 CALL_ENG_DEBUG(ENG_DEBUG, "bt_connected:[%d]\n", bstatus);
840 __vc_bt_handle_connectivity_event(pcall_core, bstatus);
842 ret = vconf_notify_key_changed(VCONFKEY_BT_DEVICE, (void *)_vc_bt_handle_phonestatus_bt_events, pcall_core);
844 CALL_ENG_DEBUG(ENG_ERR, "vconf_notify_key_changed failed..[%d]\n", ret);
851 * This function gets the blue tooth active status from the phone status server
853 * @return TRUE - if BT is enabled, FALSE otherwise
856 gboolean _vc_bt_get_bt_status(void)
858 int bt_status = VCONFKEY_BT_DEVICE_NONE;
859 gboolean ret = FALSE;
861 ret = vconf_get_int(VCONFKEY_BT_DEVICE, &bt_status);
863 CALL_ENG_DEBUG(ENG_DEBUG, "bt_status = [0x%x] \n", bt_status);
865 CALL_ENG_DEBUG(ENG_ERR, "vconf_get_int failed..[%d]\n", ret);
868 return (VCONFKEY_BT_DEVICE_HEADSET_CONNECTED == (bt_status & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED)) ? TRUE : FALSE;
872 * This function gets the BT inband ringtone activate settings
874 * @return TRUE - if BT inband ringtone activate settings is ON, FALSE otherwise
877 gboolean _vc_bt_get_inband_ringtone_active(void)
879 /* InBand_Ringtone_Active for vconf.. */
884 * This function handles the notifications sent by phone status server
886 * @return TRUE -if notification is handled, FALSE otherwise
887 * @param[in] pcall_core Handle to voicecall core
888 * @param[in] bt_status Blue tooth status
890 gboolean _vc_bt_handle_phonestatus_bt_events(keynode_t *node, call_vc_core_state_t *pcall_core)
892 VOICECALL_RETURN_FALSE_IF_FAIL(node != NULL);
893 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
895 gboolean bt_conn_status = FALSE;
896 int bt_status = vconf_keynode_get_int(node);
898 CALL_ENG_DEBUG(ENG_DEBUG, "bt_status = [0x%x] \n", bt_status);
900 /*set the sound status */
901 bt_conn_status = (VCONFKEY_BT_DEVICE_HEADSET_CONNECTED == (bt_status & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED)) ? TRUE : FALSE;
902 CALL_ENG_DEBUG(ENG_DEBUG, "bt_conn_status = %d\n", bt_conn_status);
904 __vc_bt_handle_connectivity_event(pcall_core, bt_conn_status);
909 * This function retreives volume level of headset
912 * @param[in] pcall_core Handle to voicecall core
914 void _vc_bt_get_headset_volume(call_vc_core_state_t *pcall_core)
916 VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
918 _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_HEADSET_VOL, 0, NULL);
922 * This function returns the BT connection status
924 * @return TRUE if bt is connected, FALSE otherwise
925 * @param[in] pcall_core Handle to voicecall core
927 gboolean _vc_bt_is_bt_connected(call_vc_core_state_t *pcall_core)
929 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
931 return pcall_core->bt_connected;
935 * This function returns the BT SCO status.(Synchronized Connection Oriented link)
937 * @return TRUE if bt is connected, FALSE otherwise
940 gboolean _vc_bt_get_bt_sco_status(void)
942 gboolean sco_status = FALSE;
943 gboolean ret = FALSE;
945 ret = vconf_get_bool(VCONFKEY_BT_HEADSET_SCO, &sco_status);
947 CALL_ENG_DEBUG(ENG_DEBUG, "sco_status = [%d] \n", sco_status);
949 CALL_ENG_DEBUG(ENG_ERR, "vconf_get_int failed..[%d]\n", ret);
956 * This function processed bt handset event
958 * @return TRUE if bt is connected, FALSE otherwise
959 * @param[in] pcall_core Handle to voicecall core
960 * @param[in] bheadset headset status
962 gboolean _vc_bt_process_bt_handset(call_vc_core_state_t *pcall_core, int bheadset)
964 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
966 CALL_ENG_DEBUG(ENG_DEBUG, "bheadset:[%d] \n", bheadset);
968 if (FALSE == _vc_bt_get_bt_status()) {
969 vc_engine_on_dbus_send_connect_to_bt();
971 CALL_ENG_DEBUG(ENG_DEBUG, "BT is ON.. switch path to BT");
972 _vc_bt_switch_headset_path(pcall_core, bheadset, TRUE);
975 _vc_bt_switch_headset_path(pcall_core, bheadset, TRUE);