📄 modem.c
字号:
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 (DEVST_DISCONNECTED == pLineDev->DevState) {
pLineDev->DevState = DEVST_PORTLISTENINIT;
}
if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
hPrevCall = pLineDev->htCall;
} else {
hPrevCall = NULL;
}
rc = DevlineOpen(pLineDev);
if ((rc) && (rc != LINEERR_ALLOCATED)) {
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) DevlineOpen failed\n"), pLineDev->dwDeviceID));
goto uct_leave;
}
FreeNextCmd(pLineDev);
MdmCommandMode(pLineDev);
pLineDev->dwWaitMask = EV_DEFAULT;
SetCommMask(pLineDev->hDevice, EV_DEFAULT);
if (!IS_NULL_MODEM(pLineDev)) {
//
// Don't init a manual dial modem
//
if (!(pLineDev->DevMiniCfg.fwOptions & MANUAL_DIAL)) {
//
// If modeminit fails, we sure won't be able to anything!
//
if (!DoModemInit(pLineDev)) {
if (pLineDev->fTakeoverMode) {
goto uct_calldone;
}
pLineDev->DevState = DEVST_DISCONNECTED;
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) ModemInit failed\n"), pLineDev->dwDeviceID));
goto uct_leave;
}
}
}
if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
pLineDev->DevState = DEVST_PORTCONNECTDIAL;
LeaveCriticalSection(&pLineDev->OpenCS);
if (ProcessModemFailure(pLineDev)) {
EnterCriticalSection(&pLineDev->OpenCS);
goto uct_leave;
}
EnterCriticalSection(&pLineDev->OpenCS);
} 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_leave;
}
}
}
bPendingOp = FALSE;
MdmResp = MODEM_FAILURE;
uct_monitor: // NOTE: OpenCS must be owned here
//
// Monitor modem responses
//
while (pLineDev->htLine && (pLineDev->DevState != DEVST_DISCONNECTED)) {
if ((pLineDev->DevState == DEVST_PORTLISTENING) || (pLineDev->DevState == DEVST_PORTLISTENOFFER)) {
if (pLineDev->lpstrNextCmd) {
if (!MdmSendCommand(pLineDev, pLineDev->lpstrNextCmd)) {
goto uct_calldone;
}
}
switch (pLineDev->dwPendingType) {
//
// If the user did an open/close in quick succession then check for it.
//
case PENDING_EXIT:
MdmResp = MODEM_EXIT;
goto uct_leave;
break;
case PENDING_LINEMAKECALL:
pLineDev->DevState = DEVST_PORTCONNECTDIAL;
MdmResp = MODEM_FAILURE;
LeaveCriticalSection(&pLineDev->OpenCS);
goto uct_process;
break;
case PENDING_LINEANSWER:
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);
goto uct_process;
}
break;
}
if (pLineDev->lpstrNextCmd) {
//
// 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, OPENED)) == MODEM_SUCCESS) {
if (pLineDev->dwPendingType == PENDING_LISTEN) {
MdmResp = MdmGetResponse(pLineDev, pLineDev->lpstrNextCmd, NOCS, OPENED);
}
}
} else {
//
// Still listening for an incoming call
//
MdmResp = MdmGetResponse(pLineDev, "listening", LEAVECS, OPENED);
}
} else {
LeaveCriticalSection(&pLineDev->OpenCS);
}
uct_process: // NOTE: OpenCS must not be owned here
FreeNextCmd(pLineDev);
switch (MdmResp) {
case MODEM_RING:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) MODEM_RING\n"), pLineDev->dwDeviceID));
if (ProcessModemRing(pLineDev)) {
EnterCriticalSection(&pLineDev->OpenCS);
goto uct_calldone;
}
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)) {
EnterCriticalSection(&pLineDev->OpenCS);
goto uct_calldone;
}
break;
case MODEM_EXIT:
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) MODEM_EXIT\n"), pLineDev->dwDeviceID));
EnterCriticalSection(&pLineDev->OpenCS);
goto uct_calldone;
break;
} // switch
MdmResp = MODEM_FAILURE;
EnterCriticalSection(&pLineDev->OpenCS);
} // while
uct_calldone:
FreeNextCmd(pLineDev);
//
// 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;
}
//
// Go back to monitoring for incoming calls if needed
//
if (pLineDev->dwDetMediaModes) {
LeaveCriticalSection(&pLineDev->OpenCS);
DoDevlineDrop(pLineDev);
EnterCriticalSection(&pLineDev->OpenCS);
//
// Make sure the handle is still valid.
//
if (SetCommMask(pLineDev->hDevice, EV_DEFAULT)) {
pLineDev->dwWaitMask = EV_DEFAULT;
pLineDev->DevState = DEVST_PORTLISTENING;
if (IS_NULL_MODEM(pLineDev)) {
pLineDev->dwNumRings = 0;
SetDialerTimeouts(pLineDev);
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) Continue monitoring\n"), pLineDev->dwDeviceID));
goto uct_monitor;
}
if (GetMonitorCommand(pLineDev)) {
MdmCommandMode(pLineDev);
pLineDev->dwNumRings = 0;
if (pLineDev->dwPendingStatus == LINEERR_ALLOCATED) {
SetAsyncStatus(pLineDev, LINEERR_OPERATIONFAILED);
}
DEBUGMSG(ZONE_THREAD, (TEXT("UnimodemControlThread(%d) Continue monitoring\n"), pLineDev->dwDeviceID));
SetDialerTimeouts(pLineDev);
goto uct_monitor;
}
}
}
uct_leave:
FreeNextCmd(pLineDev);
// Make sure that we do not leave anything open
SetWatchdog(pLineDev, 0 ); // Cancel watchdog
pLineDev->bControlThreadRunning = FALSE;
LeaveCriticalSection(&pLineDev->OpenCS);
SetAsyncStatus(pLineDev, LINEERR_OPERATIONFAILED);
if (bPendingOp) {
if (pLineDev->dwPendingType == PENDING_LINEMAKECALL) {
pLineDev->htCall = hPrevCall;
NewCallState(pLineDev, LINECALLSTATE_DISCONNECTED, 0L);
pLineDev->htCall = NULL;
}
}
DevlineClose(pLineDev, TRUE);
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 = SignalCommMask(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 + -