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

📄 dial.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 5 页
字号:
                            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:    
    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\r\n"),
        dwThisWatchdog, dwTimeout/1000));
    
    
    // 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!\n"),
            dwThisWatchdog, GetPendingName(pLineDev->dwPendingType)));

        // 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.
        ToggleCommMask(pLineDev);

        switch (pLineDev->dwPendingType) {
        case PENDING_LINEMAKECALL:
            //
            // Allow an in progress DCC lineMakeCall to retry
            //
            bAbort = !(IS_NULL_MODEM(pLineDev));
            break;

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

        case PENDING_LINEDIAL:
        case PENDING_LINEDROP:
            bAbort = TRUE;
            break;

        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\r\n"), dwThisWatchdog));
    }
#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++;
    pLineDev->bWatchdogTimedOut = FALSE;

    // First, lets cancel any current outstanding watchdogs for this line
    PulseEvent(pLineDev->hTimeoutEvent);  // Stop the watchdog

    // And now, start a new watchdog if they want us to 
    if( dwTimeout ) {
        pWDInfo = TSPIAlloc(sizeof(UNIMODEM_WATCHDOG_INFO));
        if (NULL == pWDInfo) {
            NKDbgPrintfW( TEXT("UNIMODEM:SetWatchDog Unable to alloc Watchdog info\n") );
            return (DWORD)-1;
        }

        pWDInfo->pLineDev       = pLineDev;
        pWDInfo->dwTimeout      = dwTimeout;
        pWDInfo->dwThisWatchdog = pLineDev->dwCurWatchdog;

        hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ModemWatchdog,
                                pWDInfo, 0, NULL );
        if ( ! hThread ) {
            TSPIFree(pWDInfo);
            NKDbgPrintfW( TEXT("UNIMODEM:SetWatchDog Unable to Create Watchdog Thread\n") );
            return (DWORD)-1;
        }
        CeSetThreadPriority(hThread, g_dwUnimodemThreadPriority);   
        CloseHandle( hThread );
    }
    return STATUS_SUCCESS;
}


BOOL
ModemInit(
    PTLINEDEV pLineDev
    )
{
    MODEMRESPCODES MdmResp = MODEM_FAILURE;
    DWORD dwSize, dwCmdLen;
    int   RetryCount = 0;
    PWCHAR pszTemp = NULL;
    PWCHAR pszExpand = NULL;
    PCHAR pchCmd = NULL;
    MODEMMACRO ModemMacro;
    DWORD dwCallSetupFailTimer;
    DEVSTATES OrigDevState;

    static const WCHAR szReset[] =   TEXT("Reset");
    static const WCHAR szFlowHard[] =  TEXT("FlowHard");
    static const WCHAR szFlowSoft[] =  TEXT("FlowSoft");
    static const WCHAR szFlowNone[] =  TEXT("FlowOff");
    static const WCHAR *szFlowType;  // Hard, Soft, None
    static const WCHAR szCallFail[] =   TEXT("CallSetupFailTimeout");

    static const UCHAR szEscapeCmd[] = "+++";
    

    OrigDevState = pLineDev->DevState;

    try
    {
        DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ModemInit\r\n")));

        // Allocate temp buffers for registry results
        pszTemp = (PWCHAR)TSPIAlloc( (pLineDev->dwMaxCmd + 1) * SZWCHAR );
        pszExpand = (PWCHAR)TSPIAlloc( (pLineDev->dwMaxCmd + 1) * SZWCHAR );
        pchCmd =  (PCHAR)TSPIAlloc( pLineDev->dwMaxCmd + 1 );
    
        // First, read the reset command from the registry
        dwSize = pLineDev->dwMaxCmd * SZWCHAR;
        if (ERROR_SUCCESS !=
            MdmRegGetValue( pLineDev,
                            szSettings,
                            szReset,
                            REG_SZ,
                            (PUCHAR)pszTemp,
                            &dwSize) )
        {
            goto init_error;
        }

        MdmConvertCommand(pszTemp, pchCmd, &dwCmdLen);
        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Reset string is \"%s\" (%d)\r\n"),
                              pszTemp, dwCmdLen));
    
        // ***** reset modem by clearing DTR    
        if(LineNotDropped(pLineDev, OrigDevState))
        {
            DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit SetCommState - DTR off\r\n")));
            EscapeCommFunction ( pLineDev->hDevice, CLRDTR);
            Sleep( 400 );
        }
    
    
        if(LineNotDropped(pLineDev, OrigDevState))
        {
            DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit SetCommState - DTR on\r\n")));
            EscapeCommFunction ( pLineDev->hDevice, SETDTR);
            Sleep( 200 );
        }
    
        // No matter what the state was, we are now initializing
        pLineDev->MdmState = MDMST_INITIALIZING;
    
        while( (LineNotDropped(pLineDev, OrigDevState)) &&
                 (RetryCount < MAX_COMMAND_TRIES) )
        {
            // Set short timeout for init strings
            if( SetWatchdog( pLineDev, 8000 ) )
            {
                pLineDev->MdmState = MDMST_UNKNOWN;
                goto init_error;
            }
        
            if( LineNotDropped(pLineDev, OrigDevState) )
            {
                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Send Init\r\n")));
                MdmResp = MODEM_FAILURE;
                if (MdmSendCommand( pLineDev, pchCmd )) {
                    MdmResp = MdmGetResponse( pLineDev, pchCmd, NOCS );
                }
            }
        
            // See if we managed to get initialized
            if( MODEM_SUCCESS == MdmResp )
            {
                pLineDev->MdmState = MDMST_DISCONNECTED;  // It worked
                break;
            }
            else
            {
                if( LineNotDropped(pLineDev, OrigDevState) )
                {
                    // the modem didn't reset
                    pLineDev->MdmState = MDMST_UNKNOWN;

                    // If szReset didn't work, we likely need a +++
                    MdmSendCommand( pLineDev, szEscapeCmd );
                    Sleep( 200 );
                }
            }
            RetryCount++;
        }

        if( (MDMST_DISCONNECTED == pLineDev->MdmState) &&
            (LineNotDropped(pLineDev, OrigDevState)) )
        {
            DWORD mdmRegRslt = ERROR_SUCCESS;
            WORD wInitKey;

            // read a sequence of additional init strings from the
            // registry and send them down now. Can't enumerate the 
            // keys since that wouldn't allow us to have modem specific

⌨️ 快捷键说明

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