📄 dial.c
字号:
pLineDev->bWatchdogTimedOut = FALSE;
// First, lets cancel any current outstanding watchdogs for this line
PulseEvent(pLineDev->hTimeoutEvent); // Stop the watchdog
// And now, start a new watchdog if they want us to
if( dwTimeout ) {
pWDInfo = TSPIAlloc(sizeof(UNIMODEM_WATCHDOG_INFO));
if (NULL == pWDInfo) {
NKDbgPrintfW( TEXT("UNIMODEM:SetWatchDog Unable to alloc Watchdog info\n") );
return (DWORD)-1;
}
pWDInfo->pLineDev = pLineDev;
pWDInfo->dwTimeout = dwTimeout;
pWDInfo->dwThisWatchdog = pLineDev->dwCurWatchdog;
hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ModemWatchdog,
pWDInfo, 0, NULL );
if ( ! hThread ) {
TSPIFree(pWDInfo);
NKDbgPrintfW( TEXT("UNIMODEM:SetWatchDog Unable to Create Watchdog Thread\n") );
return (DWORD)-1;
}
CeSetThreadPriority(hThread, g_dwUnimodemThreadPriority - 1);
CloseHandle( hThread );
}
return STATUS_SUCCESS;
}
#define INIT_WATCHDOG_TIMEOUT 4000
BOOL
ModemInit(
PTLINEDEV pLineDev
)
{
MODEMRESPCODES MdmResp = MODEM_FAILURE;
DWORD dwSize, dwCmdLen;
int RetryCount = 0;
PWCHAR pszTemp = NULL;
PWCHAR pszExpand = NULL;
PCHAR pchCmd = NULL;
MODEMMACRO ModemMacro;
DWORD dwCallSetupFailTimer;
DEVSTATES OrigDevState;
BOOL bFailed;
BOOL bEscapeSent; // only send "+++" once.
MDMSTATE NewMdmState;
static const WCHAR szReset[] = TEXT("Reset");
static const WCHAR szFlowHard[] = TEXT("FlowHard");
static const WCHAR szFlowSoft[] = TEXT("FlowSoft");
static const WCHAR szFlowNone[] = TEXT("FlowOff");
static const WCHAR *szFlowType; // Hard, Soft, None
static const WCHAR szCallFail[] = TEXT("CallSetupFailTimeout");
static const UCHAR szEscapeCmd[] = "+++";
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+ModemInit\r\n")));
EnterCriticalSection(&pLineDev->OpenCS);
if (bFailed = (pLineDev->MdmState == MDMST_INITIALIZING)) {
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Already MDMST_INITIALIZING!\r\n")));
} else {
pLineDev->MdmState = MDMST_INITIALIZING;
OrigDevState = pLineDev->DevState;
}
LeaveCriticalSection(&pLineDev->OpenCS);
if (bFailed) {
return FALSE;
}
bFailed = TRUE;
bEscapeSent = FALSE;
NewMdmState = MDMST_UNKNOWN;
try
{
// Allocate temp buffers for registry results
pszTemp = (PWCHAR)TSPIAlloc( (pLineDev->dwMaxCmd + 1) * SZWCHAR );
pszExpand = (PWCHAR)TSPIAlloc( (pLineDev->dwMaxCmd + 1) * SZWCHAR );
pchCmd = (PCHAR)TSPIAlloc( pLineDev->dwMaxCmd + 1 );
if (!(pszTemp && pszExpand && pchCmd))
{
goto init_error;
}
// First, read the reset command from the registry
dwSize = pLineDev->dwMaxCmd * SZWCHAR;
if (ERROR_SUCCESS !=
MdmRegGetValue( pLineDev,
szSettings,
szReset,
REG_SZ,
(PUCHAR)pszTemp,
&dwSize) )
{
goto init_error;
}
MdmConvertCommand(pszTemp, pchCmd, &dwCmdLen);
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Reset string is \"%s\" (%d)\r\n"),
pszTemp, dwCmdLen));
// ***** reset modem by clearing DTR
if(LineNotDropped(pLineDev, OrigDevState))
{
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit EscapeCommFunction - DTR off\r\n")));
EscapeCommFunction ( pLineDev->hDevice, CLRDTR);
Sleep( 400 );
}
if(LineNotDropped(pLineDev, OrigDevState))
{
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit EscapeCommFunction - DTR on\r\n")));
EscapeCommFunction ( pLineDev->hDevice, SETDTR);
Sleep( 200 );
}
while( (LineNotDropped(pLineDev, OrigDevState)) &&
(RetryCount < MAX_COMMAND_TRIES) )
{
// Set short timeout for init strings
if( SetWatchdog( pLineDev, INIT_WATCHDOG_TIMEOUT ) )
{
goto init_error;
}
if( LineNotDropped(pLineDev, OrigDevState) )
{
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Send Init\r\n")));
MdmResp = MODEM_FAILURE;
if (MdmSendCommand( pLineDev, pchCmd )) {
MdmResp = MdmGetResponse( pLineDev, pchCmd, NOCS, OPENED);
}
}
// See if we managed to get initialized
if( MODEM_SUCCESS == MdmResp )
{
NewMdmState = MDMST_DISCONNECTED; // It worked
break;
}
else
{
if (bEscapeSent) {
//
// Avoid trying "+++" 3 times. If there is no modem on the port
// we'd take over 15 seconds to fail. If there is a modem, one "+++"
// ought to be enough.
//
goto init_error;
} else {
bEscapeSent = TRUE;
if( LineNotDropped(pLineDev, OrigDevState) )
{
// the modem didn't reset
NewMdmState = MDMST_UNKNOWN;
// If szReset didn't work, we likely need a +++
MdmSendCommand( pLineDev, szEscapeCmd );
Sleep( 200 );
}
}
}
RetryCount++;
}
if( (MDMST_DISCONNECTED == NewMdmState) &&
(LineNotDropped(pLineDev, OrigDevState)) )
{
DWORD mdmRegRslt = ERROR_SUCCESS;
WORD wInitKey;
// read a sequence of additional init strings from the
// registry and send them down now. Can't enumerate the
// keys since that wouldn't allow us to have modem specific
// values mixed with default values.
wInitKey = 0;
while( (wInitKey < MAXINITKEYS) &&
(LineNotDropped(pLineDev, OrigDevState)) &&
(ERROR_SUCCESS == mdmRegRslt) )
{
dwSize = pLineDev->dwMaxCmd * SZWCHAR;
mdmRegRslt = MdmRegGetValue( pLineDev,
szInit,
szInitNum[wInitKey],
REG_SZ,
(PUCHAR)pszTemp,
&dwSize);
if (ERROR_SUCCESS == mdmRegRslt)
{
MdmConvertCommand(pszTemp, pchCmd, &dwCmdLen);
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Init string %d - %s\r\n"),
wInitKey, pszTemp));
// Set short timeout for init strings
if( SetWatchdog( pLineDev, INIT_WATCHDOG_TIMEOUT ) )
{
goto init_error;
}
if (LineNotDropped(pLineDev, OrigDevState)) {
// We got a value, write it out to modem
MdmResp = MODEM_FAILURE;
if (MdmSendCommand( pLineDev, pchCmd )) {
if (LineNotDropped(pLineDev, OrigDevState)) {
MdmResp = MdmGetResponse( pLineDev, pchCmd, NOCS, OPENED);
}
}
}
if( MODEM_SUCCESS != MdmResp )
{
// bad init string. We can't recover from this so exit
goto init_error;
}
}
else
{
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ModemInit Error x%X reading Init string %d\r\n"),
mdmRegRslt, wInitKey));
}
wInitKey++;
}
// And now that we have the basic init in place, we still need to
// make sure the flow control settings match what we are doing in
// the UART.
if( MDM_FLOWCONTROL_HARD & pLineDev->DevMiniCfg.dwModemOptions )
{ // Set Modem for hardware flow control
szFlowType = szFlowHard;
}
else if( MDM_FLOWCONTROL_SOFT & pLineDev->DevMiniCfg.dwModemOptions )
{ // Set Modem for software flow control
szFlowType = szFlowSoft;
}
else
{ // Set modem for no flow control
szFlowType = szFlowNone;
}
dwSize = pLineDev->dwMaxCmd * SZWCHAR;
if( ERROR_SUCCESS == MdmRegGetValue( pLineDev,
szSettings,
szFlowType,
REG_SZ,
(PUCHAR)pszTemp,
&dwSize) )
{
// OK, we got the flow control command, send it.
MdmConvertCommand(pszTemp, pchCmd, &dwCmdLen);
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Flow Control string %s\r\n"),
pszTemp));
if (LineNotDropped(pLineDev, OrigDevState))
{
// We got a value, write it out to modem
MdmResp = MODEM_FAILURE;
if (MdmSendCommand( pLineDev, pchCmd )) {
if (LineNotDropped(pLineDev, OrigDevState)) {
MdmResp = MdmGetResponse( pLineDev, pchCmd, NOCS, OPENED);
}
}
}
if( MODEM_SUCCESS != MdmResp )
{
// bad flow control string. We can't recover from this.
goto init_error;
}
}
// Now we set up the call fail timer if it exists.
dwSize = pLineDev->dwMaxCmd * SZWCHAR;
if( ERROR_SUCCESS == MdmRegGetValue( pLineDev,
szSettings,
szCallFail,
REG_SZ,
(PUCHAR)pszTemp,
&dwSize) )
{
// OK, we got the Call Fail setup command, send it.
// Most modems can't handle a value > 255 for call fail time
// And a time of 0 usually really means wait the maximum
dwCallSetupFailTimer = pLineDev->DevMiniCfg.dwCallSetupFailTimer;
if( (dwCallSetupFailTimer > 255) ||
(dwCallSetupFailTimer == 0) )
dwCallSetupFailTimer = 255;
// Expand macros, including the fail time <#>
wcscpy(ModemMacro.MacroName, INTEGER_MACRO);
StringCchPrintfW(ModemMacro.MacroValue, sizeof(ModemMacro.MacroValue)/sizeof(WCHAR), L"%d", dwCallSetupFailTimer);
ExpandMacros(pszTemp, pszExpand, pLineDev->dwMaxCmd, &ModemMacro);
// We need to convert the UniCode to ASCII
dwCmdLen = wcslen(pszExpand) + 1;
dwCmdLen = wcstombs( pchCmd, pszExpand, dwCmdLen );
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Call fail timer string %s\r\n"),
pszTemp));
if (LineNotDropped(pLineDev, OrigDevState))
{
// We got a value, write it out to modem
MdmResp = MODEM_FAILURE;
if (MdmSendCommand( pLineDev, pchCmd )) {
if (LineNotDropped(pLineDev, OrigDevState)) {
MdmResp = MdmGetResponse( pLineDev, pchCmd, NOCS, OPENED);
}
}
}
if( MODEM_SUCCESS != MdmResp )
{
// Hmm, we could probably ignore this failure, but the call might
// never time out. Lets be safe and abort now.
goto init_error;
}
}
// And finally, see if user requested any special modifier string
if( dwCmdLen = wcslen(pLineDev->DevMiniCfg.szDialModifier) )
{
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Dial Modifier string %s\r\n"),
pLineDev->DevMiniCfg.szDialModifier));
// Convert the UniCode to ASCII, and insert 'AT' in command
pchCmd[0] = 'A';
pchCmd[1] = 'T';
dwCmdLen += 1;
dwCmdLen = wcstombs( pchCmd+2, pLineDev->DevMiniCfg.szDialModifier, dwCmdLen );
// OK, now don't forget the CR at end.
strcat( pchCmd, "\r" );
DEBUGMSG(ZONE_CALLS, (TEXT("UNIMODEM:ModemInit Generated Modifier string %a\r\n"),
pchCmd));
if (LineNotDropped(pLineDev, OrigDevState))
{
// And write this out to modem
MdmResp = MODEM_FAILURE;
if (MdmSendCommand( pLineDev, pchCmd )) {
if (LineNotDropped(pLineDev, OrigDevState)) {
MdmResp = MdmGetResponse( pLineDev, pchCmd, NOCS, OPENED);
}
}
}
if( MODEM_SUCCESS != MdmResp )
{
// bad modifier string. We can't recover from this.
DEBUGMSG(ZONE_CALLS | ZONE_ERROR,
(TEXT("UNIMODEM:ModemInit Bad user supplied dial modifier %s\r\n"),
pLineDev->DevMiniCfg.szDialModifier));
goto init_error;
}
}
}
bFailed = FALSE;
} except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Most likely a bad handle. Just give up
bFailed = TRUE;
}
init_error:
EnterCri
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -