📄 modem.c
字号:
voidDoHangUp( 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.////****************************************************************************LONGDevlineDrop ( 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;}LONGDoDevlineDrop( PTLINEDEV pLineDev ){ LONG rc; rc = DevlineDrop(pLineDev); SetCommMask(pLineDev->hDevice, EV_DEFAULT); SetAsyncStatus(pLineDev, 0); return rc;}voidFreeNextCmd( 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.//voidWatchForDisconnect( 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//LONGProcessModemRing( 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//LONGProcessModemProceeding( 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//LONGProcessModemConnect( 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//LONGProcessModemSuccess( 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;} // ProcessModemSuccessextern 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.//LONGProcessModemFailure( 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 + -