?? modem.c
字號:
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-ProcessModemFailure %d\n"), rc));
return rc;
} // ProcessModemFailure
BOOL
GetMonitorCommand(
PTLINEDEV pLineDev
)
{
LPWSTR lpszTemp;
DWORD dwSize;
//
// For manual dial modems, don't listen for incoming calls
//
if (pLineDev->DevMiniCfg.fwOptions & MANUAL_DIAL) {
FreeNextCmd(pLineDev);
return TRUE;
}
if (MdmRegGetValue(
pLineDev,
szSettings,
szMonitor,
REG_SZ,
NULL,
&dwSize) == ERROR_SUCCESS) {
lpszTemp = TSPIAlloc(dwSize);
if (!lpszTemp) {
DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:GetMonitorCommand - Monitor cmd alloc failed 1\n")));
goto gmc_DefaultMonitorCmd;
}
if (MdmRegGetValue(
pLineDev,
szSettings,
szMonitor,
REG_SZ,
(PUCHAR)lpszTemp,
&dwSize) == ERROR_SUCCESS) {
pLineDev->lpstrNextCmd = MdmConvertCommand(lpszTemp, NULL, NULL);
TSPIFree(lpszTemp);
} else {
goto gmc_DefaultMonitorCmd;
}
} else {
gmc_DefaultMonitorCmd:
pLineDev->lpstrNextCmd = TSPIAlloc(strlen(szDefaultMonitorCmd)+1);
if (!pLineDev->lpstrNextCmd) {
DEBUGMSG(ZONE_THREAD, (TEXT("UNIMODEM:GetMonitorCommand - Monitor cmd alloc failed 2\n")));
return FALSE;
}
strcpy(pLineDev->lpstrNextCmd, szDefaultMonitorCmd);
}
return TRUE;
}
BOOL
DoModemInit(
PTLINEDEV pLineDev
)
{
DCB commDCB;
BOOL bRet;
//
// Turn off hardware flow control while sending commands.
//
GetCommState( pLineDev->hDevice, &commDCB );
commDCB.fRtsControl = RTS_CONTROL_ENABLE;
commDCB.fOutxCtsFlow = 0;
SetCommState( pLineDev->hDevice, &commDCB );
bRet = ModemInit(pLineDev);
//
// Restore original settings
//
SetDCBfromDevMiniCfg(&commDCB, &(pLineDev->DevMiniCfg));
SetCommState( pLineDev->hDevice, &commDCB );
return bRet;
}
//
// Send commands and listen for responses until the line is closed
//
DWORD
UnimodemControlThread(
PTLINEDEV pLineDev
)
{
MODEMRESPCODES MdmResp;
DWORD rc;
BOOL bPendingOp;
HTAPICALL hPrevCall;
EnterCriticalSection(&pLineDev->OpenCS);
bPendingOp = !((PENDING_LISTEN == pLineDev->dwPendingType) || (INVALID_PENDINGOP == pLineDev->dwPendingType));
DEBUGMSG(ZONE_FUNC|ZONE_THREAD, (TEXT("+UnimodemControlThread(%d)\n"), pLineDev->dwDeviceID));
if (bPendingOp) {
DEBUGMSG(ZONE_THREAD, (L"UnimodemControlThread(%d) PendingOp=%s\n",
pLineDev->dwDeviceID, GetPendingName(pLineDev->dwPendingType)));
}
if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
hPrevCall = pLineDev->htCall;
}
rc = DevlineOpen(pLineDev);
if ((rc) && (rc != LINEERR_ALLOCATED)) {
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) DevlineOpen failed\n"), pLineDev->dwDeviceID));
goto uct_endCS;
}
FreeNextCmd(pLineDev);
if (IS_NULL_MODEM(pLineDev)) {
SetCommMask(pLineDev->hDevice, EV_DEFAULT);
} else {
//
// Don't init a manual dial modem
//
if (pLineDev->DevMiniCfg.fwOptions & MANUAL_DIAL) {
SetCommMask(pLineDev->hDevice, EV_DEFAULT);
} else {
//
// If modeminit fails, we sure won't be able to anything!
//
if (!DoModemInit(pLineDev)) {
pLineDev->DevState = DEVST_DISCONNECTED;
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) ModemInit failed\n"), pLineDev->dwDeviceID));
goto uct_endCS;
}
}
}
LeaveCriticalSection(&pLineDev->OpenCS);
if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
pLineDev->DevState = DEVST_PORTCONNECTDIAL;
ProcessModemFailure(pLineDev);
} else {
pLineDev->DevState = DEVST_PORTLISTENING;
if (!IS_NULL_MODEM(pLineDev)) {
//
// Not making a call so monitor the line for incoming calls.
//
if (!GetMonitorCommand(pLineDev)) {
goto uct_end;
}
}
}
bPendingOp = FALSE;
MdmResp = MODEM_FAILURE;
uct_monitor:
//
// Monitor modem responses
//
while (pLineDev->DevState != DEVST_DISCONNECTED) {
if ((pLineDev->DevState == DEVST_PORTLISTENING) || (pLineDev->DevState == DEVST_PORTLISTENOFFER)) {
if (pLineDev->lpstrNextCmd) {
if (!MdmSendCommand(pLineDev, pLineDev->lpstrNextCmd)) {
goto uct_end;
}
}
EnterCriticalSection(&pLineDev->OpenCS);
//
// If the user did an open/close in quick succession then check for it.
//
switch (pLineDev->dwPendingType) {
case PENDING_EXIT:
MdmResp = MODEM_EXIT;
goto uct_endCS;
break;
case PENDING_LINEMAKECALL:
pLineDev->DevState = DEVST_PORTCONNECTDIAL;
MdmResp = MODEM_FAILURE;
LeaveCriticalSection(&pLineDev->OpenCS);
goto uct_process;
break;
}
if (pLineDev->lpstrNextCmd) {
if (IS_NULL_MODEM(pLineDev)) {
//
// We only get here if we just responded with "CLIENTSERVER" to someone's "CLIENT",
// so no further responses are needed. The connection is established.
//
MdmResp = MODEM_CONNECT;
SetEvent(pLineDev->hCallComplete);
LeaveCriticalSection(&pLineDev->OpenCS);
} else {
//
// Some modems don't respond to the monitor command until an incoming call is made,
// but some modems do respond to the monitor command so we wait for a MODEM_RING response.
//
if ((MdmResp = MdmGetResponse(pLineDev, pLineDev->lpstrNextCmd, LEAVECS)) == MODEM_SUCCESS) {
if (pLineDev->dwPendingType == PENDING_LISTEN) {
MdmResp = MdmGetResponse(pLineDev, pLineDev->lpstrNextCmd, NOCS);
}
}
}
} else {
PurgeComm(pLineDev->hDevice, PURGE_RXCLEAR|PURGE_TXCLEAR);
//
// DCC server has no specific monitor command.
// Also for manual dial, this thread needs to be in a WaitCommEvent
//
MdmResp = MdmGetResponse(pLineDev, "listening", LEAVECS);
}
}
uct_process:
FreeNextCmd(pLineDev);
switch (MdmResp) {
case MODEM_RING:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) MODEM_RING\n"), pLineDev->dwDeviceID));
ProcessModemRing(pLineDev);
break;
case MODEM_CARRIER:
case MODEM_PROTOCOL:
case MODEM_PROGRESS:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) LINECALLSTATE_PROCEEDING\n"), pLineDev->dwDeviceID));
ProcessModemProceeding(pLineDev);
break;
case MODEM_CONNECT:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) LINECALLSTATE_CONNECTED\n"), pLineDev->dwDeviceID));
ProcessModemConnect(pLineDev);
break;
case MODEM_SUCCESS:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) MODEM_SUCCESS\n"), pLineDev->dwDeviceID));
ProcessModemSuccess(pLineDev);
break;
case MODEM_FAILURE:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) MODEM_FAILURE\n"), pLineDev->dwDeviceID));
if (ProcessModemFailure(pLineDev)) {
goto uct_end;
}
break;
case MODEM_EXIT:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) MODEM_EXIT\n"), pLineDev->dwDeviceID));
goto uct_end;
break;
} // switch
MdmResp = MODEM_FAILURE;
} // while
uct_end:
//
// Go back to monitoring for incoming calls if needed
//
if (pLineDev->dwDetMediaModes) {
//
// Make sure the handle is still valid.
//
if (SetCommMask(pLineDev->hDevice, EV_DEFAULT)) {
pLineDev->DevState = DEVST_PORTLISTENING;
if (IS_NULL_MODEM(pLineDev)) {
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) Continue monitoring\n"), pLineDev->dwDeviceID));
goto uct_monitor;
}
if (GetMonitorCommand(pLineDev)) {
pLineDev->dwNumRings = 0;
EnterCriticalSection(&pLineDev->OpenCS);
if (pLineDev->dwPendingStatus == LINEERR_ALLOCATED) {
SetAsyncStatus(pLineDev, LINEERR_OPERATIONFAILED);
}
LeaveCriticalSection(&pLineDev->OpenCS);
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) Continue monitoring\n"), pLineDev->dwDeviceID));
goto uct_monitor;
}
}
}
EnterCriticalSection(&pLineDev->OpenCS);
//
// Special case for PASSTHROUGH connections
//
if (pLineDev->fTakeoverMode) {
pLineDev->bControlThreadRunning = FALSE;
LeaveCriticalSection(&pLineDev->OpenCS);
DEBUGMSG(ZONE_THREAD|ZONE_FUNC, (TEXT("-UnimodemControlThread(%d) - PASSTHROUGH\n"), pLineDev->dwDeviceID));
return 0;
}
uct_endCS:
FreeNextCmd(pLineDev);
// Make sure that we do not leave anything open
SetWatchdog(pLineDev, 0 ); // Cancel watchdog
DevlineClose(pLineDev, TRUE);
pLineDev->bControlThreadRunning = FALSE;
LeaveCriticalSection(&pLineDev->OpenCS);
if (bPendingOp) {
if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
pLineDev->htCall = hPrevCall;
NewCallState(pLineDev, LINECALLSTATE_DISCONNECTED, 0L);
pLineDev->htCall = NULL;
}
SetAsyncStatus(pLineDev, LINEERR_OPERATIONFAILED);
}
DEBUGMSG(ZONE_THREAD|ZONE_FUNC, (TEXT("-UnimodemControlThread(%d)\n"), pLineDev->dwDeviceID));
return 0;
} // UnimodemControlThread
LONG
StartControlThread(
PTLINEDEV pLineDev
)
{
HANDLE hThd;
LONG rc;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+StartControlThread\n")));
rc = 0;
if (pLineDev->bControlThreadRunning == FALSE) {
pLineDev->bControlThreadRunning = TRUE;
hThd = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)UnimodemControlThread,
pLineDev, 0, NULL );
if (!hThd) {
NKDbgPrintfW( TEXT("Unable to Create UnimodemControlThread\n") );
pLineDev->bControlThreadRunning = FALSE;
rc = LINEERR_OPERATIONFAILED;
} else {
CeSetThreadPriority(hThd, g_dwUnimodemThreadPriority);
CloseHandle(hThd);
}
}
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-StartControlThread returning %x\n"), rc));
return rc;
} // StartControlThread
LONG
SignalControlThread(
PTLINEDEV pLineDev
)
{
LONG rc;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+SignalControlThread\n")));
//
// Signal UnimodemListenThread
//
rc = ToggleCommMask(pLineDev);
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-SignalControlThread returning %x\n"), rc));
return rc;
} // SignalControlThread
//
// All TSPI_line* functions that need access to the modem go through here.
// The UnimodemControlThread sends the actual commands and processes the
// responses
//
LONG
ControlThreadCmd(
PTLINEDEV pLineDev,
DWORD dwPendingOP,
DWORD dwPendingID
)
{
LONG rc;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ControlThreadCmd\n")));
// Fail current outstanding async request (if any) and remember this one
SetAsyncOp(pLineDev, dwPendingOP);
EnterCriticalSection(&pLineDev->OpenCS);
if (pLineDev->bControlThreadRunning) {
switch (dwPendingOP) {
case PENDING_LINEDROP:
case PENDING_EXIT:
case PENDING_LINEANSWER:
case PENDING_LINEDIAL:
case PENDING_LINEMAKECALL:
case PENDING_LISTEN:
rc = SignalControlThread(pLineDev);
break;
default:
rc = 0;
break;
}
} else {
switch (dwPendingOP) {
case PENDING_LINEMAKECALL:
case PENDING_LISTEN:
rc = StartControlThread(pLineDev);
break;
case PENDING_EXIT:
default:
rc = LINEERR_OPERATIONFAILED;
break;
}
}
if (rc == 0) {
switch (dwPendingOP) {
case PENDING_LINEANSWER:
case PENDING_LINEDIAL:
case PENDING_LINEDROP:
case PENDING_LINEMAKECALL:
rc = dwPendingID;
break;
}
}
LeaveCriticalSection(&pLineDev->OpenCS);
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-ControlThreadCmd returning %x\n"), rc));
return rc;
} // ControlThreadCmd
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -