?? callctrl.cpp
字號:
pnd = NULL;
}
}
if ( RIL_CALLTYPE_VT == g_dwCallType )
{
// Currently VT is not supported.
delete pnd;
pnd = NULL;
hr = E_NOTIMPL;
goto Error;
}
else if (!QueueCmd(pHandle, "ATH\r", CMDOPT_HANGUP, APIID_HANGUP, NULL, pnd, hr)) {
hr = E_FAIL;
goto Error;
}
pnd = NULL;
Error:
return hr;
}
//
//
//
HRESULT RILDrv_SendDTMF(DWORD dwParam, LPCSTR lpszChars, DWORD dwDuration)
{
FUNCTION_TRACE(RILDrv_SendDTMF);
DEBUGCHK(NULL != lpszChars);
DEBUGCHK(0 < strlen(lpszChars));
UINT NumVals;
DWORD dwTimeout;
char szCmd[MAX_PATH];
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle || !lpszChars) {
hr = E_FAIL;
goto Error;
}
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_SendDTMF( szCmd, MAX_PATH, lpszChars, dwDuration, NumVals ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_SendDTMF failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
// Pick a timeout value to use
dwTimeout = (2 * NumVals * dwDuration) + g_TimeoutAPIDefault;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : RILDrv_SendDTMF : Sending DTMF, NumVals=%d, dwDuration=%d, Timeout = %d ms\r\n"), NumVals, dwDuration, dwTimeout));
if (!QueueCmdWithTimeout(pHandle, szCmd, NULL, CMDOPT_SUPPRESSLOGGING, APIID_SENDDTMF, NULL, NULL, hr, dwTimeout,0)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_StartDTMF(DWORD dwParam, CHAR ch)
{
FUNCTION_TRACE(RILDrv_StartDTMF);
char szCmd[MAX_PATH];
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_StartDTMF( szCmd, MAX_PATH, ch ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_StartDTMF failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : RILDrv_StartDTMF : Start DTMF, DTMF = %c\r\n"), ch));
if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_STARTDTMF, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_StopDTMF(DWORD dwParam, CHAR ch)
{
FUNCTION_TRACE(RILDrv_StopDTMF);
char szCmd[MAX_PATH];
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
SAFE_PDD_CREATECOMMAND( szCmd, MAX_PATH, hr, PDD_CreateCommand_StopDTMF( szCmd, MAX_PATH, ch ) );
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : PDD_CreateCommand_StopDTMF failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : RILDrv_StopDTMF : Stop DTMF\r\n")));
if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_STOPDTMF, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
void SendRilCPIMessage ( const RILCALLINFO *prciCallInfo )
{
FUNCTION_TRACE(SendRilCPIMessage);
CNotificationData* pnd = NULL;
if (NULL != g_pRilHandleDevice)
{
// Setup the notification.
pnd = new CNotificationData;
if (pnd)
{
if (pnd->InitFromRealBlob(RIL_NOTIFY_CALLPROGRESSINFO, prciCallInfo, sizeof(RILCALLINFO)))
{
g_pRilHandleDevice->BroadcastNotification(pnd);
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : SendRilCPIMessage : Successful notification sent\r\n")));
}
else
{
delete pnd;
pnd = NULL;
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : SendRilCPIMessage : Unsuccessful notification sent\r\n")));
}
}
}
#ifdef DEBUG
else
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : SendRilCPIMessage : Invalid g_pRilHandleDevice\r\n")));
}
#endif
}
void SendCallListChangedNotification (void)
{
FUNCTION_TRACE(SendCallListChangedNotification);
for (uint GlobalCallStateIndex = 1 /* first valid call ID */; GlobalCallStateIndex < RIL_MAX_TRACKED_CALL_ID; GlobalCallStateIndex++ )
{
if (g_rgfCallStates[GlobalCallStateIndex].dwID) // Valid Call ID
{
SendRilCPIMessage(&g_rgfCallStates[GlobalCallStateIndex]);
// If we sent a disconnect, remove it from the list so we don't keep sending stale DISCONNECTS
if ( RIL_CPISTAT_DISCONNECTED == g_rgfCallStates[GlobalCallStateIndex].dwStatus )
{
g_rgfCallStates[GlobalCallStateIndex].dwID = 0;
g_rgfCallStates[GlobalCallStateIndex].dwStatus = 0;
g_rgfCallStates[GlobalCallStateIndex].dwParams = 0;
}
}
}
}
#ifdef DEBUG
static void DebugDisplayGlobalCallList ( void )
{
for (uint GlobalCallStateIndex = 1 /* first valid call ID */; GlobalCallStateIndex < RIL_MAX_TRACKED_CALL_ID; GlobalCallStateIndex++ )
{
if (g_rgfCallStates[GlobalCallStateIndex].dwID) // Valid Call ID
{
DEBUGMSG(ZONE_ATCMD, (TEXT("RILDrv : i : CALL_LIST : cid = %x, status = %x, params = %x\r\n"), \
g_rgfCallStates[GlobalCallStateIndex].dwID, \
g_rgfCallStates[GlobalCallStateIndex].dwStatus, \
g_rgfCallStates[GlobalCallStateIndex].dwParams));
}
}
}
static void DebugDisplayCLCC ( const RILCALLINFO *prci, DWORD CallInfoSize)
{
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CLCC : CallInfoSize = %d\r\n"), CallInfoSize ));
if ( prci && (CallInfoSize < RIL_MAX_TRACKED_CALL_ID))
{
for(uint CallInfoIndex = 0; CallInfoIndex < CallInfoSize; CallInfoIndex++)
{
DEBUGMSG(ZONE_ATCMD, (TEXT("RILDrv : i : CLCC : cid = %x, status = %x, params = %x\r\n"), \
prci[CallInfoIndex].dwID, \
prci[CallInfoIndex].dwStatus, \
prci[CallInfoIndex].dwParams));
}
}
}
#endif
HRESULT LocalParseGetCallList(bool bSaveDataInGlobals, LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
FUNCTION_TRACE(LocalParseGetCallList);
UINT nValue;
UINT nCid;
UINT nUsed = 0;
UINT nAllocated = 0;
char szAddress[MAXLENGTH_ADDRESS];
RILCALLINFO* rgrci = NULL;
HRESULT hr = S_OK;
BOOL bSuccess;
BOOL bIncomingCall = FALSE;
BOOL rgfNewCallsInProgress[RIL_MAX_TRACKED_CALL_ID] = { 0 }; // Initialize to FALSE
pBlob = NULL;
cbBlob = 0;
// Parse "<prefix>"
if (!ParseRspPrefix(szRsp, szRsp)) {
hr = E_FAIL;
goto Error;
}
/*
Some facts about CLCC parsing:
1. The CLCC request may have been generated from a RIL API or internally.
2. The basic CLCC response data, <rgci>, must be retained to act as the response to the CLCC API response.
3. The CLCC response data is also copied into the global call state structure, g_rgfCallStates.
4. The mapping between CLCC and CPI is identical with the following exceptions:
a. <status> must be converted
b. <multiparty> only exists in CLCC
5. The <rgci> response starts at index 0
6. The <g_rgfCallStates> indexing is defined as index = Callid.
7. The global callstates, g_rgfCallStates, is written to by both the CLCC processing (this function) and the CPI parsing routine (PDD).
*/
// Parse "+CLCC: "
while (MatchStringBeginning(szRsp, "+CLCC: ", szRsp))
{
if (nUsed == nAllocated)
{
if (!AllocateOrReallocateStorage((BYTE**)&rgrci, sizeof(RILCALLINFO), nUsed, &nAllocated, CALLCTRL_ALLOC_NUMBER))
{
hr = E_OUTOFMEMORY;
goto Error;
}
}
memset(&rgrci[nUsed], 0x00, sizeof(RILCALLINFO));
rgrci[nUsed].cbSize = sizeof(RILCALLINFO);
rgrci[nUsed].raAddress.cbSize = sizeof(RILADDRESS);
// Parse "<id>"
if (!ParseUInt(szRsp, TRUE, nValue, szRsp)) {
goto Continue;
}
rgrci[nUsed].dwID = nValue;
rgrci[nUsed].dwParams |= RIL_PARAM_CI_ID;
if (true == bSaveDataInGlobals)
{
nCid = nValue;
if ( nCid >= RIL_MAX_TRACKED_CALL_ID )
{
nCid = 0;
}
// We're going to update this call ID. Erase all other info regarding this call
memset( &g_rgfCallStates[nCid], 0, sizeof(g_rgfCallStates[nCid]));
g_rgfCallStates[nCid].cbSize = sizeof(g_rgfCallStates[nCid]);
g_rgfCallStates[nCid].raAddress.cbSize = sizeof(g_rgfCallStates[nCid].raAddress);
g_rgfCallStates[nCid].dwID = nCid;
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_ID;
}
// Track the call
DEBUGCHK((0 <= nValue) && (nValue < ARRAY_LENGTH(rgfNewCallsInProgress))); // Otherwise, it may be necessary to increase RIL_MAX_TRACKED_CALL_ID
if ((0 <= nValue) && (nValue < ARRAY_LENGTH(rgfNewCallsInProgress))) {
rgfNewCallsInProgress[nValue] = TRUE;
}
// Parse ",<direction>"
if (!MatchStringBeginning(szRsp, ",", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, TRUE, 2, nValue, szRsp)) {
goto Continue;
}
rgrci[nUsed].dwDirection = (nValue ? RIL_CALLDIR_INCOMING : RIL_CALLDIR_OUTGOING);
rgrci[nUsed].dwParams |= RIL_PARAM_CI_DIRECTION;
if (true == bSaveDataInGlobals)
{
g_rgfCallStates[nCid].dwDirection = (nValue ? RIL_CALLDIR_INCOMING : RIL_CALLDIR_OUTGOING);
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_DIRECTION;
}
// Parse ",<status>"
if (!MatchStringBeginning(szRsp, ",", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, TRUE, NUM_CALLSTATS, nValue, szRsp)) {
goto Continue;
}
rgrci[nUsed].dwStatus = g_rgdwCallStats[nValue];
rgrci[nUsed].dwParams |= RIL_PARAM_CI_STATUS;
switch (g_rgdwCallStats[nValue])
{
case RIL_CALLSTAT_INCOMING:
case RIL_CALLSTAT_WAITING:
bIncomingCall = TRUE;
}
if (true == bSaveDataInGlobals)
{
g_rgfCallStates[nCid].dwStatus = g_rgdwCallStats[nValue];
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_CPISTATUS;
switch (g_rgfCallStates[nCid].dwStatus)
{
case RIL_CALLSTAT_ALERTING:
case RIL_CALLSTAT_DIALING:
g_rgfCallStates[nCid].dwStatus = RIL_CPISTAT_NEW_OUTGOING;
break;
case RIL_CALLSTAT_INCOMING:
case RIL_CALLSTAT_WAITING:
g_rgfCallStates[nCid].dwStatus = RIL_CPISTAT_NEW_INCOMING;
break;
case RIL_CALLSTAT_ACTIVE:
g_rgfCallStates[nCid].dwStatus = RIL_CPISTAT_CONNECTED;
break;
case RIL_CALLSTAT_ONHOLD:
g_rgfCallStates[nCid].dwStatus = RIL_CPISTAT_ONHOLD;
break;
default:
g_rgfCallStates[nCid].dwStatus = RIL_CPISTAT_UNKNOWN;
g_rgfCallStates[nCid].dwParams &= ~RIL_PARAM_CI_CPISTATUS;
break;
}
}
// Parse ",<type>"
if (!MatchStringBeginning(szRsp, ",", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, TRUE, NUM_CALLTYPES, nValue, szRsp)) {
goto Continue;
}
rgrci[nUsed].dwType = g_rgdwCallTypes[nValue];
rgrci[nUsed].dwParams |= RIL_PARAM_CI_TYPE;
if (true == bSaveDataInGlobals)
{
g_rgfCallStates[nCid].dwType = g_rgdwCallTypes[nValue];
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_TYPE;
}
// Parse ",<multiparty>"
if (!MatchStringBeginning(szRsp, ",", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, TRUE, 2, nValue, szRsp)) {
goto Continue;
}
rgrci[nUsed].dwMultiparty = (nValue ? RIL_CALL_MULTIPARTY : RIL_CALL_SINGLEPARTY);
rgrci[nUsed].dwParams |= RIL_PARAM_CI_MULTIPARTY;
if (true == bSaveDataInGlobals)
{
g_rgfCallStates[nCid].dwMultiparty = (nValue ? RIL_CALL_MULTIPARTY : RIL_CALL_SINGLEPARTY);
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_MULTIPARTY;
}
// Parse ","
if (MatchStringBeginning(szRsp, ",", szRsp)) {
// Parse "<address>,<type>"
if (ParseString(szRsp, szAddress, MAXLENGTH_ADDRESS, szRsp)) {
if (!MatchStringBeginning(szRsp, ",", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, FALSE, 0x100, nValue, szRsp) ||
!StringToRILAddress(szAddress, (BYTE)nValue, rgrci[nUsed].raAddress)) {
goto Continue;
}
rgrci[nUsed].dwParams |= RIL_PARAM_CI_ADDRESS;
if (true == bSaveDataInGlobals)
{
g_rgfCallStates[nCid].dwParams |= RIL_PARAM_CI_ADDRESS;
StringToRILAddress(szAddress, (BYTE)nValue, g_rgfCallStates[nCid].raAddress);
}
}
else {
// If we couldn't parse an address, then it might be empty,
// meaning the ID is blocked. Since the address parameter
// is present, make sure the type also exists before continuing.
if (!MatchStringBeginning(szRsp, ",", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, FALSE, 0x100, nValue, szRsp)) {
goto Continue;
}
}
// Parse ","
if (MatchStringBeginning(szRsp, ",", szRsp)) {
// Parse "<description>"
if (!ParseQuotedEncodedString(g_rppPDDParams->etEncodingTECharset, szRsp, rgrci[nUsed].wszDescription, rgrci[nUsed].wszDescription + MAXLENGTH_DESCRIPTION)) {
goto Continue;
}
rgrci[nUsed].dwParams |= RIL_PARAM_CI_DESCRIPTION;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -