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

📄 modem.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:

void
DoHangUp(
    PTLINEDEV pLineDev
    )
{
    DCB  commDCB, origDCB;    
    DWORD dwWaitReturn;
    DWORD dwLen;
    static const UCHAR szHangup[] = "\rATH\r\nATZ\r\n";
    // If a TermCtrl is displayed, get rid of it.
    if( pLineDev->hwTermCtrl )
    {
        PFN_SENDMESSAGE pfnSendMessage;

        if (pfnSendMessage = (PFN_SENDMESSAGE)GetProcAddress(g_hCoreDLL, L"SendMessageW")) {
            // send a WM_CLOSE to the handle
            DEBUGMSG(ZONE_CALLS,
                     (TEXT("UNIMODEM:DoHangUp - WM_CLOSE TermWnd\r\n")));            
            pfnSendMessage (pLineDev->hwTermCtrl, WM_CLOSE, 0, 0);
        }
    }

    ToggleCommMask(pLineDev);

    // We don't want to finish up before the dialer thread has
    // done his thing.  So wait for the CallComplete event that
    // the thread sets before exiting.  Lets assume he'll finish
    // within 4 seconds or we just give up.
    dwWaitReturn = WaitForSingleObject(pLineDev->hCallComplete, 4*1000);
#ifdef DEBUG
    if( WAIT_TIMEOUT == dwWaitReturn )
        DEBUGMSG(ZONE_CALLS | ZONE_ERROR,
                 (TEXT("UNIMODEM:DoHangUp - timeout waiting for call complete\r\n")));
#endif         
     // Drop the line, aborting any call in progress.
    if(  (HANDLE)INVALID_DEVICE != pLineDev->hDevice )
    {
        try
        {
            // Make sure the modem hangs up, etc.
            if( ! IS_NULL_MODEM(pLineDev) )
            {
                DEBUGMSG(ZONE_CALLS,
                         (TEXT("UNIMODEM:DoHangUp - hanging up\r\n")));

                if( (HANDLE)INVALID_DEVICE != pLineDev->hDevice )
                {
                    GetCommState( pLineDev->hDevice, &commDCB );
                    origDCB = commDCB;
                    commDCB.fRtsControl = RTS_CONTROL_ENABLE;
                    commDCB.fOutxCtsFlow = 0;
                    SetCommState( pLineDev->hDevice, &commDCB );

                    dwLen = 0;
                    PurgeComm(pLineDev->hDevice, PURGE_RXCLEAR|PURGE_TXCLEAR);
                    WriteFile(pLineDev->hDevice, (LPVOID)szHangup, strlen((LPVOID)szHangup), &dwLen, 0 );
                    WriteModemLog(pLineDev, (PUCHAR)szHangup, MDMLOG_COMMAND_OK);
                    PurgeComm(pLineDev->hDevice, PURGE_RXCLEAR|PURGE_TXCLEAR);
                    RETAILMSG (dwLen != strlen((LPVOID)szHangup),
                                (TEXT("UNIMODEM:!!!DoHangUp wrote %d of %d byte dial string\r\n"),
                                dwLen, strlen((LPVOID)szHangup)) );

                    commDCB.fRtsControl = RTS_CONTROL_DISABLE;
                    commDCB.fDtrControl     = DTR_CONTROL_DISABLE;
                    SetCommState( pLineDev->hDevice, &commDCB );

                    Sleep( 100 );
                    SetCommState( pLineDev->hDevice, &origDCB );
                }

                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DoHangUp - hangup done\r\n")));
            }
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // Exception means bad handle, so we can't do anything
        }
    }
#ifdef DEBUG
    else
    {
        DEBUGMSG(ZONE_CALLS | ZONE_ERROR,
                 (TEXT("UNIMODEM:DoHangUp - handle invalid.  Can't cancel call\r\n")));
    }
#endif
}


//****************************************************************************
// DevlineDrop()
//
// Function: Emulate the TAPI lineDrop call.
//
//****************************************************************************

LONG
DevlineDrop (
    PTLINEDEV pLineDev
    )
{
    DEBUGMSG(ZONE_FUNC|ZONE_CALLS,
             (TEXT("UNIMODEM:+DevlineDrop\r\n")));

    EnterCriticalSection(&pLineDev->OpenCS);

    // Don't unnecessarily attempt to drop
    if ((LINECALLSTATE_DISCONNECTED == pLineDev->dwCallState ) || (LINECALLSTATE_IDLE == pLineDev->dwCallState )) {
        switch(pLineDev->DevState) {
        case DEVST_DISCONNECTED:
        case DEVST_PORTLISTENINIT:
        case DEVST_PORTLISTENING:
            pLineDev->DevState = DEVST_DISCONNECTED;
            LeaveCriticalSection(&pLineDev->OpenCS);
            SetAsyncStatus(pLineDev, 0);
            DEBUGMSG(ZONE_FUNC|ZONE_CALLS,
                 (TEXT("UNIMODEM:-DevlineDrop, line already dropped\r\n")));
            return SUCCESS;
        }
    }

    pLineDev->dwCallFlags |= CALL_DROPPING;  // Flag that this call is going away
    pLineDev->dwCallFlags &= ~CALL_ACTIVE;

     // Do we need to do a hangup?
    if (LINECALLSTATE_IDLE == pLineDev->dwCallState &&
        DEVST_DISCONNECTED == pLineDev->DevState)

    {
        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DevlineDrop - no action required\r\n")));
        SetAsyncStatus(pLineDev, 0);
    }
    else
    {
        DoHangUp(pLineDev);
    };
    
    if (pLineDev->dwCallFlags & CALL_ALLOCATED) {
        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DevlineDrop - sending LINECALLSTATE_IDLE\n")));
        NewCallState(pLineDev, LINECALLSTATE_IDLE, 0L);
    }
        
    pLineDev->dwNumRings = 0;
    pLineDev->DevState = DEVST_DISCONNECTED;
    pLineDev->dwCallState = LINECALLSTATE_IDLE;
    pLineDev->dwCallFlags = 0;
    
    LeaveCriticalSection(&pLineDev->OpenCS);    
    DEBUGMSG(ZONE_FUNC|ZONE_CALLS, (TEXT("UNIMODEM:-DevlineDrop\r\n")));
    return SUCCESS;
}

LONG
DoDevlineDrop(
    PTLINEDEV pLineDev
    )
{
    LONG rc;

    rc = DevlineDrop(pLineDev);
    SetCommMask(pLineDev->hDevice, EV_DEFAULT);
    SetAsyncStatus(pLineDev, 0);
    return rc;
}

void
FreeNextCmd(
    PTLINEDEV pLineDev
    )
{
    if (pLineDev->lpstrNextCmd) {
        TSPIFree(pLineDev->lpstrNextCmd);
        pLineDev->lpstrNextCmd = NULL;
    }
}

//
// Wait for a disconnect on a connected modem. Send a LINE_CALLSTATE
// upon disconnect.
//
void
WatchForDisconnect(
    PTLINEDEV pLineDev
    )
{
    DWORD Mask;
    DWORD ModemStatus;

    DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS, (TEXT("UNIMODEM:+WatchForDisconnect\n")));
    DEBUGMSG(ZONE_CALLS, (L"UNIMODEM:WatchForDisconnect: Call(0x%x) is %s, CallState(0x%x) is %s\n", 
        pLineDev->dwCallFlags, (pLineDev->dwCallFlags & CALL_ACTIVE) ? L"ACTIVE" : L"NOT ACTIVE",
        pLineDev->dwCallState, (pLineDev->dwCallState == LINECALLSTATE_CONNECTED) ? L"CONNECTED" : L"NOT CONNECTED"));

    SetCommMask(pLineDev->hDevice_r0, EV_RLSD);
    while ((pLineDev->dwCallState == LINECALLSTATE_CONNECTED) && (pLineDev->dwCallFlags & CALL_ACTIVE)) {
        if (WaitCommEvent(pLineDev->hDevice_r0, &Mask, NULL )) {
            //
            // Remote disconnect detection
            //
            if (Mask & EV_RLSD) {
                if (GetCommModemStatus(pLineDev->hDevice_r0, &ModemStatus)) {
                    if (!(ModemStatus & MS_RLSD_ON)) {
                        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:WatchForDisconnect RLSD went low\n")));
                        DoHangUp(pLineDev);
                        pLineDev->DevState = DEVST_DISCONNECTED;
                        pLineDev->dwCallFlags &= ~CALL_ACTIVE;
                        pLineDev->dwNumRings = 0;
                        NewCallState(pLineDev, LINECALLSTATE_DISCONNECTED, LINEDISCONNECTMODE_NORMAL);
                        NewCallState(pLineDev, LINECALLSTATE_IDLE, 0L);
                        break;
                    }
                } else {
                    DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:WatchForDisconnect GetCommModemStatus failed %d\n"), GetLastError()));
                    break;
                }
            }

            //
            // See if we got signalled to drop via TSPI_lineDrop
            //
            if ((Mask == 0) || (pLineDev->dwCallFlags & CALL_DROPPING)) {
                break;
            }
        } else {
            DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:WatchForDisconnect GetCommEvent failed %d\n"), GetLastError()));
            break;
        }
    }

    DEBUGMSG(ZONE_ASYNC, (TEXT("UNIMODEM:WatchForDisconnect Current Op=%s\n"), GetPendingName(pLineDev->dwPendingType)));
    if (pLineDev->dwPendingType != PENDING_LINEDROP) {
        DoDevlineDrop(pLineDev);
    }

    DEBUGMSG(ZONE_CALLS|ZONE_FUNCTION, (TEXT("UNIMODEM:-WatchForDisconnect\n")));
}   // WatchForDisconnect

//
// Process a RING response from the modem
//
LONG
ProcessModemRing(
    PTLINEDEV pLineDev
    )
{
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ProcessModemRing\n")));

    if (pLineDev->dwNumRings == 0) {
        if (SetWatchdog(pLineDev, 25000)) {
            DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ProcessModemRing - SetWatchDog failed!!\n")));
        }

        pLineDev->dwCallFlags = CALL_INBOUND;
        pLineDev->dwCallState = LINECALLSTATE_OFFERING;
        pLineDev->DevState = DEVST_PORTLISTENOFFER;
        
        CallLineEventProc(
            pLineDev,
            0,
            LINE_NEWCALL,
            (DWORD)pLineDev,            // HDRVCALL
            (DWORD)&pLineDev->htCall,   // LPHTAPICALL
            0);
        
        pLineDev->dwCurMediaModes = pLineDev->dwDefaultMediaModes | LINEMEDIAMODE_UNKNOWN;
        NewCallState(pLineDev, LINECALLSTATE_OFFERING, 0);
    }
    CallLineEventProc(
        pLineDev,
        0,
        LINE_LINEDEVSTATE,
        LINEDEVSTATE_RINGING,
        0,
        pLineDev->dwNumRings);

    pLineDev->dwNumRings++;
    
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-ProcessModemRing\n")));
    return 0;
}   // ProcessModemRing


//
// Process a CARRIER, PROTOCOL or PROGRESS response from the modem
//
LONG
ProcessModemProceeding(
    PTLINEDEV pLineDev
    )
{
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ProcessModemProceeding\n")));
    if ((pLineDev->DevState == DEVST_PORTLISTENING) || (pLineDev->DevState == DEVST_PORTLISTENOFFER)) {
        SetAsyncStatus(pLineDev, 0);
    }
    NewCallState(pLineDev, LINECALLSTATE_PROCEEDING, 0);
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-ProcessModemProceeding\n")));
    return 0;
}   // ProcessModemProceeding


//
// Process a CONNECT response from the modem
//
LONG
ProcessModemConnect(
    PTLINEDEV pLineDev
    )
{
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ProcessModemConnect\n")));
    SetWatchdog( pLineDev, 0 ); // Cancel watchdog
    pLineDev->dwCallFlags |= CALL_ACTIVE;
    if ((pLineDev->DevState == DEVST_PORTLISTENING) || (pLineDev->DevState == DEVST_PORTLISTENOFFER)) {
        pLineDev->DevState = DEVST_CONNECTED;
        SetAsyncStatus(pLineDev, 0);
    }
    NewCallState(pLineDev, LINECALLSTATE_CONNECTED, 0);
       
    //
    // Now watch the comm state to notify of disconnect
    //
    WatchForDisconnect(pLineDev);
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-ProcessModemConnect\n")));
    return 0;
}   // ProcessModemConnect


//
// Process a SUCCESS response from the modem
//
LONG
ProcessModemSuccess(
    PTLINEDEV pLineDev
    )
{
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ProcessModemSuccess\n")));
    if ((pLineDev->DevState == DEVST_PORTLISTENING) || (pLineDev->DevState == DEVST_PORTLISTENOFFER)) {
        SetAsyncStatus(pLineDev, 0);
    }
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-ProcessModemSuccess\n")));
    return 0;
}   // ProcessModemSuccess


extern const UCHAR pchDCCResp[];

//
// Process a FAILURE response from the modem
//
// SetCommMask(0) is used to signal UnimodemControlThread when some new command
// has been requested. This gets interpreted by MdmGetResponse as a
// MODEM_FAILURE.
//
LONG
ProcessModemFailure(
    PTLINEDEV pLineDev
    )
{
    WCHAR szTemp[256];
    DWORD dwSize;
    LONG rc = 0;

    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ProcessModemFailure\n")));

pmf_next:
    
    switch (pLineDev->dwPendingType) {
    case PENDING_LINEANSWER:
    {
        DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:ProcessModemFailure PENDING_LINEANSWER\n")));
        if (SetWatchdog(pLineDev, 25000)) {
            return 1;
        }

        pLineDev->dwCallFlags |= CALL_ALLOCATED;

        if (IS_NULL_MODEM(pLineDev)) {
            pLineDev->lpstrNextCmd = TSPIAlloc(strlen(pchDCCResp)+1); // answer DCC w/"CLIENTSERVER"
            if (pLineDev->lpstrNextCmd) {
                strcpy(pLineDev->lpstrNextCmd, pchDCCResp);
            }
        } else {
            if (MdmRegGetValue(
                    pLineDev,
                    szSettings,
                    szAnswer,
                    REG_SZ,
                    (PUCHAR)szTemp,
                    &dwSize) == ERROR_SUCCESS) {
                pLineDev->lpstrNextCmd = MdmConvertCommand(szTemp, NULL, NULL);
            } else {
                pLineDev->lpstrNextCmd = TSPIAlloc(sizeof(szDefaultAnswerCmd));
                if (pLineDev->lpstrNextCmd) {
                    strcpy(pLineDev->lpstrNextCmd, szDefaultAnswerCmd);
                }
            }
        }
    }
    break;

    case PENDING_EXIT:
    {
        DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:ProcessModemFailure PENDING_EXIT\n")));
        return 2;
    }
    break;

    case PENDING_LINEMAKECALL:
    case PENDING_LINEDIAL:
    {
        DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:ProcessModemFailure PENDING_LINEDIAL/PENDING_LINEMAKECALL\n")));
        Dialer(pLineDev);
        switch (pLineDev->dwCallState) {
        case LINECALLSTATE_CONNECTED:
            WatchForDisconnect(pLineDev);
            goto pmf_next;

        case LINECALLSTATE_DIALING:
            MdmGetResponse(pLineDev, "listening", NOCS);
            goto pmf_next;
        }
     
    }
    break;

    case PENDING_LINEDROP:
    {
        DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:ProcessModemFailure PENDING_LINEDROP\n")));
        rc = DoDevlineDrop(pLineDev);
    }
    break;

    case PENDING_LISTEN:
    {
        // The WatchDog that was set after the first RING has timed out
        DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:ProcessModemFailure PENDING_LISTEN\n")));
        rc = DevlineDrop(pLineDev);
        SetCommMask(pLineDev->hDevice, EV_DEFAULT);
    }
    break;

    default:
    {
        DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:ProcessModemFailure default case %d\n"), pLineDev->dwPendingType));
        return 3;
    }

    }   // switch

⌨️ 快捷键说明

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