2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
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"
25 /* For Debug Information, Inout state name string constant */
26 char *gszcall_vc_inout_state[VC_INOUT_STATE_MAX_NUM] = {
31 "OUTGOING_WAIT_ALERT",
32 "OUTGOING_WAIT_CONNECTED",
33 "OUTGOING_WAIT_RELEASE",
35 "OUTGOING_SHOW_REDIALCAUSE",
36 "OUTGOING_WAIT_REDIAL",
37 "OUTGOING_SHOW_RETRY_CALLBOX",
39 "INCOME_SELFEVENT_WAIT",
42 "INCOME_WAIT_REDIRECTCNF",
43 "INCOME_WAIT_REDIRECT_END",
44 "INCOME_WAIT_CONNECTED",
45 "INCOME_WAIT_HOLD_CONNECTED",
46 "INCOME_WAIT_RELEASE_ACTIVE_CONNECTED",
48 "INCOME_WAIT_RELEASE_ACTIVECALL",
49 "INCOME_WAIT_RELEASE_HOLDCALL",
50 "INCOME_WAIT_RELEASE",
54 /* For Debug Information, Call Agent State name string constant */
55 char *gszcall_vc_ca_state[CALL_VC_CA_STATE_MAX_NUM] = {
57 "CA_STATE_SPLIT_CALLBOX",
58 "CA_STATE_WAIT_SPLIT",
59 "CA_STATE_DROP_CALLBOX",
61 "CA_STATE_WAIT_SWAP_HOLD_OR_ACTIVATE",
62 "CA_STATE_WAIT_SWAP_HOLD",
63 "CA_STATE_WAIT_SWAP_ACTIVATE",
66 "CA_STATE_WAIT_UNHOLD",
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"
82 * This function intializes the call agent
84 * @return Pointer to call agent state.
86 call_vc_callagent_state_t *_vc_core_ca_init_agent()
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");
95 /*Initialize Call Manager */
96 _vc_core_call_manager_init(&pcall_agent->call_manager);
98 /* Initialize Call Agent Flags */
99 _vc_core_ca_init_data(pcall_agent);
101 #ifdef _CCBS_DEFINED_
103 _vc_core_init_ccbs_info(pcall_agent);
107 #ifdef _CPHS_DEFINED_
108 _vc_core_svcall_init_cphs_info(pcall_agent);
114 * This function intializes the callagent data
117 * @param[in] pagent Pointer to the call agent structure
119 void _vc_core_ca_init_data(call_vc_callagent_state_t *pagent)
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;
129 * This function finalizes the call agent
131 * @return Returns void
132 * @param[in] pcall_agent Pointer to the call agent structure
134 void _vc_core_ca_finish_agent(call_vc_callagent_state_t *pcall_agent)
136 if (NULL != pcall_agent) {
143 * This function changes the in out state of the call agent
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
150 gboolean _vc_core_ca_change_inout_state(call_vc_callagent_state_t *pagent, voicecall_inout_state_t new_state)
152 VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
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;
160 * This function changes the in call agent state
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
167 gboolean _vc_core_ca_change_agent_state(call_vc_callagent_state_t *pAgent, call_vc_ca_state_t new_state)
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;
176 * This function checks if all the call members have terminated or not
178 * @return Returns TRUE if no call members exist, FALSE otherwise
179 * @param[in] pAgent Pointer to the call agent structure
181 gboolean _vc_core_ca_check_end(call_vc_callagent_state_t *pAgent)
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");
191 CALL_ENG_DEBUG(ENG_DEBUG, "FALSE");
199 * This function sends the response to the SAT engine
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
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)
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:
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;
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;
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;
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;
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;
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;
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));
275 case SAT_RQST_SEND_DTMF:
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;
282 case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND:
283 sat_engine_ret_dtmf.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
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;
288 case CALL_VC_ME_CLEAR_DOWN_BEFORE_CONN:
289 sat_engine_ret_dtmf.resp = TAPI_SAT_R_USER_CLEAR_DOWN_CALL_BEFORE_CONN;
291 case CALL_VC_ME_RET_SUCCESS:
292 sat_engine_ret_dtmf.resp = TAPI_SAT_R_SUCCESS;
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));
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");
309 CALL_ENG_DEBUG(ENG_DEBUG, "Invalid SAT Rquest Response Type");
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);
320 CALL_ENG_DEBUG(ENG_DEBUG, "tel_send_sat_app_exec_result: Success");
327 * This function checks whether outgoing call is possible
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
333 gboolean _vc_core_ca_is_mocall_possible(call_vc_callagent_state_t *pagent, gboolean bemergency_number)
335 gboolean bactive_call = FALSE;
336 gboolean bheld_call = FALSE;
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);
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..");
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 ..");
359 member_num = _vc_core_cm_get_call_member_count(&pagent->call_manager);
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");
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 ..");
374 CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_ca_is_mocall_possible: ended with TRUE ..");
382 * This function ends all the active calls
384 * @return Returns TRUE on success and FALSE on failure
385 * @param[in] pagent Handle to voicecall engine
387 gboolean _vc_core_ca_end_active_calls(call_vc_callagent_state_t *pagent)
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);
401 * This function ends all the calls
403 * @return Returns TRUE on success and FALSE on failure
404 * @param[in] pagent Handle to voicecall engine
406 gboolean _vc_core_ca_end_all_calls(call_vc_callagent_state_t *pagent)
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);
418 * This function ends all the held calls
420 * @return Returns TRUE on success and FALSE on failure
421 * @param[in] pagent Handle to voicecall engine
423 gboolean _vc_core_ca_end_held_calls(call_vc_callagent_state_t *pagent)
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);
437 * This function checks whether private call is possible or not
439 * @return This function returns TRUE if private is possible or else FALSE
440 * @param[in] pcall_agent Pointer to the call agent structure
442 gboolean _vc_core_ca_is_private_call_possible(call_vc_callagent_state_t *pcall_agent)
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) {
457 * This function checks whether call transfer is possible
459 * @return This function returns TRUE if transfer is possible or else FALSE
460 * @param[in] pcall_agent Pointer to the call agent structure
462 gboolean _vc_core_ca_is_transfer_call_possible(call_vc_callagent_state_t *pcall_agent)
464 gboolean active_calls = FALSE;
465 gboolean held_calls = FALSE;
466 int total_call_member = 0;
468 #ifdef _CPHS_DEFINED_
469 if (FALSE == _vc_core_svcall_cphs_csp_get_status(pcall_agent, VC_CPHS_CSP_CT)) {
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);
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..");
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)) {
489 else if ((FALSE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX != pcall_agent->call_manager.mtcall_index)) {
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)) {
502 * This function checks whether conference call is possible
504 * @return This function returns TRUE if transfer is possible or else FALSE
505 * @param[in] pcall_agent Pointer to the call agent structure
507 gboolean _vc_core_ca_is_conf_call_possible(call_vc_callagent_state_t *pcall_agent)
509 gboolean active_calls = FALSE;
510 gboolean held_calls = FALSE;
511 int total_call_member = 0;
513 #ifdef _CPHS_DEFINED_
514 if (FALSE == _vc_core_svcall_cphs_csp_get_status(pcall_agent, VC_CPHS_CSP_MPTY)) {
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);
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...");
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...");
537 CALL_ENG_DEBUG(ENG_DEBUG, "Ended with TRUE...");
545 * This function clears the data of a connected call givenits call handle
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
551 gboolean _vc_core_ca_clear_connected_call(call_vc_callagent_state_t *pcall_agent, int call_handle)
553 call_vc_call_objectinfo_t call_object;
554 gboolean remove = FALSE;
555 int group_index = -1;
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");
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)) {
574 _vc_core_cm_remove_call_object(&pcall_agent->call_manager, call_handle);
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;
585 if (clear_end_call) {
586 _vc_core_cm_clear_endcall_member(&pcall_agent->call_manager);