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

📄 modem.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:

    if( (HANDLE)INVALID_DEVICE != pLineDev->hDevice )
    {
        try
        {
            //
            // We (device.exe PSL) were the current process when the device
            // was opened, so we need to be the owner for DevlineDrop and
            // the CloseHandle() to work as expected.
            //
            dwPrevProcPerms = SetProcPermissions(-1);
            SetHandleOwner((HANDLE) pLineDev->hDevice, GetCurrentProcess());
            SetProcPermissions(dwPrevProcPerms);
            // If a call is in progress, terminate it
            if (fDoDrop) {
                DEBUGMSG(ZONE_CALLS, (L"UNIMODEM:DevlineClose - Callstate x%X, dropping call\r\n", pLineDev->dwCallState));
                LeaveCriticalSection(&pLineDev->OpenCS);
                DevlineDrop(pLineDev);   
                EnterCriticalSection(&pLineDev->OpenCS);
            }
    
            CloseHandle( pLineDev->hDevice );
            CloseHandle( pLineDev->hDevice_r0);
            CloseHandle( pLineDev->hMdmLog);
            NullifyLineDevice(pLineDev, FALSE);    // Reinit the line device
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // Oops, we must have hit a bad handle.  Fall thru & release the CS.
            dwPrevProcPerms = 0;
        }
    }
    
    pLineDev->dwPendingID = INVALID_PENDINGID;
    LeaveCriticalSection(&pLineDev->OpenCS);

    if (dwPrevCallState != LINECALLSTATE_IDLE) {
        pLineDev->htCall = hPrevCall;
        NewCallState(pLineDev, LINECALLSTATE_IDLE, 0L);
        pLineDev->htCall = NULL;
    }

    DEBUGMSG(ZONE_FUNC|ZONE_CALLS, (TEXT("UNIMODEM:-DevlineClose\r\n")));
    return SUCCESS;
}

//
// Function to signal any threads stuck in WaitCommEvent
//
LONG
SignalCommMask(
    PTLINEDEV pLineDev
    )
{
    LONG rc = 0;
    DWORD dwPrevProcPerms;

    EnterCriticalSection(&pLineDev->OpenCS);

    if ((HANDLE)INVALID_DEVICE != pLineDev->hDevice) {
        try {
            if (!SetCommMask( pLineDev->hDevice, 0)) {
                DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:SignalCommMask SetCommMask(0) failed %d\n"), GetLastError()));

                //
                // It could be the case that the app called CloseHandle on the handle it got from lineGetID.
                // If so, then try to get it back or open it again.
                //
                if (pLineDev->hDevice != INVALID_HANDLE_VALUE) {
                    dwPrevProcPerms = SetProcPermissions(-1);
                    rc = SetHandleOwner((HANDLE) pLineDev->hDevice, GetCurrentProcess());
                    SetProcPermissions(dwPrevProcPerms);

                    //
                    // If we can't change the handle owner, then we'll have to open it again
                    //
                    if (0 == rc) {
                        if ((pLineDev->hDevice = CreateFile(pLineDev->szDeviceName, GENERIC_READ | GENERIC_WRITE, 0,
                                                            NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
                            rc = LINEERR_OPERATIONFAILED;                           
                        } else {
                            rc = 0;
                        }
                    } else {
                        rc = 0;
                    }

                    if (0 == rc) {
                        DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:SignalCommMask recovered handle\n")));
                        SetCommMask(pLineDev->hDevice, 0);
                    }

                } else {
                    rc = LINEERR_OPERATIONFAILED;
                }
            }
        } except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // Exception means bad handle, so we can't do anything to cancel call
            rc = LINEERR_OPERATIONFAILED;
        }
    }
    if ((HANDLE)INVALID_DEVICE != pLineDev->hDevice_r0) {
        if (!SetCommMask( pLineDev->hDevice_r0, 0)) {
            DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:SignalCommMask SetCommMask(r0) failed %d\n"), GetLastError()));
            rc = LINEERR_OPERATIONFAILED;
        }
    }
    pLineDev->dwWaitMask = 0;
    LeaveCriticalSection(&pLineDev->OpenCS);
    return rc;
}   // SignalCommMask


void
MdmCommandMode(
    PTLINEDEV pLineDev
    )
{
    DCB  commDCB;    
    //
    // Turn off hardware flow control while sending commands.
    //
    GetCommState( pLineDev->hDevice, &commDCB );
    commDCB.fRtsControl = RTS_CONTROL_ENABLE;
    commDCB.fOutxCtsFlow = 0;
    SetCommState( pLineDev->hDevice, &commDCB );
}


typedef LRESULT (WINAPI * PFN_SENDMESSAGE)(HWND,UINT,WPARAM,LPARAM);

#define HANGUP_TIME 4000

void
DoHangUp(
    PTLINEDEV pLineDev
    )
{
    DWORD dwWaitReturn;
    static const UCHAR szEscapeCmd[] = "+++";
    static const UCHAR szHangup[] = "ATH\r\n";
    static const UCHAR szReset[]  = "ATZ\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);
        }
    }

    SignalCommMask(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
        {
            PurgeComm(pLineDev->hDevice, PURGE_RXCLEAR|PURGE_TXCLEAR);
            
            DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DoHangUp - hanging up\r\n")));

            // Make sure the modem hangs up, etc.
            if(IS_NULL_MODEM(pLineDev) ) {
                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DoHangUp EscapeCommFunction - DTR off\r\n")));
                EscapeCommFunction ( pLineDev->hDevice, CLRDTR);
                Sleep( 400 );

                DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DoHangUp EscapeCommFunction - DTR on\r\n")));
                EscapeCommFunction ( pLineDev->hDevice, SETDTR);
                Sleep( 200 );
            } else {
                MdmCommandMode(pLineDev);

                pLineDev->dwWaitMask = EV_DEFAULT;

                SetWatchdog(pLineDev, HANGUP_TIME);
                MdmSendCommand(pLineDev, szEscapeCmd);
                MdmGetResponse(pLineDev, (PUCHAR)szEscapeCmd, NOCS, CLOSING);

                SetWatchdog(pLineDev, HANGUP_TIME);
                MdmSendCommand(pLineDev, szHangup);
                MdmGetResponse(pLineDev, (PUCHAR)szHangup, NOCS, CLOSING);

                SetWatchdog(pLineDev, HANGUP_TIME/2);
                MdmSendCommand(pLineDev, szReset);
                MdmGetResponse(pLineDev, (PUCHAR)szReset, NOCS, CLOSING);

                SetWatchdog(pLineDev, 0);
            }

            DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DoHangUp - hangup done\r\n")));
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            dwWaitReturn = 0;
        }

        if (PENDING_LINEDROP == pLineDev->dwPendingType) {
            SetAsyncStatus(pLineDev, 0);
        } else {
            DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:DoHangUp - PendingType = %d\r\n"), pLineDev->dwPendingType));
        }
    }
#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);
    pLineDev->dwNumRings = 0;

    // 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
    {
        LeaveCriticalSection(&pLineDev->OpenCS);    
        DoHangUp(pLineDev);
        EnterCriticalSection(&pLineDev->OpenCS);
    };
    
    if (pLineDev->dwCallFlags & CALL_ALLOCATED) {
        DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:DevlineDrop - sending LINECALLSTATE_IDLE\n")));
        NewCallState(pLineDev, LINECALLSTATE_IDLE, 0L);
    }
        
    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);
    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;
    DWORD BaudRate;
    DCB commDCB;
    BOOL bExit;

    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"));

    // Enable devconfig settings
    GetCommState( pLineDev->hDevice, &commDCB );
    BaudRate = commDCB.BaudRate;    // Preserve connected baud rate
    SetDCBfromDevMiniCfg(&commDCB, &(pLineDev->DevMiniCfg));
    commDCB.BaudRate = BaudRate;
    SetCommState( pLineDev->hDevice, &commDCB );

    DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
             (TEXT("UNIMODEM:WatchForDisconnect - RTS Control %d, CTS Out Flow %d, XON/XOFF out/in %d/%d\r\n\r\n"),
              commDCB.fRtsControl, commDCB.fOutxCtsFlow, commDCB.fOutX, commDCB.fInX));

    EnterCriticalSection(&pLineDev->OpenCS);
    bExit = (pLineDev->dwWaitMask == 0);
    if (!bExit) {
        SetCommMask(pLineDev->hDevice_r0, EV_RLSD);
    }
    LeaveCriticalSection(&pLineDev->OpenCS);
    if (bExit) {
        goto wfd_exit;
    }

    while ((pLineDev->dwCallState == LINECALLSTATE_CONNECTED) && (pLineDev->dwCallFlags & CALL_ACTIVE)) {
        if (WaitCommEvent(pLineDev->hDevice_r0, &Mask, NULL )) {
            //
            // Remote disconnect detection
            //
            if (Mask & EV_RLSD) {
                ModemStatus = 0;
                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;
                    }

⌨️ 快捷键说明

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