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