【结束单线】,存在于2种情况中:
1.没有发生呼叫等待的情况。包括:
(1)1通ACTIVE CALL + 1通HOLD CALL
(2)N通ACTIVE CALL(电话会议)
(3)1通HOLD CALL + N通ACTIVE CALL
这种情况处理是挂断当前高亮的那通电话,不论是ACTIVE CALL还是HOLD CALL。
2.发生呼叫等待时
(1)N通ACTIVE CALL(电话会议)
(2)1通HOLD CALL + N通ACTIVE CALL
这种情况下,是挂断ACTIVE CALL。具体操作是先列出一个电话列表,只包括所有的 ACTIVE CALL,让用户选择其中要结束的一个,然后再挂断它。
也就是说,在获取挂断电话的handle时,处理不一样。后面就一样了。
代码的详细处理如下:
1.没有发生呼叫等待的情况。
void HangupHilited(void)
{
temp = GetCallHandle(gcallList[gHilitedCall]); 获取要挂断的电话的handle。gHilitedCall是当前高亮电话的索引,gcallList[]里是电话的pName,如果没有姓名则是number。
HangupCall(temp);
}
void HangupCall(CM_CALL_HANDLE CallHandle)
{
OutgoingProcessCMEvent(CM_KB_HANGUPREQ, &CallHandle);
}
ACTION_RESULT ProcessKBHangupReqEvent(void *MsgStruct)
//参数是要挂断的电话的handle。
//在挂断一通OUTGOING CALL时,也是进入这个函数进行处理的。
{
if (GetInternalAlert() == TRUE)
{
StopInternalOutgoingTone();
}
handle = *((CM_CALL_HANDLE*) MsgStruct);
state = GetCallState(handle);
switch (GetCurrentState()) //根据状态机的当前状态来作不同处理
{
case CM_IDLE_STATE:
break;
case CM_OUTGOING_STATE: 此时,CM处于OUTGOING状态
if (state == CM_ACTIVE_STATE
|| state == CM_HOLD_STATE
|| state == CM_INCOMING_STATE)
{
SetCallState(handle, CM_DISCONNECTING_STATE, TRUE);
MakePsEndSelectiveCall((void*)HangupReqSucess, handle);
}
else if ((GetDialIndication() == FALSE) || //挂断的就是这个呼出的
(GetOutgoingCallType() == CM_CSD_CALL)) //电话了。但是此时还没有
{ //设置call handle
SetCallAbortReqSentFlag(TRUE); //gCallAbortReqSentFlag=1
handle = GetOutgoingCallHandle();
SetCallState(handle, CM_DISCONNECTING_STATE, TRUE);
MakePsAthRequest((void*)PsCBackOutgoingCallEnded);
}
else
{
SetCallState(handle, CM_DISCONNECTING_STATE, TRUE);
MakePsEndSelectiveCall((void*)HangupReqSucess, handle);
}
break;
case CM_INCOMING_STATE:
SetCallflag(handle, CM_HANGUP_REQUESTED, TRUE);
MakePsEndSelectiveCall((void*)HangupReqSucess, handle);
break;
case CM_ACTIVE_STATE:
case CM_HOLD_STATE:
SetCallflag(handle, CM_HANGUP_REQUESTED, TRUE);
SetCallState(handle, CM_DISCONNECTING_STATE, TRUE);
MakePsEndSelectiveCall((void*)HangupReqSucess, handle);
break;
}
}
两个回调函数:PsCBackOutgoingCallEnded()和HangupReqSucess(),最后都是进入状态机处理:OutgoingProcessCMEvent(CM_PS_HANGUPSUC, (void*)&handle),然后进入:ProcessPSHangupSucEvent()。在上面“放弃OUTGOING CALL”中已经描述过了。
2.发生呼叫等待时
void EndSingleActiveAndGoBack(void)
{
gcallListlen = GetAllActDispNameorNum(gcallList);获取所有ACTIVE CALL姓名或号码
gListOperation = 1; 用来控制后面的操作
EntryScr1009CallListScreen();
}
这个函数:显示变量gcallList中的电话的姓名或者号码。gcallList包含的列表可能是所有ACTIVE CALLs,也可能是所有的HOLD CALLs。
然后,再根据变量gListOperation来设置左软件的处理函数。
gListOperation=1,左软件操作是:HANGUP request
gListOperation=0,左软件操作是:SPLIT request。
void EntryScr1009CallListScreen(void)
{
RegisterHighlightHandler(SetCurrHiliteCall); 获取高亮的电话索引,设置gHilitedCall
ShowCategory6Screen(
STR_SCR1009_CAPTION,
IMG_SCR1009_CAPTION,
STR_GLOBAL_OK,
IMG_GLOBAL_OK,
STR_GLOBAL_BACK,
IMG_GLOBAL_BACK,
gcallListlen,
gcallList,
NULL,
0,
guiBuffer);
根据变量gListOperation来设置左软件的处理函数。
if (gListOperation == 1)
{
SetLeftSoftkeyFunction(HangupHilited, KEY_EVENT_UP);
}
else if (gListOperation == 2)
{
SetLeftSoftkeyFunction(SplitHilited, KEY_EVENT_UP);
}
}
这里是【结束单线】,因此就进入HangupHilited( ),结束高亮的电话,与1中的处理相同。
【分机】菜单:存在于只有N通ACTIVE电话的情况(无论是否有呼叫等待发生)
void HiliteM2018Split(void)
{
ClearKeyHandler(KEY_RIGHT_ARROW, KEY_EVENT_DOWN);
ChangeLeftSoftkey(STR_GLOBAL_OK, IMG_SCR1003_LSK);
#ifdef __GPRS_MODE__
SetLeftSoftkeyFunction(SplitHilited, KEY_EVENT_UP);
#else
SetLeftSoftkeyFunction(SplitAndGoBack, KEY_EVENT_UP);
#endif
SetRightSoftkeyFunction(GoBackHistory, KEY_EVENT_UP);
}
第二种情况:#ifdef __GPRS_MODE__不成立
void SplitAndGoBack(void) 这里的处理与【结束单线】中唯一不同是gListOperation = 2
{
gcallListlen = GetAllActDispNameorNum(gcallList);
if (gcallListlen != GetTotalActiveCallCount())
{
PRINT_INFORMATION(("\nFatal Error in CM Call Structure 4\n"));
}
gListOperation = 2; 表示这是用来SPLIT一个ACTIVE CALL
EntryScr1009CallListScreen();
}
void EntryScr1009CallListScreen(void)
{
U8 *guiBuffer;
RegisterHighlightHandler(SetCurrHiliteCall);设置变量gHilitedCall,获取call_handle.
ShowCategory6Screen(
STR_SCR1009_CAPTION,
IMG_SCR1009_CAPTION,
STR_GLOBAL_OK,
IMG_GLOBAL_OK,
STR_GLOBAL_BACK,
IMG_GLOBAL_BACK,
gcallListlen,
gcallList,
NULL,
0,
guiBuffer);
if (gListOperation == 1)
{
SetLeftSoftkeyFunction(HangupHilited, KEY_EVENT_UP);
}
else if (gListOperation == 2)
{
SetLeftSoftkeyFunction(SplitHilited, KEY_EVENT_UP);
}
SetKeyHandler(GoBackHistory, KEY_LEFT_ARROW, KEY_EVENT_DOWN);
SetRightSoftkeyFunction(GoBackHistory, KEY_EVENT_UP);
}
此时,左软件处理函数是SplitHilited()。进入下面的“第一种情况:#ifdef __GPRS_MODE__成立”。
第一种情况:#ifdef __GPRS_MODE__成立
void SplitHilited(void)
{
CM_CALL_HANDLE temp;
temp = GetCallHandle(gcallList[gHilitedCall]); 直接获取当前高亮的电话handle
SplitCall(temp);
}
void SplitCall(CM_CALL_HANDLE CallHandle)
{
OutgoingProcessCMEvent(CM_KB_SPLITREQ, &CallHandle);
}
ACTION_RESULT ProcessKBSplitReqEvent(void *MsgStruct)
{
switch(CM当前状态)
{
case CM_INCOMING_STATE: 呼叫等待时分机
if (GetTotalActiveCallCount() >= 2)
{
SetCallflag(callIndex, CM_SPLIT_REQUESTED, TRUE);只设置那个SPLIT的CALL的status_flag。其他的将要被HOLD的CALL不用管它们。
MakePsSplitRequest(callIndex);
}
else
{
PRINT_INFORMATION(("\n Not enuf calls to make a split request \n"));
}
break;
case CM_ACTIVE_STATE: 没有呼叫等待时分机
if (GetTotalActiveCallCount() >= 2)
{
SetCallflag(callIndex, CM_SPLIT_REQUESTED, TRUE);
MakePsSplitRequest(callIndex);
}
else
{
PRINT_INFORMATION(("\n Not enuf calls to make a split request \n"));
}
break;
}
}
void MakePsSplitRequest(CM_CALL_HANDLE nCallHandle)
{
ClearInputEventHandler(MMI_DEVICE_ALL);
发送到L4的消息是:PRT_SPLITCALL_EVENT;
消息的opnode: CSMCC_HOLD_ACTIVE_EXCEPT_SPECIFIC_CALL
SetProtocolEventHandler(SplitReqSucess, PRT_END_CHLD_RSP);
}
L4返回消息:PRT_END_CHLD_RSP.进入CBACK函数:
void SplitReqSucess(void *MsgStruct)
{
OutgoingProcessCMEvent(CM_PS_SPLITSUC, (void*)MsgStruct);
}
ACTION_RESULT ProcessPSSplitSucEvent(void *MsgStruct)
{
MakeSplitSucess(); 清除SPLIT CALL的status_flag标志。其他将要被HOLD的 ACTIVE CALL,直接设置他们的当前状态为CM_HOLD_STATE。
EntryScr1010NotifySplitSucess();
}
void EntryScr1010NotifySplitSucess(void)
{
EntryScrNotifyCHLDSucess(STR_NFY_CALL_SPLIT, FALSE); 显示提示信息
}
结束所有的ACTIVE CALLs。存在2种情况:
1.没有发生呼叫等待时的:
1通HOLD CALL,N通ACTIVE CALL时,【结束所有启用】菜单
N通HOLD CALL,1通ACTIVE CALL时,【激活结束】菜单
2.发生呼叫等待时的:
只有一通ACTIVE CALL,【结束】菜单
一通ACTIVE CALL,一通HOLD CALL时,【结束启用】菜单
1通HOLD CALL,N通ACTIVE CALL时,【结束所有启用】
N通HOLD CALL,1通ACTIVE CALL时,【结束启用】菜单
void HangupallActive(void)
{
OutgoingProcessCMEvent(CM_KB_HANGUPALLACTREQ, (void*)NULL);
}
ACTION_RESULT ProcessKBHangupallActReqEvent(void *MsgStruct)
{
switch(GetCurrentState()) CM的当前状态只可能是:INCOMING或者ACTIVE
{
case CM_INCOMING_STATE:
SetAllActHangupFlag(); 对当前所有的ACTIVE CALLs,设置其标志 status_flag=CM_HANGUP_REQUESTED。
MakePsHangupallActiveRequest((void*)HangupallActReqSucess);
break;
case CM_ACTIVE_STATE:
SetAllActHangupFlag();
SetAllActiveCallState(CM_DISCONNECTING_STATE);
MakePsHangupallActiveRequest((void*)HangupallActReqSucess);
break;
}
}
void MakePsHangupallActiveRequest(void *callBack)
{
ClearInputEventHandler(MMI_DEVICE_ALL);
SetChldReqSent(CM_HANGUPALLACTIVE_REQ_SENT);设置gChldReqSent
发送到L4的消息是:PRT_ENDALLACTIVE_EVENT
消息的opnode:CSMCC_REL_ACTIVE
SetProtocolEventHandler((PsFuncPtr) callBack, PRT_ENDALLACTIVEREQ_SUCCESS);
SetProtocolEventHandler((PsFuncPtr) CBackHangupAllActive, PRT_END_CHLD_RSP);
这里为什么要设置2个CBACK函数?难道这2个消息L4都要返回?YES!
}
void HangupallActReqSucess(void *MsgStruct)
{
gMyhandle = DeriveCallHandle(MsgStruct);
OutgoingProcessCMEvent(CM_PS_HANGUPALLACTSUC, (void*)&gMyhandle);
SetProtocolEventHandler(PsCBackNetworkCallDropped, PRT_NWRK_CALL_RELEASE);
}
ACTION_RESULT ProcessPSHangupallActSucEvent(void *MsgStruct)
{
LogCallInfoForCallHistory(*handle);
GetEndTimeAndNotifyEndCallDuration(*handle);
SetCallState(*handle, CM_IDLE_STATE, TRUE);
此时,仅仅是挂断了第一通ACTIVE CALL。如果没有其他的ACTIVE CALL了,就继续往下执行,即设置CM状态;如果还有其他的ACTIVE CALL,那么这里就return。
switch (GetCurrentState()) 只可能为INCOMING或者ACTIVE状态
{
MakeAllActHangup();
设置CM的状态
}
}
总结:与结束所有的电话一样,结束所有的ACTIVE CALLs时,注册的CBACK函数仅仅处理第一通ACTIVE CALL的挂断过程,其他ACTIVE CALL都是由网络挂断的。
当所有的ACTIVE CALL都被挂断之后,L4要返回消息:PRT_END_CHLD_RSP,进入:
void CBackHangupAllActive(void)
{
SetChldReqSent(CM_ACTION_NONE); 设置gChldReqSent
if ((GetCurrentState() != CM_INCOMING_STATE) && !(holdCall >= 1))
{
GetOutOfCMApplication();
return;
}
else if (holdCall >= 1)
{
return;
}
}