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