Make TIZEN 2.0
[apps/home/call.git] / call-engine / voice-call-bt.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
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
7  *
8  * http://www.tizenopensource.org/license
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 "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"
24 #include "vconf.h"
25 #include "vconf-keys.h"
26 #include "voice-call-dbus.h"
27 #include "voice-call-engine-msg.h"
28
29 /* For Debug Information, name string constant */
30 /* CALL --> BT */
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",
35         "BT_AG_RES_CALL_END",
36         "BT_AG_RES_CALL_HOLD",
37         "BT_AG_RES_CALL_RETRIEVE",
38         "BT_AG_RES_CALL_JOINED",
39         "BT_AG_RES_SPK_GAIN",
40         "BT_AG_RES_MIC_GAIN",
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"
47 };
48
49 /* CALL <-- BT */
50 static char *gszbt_req_event[BT_AG_REQ_CALL_STATUS + 1] = {
51         "BT_AG_REQ_CONNECT",
52         "BT_AG_REQ_CONNECT_ERROR",
53         "BT_AG_REQ_DISCONNECT",
54         "BT_AG_REQ_SPK_GAIN",
55         "BT_AG_REQ_MIC_GAIN",
56         "BT_AG_REQ_CALL_ACCEPTED",
57         "BT_AG_REQ_CALL_REJECT",
58         "BT_AG_REQ_CALL_END",
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",
70         "BT_AG_REQ_DTMF",
71         "BT_AG_REQ_CALL_STATUS"
72 };
73
74 static gboolean b_user_rqst_path_change = FALSE;
75 static int __vc_bt_converted_bt_vol_to_voice_vol(int bt_vol_level);
76 static void __vc_bt_handle_connectivity_event(call_vc_core_state_t *pcall_core, gboolean bt_headset_connect_status);
77
78 static int __vc_bt_converted_bt_vol_to_voice_vol(int bt_vol_level)
79 {
80         int converted_vol_level = -1;
81
82         if (bt_vol_level <= 0) {
83                 converted_vol_level = 1;
84         } else if (bt_vol_level > 15) {
85                 converted_vol_level = 15;
86         } else {
87                 converted_vol_level = bt_vol_level;
88         }
89         return converted_vol_level;
90 }
91
92 static void __vc_bt_handle_connectivity_event(call_vc_core_state_t *pcall_core, gboolean bt_headset_connect_status)
93 {
94         VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
95
96         voicecall_engine_t *pcall_engine = pcall_core->pcall_engine;
97
98         CALL_ENG_DEBUG(ENG_DEBUG, "bt_headset_connect_status = %d", bt_headset_connect_status);
99         if (FALSE == bt_headset_connect_status) {
100                 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING, FALSE);
101         }
102
103         if (bt_headset_connect_status == pcall_core->bt_connected) {
104                 CALL_ENG_DEBUG(ENG_DEBUG, "No change in state, Ignoring Event");
105                 CALL_ENG_DEBUG(ENG_DEBUG, "bt_headset_connect_status = %d", bt_headset_connect_status);
106                 return;
107         }
108         pcall_core->bt_connected = bt_headset_connect_status;
109
110         if (TRUE == pcall_core->bt_connected) {
111                 /*Check the Call Status and Send Response event to the Bluetooth */
112                 int call_handle = -1;
113
114                 CALL_ENG_DEBUG(ENG_DEBUG, "BT connected, Not changing the sound status");
115                 /*  Headset is connected, Set the Sound Status to Headset
116                    and change the path only incase of mocall and connected call */
117
118                 _vc_core_engine_status_get_call_handle_bytype(pcall_engine, VC_INCOMING_CALL, &call_handle);
119                 if (call_handle != -1) {
120                         call_vc_call_objectinfo_t callobject_info;
121
122                         CALL_ENG_DEBUG(ENG_DEBUG, "Incoming Call Exists, call handle = %d", call_handle);
123
124                         voicecall_core_get_call_object(pcall_engine, call_handle, &callobject_info);
125
126                         /*Incoming Call Exists */
127                         _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_INCOM, call_handle, callobject_info.tel_number);
128                         return;
129                 }
130
131                 _vc_core_engine_status_get_call_handle_bytype(pcall_engine, VC_OUTGOING_CALL, &call_handle);
132                 if (call_handle != -1) {
133                         int io_state = VC_INOUT_STATE_NONE;
134
135                         CALL_ENG_DEBUG(ENG_DEBUG, "Outgoing Call Exists, call handle = %d", call_handle);
136                         _vc_core_engine_status_get_engine_iostate(pcall_engine, &io_state);
137
138                         switch (io_state) {
139                         case VC_INOUT_STATE_OUTGOING_WAIT_ORIG:
140                         case VC_INOUT_STATE_OUTGOING_WAIT_ALERT:        /*Fall Through */
141                                 {
142                                         call_vc_call_objectinfo_t callobject_info;
143
144                                         voicecall_core_get_call_object(pcall_engine, call_handle, &callobject_info);
145
146                                         _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_ORIG, call_handle, callobject_info.tel_number);
147                                 }
148                                 break;
149                         case VC_INOUT_STATE_OUTGOING_WAIT_CONNECTED:
150                                 {
151                                         _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_REMOTE_RINGING, call_handle, NULL);
152                                         voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_BT);
153                                         _vc_bt_request_switch_headset_path(pcall_core, TRUE);
154                                 }
155                                 break;
156                         default:
157                                 {
158                                         CALL_ENG_DEBUG(ENG_DEBUG, "Engine not in desired IO State, Current IO State: %d", io_state);
159                                         return;
160                                 }
161                                 break;
162                         }
163
164                         return;
165                 }
166
167                 _vc_core_engine_status_get_call_handle_bytype(pcall_engine, VC_CONNECTED_CALL, &call_handle);
168                 if (call_handle != -1) {
169                         CALL_ENG_DEBUG(ENG_DEBUG, "Connected Call Exists, call handle = %d", call_handle);
170
171                         CALL_ENG_DEBUG(ENG_DEBUG, "BT connected, Not changing the path in bt connect event");
172
173                         _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_CONNECT, call_handle, NULL);
174                 }
175
176         } else {
177                 vc_engine_headset_status_type event_data;
178
179                 if (voicecall_snd_get_path_status(pcall_core->papp_snd) == VOICE_CALL_SND_PATH_BT) {
180                         voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_RECEIVER_EARJACK);
181
182                         /* Headset is disconnected, so voice sound path should be changed to phone. */
183                         voicecall_snd_set_status(pcall_core->papp_snd, VOICE_CALL_AUDIO_HEADSET, FALSE);
184                         if (voicecall_core_is_incoming_call_exists(pcall_engine)) {
185                                 sound_manager_call_session_set_mode(pcall_core->papp_snd->psnd_session, SOUND_CALL_SESSION_MODE_RINGTONE);
186                         } else {
187                                 if (voicecall_core_is_outgoing_call_exists(pcall_engine) || (voicecall_core_is_connected_call_exist(pcall_engine))) {
188                                         voicecall_snd_change_path(pcall_core->papp_snd);
189                                 } else {
190                                         CALL_ENG_DEBUG(ENG_ERR, "No valid calls, not changing the path");
191                                 }
192                         }
193                 } else {
194                         CALL_ENG_DEBUG(ENG_ERR, "BT disconnected when path is not on BT. Do NOT change path. only update UI");
195                 }
196
197                 memset(&event_data, 0, sizeof(event_data));
198                 event_data.bstatus = FALSE;
199                 vcall_engine_send_event_to_client(VC_ENGINE_MSG_HEADSET_STATUS_TO_UI, (void *)&event_data);
200         }
201
202 }
203
204 gboolean _vc_bt_switch_headset_path(call_vc_core_state_t *pcall_core, gboolean bheadset, gboolean bsend_bt_response)
205 {
206         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
207
208         connectivity_bt_ag_res_t bt_event = BT_AG_RES_SWITCH_TO_PHONE;
209         voicecall_snd_mgr_t *papp_snd = pcall_core->papp_snd;
210         voicecall_engine_t *pcall_engine = pcall_core->pcall_engine;
211
212         CALL_ENG_DEBUG(ENG_DEBUG, "bheadset = %d,bsend_bt_response = %d", bheadset, bsend_bt_response);
213
214         CALL_ENG_DEBUG(ENG_DEBUG, "b_user_rqst_path_change(%d)", b_user_rqst_path_change);
215         if (b_user_rqst_path_change == FALSE) {
216                 if (TRUE == bheadset) {
217                         voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_BT);
218                 } else {
219                         voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_RECEIVER_EARJACK);
220                 }
221         } else {
222                 CALL_ENG_DEBUG(ENG_DEBUG, "Don't set path_status.. rqst from User. Already setted.");
223         }
224
225         /*Donot change the path for MT Call. Change the Audio Path only for MO and Connected calls */
226         if ((TRUE == voicecall_core_is_connected_call_exist(pcall_engine)) || (TRUE == voicecall_core_is_outgoing_call_exists(pcall_engine))) {
227                 CALL_ENG_DEBUG(ENG_DEBUG, "Changing the Path on BT Request");
228                 voicecall_snd_change_path_real(papp_snd);
229
230                 /*Send Response to BT only if the path is changed */
231                 if (TRUE == bsend_bt_response) {
232                         bt_event = (TRUE == bheadset) ? BT_AG_RES_SWITCH_TO_HEADSET : BT_AG_RES_SWITCH_TO_PHONE;
233                         CALL_ENG_DEBUG(ENG_DEBUG, "Sending BT Response bt_event: %d", bt_event);
234                         _vc_bt_send_response_to_bt(pcall_core, bt_event, -1, NULL);
235                 }
236                 return TRUE;
237         }
238
239         return FALSE;
240 }
241
242 /**
243  * This function sends event to BT for switch to Headset/Phone
244  *
245  * @return              void
246  * @param[in]           pcall_core              Handle to voicecall core
247  * @param[in]           bheadset                        TRUE if sound type is Audio Headset, FALSE otherwise
248  */
249 void _vc_bt_request_switch_headset_path(call_vc_core_state_t *pcall_core, gboolean bheadset)
250 {
251         VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
252
253         connectivity_bt_ag_res_t bt_event = BT_AG_RES_SWITCH_TO_PHONE;
254         voicecall_engine_t *pcall_engine = pcall_core->pcall_engine;
255
256         CALL_ENG_DEBUG(ENG_DEBUG, "..");
257
258         /*Donot change the path for MT Call. Change the Audio Path only for MO and Connected calls */
259         if ((TRUE == voicecall_core_is_connected_call_exist(pcall_engine)) || (TRUE == voicecall_core_is_outgoing_call_exists(pcall_engine))) {
260                 bt_event = (TRUE == bheadset) ? BT_AG_RES_SWITCH_TO_HEADSET : BT_AG_RES_SWITCH_TO_PHONE;
261                 CALL_ENG_DEBUG(ENG_DEBUG, "Sending BT Response bt_event: %d", bt_event);
262                 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING, TRUE);
263
264                 _vc_bt_send_response_to_bt(pcall_core, bt_event, -1, NULL);
265         } else {
266                 CALL_ENG_DEBUG(ENG_ERR, "No Valid calls to switch path");
267         }
268 }
269
270 /**
271  * This function handles the bluetooth notifications sent by blue tooth application
272  *
273  * @return              TRUE -if event is handled, FALSE otherwise
274  * @param[in]           pcall_core                      Handle to voicecall core
275  * @param[in]           pbt_info                                bt notification details
276  */
277 gboolean _vc_bt_handle_bt_events(call_vc_core_state_t *pcall_core, connectivity_bt_ag_param_info_t * pbt_info)
278 {
279         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
280         VOICECALL_RETURN_FALSE_IF_FAIL(pbt_info != NULL);
281
282         CALL_ENG_DEBUG(ENG_DEBUG, "Event: %s(%d)", gszbt_req_event[pbt_info->param1], pbt_info->param1);
283
284         /*HS Connection not required for sending response to BT_AG_REQ_CALL_STATUS */
285         if ((FALSE == pcall_core->bt_connected) && (BT_AG_REQ_CALL_STATUS != pbt_info->param1)) {
286                 CALL_ENG_DEBUG(ENG_ERR, "BT not connected, Ignoring BT Events, BT Event= %d", pbt_info->param1);
287                 return TRUE;
288         }
289
290         switch (pbt_info->param1) {
291         case BT_AG_REQ_CALL_STATUS:
292                 {
293                         /*Send the Current  Call status to BT */
294                         _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_CALL_STATUS, -1, NULL);
295
296                 }
297                 break;
298         case BT_AG_REQ_SPK_GAIN:
299                 {
300                         int bt_vol_level = pbt_info->param2;
301                         int converted_vol_level;
302                         vc_engine_vol_set_from_bt_type event_data;
303
304                         CALL_ENG_DEBUG(ENG_DEBUG, "Speaker Gain Value : %d", bt_vol_level);
305
306                         if (voicecall_snd_get_path_status(pcall_core->papp_snd) != VOICE_CALL_SND_PATH_BT) {
307                                 CALL_ENG_DEBUG(ENG_DEBUG, "Headset not switched on, Ignoring Speaker Gain Event");
308                                 return TRUE;
309                         }
310                         voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_VOL_CHNGD_BYBT, TRUE);
311
312                         converted_vol_level = __vc_bt_converted_bt_vol_to_voice_vol(bt_vol_level);
313
314                         CALL_ENG_DEBUG(ENG_DEBUG, "converted Speaker Gain Value : %d", converted_vol_level);
315
316                         memset(&event_data, 0, sizeof(event_data));
317                         event_data.vol_level = converted_vol_level;
318                         vcall_engine_send_event_to_client(VC_ENGINE_MSG_SET_VOLUME_FROM_BT_TO_UI, (void *)&event_data);
319                 }
320                 break;
321         case BT_AG_REQ_CALL_ACCEPTED:
322                 {
323                         if (voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
324                                 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming call Accept by BT");
325                                 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, TRUE);
326                                 if (_vc_core_util_phonelock_status() == FALSE)
327                                         vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
328                                 voicecall_snd_set_path_status(pcall_core->papp_snd, VOICE_CALL_SND_PATH_BT);
329                                 if (TRUE == voicecall_core_answer_call(pcall_core, FALSE)) {
330                                         CALL_ENG_DEBUG(ENG_DEBUG, "voicecall_core_answer_call success");
331                                 }
332                         } else {
333                                 CALL_ENG_DEBUG(ENG_ERR, "No Incoming call, skipping BT request");
334                         }
335                 }
336                 break;
337         case BT_AG_REQ_CALL_REJECT:
338                 {
339                         if (TRUE == voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
340                                 if (FALSE == voicecall_core_reject_mt(pcall_core, TRUE)) {
341                                         CALL_ENG_DEBUG(ENG_ERR, "voicecall_core_reject_mt returned FALSE!");
342                                 }
343                                 /*Call rejected, reset the accept by flag */
344                                 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, FALSE);
345                         } else if (TRUE == voicecall_core_is_outgoing_call_exists(pcall_core->pcall_engine)) {
346                                 /*To retrieve the held call automatically once the mo call is ended, if held is call is available */
347                                 _vc_core_engine_status_set_end_flag(pcall_core->pcall_engine, VC_RETREIVE_CALL_ON_MOCALL_END);
348
349                                 voicecall_core_end_mo_call(pcall_core->pcall_engine);
350                         } else {
351                                 CALL_ENG_DEBUG(ENG_ERR, "No Incoming/Outgoing calls, skipping BT request");
352                         }
353                 }
354                 break;
355         case BT_AG_REQ_BUTTON_PRESSED:
356                 {
357                         if (voicecall_core_is_connected_call_exist(pcall_core->pcall_engine)) {
358                                 return voicecall_core_process_hold_call(pcall_core);
359                         } else {
360                                 CALL_ENG_DEBUG(ENG_ERR, "No connected calls, skipping BT request");
361                         }
362
363                 }
364                 break;
365         case BT_AG_REQ_CALL_END:
366                 {
367                         voicecall_core_end_call(pcall_core);
368                 }
369                 break;
370         case BT_AG_REQ_CONNECT_ERROR:
371                 {
372                         /*To change path , reset flags and to update UI, if this is conisdered as Bt disconnect */
373                         __vc_bt_handle_connectivity_event(pcall_core, FALSE);
374                 }
375                 break;
376         case BT_AG_REQ_CALL_0_SEND:
377                 {
378                         if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
379                                 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_0);
380                         }
381                 }
382                 break;
383         case BT_AG_REQ_CALL_1_SEND:
384                 {
385                         if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
386                                 if (TRUE == voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
387                                         CALL_ENG_DEBUG(ENG_DEBUG, "Incoming call Accept by BT");
388                                         voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, TRUE);
389                                 }
390                                 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_1);
391                         }
392                 }
393                 break;
394         case BT_AG_REQ_CALL_2_SEND:
395                 {
396                         if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
397                                 gboolean bactive_calls = FALSE;
398                                 gboolean bheld_calls = FALSE;
399
400                                 if (TRUE == voicecall_core_is_incoming_call_exists(pcall_core->pcall_engine)) {
401                                         voicecall_core_is_call_exists(pcall_core->pcall_engine, &bactive_calls, &bheld_calls);
402                                         if (!((TRUE == bactive_calls) && (TRUE == bheld_calls))) {
403                                                 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming call Accept by BT");
404                                                 voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, TRUE);
405                                         }
406                                 }
407                                 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_2);
408                         }
409                 }
410                 break;
411         case BT_AG_REQ_CALL_3_SEND:
412                 {
413                         if (TRUE == voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
414                                 voicecall_core_start_incall_ss(pcall_core, CALL_VC_CORE_SS_3);
415                         }
416                 }
417                 break;
418         case BT_AG_REQ_HEADSET_VOL:
419                 {
420                         int bt_vol_level = pbt_info->param2;
421                         int converted_vol_level;
422
423                         CALL_ENG_DEBUG(ENG_DEBUG, "BT volume Level: %d", bt_vol_level);
424
425                         if (voicecall_core_is_any_call_exists(pcall_core->pcall_engine)) {
426                                 vc_engine_vol_resp_type event_data;
427
428                                 converted_vol_level = __vc_bt_converted_bt_vol_to_voice_vol(bt_vol_level);
429
430                                 memset(&event_data, 0, sizeof(event_data));
431                                 event_data.vol_alert_type = VOICE_CALL_VOL_TYPE_HEADSET;
432                                 event_data.vol_level = converted_vol_level;
433                                 vcall_engine_send_event_to_client(VC_ENGINE_MSG_GET_VOLUME_RESP_TO_UI, (void *)&event_data);
434                         } else {
435                                 CALL_ENG_DEBUG(ENG_ERR, "NO Calls, Skipping BT Response");
436                         }
437                 }
438                 break;
439         case BT_AG_REQ_SWITCH_TO_HEADSET:
440         case BT_AG_REQ_SWITCH_TO_PHONE:
441                 {
442                         gboolean bswitch_to_headset = FALSE;
443                         int bt_error = pbt_info->param2;
444
445                         if (voicecall_core_get_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING) == TRUE) {
446                                 b_user_rqst_path_change = TRUE;
447                         } else {
448                                 b_user_rqst_path_change = FALSE;
449                         }
450
451                         voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_BT_EVENT_WAITING, FALSE);
452
453                         /*Switch to response is received from BT, BT decision is fina, so reset the accept by BT */
454                         voicecall_core_set_status(pcall_core, CALL_VC_CORE_FLAG_ACCEPT_BY_BT, FALSE);
455
456                         CALL_ENG_DEBUG(ENG_DEBUG, "BT Error :%d", bt_error);
457                         if (0 == bt_error) {
458                                 /*Audio Connection/Disconnection Success case */
459                                 bswitch_to_headset = (BT_AG_REQ_SWITCH_TO_HEADSET == pbt_info->param1) ? TRUE : FALSE;
460                         } else {
461                                 /*Audio Connection/Disconnection Error Case */
462                                 if (BT_AG_RES_AUDIO_CONNECTION_ERROR == bt_error) {
463                                         /*Connection Error, switch to phone */
464                                         bswitch_to_headset = FALSE;
465                                 } else if (BT_AG_RES_AUDIO_DISCONNECTION_ERROR == bt_error) {
466                                         /*Disconnection Error, switch to headset */
467                                         bswitch_to_headset = TRUE;
468                                 } else {
469                                         CALL_ENG_DEBUG(ENG_ERR, "Invalid BT Error: %d", bt_error);
470                                 }
471
472                         }
473
474                         CALL_ENG_DEBUG(ENG_DEBUG, "bswitch_to_headset = %d", bswitch_to_headset);
475
476                         if ((TRUE == voicecall_core_is_connected_call_exist(pcall_core->pcall_engine)) || (TRUE == voicecall_core_is_outgoing_call_exists(pcall_core->pcall_engine))) {
477                                 gboolean bupdate = FALSE;
478
479                                 if (0 == bt_error) {
480                                         /*Connection/Diconnection is sucess, don't send response to BT */
481                                         bupdate = _vc_bt_switch_headset_path(pcall_core, bswitch_to_headset, FALSE);
482                                         CALL_ENG_DEBUG(ENG_DEBUG, "bupdate = %d, bswitch_to_headset = %d", bupdate, bswitch_to_headset);
483
484                                         vc_engine_headset_status_type event_data;
485                                         memset(&event_data, 0, sizeof(event_data));
486                                         event_data.bstatus = bswitch_to_headset;
487                                         vcall_engine_send_event_to_client(VC_ENGINE_MSG_HEADSET_STATUS_TO_UI, (void *)&event_data);
488                                 } else {
489                                         /*Connection/Diconnection is NOT sucess, change path and send response to BT */
490                                         bupdate = _vc_bt_switch_headset_path(pcall_core, bswitch_to_headset, TRUE);
491                                 }
492
493                         } else {
494                                 CALL_ENG_DEBUG(ENG_ERR, "No connected/outgoing calls, Skipping BT Request");
495                         }
496                 }
497                 break;
498         case BT_AG_REQ_DTMF:
499                 {
500                         gboolean active_calls = FALSE;
501                         gboolean held_calls = FALSE;
502
503                         CALL_ENG_DEBUG(ENG_DEBUG, "Send DTMF(%s)", pbt_info->param4);
504                         if ((voicecall_core_is_call_exists(pcall_core->pcall_engine, &active_calls, &held_calls)) && (TRUE == active_calls)) {
505                                 voicecall_core_send_dtmf(pcall_core, pbt_info->param4);
506                         }
507                 }
508                 break;
509
510         case BT_AG_REQ_CALL_REDIAL:
511         default:
512                 CALL_ENG_DEBUG(ENG_DEBUG, "Action not defined for bt event: %d", pbt_info->param1);
513                 return FALSE;
514                 break;
515
516         }
517
518         return TRUE;
519 }
520
521 /**
522  * This function sends response back to the bt application
523  *
524  * @return              void
525  * @param[in]           pcall_core                      Handle to voicecall core
526  * @param[in]           bt_event                                bluetooth event type
527  * @param[in]           param1                          user param1
528  * @param[in]           param2                          user param2
529  */
530 void _vc_bt_send_response_to_bt(call_vc_core_state_t *pcall_core, int bt_event, int param1, gpointer param2)
531 {
532         VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
533
534         connectivity_bt_ag_param_info_t bt_response_info;
535         CALL_ENG_DEBUG(ENG_DEBUG, "Event: %s(%d), param1=[%d]", gszbt_res_event[bt_event], bt_event, param1);
536
537         /*Skip events, if Bluetooth is not connected */
538 /*      if((FALSE == pcall_core->bt_connected) && (BT_AG_RES_CALL_STATUS != bt_event))
539         {
540                 CALL_ENG_DEBUG(ENG_DEBUG,"Bluetooth not connected , Not sending any responses to BT");
541                 return;
542         }
543 */
544         /*Make BT Response Info */
545         memset(&bt_response_info, 0, sizeof(connectivity_bt_ag_param_info_t));
546
547         bt_response_info.param1 = bt_event;
548
549         switch (bt_event) {
550         case BT_AG_RES_CALL_STATUS:
551         case BT_AG_RES_CALL_SWAPPED:
552                 {
553                         connectivity_bt_ag_call_status_info_t call_status_info[10];
554                         int mt_call_handle = -1;
555                         int mo_call_handle = -1;
556                         int connected_call_handle = -1;
557                         int active_group_member_num = 0;
558                         int held_group_member_num = 0;
559                         int index = 0;
560                         int i = 0;
561                         char temp_str[10] = { 0, };
562                         char result_str[256] = { 0, };
563
564                         /*Incoming Call */
565                         _vc_core_engine_status_get_call_handle_bytype(pcall_core->pcall_engine, VC_INCOMING_CALL, &mt_call_handle);
566                         if (mt_call_handle != -1) {
567                                 CALL_ENG_DEBUG(ENG_DEBUG, "Incoming Call Exists, call handle = %d", mt_call_handle);
568
569                                 call_status_info[index].call_id = mt_call_handle;
570                                 call_status_info[index].call_status = BT_AG_CALL_STATUS_INCOMING;
571                                 index++;
572                                 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after mt= %d", index);
573                         }
574
575                         /*Outgoing Call */
576                         _vc_core_engine_status_get_call_handle_bytype(pcall_core->pcall_engine, VC_OUTGOING_CALL, &mo_call_handle);
577                         if (mo_call_handle != -1) {
578                                 voicecall_call_state_t call_state;
579                                 gboolean bvalid_call = TRUE;
580
581                                 _vc_core_engine_status_get_call_state_byhandle(pcall_core->pcall_engine, mo_call_handle, &call_state);
582                                 CALL_ENG_DEBUG(ENG_DEBUG, "call state: %d", call_state);
583
584                                 switch (call_state) {
585                                 case VC_CALL_STATE_OUTGOING_ALERT:
586                                         {
587                                                 call_status_info[index].call_status = BT_AG_CALL_STATUS_ALERTING;
588                                         }
589                                         break;
590                                 case VC_CALL_STATE_PREPARE_OUTGOING:
591                                 case VC_CALL_STATE_OUTGOING:
592                                 case VC_CALL_STATE_OUTGOING_ORIG:
593                                         {
594                                                 call_status_info[index].call_status = BT_AG_CALL_STATUS_DIALLING;
595                                         }
596                                         break;
597                                 default:        /*All Other states , donot consider for mocall */
598                                         CALL_ENG_DEBUG(ENG_DEBUG, "mo call state: %d", call_state);
599                                         bvalid_call = FALSE;
600                                 }
601
602                                 if (TRUE == bvalid_call) {
603                                         call_status_info[index].call_id = mo_call_handle;
604                                         index++;
605                                         CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after mo= %d", index);
606                                 }
607
608                         }
609
610                         /*Connected call */
611                         int act_grp_index = -1;
612                         int held_grp_index = -1;
613
614                         _vc_core_engine_group_get_group_indices(pcall_core->pcall_engine, &act_grp_index, &held_grp_index);
615
616                         CALL_ENG_DEBUG(ENG_DEBUG, "act_grp_index = %d, held_grp_index = %d", act_grp_index, held_grp_index);
617                         /*Active Connected Call */
618                         if (act_grp_index != -1) {
619                                 _vc_core_engine_group_get_connected_member_count(pcall_core->pcall_engine, act_grp_index, &active_group_member_num);
620                                 CALL_ENG_DEBUG(ENG_DEBUG, "active_group_connected_member_num = %d", active_group_member_num);
621                                 for (i = 0; i < active_group_member_num; i++) {
622                                         _vc_core_engine_group_get_call_handle_byposition(pcall_core->pcall_engine, act_grp_index, i, &connected_call_handle);
623                                         if (connected_call_handle != -1) {
624                                                 call_status_info[index].call_id = connected_call_handle;
625                                                 call_status_info[index].call_status = BT_AG_CALL_STATUS_CONNECTED;
626                                                 index++;
627                                         }
628                                 }
629                                 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after active calls= %d", index);
630                         }
631
632                         /*Held Connected Call */
633                         if (held_grp_index != -1) {
634                                 _vc_core_engine_group_get_connected_member_count(pcall_core->pcall_engine, held_grp_index, &held_group_member_num);
635
636                                 CALL_ENG_DEBUG(ENG_DEBUG, "held_group_member_num = %d", held_group_member_num);
637                                 for (i = 0; i < held_group_member_num; i++) {
638                                         _vc_core_engine_group_get_call_handle_byposition(pcall_core->pcall_engine, held_grp_index, i, &connected_call_handle);
639                                         CALL_ENG_DEBUG(ENG_DEBUG, "Call Handle[%d] = %d", i, connected_call_handle);
640                                         if (connected_call_handle != -1) {
641                                                 call_status_info[index].call_id = connected_call_handle;
642                                                 call_status_info[index].call_status = BT_AG_CALL_STATUS_HELD;
643                                                 index++;
644                                         }
645                                 }
646                                 CALL_ENG_DEBUG(ENG_DEBUG, "total_call_member after held calls= %d", index);
647                         }
648
649                         CALL_ENG_DEBUG(ENG_DEBUG, "Total Calls = %d", index);
650                         bt_response_info.param2 = index;
651
652                         memset(result_str, 0x00, sizeof(result_str));
653                         for (i = 0; i < index; i++) {
654                                 memset(temp_str, 0x00, sizeof(temp_str));
655                                 snprintf(temp_str, sizeof(temp_str), "%d.%d/", call_status_info[i].call_id, call_status_info[i].call_status);
656                                 strncat(result_str, temp_str, sizeof(temp_str) - 1);
657                         }
658                         CALL_ENG_DEBUG(ENG_DEBUG, "The resultant string is %s", result_str);
659
660                         _vc_core_util_strcpy(bt_response_info.param4, sizeof(bt_response_info.param4), result_str);
661
662                         CALL_ENG_DEBUG(ENG_DEBUG, "Actual Data Passed is %s", bt_response_info.param4);
663                         CALL_ENG_DEBUG(ENG_DEBUG, "Actual Data Passed to BT");
664                         for (i = 0; i < index; i++) {
665                                 CALL_ENG_DEBUG(ENG_DEBUG, "call id = %d", call_status_info[i].call_id);
666                                 CALL_ENG_DEBUG(ENG_DEBUG, "call status= %d", call_status_info[i].call_status);
667                         }
668
669                         CALL_ENG_DEBUG(ENG_DEBUG, "Verification of BT data being sent");
670
671                 }
672                 break;
673         case BT_AG_RES_CALL_INCOM:
674                 {
675                         /*Length of Incoming Call Number */
676                         if (NULL != param2) {
677                                 CALL_ENG_DEBUG(ENG_DEBUG, "phone number=%s", (char *)param2);
678                                 bt_response_info.param2 = strlen(param2);
679                                 bt_response_info.param3 = param1;
680                                 _vc_core_util_strcpy(bt_response_info.param4, VC_PHONE_NUMBER_LENGTH_MAX, param2);
681                         }
682                 }
683                 break;
684         case BT_AG_RES_CALL_ORIG:
685                 {
686                         if (NULL != param2) {
687                                 CALL_ENG_DEBUG(ENG_DEBUG, "phone number=%s", (char *)param2);
688                                 switch (voicecall_snd_get_path_status(pcall_core->papp_snd)) {
689                                         case VOICE_CALL_SND_PATH_RECEIVER_EARJACK:
690                                         case VOICE_CALL_SND_PATH_SPEAKER:
691                                                 bt_response_info.param2 = FALSE;
692                                                 break;
693                                         case VOICE_CALL_SND_PATH_BT:
694                                                 bt_response_info.param2 = TRUE;
695                                                 break;
696                                         default:
697                                                 break;
698                                 }
699                                 bt_response_info.param3 = param1;
700                                 _vc_core_util_strcpy(bt_response_info.param4, VC_PHONE_NUMBER_LENGTH_MAX, param2);
701                         }
702                 }
703                 break;
704         case BT_AG_RES_CALL_REMOTE_RINGING:
705                 {
706                         /*Assign Call Handle */
707                         bt_response_info.param3 = param1;
708                 }
709                 break;
710         case BT_AG_RES_CALL_CONNECT:
711         case BT_AG_RES_CALL_END:
712                 {
713                         switch (voicecall_snd_get_path_status(pcall_core->papp_snd)) {
714                                 case VOICE_CALL_SND_PATH_RECEIVER_EARJACK:
715                                 case VOICE_CALL_SND_PATH_SPEAKER:
716                                         bt_response_info.param2 = FALSE;
717                                         break;
718                                 case VOICE_CALL_SND_PATH_BT:
719                                         bt_response_info.param2 = TRUE;
720                                         break;
721                                 default:
722                                         break;
723                         }
724                         /*Assign Call Handle */
725                         bt_response_info.param3 = param1;
726                 }
727                 break;
728         case BT_AG_RES_SPK_GAIN:
729                 /*BT Volume Level */
730                 bt_response_info.param2 = param1;
731                 break;
732         case BT_AG_RES_HEADSET_VOL:     /*Request For Current BT Volume Level */
733                 {
734                         CALL_ENG_DEBUG(ENG_DEBUG, "Requesting for Current BT Volume Level");
735                 }
736                 break;
737         case BT_AG_RES_SWITCH_TO_HEADSET:
738         case BT_AG_RES_SWITCH_TO_PHONE:
739                 break;
740         case BT_AG_RES_CALL_HOLD:
741         case BT_AG_RES_CALL_RETRIEVE:   /*Fall Through */
742                 bt_response_info.param3 = param1;
743                 break;
744         case BT_AG_RES_CALL_JOINED:     /*Fall Through */
745         default:
746                 break;
747         }
748
749         vc_engine_on_dbus_send_response_to_bt(bt_response_info);
750
751         CALL_ENG_DEBUG(ENG_DEBUG, "bt response ended.");
752
753 }
754
755 /**
756  * This function register bt callback.
757  *
758  * @return              TRUE if bt status is registered, FALSE otherwise
759  * @param[in]           void
760  */
761 gboolean _vc_bt_status_init(call_vc_core_state_t *pcall_core)
762 {
763         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
764
765         gboolean ret = FALSE;
766
767         int bstatus = 0;
768         bstatus = _vc_bt_get_bt_status();
769         CALL_ENG_DEBUG(ENG_DEBUG, "bt_connected:[%d]", bstatus);
770         __vc_bt_handle_connectivity_event(pcall_core, bstatus);
771
772         ret = vconf_notify_key_changed(VCONFKEY_BT_DEVICE, (void *)_vc_bt_handle_phonestatus_bt_events, pcall_core);
773         if (0 != ret) {
774                 CALL_ENG_DEBUG(ENG_ERR, "vconf_notify_key_changed failed..[%d]", ret);
775                 return FALSE;
776         }
777         return TRUE;
778 }
779
780 /**
781  * This function gets the blue tooth active status from the phone status server
782  *
783  * @return              TRUE - if BT is enabled, FALSE otherwise
784  * @param[in]           none
785  */
786 gboolean _vc_bt_get_bt_status(void)
787 {
788         int bt_status = VCONFKEY_BT_DEVICE_NONE;
789         gboolean ret = FALSE;
790
791         ret = vconf_get_int(VCONFKEY_BT_DEVICE, &bt_status);
792         if (0 == ret) {
793                 CALL_ENG_DEBUG(ENG_DEBUG, "bt_status = [0x%x]", bt_status);
794         } else {
795                 CALL_ENG_DEBUG(ENG_ERR, "vconf_get_int failed..[%d]", ret);
796         }
797
798         return (VCONFKEY_BT_DEVICE_HEADSET_CONNECTED == (bt_status & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED)) ? TRUE : FALSE;
799 }
800
801 /**
802  * This function gets the BT inband ringtone activate settings
803  *
804  * @return              TRUE - if BT inband ringtone activate settings is ON, FALSE otherwise
805  * @param[in]           none
806  */
807 gboolean _vc_bt_get_inband_ringtone_active(void)
808 {
809         /* InBand_Ringtone_Active for vconf.. */
810         return FALSE;
811 }
812
813 /**
814  * This function handles the notifications sent by phone status server
815  *
816  * @return              TRUE -if notification is handled, FALSE otherwise
817  * @param[in]           pcall_core              Handle to voicecall core
818  * @param[in]           bt_status                       Blue tooth status
819  */
820 gboolean _vc_bt_handle_phonestatus_bt_events(keynode_t *node, call_vc_core_state_t *pcall_core)
821 {
822         VOICECALL_RETURN_FALSE_IF_FAIL(node != NULL);
823         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
824
825         gboolean bt_conn_status = FALSE;
826         int bt_status = vconf_keynode_get_int(node);
827
828         CALL_ENG_DEBUG(ENG_DEBUG, "bt_status = [0x%x]", bt_status);
829
830         /*set the sound status */
831         bt_conn_status = (VCONFKEY_BT_DEVICE_HEADSET_CONNECTED == (bt_status & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED)) ? TRUE : FALSE;
832         CALL_ENG_DEBUG(ENG_DEBUG, "bt_conn_status = %d", bt_conn_status);
833
834         __vc_bt_handle_connectivity_event(pcall_core, bt_conn_status);
835         return TRUE;
836 }
837
838 /**
839  * This function retreives volume level of headset
840  *
841  * @return
842  * @param[in]           pcall_core              Handle to voicecall core
843  */
844 void _vc_bt_get_headset_volume(call_vc_core_state_t *pcall_core)
845 {
846         VOICECALL_RETURN_IF_FAIL(pcall_core != NULL);
847
848         _vc_bt_send_response_to_bt(pcall_core, BT_AG_RES_HEADSET_VOL, 0, NULL);
849 }
850
851 /**
852  * This function returns the BT connection status
853  *
854  * @return              TRUE if bt is connected, FALSE otherwise
855  * @param[in]           pcall_core              Handle to voicecall core
856  */
857 gboolean _vc_bt_is_bt_connected(call_vc_core_state_t *pcall_core)
858 {
859         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
860
861         return pcall_core->bt_connected;
862 }
863
864 /**
865  * This function returns the BT SCO status.(Synchronized Connection Oriented link)
866  *
867  * @return              TRUE if bt is connected, FALSE otherwise
868  * @param[in]           void
869  */
870 gboolean _vc_bt_get_bt_sco_status(void)
871 {
872         gboolean sco_status = FALSE;
873         gboolean ret = FALSE;
874
875         ret = vconf_get_bool(VCONFKEY_BT_HEADSET_SCO, &sco_status);
876         if (0 == ret) {
877                 CALL_ENG_DEBUG(ENG_DEBUG, "sco_status = [%d]", sco_status);
878         } else {
879                 CALL_ENG_DEBUG(ENG_ERR, "vconf_get_int failed..[%d]", ret);
880         }
881
882         return sco_status;
883 }
884
885 /**
886  * This function processed bt handset event
887  *
888  * @return              TRUE if bt is connected, FALSE otherwise
889  * @param[in]           pcall_core              Handle to voicecall core
890  * @param[in]           bheadset                        headset status
891  */
892 gboolean _vc_bt_process_bt_handset(call_vc_core_state_t *pcall_core, int bheadset)
893 {
894         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_core != NULL);
895
896         CALL_ENG_DEBUG(ENG_DEBUG, "bheadset:[%d]", bheadset);
897         if (bheadset) {
898                 if (FALSE == _vc_bt_get_bt_status()) {
899                         vc_engine_on_dbus_send_connect_to_bt();
900                 } else {
901                         CALL_ENG_DEBUG(ENG_DEBUG, "BT is ON.. switch path to BT");
902                         _vc_bt_switch_headset_path(pcall_core, bheadset, TRUE);
903                 }
904         } else {
905                 _vc_bt_switch_headset_path(pcall_core, bheadset, TRUE);
906         }
907         return TRUE;
908 }