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

📄 modem.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
// ****************************************************************************
//
//  Module:     Unimdm
//  File:       modem.c
//
//  Copyright (c) 1992-2000 Microsoft Corporation.  All rights reserved.
//
//  Revision History
//
//  Description: Intermediate modem SPI layer
//
// ****************************************************************************

#include "windows.h"
#include "types.h"
#include "memory.h"
#include "tspi.h"
#include "linklist.h"
#include "tspip.h"
#include "tapicomn.h"
#include "mcx.h"
#include "dial.h"

static const WCHAR szAnswer[] =   TEXT("Answer");   // Registry value name under Settings
static const CHAR szDefaultAnswerCmd[] = "ATA\r\n";
static const WCHAR szMonitor[] =   TEXT("Monitor"); // Registry value name under Settings
static const CHAR szDefaultMonitorCmd[] = "ATS0=0\r\n";
static const WCHAR szMdmLogBase[] =   TEXT("mdmlog");
static const WCHAR szMdmLogExt[] =   TEXT(".txt");
extern const WCHAR szSettings[];

extern DWORD SetWatchdog(PTLINEDEV pLineDev,DWORD dwTimeout);

// Unimodem thread priority
extern DWORD g_dwUnimodemThreadPriority;
extern HANDLE g_hCoreDLL;

#ifdef DEBUG
LPWSTR
GetPendingName(
    DWORD dwPendingType
    )
{
    LPWSTR lpszType;
    
    switch (dwPendingType) {
    case PENDING_LINEACCEPT:        lpszType = TEXT("LINEACCEPT");          break;
    case PENDING_LINEANSWER:        lpszType = TEXT("LINEANSWER");          break;
    case PENDING_LINEDEVSPECIFIC:   lpszType = TEXT("LINEDEVSPECIFIC");     break;
    case PENDING_LINEDIAL:          lpszType = TEXT("LINEDIAL");            break;
    case PENDING_LINEDROP:          lpszType = TEXT("LINEDROP");            break;
    case PENDING_LINEMAKECALL:      lpszType = TEXT("LINEMAKECALL");        break;
    case PENDING_LISTEN:            lpszType = TEXT("LISTEN");              break;
    case PENDING_EXIT:              lpszType = TEXT("EXIT");                break;
    case INVALID_PENDINGOP:         lpszType = TEXT("INVALIDOP");           break;
    default:                        lpszType = TEXT("UNKNOWN!!!");          break;
    }
    
    return lpszType;
}
#endif

//
// Function to open the modem command log file for the specified line device
//
void
OpenModemLog(
    PTLINEDEV pLineDev
    )
{
    WCHAR FileName[16];
    LPWSTR lpwsz;
    HANDLE hFile;

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

    if (pLineDev->hMdmLog != (HANDLE)INVALID_DEVICE) {
        CloseHandle(pLineDev->hMdmLog);
    }

    //
    // Format modem log file name "mdmlog<dwDeviceID>.txt"
    //
    wcscpy(FileName, szMdmLogBase);
    lpwsz = FileName + wcslen(FileName);
    wsprintf(lpwsz, TEXT("%d"), pLineDev->dwDeviceID);
    wcscat(FileName, szMdmLogExt);

    hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        DEBUGMSG(ZONE_CALLS|ZONE_FUNC|ZONE_ERROR,
            (TEXT("UNIMODEM:OpenModemLog CreateFile(%s) failed %d\n"), FileName, GetLastError()));
        pLineDev->hMdmLog = (HANDLE)INVALID_DEVICE;
    } else {
        DEBUGMSG(ZONE_CALLS|ZONE_FUNC, (TEXT("UNIMODEM:OpenModemLog CreateFile(%s) succeeded\n"), FileName));
        pLineDev->hMdmLog = hFile;
    }

    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-OpenModemLog\n")));
} // OpenModemLog


//
// Function to write modem commands to the line device's command history file.
// 
void
WriteModemLog(
    PTLINEDEV pLineDev,
    UCHAR * szCommand,
    DWORD   dwOp
    )
{
    CHAR Buf[MAXSTRINGLENGTH];
    LPSTR  lpsz;
    DWORD  dwLen;
    DWORD  dwIO;

    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+WriteModemLog %a\n"), szCommand));

    switch (dwOp) {
    case MDMLOG_COMMAND_OK:
        lpsz = "Modem Command:   ";
        break;
    case MDMLOG_COMMAND_FAIL:
        lpsz = "Failed Command:  ";
        break;
    case MDMLOG_RESPONSE:
        lpsz = "Modem Response:  ";
        break;

    default:
        lpsz = "                 ";
        break;
    }

    Buf[MAXSTRINGLENGTH-2] = 0;
    strcpy(Buf, lpsz);
    dwLen = strlen(Buf);
    strncat(Buf, szCommand, MAXSTRINGLENGTH - dwLen - 2);
    dwLen += strlen(szCommand);
    if (dwLen > (MAXSTRINGLENGTH - 2)) {
        dwLen = MAXSTRINGLENGTH - 2;
    }
    Buf[dwLen] = '\n';
    dwLen++;
    Buf[dwLen] = '\0';

    DEBUGMSG(ZONE_CALLS|ZONE_FUNC, (TEXT("UNIMODEM:WriteModemLog(%a) %d bytes\n"), Buf, dwLen));
    if (!WriteFile(pLineDev->hMdmLog, (PUCHAR)Buf, dwLen, &dwIO, NULL)) {
        DEBUGMSG(ZONE_CALLS|ZONE_FUNC, (TEXT("UNIMODEM:WriteModemLog WriteFile() failed %d\n"), GetLastError()));
    }
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-WriteModemLog\n")));
}   // WriteModemLog


void
SetDCBfromDevMiniCfg(
    DCB * pDCB,
    PDEVMINICFG lpDevMiniCfg
    )
{
    pDCB->BaudRate = lpDevMiniCfg->dwBaudRate;
    pDCB->ByteSize = lpDevMiniCfg->ByteSize;
    pDCB->StopBits = lpDevMiniCfg->StopBits;
    pDCB->fParity = (NOPARITY == lpDevMiniCfg->Parity) ? FALSE : TRUE;
    pDCB->Parity   = lpDevMiniCfg->Parity;
    pDCB->fDsrSensitivity = FALSE;
    pDCB->fDtrControl     = DTR_CONTROL_ENABLE;
    
    if( MDM_FLOWCONTROL_HARD & lpDevMiniCfg->dwModemOptions ) {
        // Enable RTS/CTS Flow Control
        pDCB->fRtsControl = RTS_CONTROL_HANDSHAKE;
        pDCB->fOutxCtsFlow = 1;
        pDCB->fOutX = 0;
        pDCB->fInX = 0;
    } else if( MDM_FLOWCONTROL_SOFT & lpDevMiniCfg->dwModemOptions ) {
        // Enable XON/XOFF Flow Control
        pDCB->fRtsControl = RTS_CONTROL_ENABLE;
        pDCB->fOutxCtsFlow = 0;
        pDCB->fOutX = 1;
        pDCB->fInX  = 1;  
    } else {
        pDCB->fRtsControl = RTS_CONTROL_ENABLE;
        pDCB->fOutxCtsFlow = 0;
        pDCB->fOutX = 0;
        pDCB->fInX  = 0;
    }
}   // SetDCBfromDevMiniCfg


void
SetDialerTimeouts(
    HANDLE hComDev
    )
{
    COMMTIMEOUTS commTimeouts;

    GetCommTimeouts (hComDev, &commTimeouts);
    commTimeouts.ReadIntervalTimeout = 50;
    commTimeouts.ReadTotalTimeoutMultiplier = 0;
    commTimeouts.ReadTotalTimeoutConstant = 50;
    commTimeouts.WriteTotalTimeoutMultiplier = 5;
    commTimeouts.WriteTotalTimeoutConstant = 500;
    SetCommTimeouts (hComDev, &commTimeouts);
}   // SetDialerTimeouts

DWORD
OpenModem (
    LPCWSTR      lpszPortName,
    LPDWORD      lpR3handle,
    LPDWORD      lpR0handle,
    PDEVMINICFG  lpDevMiniCfg )
{
    HANDLE hComDev;
    HANDLE hComDev0;
    WCHAR  szDeviceName[16];

    DEBUGMSG(ZONE_FUNC|ZONE_CALLS, (TEXT("UNIMODEM:+OpenModem('%s')\r\n"), lpszPortName));

        // Compose the device name from the portname
    wcscpy(szDeviceName, lpszPortName);
    
     // Open the device
     //
    if ((hComDev = CreateFile(szDeviceName, GENERIC_READ | GENERIC_WRITE, 0,
                              NULL, OPEN_EXISTING, 0, 0))
        == INVALID_HANDLE_VALUE) {
        goto om_fail;
    }
    if ((hComDev0 = CreateFile(szDeviceName, 0, 0,
                              NULL, OPEN_EXISTING, 0, 0))
        != INVALID_HANDLE_VALUE) {
        DCB          commDCB;

        DEBUGMSG(ZONE_MISC|ZONE_CALLS,
                 (TEXT("UNIMODEM:OpenModem - createfile OK, handle x%X\n"),
                  hComDev));
        
        // ********************************************************
        // Set the device configuration based on DEVMINICFG
        //
        GetCommState( hComDev, &commDCB );
        SetDCBfromDevMiniCfg(&commDCB, lpDevMiniCfg);

        DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
                 (TEXT("UNIMODEM:OpenModem Setting port configuration :\n")));
        DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
                 (TEXT("UNIMODEM:OpenModem Baud %d, Byte Size %d, Stop bits %d, Parity %d\n"),
                  commDCB.BaudRate, commDCB.ByteSize, commDCB.StopBits, commDCB.Parity));
        DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
                 (TEXT("UNIMODEM:OpenModem RTS Control %d, CTS Out Flow %d, XON/XOFF out/in %d/%d\n"),
                  commDCB.fRtsControl, commDCB.fOutxCtsFlow, commDCB.fOutX, commDCB.fInX));
        SetCommState( hComDev, &commDCB );
        
        // Adjust the read/write timeouts as required by dialer thread
        SetDialerTimeouts(hComDev);
        
        *lpR3handle = (DWORD)hComDev;
        *lpR0handle = (DWORD)hComDev0;
        
        DEBUGMSG(ZONE_FUNCTION, (TEXT("UNIMODEM:-OpenModem\n")));
        return ERROR_SUCCESS;
    } else {
        CloseHandle(hComDev);
    }

om_fail:
    DEBUGMSG(ZONE_FUNCTION,
             (TEXT("UNIMODEM:-OpenModem : Unable to open %s, hComdev x%X\n"),
              szDeviceName, hComDev));

    return ERROR_OPEN_FAILED;
}

// ****************************************************************************
// lineOpen()
//
// Function: Emulate the TAPI lineOpen call.
//
// ****************************************************************************

LONG
DevlineOpen (
    PTLINEDEV pLineDev
    )
{
    DWORD idMdm;
    DWORD idMdm0;
    DWORD dwRet;

    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+DevlineOpen\r\n")));
    EnterCriticalSection(&pLineDev->OpenCS);
    
    // The line must be closed
    if (pLineDev->hDevice != (HANDLE)INVALID_DEVICE) {
        DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:DevlineOpen - device already open\r\n")));
        dwRet = LINEERR_ALLOCATED;
        goto exit_Point;
    }
    
    if (0 == pLineDev->wDeviceAvail) {
        DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:DevlineOpen - device has been removed\r\n")));
        dwRet = LINEERR_NODEVICE;
        goto exit_Point;
    }

     // Open the modem port
    DEBUGMSG(ZONE_MISC, (TEXT("UNIMODEM:DevlineOpen - calling openmodem\r\n")));
    dwRet = OpenModem(pLineDev->szDeviceName,
                      &idMdm, &idMdm0,
                      &pLineDev->DevMiniCfg);
    if (dwRet == SUCCESS) {                                             
        // we successfully opened the modem

        // Convert modem handle to ring 0 handle
        pLineDev->hDevice       = (HANDLE)idMdm;
        pLineDev->hDevice_r0    = (HANDLE)idMdm0;
        pLineDev->DevState      = DEVST_DISCONNECTED;

        OpenModemLog(pLineDev);

    } else {
        dwRet = LINEERR_RESOURCEUNAVAIL;
    };

exit_Point:
    LeaveCriticalSection(&pLineDev->OpenCS);
    DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-DevlineOpen x%X\r\n"), dwRet));
    return dwRet;
}

//****************************************************************************
// lineClose()
//
// Function: Emulate the TAPI lineClose call.
//
// NOTE : The fDoDrop flag is used to indicate that we should
//        make sure the line gets dropped before we close it.
//
//****************************************************************************

LONG
DevlineClose (
    PTLINEDEV pLineDev,
    BOOL fDoDrop
    )
{
    DWORD dwPrevCallState;
    HTAPICALL hPrevCall;
    DWORD dwPrevProcPerms;

    DEBUGMSG(ZONE_FUNC|ZONE_CALLS,
             (TEXT("UNIMODEM:+DevlineClose, handle x%X, callstate x%X\r\n"),
              pLineDev->hDevice, pLineDev->dwCallState));

    // Grab a critical section to ensure the app doesn't call in and
    // cause a line close while we are in the middle of doing a close
    // ourselves.
    EnterCriticalSection(&pLineDev->OpenCS);

    dwPrevCallState = pLineDev->dwCallState;
    hPrevCall = pLineDev->htCall;

    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 && LINECALLSTATE_CONNECTED == pLineDev->dwCallState) {
                DEBUGMSG(ZONE_CALLS, (L"UNIMODEM:DevlineClose - Callstate x%X, dropping call\r\n",
                    pLineDev->dwCallState));
                DevlineDrop(pLineDev);   
            }
    
            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.
        }
    }
    
    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
ToggleCommMask(
    PTLINEDEV pLineDev
    )
{
    LONG rc = 0;

    if ((HANDLE)INVALID_DEVICE != pLineDev->hDevice) {
        try {
            if (!SetCommMask( pLineDev->hDevice, 0)) {
                DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask(0) failed %d\n"), GetLastError()));
                rc = LINEERR_OPERATIONFAILED;
            }
            if (!SetCommMask( pLineDev->hDevice_r0, 0)) {
                DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask(r0,0) failed %d\n"), GetLastError()));
                rc = LINEERR_OPERATIONFAILED;
            }
            if (!SetCommMask( pLineDev->hDevice, EV_DEFAULT)) {
                DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask() failed %d\n"), GetLastError()));
                rc = LINEERR_OPERATIONFAILED;
            }
            if (!SetCommMask( pLineDev->hDevice_r0, EV_RLSD)) {
                DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask(r0) failed %d\n"), GetLastError()));
                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;
        }
    }
    return rc;
}   // ToggleCommMask



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

⌨️ 快捷键说明

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