⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dial.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    while (MODEM_IGNORE == ModemResp)
    {
        if (bOpened) {
            if (!LineNotDropped(pLineDev, OrigDevState)) {
                break;
            }
        }

        try
        {
            ModemStat = 0;

            if (bInCS) {
                //
                // To help avoid missing signals from SignalControlThread, stay in CS as long
                // as possible before calling WaitCommEvent.
                //
                LeaveCriticalSection(&pLineDev->OpenCS);
                bInCS = FALSE;
            }
            bStatus = WaitCommEvent(pLineDev->hDevice, &ModemStat, NULL);
            //
            // Look for signals from SignalControlThread
            //
            if (pLineDev->dwPendingType != OrigPendingOp) {
                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse %s interrupted %s\n"),PendingOpName(pLineDev->dwPendingType) , PendingOpName(OrigPendingOp)));
                switch (pLineDev->dwPendingType){
                case PENDING_LINEDROP:
                    ModemResp = MODEM_ABORT;
                   break;
                default:
                    ModemResp = MODEM_FAILURE;
                    break;
                } // endswitch
                goto mgr_exit;
            }

            if (pLineDev->bWatchdogTimedOut) {
                pLineDev->bWatchdogTimedOut = FALSE;
                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse - Watchdog timed out\n")));
                ModemResp = MODEM_EXIT;
                goto mgr_exit;
            }

            if (FALSE == bStatus) {
                dwLen = GetLastError();
                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse - WaitCommEvent failed %d\n"), dwLen));
                ModemResp = MODEM_EXIT;
                goto mgr_exit;
            }

            if (ModemStat) {
#ifdef DEBUG
                DisplayModemStatus(ModemStat);
#endif
                if (ModemStat & EV_ERR) {
                    if (ClearCommError(pLineDev->hDevice, &dwLen, NULL)) {
#ifdef DEBUG
                        if (dwLen) {
                            DisplayCommError(dwLen);
                        }
                    } else {
                        dwLen = GetLastError();
                        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse ClearCommError failed %d\n"), dwLen));
#endif
                    }
                }

                if( ModemStat & EV_RING) {
                    ModemResp = MODEM_RING;
                }

                if (ModemStat & EV_RXCHAR) {
                    if (bOpened) {
                        if (!LineNotDropped(pLineDev, OrigDevState)) {
                            break;
                        }
                    }

                    if (!ReadFile (pLineDev->hDevice, (LPVOID)InBuf, sizeof(InBuf)-1, &dwLen, 0)) {
                        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse - ReadFile failed %d\n"), GetLastError()));
                        ModemResp = MODEM_EXIT;
                        goto mgr_exit;
                    }

                    // If we didn't read much data, retry to make sure we have all of it.
                    if ( dwLen < LOW_COMPLETE_READ_THRESHOLD) {
                        DWORD dwNewLen;

                        // Sleep here to give the other threads ( IRCOMM ... ) time to procoess
                        Sleep(50);

                        // Null terminate for the debug output
                        InBuf[dwLen] = 0;
                        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:First MdmGetResponse Response = %a\n"), InBuf));

                        // Read from the port again
                        if (ReadFile (pLineDev->hDevice, (LPVOID)(InBuf+dwLen), sizeof(InBuf)-1-dwLen, &dwNewLen, 0)) {
                            DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse - Second ReadFile succeeded. %i characters recovered\n"),dwNewLen));
                            dwLen += dwNewLen;
                        }
                    }

                    InBuf[dwLen] = 0;
                    WriteModemLog(pLineDev, (PUCHAR)InBuf, MDMLOG_RESPONSE);
#ifdef DEBUG_RESPONSES
                    if (dwLen) {
                        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse Response = %a\n"), InBuf));
                    }
#endif
                    // Now lets process each response as they arrive
                    for( i=0; i<(int)dwLen; i++ )
                    {
                        ModemResponse[ModemResponseIndex] = InBuf[i];

                        if(  IS_NULL_MODEM(pLineDev) )
                        {
                            //
                            // Only allow one response per call to MdmGetResponse for a DCC connection
                            //
                            ModemResp = MODEM_FAILURE;

                            //
                            // Are we client or server?
                            //
                            if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
                                pchDCC = (PUCHAR)pchDCCResp;
                                DCCResp = MODEM_CONNECT;
                            } else {
                                pchDCC = (PUCHAR)pchDCCCmd;
                                DCCResp = MODEM_RING;
                            }
                            dwDCCLen = strlen(pchDCC);

                            if( ModemResponse[ModemResponseIndex] == pchDCC[ModemResponseIndex] )
                            {
                                ModemResponseIndex++;

                                // characters match so far, see if we have a complete response.
                                if( ModemResponseIndex >= dwDCCLen )
                                {
                                    // OK, we got a full response.  Zero terminate it and exit
                                    ModemResponse[ModemResponseIndex] = 0;
                                    // No need to call response handler, we already did all the work.
                                    ModemResp = DCCResp;
                                    DEBUGMSG (ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse Null Response detected\r\n")));
                                    break;
                                }
                                
                            }
                            else // character mismatch - restart scan sequence.
                            {
                                // If character is 'C', it might be first character of the actual
                                // response.  Any other case means that all data up to here is useless
                                // so we should toss it.  This is only true because 'C' appears only as
                                // the first character of a response, and never after that.
                                ModemResponseIndex = 0;
                                if (pchDCC[0] == InBuf[i])
                                {
                                    ModemResponse[ModemResponseIndex] = InBuf[i];
                                    ModemResponseIndex++;
                                }
                            }
                        }
                        else
                        {
                            if( (CR == InBuf[i]) ||
                                (LF == InBuf[i]) ||
                                ((DWORD)i == dwLen-1)   ||
                                ((pLineDev->dwMaxCmd - 1) <= ModemResponseIndex) ) 
                            {
                                // have a complete response (or max length).  Now we parse it.
                                ModemResponse[ModemResponseIndex] = 0;  // Lets Zero Terminate the string
                                ModemResp = ModemResponseHandler( pLineDev, ModemResponse, pszCommand );
                                
                                                                switch (ModemResp) {
                                case MODEM_CARRIER:
                                    ParseConnectSpeed(pLineDev, ModemResponse);
                                    // fall through!!!

                                case MODEM_PROTOCOL:
                                case MODEM_PROGRESS:
                                    NewCallState(pLineDev, LINECALLSTATE_PROCEEDING, 0L);
                                    if (i < (int)(dwLen - 1)) {
                                        ModemResponseIndex = 0;  // Start a new response
                                        ModemResp = MODEM_IGNORE;
                                    }
                                    break;

                                case MODEM_UNKNOWN:
                                case MODEM_IGNORE:
                                    ModemResponseIndex = 0;  // Start a new response
                                    ModemResp = MODEM_IGNORE;
                                    break;

                                case MODEM_CONNECT:
                                    ParseConnectSpeed(pLineDev, ModemResponse);
                                    // fall through

                                default:
                                    goto mgr_exit;
                                }

                                ModemResponseIndex = 0;  // Start a new response
                            }
                            else
                            {
                                ModemResponseIndex++;  //Add another character to the string
                            }
                        }
                    }
                
                }
            }
            else
            {
                // A zero ModemStat is an error, and indicates that the
                // waitcommevent was stopped by our watchdog or linedrop.
                ModemResp = MODEM_FAILURE;
                DEBUGMSG (ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse - Timeout\r\n")));
                goto mgr_exit;
            }
        
            DEBUGMSG(ZONE_FUNC|ZONE_CALLS, (TEXT("UNIMODEM:MdmGetResponse %s\n"), ResponseName(ModemResp)));
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // Must have been a bad handle.  Give up
            ModemResp = MODEM_FAILURE;
            DEBUGMSG (ZONE_FUNC|ZONE_CALLS,
                      (TEXT("UNIMODEM:MdmGetResponse - Exception.  Handle \r\n"),
                        pLineDev->hDevice ));
        }
    }
    
mgr_exit:    
    EnterCriticalSection(&pLineDev->OpenCS);
    pLineDev->dwWaitMask = EV_DEFAULT;
    LeaveCriticalSection(&pLineDev->OpenCS);

    if (bInCS) {
        LeaveCriticalSection(&pLineDev->OpenCS);
    }

    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-MdmGetResponse %s\r\n"), ResponseName(ModemResp)));
    return ModemResp;
}


//
// There were cases where the ModemWatchdog thread would not make it to the WaitForSingleObject
// before the next SetWatchdog happened. This would leave two or more watchdogs runnning at the
// same time which leads to all kinds of problems. Now SetWatchdog passes a UNIMODEM_WATCHDOG_INFO
// structure to the thread and the watchdog checks that it is the current one before aborting
// any pending operations.
//
typedef struct _UNIMODEM_WATCHDOG_INFO {
    PTLINEDEV pLineDev;
    DWORD dwTimeout;
    DWORD dwThisWatchdog;
} UNIMODEM_WATCHDOG_INFO, * PUNIMODEM_WATCHDOG_INFO;


// **********************************************************************
//
// This is the dialer/answer watchdog thread.  It is created by the dialer thread.
// Its purpose is to wait for a specified interval, or until signalled by
// the dialer.  If the wait times out, then the watchdog calls into the
// COM port driver, causing the waitcommevent in the dialer thread to
// return.
// 
// **********************************************************************
void
ModemWatchdog(
    PUNIMODEM_WATCHDOG_INFO pWDInfo
    )
{
    DWORD RetCode;
    BOOL bAbort;
    PTLINEDEV pLineDev;
    DWORD dwTimeout;
    DWORD dwThisWatchdog;

    pLineDev        = pWDInfo->pLineDev;
    dwTimeout       = pWDInfo->dwTimeout;
    dwThisWatchdog  = pWDInfo->dwThisWatchdog;
    TSPIFree(pWDInfo);

    DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:+ModemWatchdog(%d) - timeout set to %d seconds (ends %d)\r\n"),
        dwThisWatchdog, dwTimeout/1000, GetTickCount() + dwTimeout));
    
    
    // Wait for the specified interval.
    RetCode = WaitForSingleObject( pLineDev->hTimeoutEvent, dwTimeout );

    if ((dwThisWatchdog == pLineDev->dwCurWatchdog) && ( WAIT_TIMEOUT == RetCode )) {
        pLineDev->bWatchdogTimedOut = TRUE;

        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemWatchdog(%d)  *** %s TIMEOUT at %d\n"),
            dwThisWatchdog, GetPendingName(pLineDev->dwPendingType), GetTickCount()));

        // We need to stop the waitcommevent.  Note that we set the
        // mask to 0, which will cause any subsequent waitcommevent
        // calls to also return immediately.
        SignalCommMask(pLineDev);

        switch (pLineDev->dwPendingType) {
        case PENDING_LINEMAKECALL:
            //
            // Allow retries for DCC connections and ModemInit()
            //
            if (IS_NULL_MODEM(pLineDev)) {
                bAbort = FALSE;
            } else {
                bAbort = (pLineDev->MdmState != MDMST_INITIALIZING);
            }
            break;

        case PENDING_LINEANSWER:
            NewCallState(pLineDev, LINECALLSTATE_DISCONNECTED, LINEDISCONNECTMODE_UNKNOWN);
            NewCallState(pLineDev, LINECALLSTATE_IDLE, 0L);
            bAbort = TRUE;
            break;

        case PENDING_LINEDIAL:
            bAbort = TRUE;
            break;

        case PENDING_LINEDROP:
            // Don't fail lineDrop due to timeouts
            SetEvent(pLineDev->hCallComplete);
            // FALLTHROUGH
        default:
            bAbort = FALSE;
            break;
        }

        // We set an event when we are done so that DevLineDrop can
        // continue with his cleanup.
        if (bAbort) {
            SetEvent(pLineDev->hCallComplete);
            SetAsyncStatus(pLineDev, LINEERR_OPERATIONFAILED);
        }
    }
#ifdef DEBUG
    else {
        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemWatchdog(%d) cancelled at %d\r\n"), dwThisWatchdog, GetTickCount()));
    }
#endif

    // This is a one shot timeout.  The thread should go away as
    // soon as the timer expires or is signalled/cancelled.
}

// **********************************************************************
// Wrapper function to start the watchdog.
// Note that a timeout of 0 cancels the current watchdog.
// **********************************************************************
DWORD
SetWatchdog(
    PTLINEDEV pLineDev,
    DWORD dwTimeout
    )
{
    HANDLE hThread;
    PUNIMODEM_WATCHDOG_INFO pWDInfo;

    pLineDev->dwCurWatchdog++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -