8c68abb542d5d0ae6d1198e1c0b84761f03a67e5
[apps/home/call.git] / call-engine / core / vc-core-callagent.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 #include "vc-core-callagent.h"
18 #include "vc-core-engine.h"
19 #include "vc-core-ccbs.h"
20 #include "vc-core-tapi-rqst.h"
21 #include "vc-core-tapi-evnt.h"
22 #include "vc-core-svcall.h"
23 #include <assert.h>
24
25 /* For Debug Information, Inout state name string constant */
26 char *gszcall_vc_inout_state[VC_INOUT_STATE_MAX_NUM] = {
27         "NONE",
28         "OUTGOING_START",
29         "OUTGOING_WAIT_HOLD",
30         "OUTGOING_WAIT_ORIG",
31         "OUTGOING_WAIT_ALERT",
32         "OUTGOING_WAIT_CONNECTED",
33         "OUTGOING_WAIT_RELEASE",
34         "OUTGOING_ABORTED",
35         "OUTGOING_SHOW_REDIALCAUSE",
36         "OUTGOING_WAIT_REDIAL",
37         "OUTGOING_SHOW_RETRY_CALLBOX",
38         "OUTGOING_END",
39         "INCOME_SELFEVENT_WAIT",
40         "INCOME_START",
41         "INCOME_BOX",
42         "INCOME_WAIT_REDIRECTCNF",
43         "INCOME_WAIT_REDIRECT_END",
44         "INCOME_WAIT_CONNECTED",
45         "INCOME_WAIT_HOLD_CONNECTED",
46         "INCOME_WAIT_RELEASE_ACTIVE_CONNECTED",
47         "INCOME_WAIT_HOLD",
48         "INCOME_WAIT_RELEASE_ACTIVECALL",
49         "INCOME_WAIT_RELEASE_HOLDCALL",
50         "INCOME_WAIT_RELEASE",
51         "INCOME_END"
52 };
53
54 /* For Debug Information, Call Agent State name string constant */
55 char *gszcall_vc_ca_state[CALL_VC_CA_STATE_MAX_NUM] = {
56         "CA_STATE_NORMAL",
57         "CA_STATE_SPLIT_CALLBOX",
58         "CA_STATE_WAIT_SPLIT",
59         "CA_STATE_DROP_CALLBOX",
60         "CA_STATE_WAIT_DROP",
61 #ifdef SWAP_SUPPORT
62         "CA_STATE_WAIT_SWAP_HOLD_OR_ACTIVATE",
63         "CA_STATE_WAIT_SWAP_HOLD",
64         "CA_STATE_WAIT_SWAP_ACTIVATE",
65 #endif                          /*                */
66         "CA_STATE_WAIT_SWAP",
67         "CA_STATE_WAIT_HOLD",
68         "CA_STATE_WAIT_UNHOLD",
69         "CA_STATE_WAIT_JOIN",
70         "CA_STATE_WAIT_TRANSFER_CNF",
71         "CA_STATE_WAIT_TRANSFER_CALLEND",
72         "CA_STATE_WAIT_RELEASE_ALL_ACTIVECALL",
73         "CA_STATE_WAIT_RELEASE_ALL_HOLDCALL",
74         "CA_STATE_SENDMSG_CALLBOX",
75         "CA_STATE_VIEW_CONTACT_DETAIL_CALLBOX",
76         "CA_STATE_SAVE_TO_CONTACT_CALLBOX",
77         "CA_STATE_SS_WAIT_RELEASE_ALL_ACTIVECALL",
78         "CA_STATE_WAIT_RELEASE_ALL_CALLS",
79         "CA_STATE_WAIT_RELEASE_ALL_CALLS_TO_SETUP",
80         "CA_STATE_WAIT_RELEASE_ALL_CALLS_TO_SWITCH_TO_VIDEO_CALL"
81 };
82
83 /**
84  * This function intializes the call agent
85  *
86  * @return              Pointer to call agent state.
87  */
88 call_vc_callagent_state_t *_vc_core_ca_init_agent()
89 {
90         call_vc_callagent_state_t *pcall_agent = NULL;
91         pcall_agent = (call_vc_callagent_state_t *)calloc(1, sizeof(call_vc_callagent_state_t));
92         if (NULL == pcall_agent) {
93                 CALL_ENG_DEBUG(ENG_DEBUG, "Voicecall Engine Initialization Failed: MEM ALLOC Failure");
94                 return NULL;
95         }
96
97         /*Initialize Call Manager */
98         _vc_core_call_manager_init(&pcall_agent->call_manager);
99
100         /* Initialize Call Agent Flags */
101         _vc_core_ca_init_data(pcall_agent);
102
103 #ifdef _CCBS_DEFINED_
104         /* Init CCBS Info */
105         _vc_core_init_ccbs_info(pcall_agent);
106 #endif
107
108         /* Init CPHS Info */
109 #ifdef _CPHS_DEFINED_
110         _vc_core_svcall_init_cphs_info(pcall_agent);
111 #endif
112         return pcall_agent;
113 }
114
115 /**
116  * This function intializes the callagent data
117  *
118  * @return              void
119  * @param[in]           pagent                                  Pointer to the call agent structure
120  */
121 void _vc_core_ca_init_data(call_vc_callagent_state_t *pagent)
122 {
123         VOICECALL_RETURN_IF_FAIL(pagent != NULL);
124         pagent->bonly_sos_call = FALSE;
125         pagent->callagent_state = CALL_VC_CA_STATE_NORMAL;
126         pagent->io_state = VC_INOUT_STATE_NONE;
127         pagent->bis_no_sim = FALSE;
128         pagent->aoc_ppm = VC_INVALID_PPM;
129 }
130
131 /**
132  * This function finalizes the call agent
133  *
134  * @return              Returns void
135  * @param[in]           pcall_agent Pointer to the call agent structure
136  */
137 void _vc_core_ca_finish_agent(call_vc_callagent_state_t *pcall_agent)
138 {
139         if (NULL != pcall_agent) {
140                 free(pcall_agent);
141                 pcall_agent = NULL;
142         }
143 }
144
145 /**
146  * This function changes the in out state of the call agent
147  *
148  * @return              This function returns TRUE on success and FALSE on failure
149  * @param[in]           pagent          Pointer to the call agent structure
150  * @param[in]           new_state               The new i/o state that should be set
151  * @see                 _vc_core_ca_change_agent_state
152  */
153 gboolean _vc_core_ca_change_inout_state(call_vc_callagent_state_t *pagent, voicecall_inout_state_t new_state)
154 {
155         VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
156
157         CALL_ENG_DEBUG(ENG_ERR, "%s(%d) --> %s(%d)", gszcall_vc_inout_state[pagent->io_state], pagent->io_state, gszcall_vc_inout_state[new_state], new_state);
158         pagent->io_state = new_state;
159         return TRUE;
160 }
161
162 /**
163  * This function changes the in call agent state
164  *
165  * @return              This function returns TRUE on success and FALSE on failure
166  * @param[in]           pAgent          Pointer to the call agent structure
167  * @param[in]           new_state               The new call agent state that should be set
168  * @see                 _vc_core_ca_change_inout_state
169  */
170 gboolean _vc_core_ca_change_agent_state(call_vc_callagent_state_t *pAgent, call_vc_ca_state_t new_state)
171 {
172         VOICECALL_RETURN_FALSE_IF_FAIL((new_state >= CALL_VC_CA_STATE_NORMAL && new_state < CALL_VC_CA_STATE_MAX_NUM));
173         CALL_ENG_DEBUG(ENG_DEBUG, "%s(%d) --> %s(%d)", gszcall_vc_ca_state[pAgent->callagent_state], pAgent->callagent_state, gszcall_vc_ca_state[new_state], new_state);
174         pAgent->callagent_state = new_state;
175         return TRUE;
176 }
177
178 /**
179  * This function checks if all the call members have terminated or not
180  *
181  * @return              Returns TRUE if no call members exist, FALSE otherwise
182  * @param[in]           pAgent          Pointer to the call agent structure
183  */
184 gboolean _vc_core_ca_check_end(call_vc_callagent_state_t *pAgent)
185 {
186         gboolean result = FALSE;
187         VOICECALL_RETURN_FALSE_IF_FAIL(pAgent != NULL);
188         if ((_vc_core_cm_get_call_member_count(&pAgent->call_manager) == 0) && (pAgent->io_state == VC_INOUT_STATE_NONE)) {
189                 CALL_ENG_DEBUG(ENG_DEBUG, "TRUE");
190                 result = TRUE;
191         }
192
193         else {
194                 CALL_ENG_DEBUG(ENG_DEBUG, "FALSE");
195                 result = FALSE;
196         }
197         return result;
198 }
199
200
201 /**
202  * This function sends the response to the SAT engine
203  *
204  * @return              This function returns TRUE on success and FALSE on failure
205  * @param[in]   pagent                          Pointer to the call agent structure
206  * @param[in]   sat_rqst_resp_type      sat rquest/response type used by the client
207  * @param[in]   sat_response_type       response to be sent to sat
208  */
209 gboolean _vc_core_ca_send_sat_response(call_vc_callagent_state_t *pagent, voicecall_engine_sat_rqst_resp_type sat_rqst_resp_type, call_vc_sat_reponse_type_t sat_response_type)
210 {
211         call_vc_satsetup_info_t *pcall_vc_satcall_info = (call_vc_satsetup_info_t *) &(pagent->call_manager.setupcall_info.satcall_setup_info);
212         TelSatAppsRetInfo_t call_vc_sat_response = {0,};
213         TapiResult_t error_code;
214         CALL_ENG_DEBUG(ENG_DEBUG, "sat_rqst_resp_type: %d, sat_response_type: %d", sat_rqst_resp_type, sat_response_type);
215         switch (sat_rqst_resp_type) {
216         case SAT_RQST_SETUP_CALL:
217                 {
218                         TelSatCallRetInfo_t sat_engine_ret_call = {0,};
219                         switch (sat_response_type) {
220                         case CALL_VC_ME_UNABLE_TO_PROCESS_COMMAND:
221                                 sat_engine_ret_call.resp = TAPI_SAT_R_ME_UNABLE_TO_PROCESS_COMMAND;
222                                 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
223                                 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
224                                 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_ME_BUSY_ON_CALL;
225                                 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
226                                 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
227                                 break;
228                         case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND:
229                                 sat_engine_ret_call.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
230                                 sat_engine_ret_call.bIsTapiCauseExist = TRUE;
231                                 sat_engine_ret_call.tapiCause = TAPI_CAUSE_BUSY;
232                                 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_NO_SERVICE;
233                                 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
234                                 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
235                                 break;
236                         case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND_WITHOUT_CAUSE:
237                                 sat_engine_ret_call.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
238                                 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
239                                 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
240                                 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_NO_SPECIFIC_CAUSE;
241                                 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
242                                 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
243                                 break;
244                         case CALL_VC_ME_CONTROL_PERMANENT_PROBLEM:
245                                 sat_engine_ret_call.resp = TAPI_SAT_R_INTRCTN_WITH_CC_OR_SMS_CTRL_PRMNT_PRBLM;
246                                 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
247                                 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
248                                 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_ACCESS_CONTROL_CLASS_BAR;
249                                 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
250                                 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_ACTION_NOT_ALLOWED;
251                                 break;
252                         case CALL_VC_ME_CLEAR_DOWN_BEFORE_CONN:
253                                 sat_engine_ret_call.resp = TAPI_SAT_R_USER_CLEAR_DOWN_CALL_BEFORE_CONN;
254                                 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
255                                 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
256                                 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_ME_BUSY_ON_CALL;
257                                 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
258                                 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
259                                 break;
260                         case CALL_VC_ME_RET_SUCCESS:
261                                 sat_engine_ret_call.resp = TAPI_SAT_R_SUCCESS;
262                                 sat_engine_ret_call.bIsTapiCauseExist = TRUE;
263                                 sat_engine_ret_call.tapiCause = TAPI_CAUSE_SUCCESS;
264                                 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_NO_SPECIFIC_CAUSE;
265                                 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
266                                 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
267                                 break;
268                         default:
269                                 return FALSE;
270                                 break;
271                         }
272                         call_vc_sat_response.commandType = TAPI_SAT_CMD_TYPE_SETUP_CALL;
273                         call_vc_sat_response.commandId = pcall_vc_satcall_info->satengine_setupcall_data.commandId;
274                         memset(&(call_vc_sat_response.appsRet.setupCall), 0, sizeof(call_vc_sat_response.appsRet.setupCall));
275                         memcpy(&(call_vc_sat_response.appsRet.setupCall), &sat_engine_ret_call, sizeof(call_vc_sat_response.appsRet.setupCall));
276                 }
277                 break;
278         case SAT_RQST_SEND_DTMF:
279                 {
280                         TelSatDtmfRetInfo_t sat_engine_ret_dtmf;
281                         switch (sat_response_type) {
282                         case CALL_VC_ME_UNABLE_TO_PROCESS_COMMAND:
283                                 sat_engine_ret_dtmf.resp = TAPI_SAT_R_ME_UNABLE_TO_PROCESS_COMMAND;
284                                 break;
285                         case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND:
286                                 sat_engine_ret_dtmf.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
287                                 break;
288                         case CALL_VC_ME_CONTROL_PERMANENT_PROBLEM:
289                                 sat_engine_ret_dtmf.resp = TAPI_SAT_R_INTRCTN_WITH_CC_OR_SMS_CTRL_PRMNT_PRBLM;
290                                 break;
291                         case CALL_VC_ME_CLEAR_DOWN_BEFORE_CONN:
292                                 sat_engine_ret_dtmf.resp = TAPI_SAT_R_USER_CLEAR_DOWN_CALL_BEFORE_CONN;
293                                 break;
294                         case CALL_VC_ME_RET_SUCCESS:
295                                 sat_engine_ret_dtmf.resp = TAPI_SAT_R_SUCCESS;
296                                 break;
297                         default:
298                                 return FALSE;
299                                 break;
300                         }
301                         call_vc_sat_response.commandType = TAPI_SAT_CMD_TYPE_SEND_DTMF;
302                         call_vc_sat_response.commandId = pcall_vc_satcall_info->satengine_dtmf_data.commandId;
303                         memset(&(call_vc_sat_response.appsRet.sendDtmf), 0, sizeof(call_vc_sat_response.appsRet.sendDtmf));
304                         memcpy(&(call_vc_sat_response.appsRet.sendDtmf), &sat_engine_ret_dtmf, sizeof(call_vc_sat_response.appsRet.sendDtmf));
305
306                         /*Reset SAT DATA after sending response */
307                         pcall_vc_satcall_info->satengine_dtmf_data.bIsHiddenMode = FALSE;
308                         CALL_ENG_DEBUG(ENG_ERR, "SAT Hidden mode has been reset");
309                 }
310                 break;
311         default:
312                 CALL_ENG_DEBUG(ENG_DEBUG, "Invalid SAT Rquest Response Type");
313                 break;
314         }
315         error_code = tel_send_sat_app_exec_result(&call_vc_sat_response);
316         if (error_code != TAPI_API_SUCCESS) {
317                 CALL_ENG_DEBUG(ENG_DEBUG, "Error tel_send_sat_app_exec_result():%#X", error_code);
318                 return FALSE;
319         }
320
321         else {
322                 CALL_ENG_DEBUG(ENG_DEBUG, "tel_send_sat_app_exec_result: Success");
323         }
324         return TRUE;
325 }
326
327 /**
328  * This function checks whether outgoing call is possible
329  *
330  * @return              This function returns TRUE if outgoing call is possible or else FALSE
331  * @param[in]           pagent                  Pointer to the call agent structure
332  * @param[in]           bemergency_number       TRUE - if outgoing call being made is emergency call or else FALSE
333  */
334 gboolean _vc_core_ca_is_mocall_possible(call_vc_callagent_state_t *pagent, gboolean bemergency_number)
335 {
336         gboolean bactive_call = FALSE;
337         gboolean bheld_call = FALSE;
338         int member_num = 0;
339         VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
340         bactive_call = _vc_core_cm_isexists_active_call(&pagent->call_manager);
341         bheld_call = _vc_core_cm_isexists_held_call(&pagent->call_manager);
342         if (pagent->io_state != VC_INOUT_STATE_NONE) {
343                 CALL_ENG_DEBUG(ENG_DEBUG, "io_state=%d with FALSE ..", pagent->io_state);
344                 return FALSE;
345         }
346
347         /* If it is emergency number, the call can be made by disconnecting all calls */
348         if (bemergency_number) {
349                 CALL_ENG_DEBUG(ENG_DEBUG, "Emergency number with TRUE..");
350                 return TRUE;
351         }
352
353         /* Mo is impossile when both active and hold call exist */
354         if (bactive_call && bheld_call) {
355                 CALL_ENG_DEBUG(ENG_DEBUG, "ended with FALSE ..");
356                 return FALSE;
357         }
358
359         else {
360                 member_num = _vc_core_cm_get_call_member_count(&pagent->call_manager);
361
362 #ifdef _CPHS_DEFINED_
363                 if (bactive_call && _vc_core_svcall_cphs_csp_get_status(VC_CPHS_CSP_HOLD) == FALSE) {
364                         CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_svcall_cphs_csp_get_status : Hold is not possible");
365                         return FALSE;
366                 }
367 #endif                          /* */
368                 /* Mo is impossile when member is more than max */
369                 if (member_num >= (VC_MAX_CALL_GROUP_MEMBER + 1)) {
370                         CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_ca_is_mocall_possible: ended with FALSE ..");
371                         return FALSE;
372                 }
373
374                 else {
375                         CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_ca_is_mocall_possible: ended with TRUE ..");
376                         return TRUE;
377                 }
378         }
379         return FALSE;
380 }
381
382 /**
383  * This function ends all the active calls
384  *
385  * @return              Returns TRUE on success and FALSE on failure
386  * @param[in]   pagent  Handle to voicecall engine
387  */
388 gboolean _vc_core_ca_end_active_calls(call_vc_callagent_state_t *pagent)
389 {
390         gboolean result = FALSE;
391         VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
392         if (TRUE == _vc_core_cm_isexists_active_call(&pagent->call_manager)) {
393                 result = _vc_core_tapi_rqst_release_active_calls(pagent);
394                 if (TRUE == result) {
395                         _vc_core_ca_change_agent_state(pagent, CALL_VC_CA_STATE_WAIT_RELEASE_ALL_ACTIVECALL);
396                 }
397         }
398         return result;
399 }
400
401 /**
402  * This function ends all the calls
403  *
404  * @return              Returns TRUE on success and FALSE on failure
405  * @param[in]   pagent  Handle to voicecall engine
406  */
407 gboolean _vc_core_ca_end_all_calls(call_vc_callagent_state_t *pagent)
408 {
409         gboolean result = FALSE;
410         VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
411         result = _vc_core_tapi_rqst_release_all_calls(pagent);
412         if (TRUE == result) {
413                 _vc_core_ca_change_agent_state(pagent, CALL_VC_CA_STATE_WAIT_RELEASE_ALL_CALLS);
414         }
415         return result;
416 }
417
418 /**
419  * This function ends all the held calls
420  *
421  * @return              Returns TRUE on success and FALSE on failure
422  * @param[in]   pagent        Handle to voicecall engine
423  */
424 gboolean _vc_core_ca_end_held_calls(call_vc_callagent_state_t *pagent)
425 {
426         gboolean result = FALSE;
427         VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
428         if (TRUE == _vc_core_cm_isexists_held_call(&pagent->call_manager)) {
429                 result = _vc_core_tapi_rqst_release_held_calls(pagent);
430                 if (TRUE == result) {
431                         _vc_core_ca_change_agent_state(pagent, CALL_VC_CA_STATE_WAIT_RELEASE_ALL_HOLDCALL);
432                 }
433         }
434         return result;
435 }
436
437 /**
438  * This function checks whether private call is possible or not
439  *
440  * @return              This function returns TRUE if private is possible or else FALSE
441  * @param[in]           pcall_agent                     Pointer to the call agent structure
442  */
443 gboolean _vc_core_ca_is_private_call_possible(call_vc_callagent_state_t *pcall_agent)
444 {
445         gboolean active_calls = FALSE, held_calls = FALSE;
446         int active_call_member = 0;
447         _vc_core_cm_isexists_call_ingroup(&pcall_agent->call_manager, &active_calls, &held_calls);
448         active_call_member = _vc_core_cm_get_active_call_count(&pcall_agent->call_manager);
449         if (TRUE == active_calls && FALSE == held_calls) {
450                 if (active_call_member > 1) {
451                         return TRUE;
452                 }
453         }
454         return FALSE;
455 }
456
457 /**
458  * This function checks whether call transfer is possible
459  *
460  * @return              This function returns TRUE if transfer is possible or else FALSE
461  * @param[in]           pcall_agent                     Pointer to the call agent structure
462  */
463 gboolean _vc_core_ca_is_transfer_call_possible(call_vc_callagent_state_t *pcall_agent)
464 {
465         gboolean active_calls = FALSE;
466         gboolean held_calls = FALSE;
467         int total_call_member = 0;
468
469 #ifdef _CPHS_DEFINED_
470         if (FALSE == _vc_core_svcall_cphs_csp_get_status(pcall_agent, VC_CPHS_CSP_CT)) {
471                 return FALSE;
472         }
473 #endif                          /* */
474         _vc_core_cm_isexists_call_ingroup(&pcall_agent->call_manager, &active_calls, &held_calls);
475         total_call_member = _vc_core_cm_get_call_member_count(&pcall_agent->call_manager);
476
477         /* The Explicit Call Transfer (ECT) function should be invoked in association with two existing calls which 1) one is answered and in the held state and 2) the other is answered and active or alerting. */
478         if (3 == total_call_member) {
479                 if ((TRUE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX != pcall_agent->call_manager.mtcall_index)) {
480                         CALL_ENG_DEBUG(ENG_DEBUG, "Transfer possible..1 active, 1 held, 1 waiting..");
481                         return TRUE;
482                 }
483         }
484
485         else if (2 == total_call_member) {
486                 if ((TRUE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX == pcall_agent->call_manager.mtcall_index)) {
487                         return TRUE;
488                 }
489
490                 else if ((FALSE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX != pcall_agent->call_manager.mtcall_index)) {
491                         return TRUE;
492                 }
493
494                 else if ((FALSE == active_calls) && (TRUE == held_calls) && (-1 != pcall_agent->call_manager.setupcall_info.mocall_index)       /*Outgoing call exists */
495                          && (VC_INOUT_STATE_OUTGOING_WAIT_CONNECTED == pcall_agent->io_state)) {
496                         return TRUE;
497                 }
498         }
499         return FALSE;
500 }
501
502 /**
503  * This function checks whether conference call is possible
504  *
505  * @return              This function returns TRUE if transfer is possible or else FALSE
506  * @param[in]   pcall_agent                     Pointer to the call agent structure
507  */
508 gboolean _vc_core_ca_is_conf_call_possible(call_vc_callagent_state_t *pcall_agent)
509 {
510         gboolean active_calls = FALSE;
511         gboolean held_calls = FALSE;
512         int total_call_member = 0;
513
514 #ifdef _CPHS_DEFINED_
515         if (FALSE == _vc_core_svcall_cphs_csp_get_status(pcall_agent, VC_CPHS_CSP_MPTY)) {
516                 return FALSE;
517         }
518 #endif                          /* */
519         _vc_core_cm_isexists_call_ingroup(&pcall_agent->call_manager, &active_calls, &held_calls);
520         total_call_member = _vc_core_cm_get_call_member_count(&pcall_agent->call_manager);
521
522         /* Joining call is impossile when active or hold call doesn't exist */
523         if ((FALSE == active_calls) || (FALSE == held_calls)) {
524                 CALL_ENG_DEBUG(ENG_DEBUG, "Join Impossible...");
525                 return FALSE;
526         }
527
528         else {
529
530                 /*Joining call is impossile when member is more than max
531                  * if ( total_call_member >= (CALL_VC_CALL_GROUP_MEMBER_MAX + 1)) : Max Number in Group + Another Call*/
532                 if (total_call_member > VC_MAX_CALL_GROUP_MEMBER) {     /*Logic Changed from above line for same condition */
533                         CALL_ENG_DEBUG(ENG_DEBUG, "Ended with FALSE...");
534                         return FALSE;
535                 }
536
537                 else {
538                         CALL_ENG_DEBUG(ENG_DEBUG, "Ended with TRUE...");
539                         return TRUE;
540                 }
541         }
542         return FALSE;
543 }
544
545 /**
546  * This function clears the data of a connected call givenits call handle
547  *
548  * @return              Returns TRUE on success and FALSE on failure
549  * @param[in]   pcall_agent     Handle to voicecall engine
550  * @param[in]   call_handle     Call handle of the connected call to be cleared
551  */
552 gboolean _vc_core_ca_clear_connected_call(call_vc_callagent_state_t *pcall_agent, int call_handle)
553 {
554         call_vc_call_objectinfo_t call_object;
555         gboolean remove = FALSE;
556         int group_index = -1;
557         int grp_mem_num = 0;
558         int i = 0;
559         VOICECALL_RETURN_FALSE_IF_FAIL(pcall_agent != NULL);
560         VOICECALL_RETURN_FALSE_IF_FAIL(call_handle >= 0);
561         CALL_ENG_DEBUG(ENG_DEBUG, "..");
562         _vc_core_cm_get_call_object(&pcall_agent->call_manager, call_handle, &call_object);
563         group_index = _vc_core_cm_get_group_index(&pcall_agent->call_manager, (call_vc_handle) call_handle);
564         if (group_index == -1) {
565                 CALL_ENG_DEBUG(ENG_DEBUG, "ERROR: Not exist");
566                 return FALSE;
567         }
568         grp_mem_num = _vc_core_cm_get_member_count_ingroup(&pcall_agent->call_manager, group_index);
569         for (i = 0; i < grp_mem_num; i++) {
570                 if ((_vc_core_cm_get_call_state_ingroup_byposition(&pcall_agent->call_manager, group_index, i) != VC_CALL_STATE_ENDED) && (_vc_core_cm_get_call_state_ingroup_byposition(&pcall_agent->call_manager, group_index, i) != VC_CALL_STATE_ENDED_FINISH)) {
571                         remove = TRUE;
572                 }
573         }
574         if (remove) {
575                 _vc_core_cm_remove_call_object(&pcall_agent->call_manager, call_handle);
576         }
577
578         else {
579                 gboolean clear_end_call = TRUE;
580                 _vc_core_cm_change_call_state(&call_object, VC_CALL_STATE_ENDED_FINISH);
581                 _vc_core_cm_set_call_object(&pcall_agent->call_manager, &call_object);
582                 for (i = 0; i < grp_mem_num; i++) {
583                         if (_vc_core_cm_get_call_state_ingroup_byposition(&pcall_agent->call_manager, group_index, i) != VC_CALL_STATE_ENDED_FINISH)
584                                 clear_end_call = FALSE;
585                 }
586                 if (clear_end_call) {
587                         _vc_core_cm_clear_endcall_member(&pcall_agent->call_manager);
588                 }
589         }
590         return TRUE;
591 }