📄 callctrl.cpp
字号:
if (true == bSaveDataInGlobals)
{
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_DESCRIPTION;
StringCchCopyNW(g_rgfCallStates[nCid].wszDescription, MAXLENGTH_DESCRIPTION, rgrci[nUsed].wszDescription, MAXLENGTH_DESCRIPTION-1);
}
}
}
// do external calltype progessing for this call
if (g_rfExternalCalltypeDetermination)
{
// get the calltype and associate it with the call id
SetCalltypeFromCallInfo(&rgrci[nUsed]);
}
// Increment the array index
nUsed++;
Continue:
// Find "<postfix>"
bSuccess = ParseRspPostfix(szRsp, szRsp);
if (!bSuccess)
{
hr = E_FAIL;
goto Error;
}
}
if (true == bSaveDataInGlobals)
{
g_dwNumCallsInCallList = nUsed;
/* Now that we've succeeded parsing the notification, record the new call states. We have already updated all of the
global calls that exist in the CLCC. Calls absent from the CLCC, but still remaining in the global call state list can
be considered disconnected. We need to go through the global call list and find stale calls. Stale calls should be
marked as disconnected.
*/
#ifdef DEBUG
DebugDisplayGlobalCallList();
DebugDisplayCLCC(rgrci, g_dwNumCallsInCallList);
#endif
for (uint GlobalCallStateIndex = 1 /* first valid call ID */; GlobalCallStateIndex < RIL_MAX_TRACKED_CALL_ID; GlobalCallStateIndex++ )
{
if (g_rgfCallStates[GlobalCallStateIndex].dwID) // Valid Call ID
{
BOOL fDisconnect = TRUE;
for(uint rgrciIndex = 0 /*response structure begins at 0*/; rgrciIndex < g_dwNumCallsInCallList; rgrciIndex++)
{
if (g_rgfCallStates[GlobalCallStateIndex].dwID == rgrci[rgrciIndex].dwID) // The call is still valid
{
fDisconnect = FALSE;
break;
}
}
/*
If we have a call in the global list that is not in the new CLCC list, we can assume that it has been disconnected.
Don't remove the entry from the global list because it will need to be reported. Mark the entry as disconnected.
*/
if ( TRUE == fDisconnect )
{
g_rgfCallStates[GlobalCallStateIndex].dwStatus = RIL_CPISTAT_DISCONNECTED;
g_rgfCallStates[GlobalCallStateIndex].dwDisconnectCode = RIL_RESULT_CALLABORTED;
g_rgfCallStates[GlobalCallStateIndex].dwParams = RIL_PARAM_CI_ID | RIL_PARAM_CI_CPISTATUS | RIL_PARAM_CI_DISCONNECTCODE;
}
}
}
#ifdef DEBUG
DebugDisplayGlobalCallList();
#endif
}
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : ParseGetCallList : sizeof(rgfNewCallsInProgress) = %d \r\n"), sizeof(rgfNewCallsInProgress)));
// clean up externally determined calltypes, if necessary
if (g_rfExternalCalltypeDetermination)
{
UINT uiRilCall = 0;
while(uiRilCall < RIL_MAX_TRACKED_CALL_ID)
{
if (FALSE == rgfNewCallsInProgress[uiRilCall])
{
// no current call with this id, make sure that the calltype tracking data is erased
g_rgfCalltypeChecked[uiRilCall] = FALSE;
g_rgctCalltype[uiRilCall] = RIL_CALLTYPE_UNKNOWN;
// Was this a ringing call?
EnterCriticalSection(&g_csRingingCallData);
if ((TRUE == g_rcdRingingCallData.fCallIdValid) && (uiRilCall == g_rcdRingingCallData.dwCallId))
{
g_rcdRingingCallData.fCallIdValid = FALSE;
g_rcdRingingCallData.dwCallId = RIL_MAX_TRACKED_CALL_ID;
g_rcdRingingCallData.dwCalltype = RIL_CALLTYPE_UNKNOWN;
g_rcdRingingCallData.fCalltypeValid = FALSE;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : ParseGetCallList : Ringing Call TypeValid = %d, type = %d, IdValid = %d, Id = %d, \r\n"),
g_rcdRingingCallData.fCalltypeValid, g_rcdRingingCallData.dwCalltype,g_rcdRingingCallData.fCallIdValid,g_rcdRingingCallData.dwCallId));
}
LeaveCriticalSection(&g_csRingingCallData);
}
uiRilCall++;
}
}
SetBacklightIncomingCall(bIncomingCall);
pBlob = (void*)rgrci;
cbBlob = nUsed * sizeof(RILCALLINFO);
Error:
if( nUsed == 0 )
{
// Indicate call is inactive to audio driver
IndicateCallActivityToAudioSubsystem(FALSE, FALSE);
}
if (FAILED(hr)) {
FreeBlob(rgrci);
}
return hr;
}
HRESULT PreParseGetCallList(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
HRESULT hReturnValue;
FUNCTION_TRACE(PreParseGetCallList);
DEBUGMSG(ZONE_INFO, (TEXT("PreParseGetCallList : i : \r\n")));
EnterCriticalSection(&g_csCallStates);
hReturnValue = LocalParseGetCallList (true, szRsp, pBlob, cbBlob);
SendCallListChangedNotification ();
LeaveCriticalSection(&g_csCallStates);
return (hReturnValue);
}
HRESULT ParseGetCallList(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
FUNCTION_TRACE(ParseGetCallList);
return (LocalParseGetCallList (false, szRsp, pBlob, cbBlob));
}
BOOL SetupCallListEvaluation (void)
{
FUNCTION_TRACE(SetupCallListEvaluation);
DEBUGMSG(ZONE_INFO, (TEXT("SetupCallListEvaluation : i \r\n")));
return (QueueCmdIgnoreRsp(APIID_GETCALLLIST, "AT+CLCC\r", CMDOPT_NONE /* CMDOPT_IGNORERSP */, g_TimeoutCmdInit, (PFN_CMD_PARSE) PreParseGetCallList, NULL, 0, 0, 0));
}
//
//
//
HRESULT RILDrv_ManageCalls(DWORD dwParam, DWORD dwCommand, DWORD dwID)
{
FUNCTION_TRACE(RILDrv_ManageCalls);
char szCmd[MAX_PATH];
DWORD dwOpt = CMDOPT_NONE;
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
switch (dwCommand)
{
case RIL_CALLCMD_RELEASEHELD:
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_ReleaseHeld( szCmd, MAX_PATH ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_ReleaseHeld failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
dwOpt |= CMDOPT_HANGUP; // Necessary when attempting to end a single outgoing call
break;
case RIL_CALLCMD_RELEASEACTIVE_ACCEPTHELD:
(void)strncpyz(szCmd, "AT+CHLD=1\r", MAX_PATH);
break;
case RIL_CALLCMD_RELEASECALL:
if (dwID==0)
{
// Id of 0 is a magic value which says to release a call being dialed while
// another call is on hold.
// This activates code in HangupThreadProc to force it to send AT\r to the modem
// to try to abort a call being dialed.
// We don't need to send a command to the modem because
// HangupThreadProc's AT\r will cancel the dial.
(void)strncpyz(szCmd, "AT\r", MAX_PATH);
dwOpt = CMDOPT_HANGUP | CMDOPT_NOOP;
}
else if (9 == dwID)
{
// This is a special-case to enable us to pass FTA case GSM 51.010 31.4.4.2 which requires
// a way to end all calls in one operation (i.e., "19<SEND>")
(void)strncpyz(szCmd, "ATH\r", MAX_PATH);
}
else if (8 == dwID)
{
// This is a special-case to enable us to pass FTA case GSM 51.010 31.4.4.1.2.4 which requires
// a way to end a held conference call in one operation (i.e., "18<SEND>")
(void)strncpyz(szCmd, "at+chld=11\rAT\rat+chld=12\r", MAX_PATH);
}
else
{
if ((0 <= dwID) && (dwID < ARRAY_LENGTH(g_rgfCallStates)) && (g_rgfCallStates[dwID].dwParams & RIL_PARAM_CI_CPISTATUS) && \
(RIL_CPISTAT_DISCONNECTED != g_rgfCallStates[dwID].dwStatus) && (RIL_CPISTAT_UNKNOWN!= g_rgfCallStates[dwID].dwStatus))
{
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_ReleaseCall( szCmd, MAX_PATH, dwID ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_ReleaseCall failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
}
else
{
// Special case for FTA case GSM 51.010 31.9.1.1.16 which requires us to send the command as USSD
// if there isn't an active call associated with this ID
(void)_snprintfz(szCmd, MAX_PATH, "AT+CUSD=1,\"1%u\",15\r", dwID);
dwOpt |= CMDOPT_SUPPRESSLOGGING;
}
}
break;
case RIL_CALLCMD_HOLDACTIVE_ACCEPTHELD:
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_HoldActiveAcceptHeld( szCmd, MAX_PATH ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_HoldActiveAcceptHeld failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
break;
case RIL_CALLCMD_HOLDALLBUTONE:
if ((0 <= dwID) && (dwID < ARRAY_LENGTH(g_rgfCallStates)) && (g_rgfCallStates[dwID].dwParams & RIL_PARAM_CI_CPISTATUS) && \
(RIL_CPISTAT_DISCONNECTED != g_rgfCallStates[dwID].dwStatus) && (RIL_CPISTAT_UNKNOWN!= g_rgfCallStates[dwID].dwStatus))
{
(void)_snprintfz(szCmd, MAX_PATH, "AT+CHLD=2%u\r", dwID);
}
else
{
// Special case for FTA case GSM 51.010 31.9.1.1.16 which requires us to send the command as USSD
// if there isn't an active call associated with this ID
dwOpt |= CMDOPT_SUPPRESSLOGGING;
(void)_snprintfz(szCmd, MAX_PATH, "AT+CUSD=1,\"2%u\",15\r", dwID);
}
break;
case RIL_CALLCMD_ADDHELDTOCONF:
(void)strncpyz(szCmd, "AT+CHLD=3\r", MAX_PATH);
break;
case RIL_CALLCMD_ADDHELDTOCONF_DISCONNECT:
(void)strncpyz(szCmd, "AT+CHLD=4\r", MAX_PATH);
break;
case RIL_CALLCMD_INVOKECCBS:
(void)strncpyz(szCmd, "AT+CHLD=5\r", MAX_PATH);
break;
default:
// The proxy code should never let us get here
DEBUGCHK(FALSE);
}
if (!QueueCmd(pHandle, szCmd, dwOpt, APIID_MANAGECALLS, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
// Since the manage calls command has been queued, we need to now send the message to check the call list
// to handle the changes that the manage calls command made.
SetupCallListEvaluation ();
Error:
return hr;
}
//
//
//
HRESULT RILDrv_TransferCall(DWORD dwParam, const RILADDRESS* lpAddress, const RILSUBADDRESS* lpSubAddress)
{
FUNCTION_TRACE(RILDrv_TransferCall);
BYTE bTypeOfAddress;
BYTE bType;
char szAddress[MAXLENGTH_ADDRESS];
char szSubAddress[MAXLENGTH_SUBADDR];
char szCmd[CALLCTRL_CMDBUF_LENGTH];
LPSTR szWalk = szCmd;
HRESULT hrSubAddress;
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle || !lpAddress) {
hr = E_FAIL;
goto Error;
}
// Determine address and type-of-address byte
hr = RILAddressToString(*lpAddress, szAddress, MAXLENGTH_ADDRESS, bTypeOfAddress);
if (FAILED(hr)) {
goto Error;
}
(void)_snprintfz(szWalk, CALLCTRL_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CTFR=\"%s\",%u", szAddress, bTypeOfAddress);
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
if (lpSubAddress) {
hrSubAddress = RILSubAddressToString(*lpSubAddress, szSubAddress, MAXLENGTH_SUBADDR, bType);
if (SUCCEEDED(hrSubAddress)) {
(void)_snprintfz(szWalk, CALLCTRL_CMDBUF_LENGTH - (szWalk - szCmd), ",\"%s\",%u", szSubAddress, bType);
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
}
}
(void)strncpyz(szWalk, "\r", CALLCTRL_CMDBUF_LENGTH - (szWalk - szCmd)); // NO_TYPO: 30
if (!QueueCmd(pHandle, szCmd, CMDOPT_NONE, APIID_TRANSFERCALL, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_SetCurrentAddressId(DWORD dwParam, DWORD dwAddressId)
{
FUNCTION_TRACE(RILDrv_SetCurrentAddressId);
HRESULT hr = S_OK;
char szCmd[MAX_PATH];
CNotificationData* pnd = NULL;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
pnd = new CNotificationData;
if (pnd && !pnd->InitFromDWORDBlob(RIL_NOTIFY_CURRENTLINECHANGED, dwAddressId)) {
delete pnd;
pnd = NULL;
}
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_SetCurrentAddressId( szCmd, MAX_PATH, dwAddressId ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_SetCurrentAddressId failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
if (!QueueCmd(pHandle, szCmd, CMDOPT_NONE, APIID_SETCURRENTADDRESSID, NULL, pnd, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_GetCurrentAddressId(DWORD dwParam)
{
FUNCTION_TRACE(RILDrv_GetCurrentAddressId);
HRESULT hr = S_OK;
char szCmd[MAX_PATH];
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_GetCurrentAddressId( szCmd, MAX_PATH ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_GetCurrentAddressId failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
if (!QueueCmd(pHandle, szCmd, CMDOPT_NONE, APIID_GETCURRENTADDRESSID, g_rppPDDParams->pfnParseGetCurrentAddressId, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -