📄 modem.c
字号:
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 + -