533 lines
13 KiB
C
533 lines
13 KiB
C
//****************************************************************************
|
|
//
|
|
// Module: Unimdm
|
|
// File: modem.c
|
|
//
|
|
// Copyright (c) 1992-1993, Microsoft Corporation, all rights reserved
|
|
//
|
|
// Revision History
|
|
//
|
|
//
|
|
// 6/15/93 Nick Manson Modified OpenModem and CloseModem calls
|
|
// 1/6/93 Viroon Touranachun Revised for RNA
|
|
//
|
|
//
|
|
// Description: Intermediate modem SPI layer
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
#include "unimdm.h"
|
|
#include "umdmspi.h"
|
|
|
|
#ifdef UNDER_CONSTRUCTION
|
|
|
|
#include <regstr.h>
|
|
|
|
#define Not_VxD
|
|
#include <vmm.h>
|
|
#include <configmg.h>
|
|
|
|
#endif // UNDER_CONSTRUCTION
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineOpen(PLINEDEV)
|
|
//
|
|
// Function: Opens the modem device.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// LINEERR_ALLOCATED if the modem was already opened
|
|
// LINEERR_RESOURCEUNAVAIL if the modem cannot be opened
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineOpen (PLINEDEV pLineDev)
|
|
{
|
|
LPCOMMCONFIG lpComConfig;
|
|
DWORD dwRet;
|
|
|
|
// The line must be closed
|
|
//
|
|
if (pLineDev->hDevice != INVALID_DEVICE)
|
|
return LINEERR_ALLOCATED;
|
|
|
|
ASSERT(pLineDev->pDevCfg != NULL);
|
|
|
|
// Nullify the terminal window
|
|
//
|
|
STOP_UI_DLG (pLineDev, UI_DLG_TERMINAL);
|
|
|
|
pLineDev->LineClosed=FALSE;
|
|
|
|
// Open the modem port
|
|
//
|
|
lpComConfig = (LPCOMMCONFIG)&(pLineDev->pDevCfg->commconfig);
|
|
dwRet = OpenModem(pLineDev, (LPBYTE)lpComConfig, lpComConfig->dwSize);
|
|
|
|
// If we successfully opened the modem, reinitialize the rest of the CB
|
|
//
|
|
if (dwRet == ERROR_SUCCESS)
|
|
{
|
|
// The modem is just opened, it is not connected
|
|
//
|
|
pLineDev->DevState = DEVST_DISCONNECTED;
|
|
|
|
}
|
|
else
|
|
{
|
|
dwRet = LINEERR_RESOURCEUNAVAIL;
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineDetectCall(PLINEDEV)
|
|
//
|
|
// Function: Starts the modem to monitor a call.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// LINEERR_OPERATIONFAILED if the modem fails
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineDetectCall(PLINEDEV pLineDev)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
switch (pLineDev->DevState)
|
|
{
|
|
// Do nothing if listening in progress
|
|
//
|
|
case DEVST_PORTLISTENINIT:
|
|
case DEVST_PORTLISTENING:
|
|
dwRet = ERROR_SUCCESS;
|
|
break;
|
|
|
|
// If the modem is not started, start listening
|
|
//
|
|
case DEVST_DISCONNECTED:
|
|
//
|
|
// If the privilege is to own an inbound call, start listening now
|
|
// First Initialize modem
|
|
//
|
|
pLineDev->DevState = DEVST_PORTLISTENINIT;
|
|
|
|
switch (UnimodemInit(pLineDev))
|
|
{
|
|
case ERROR_SUCCESS:
|
|
ASSERT(0); // We do not expect a success return
|
|
|
|
case ERROR_IO_PENDING:
|
|
dwRet = ERROR_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
pLineDev->DevState = DEVST_DISCONNECTED;
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
break;
|
|
};
|
|
break;
|
|
|
|
default:
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineMakeCall(PLINEDEV)
|
|
//
|
|
// Function: Dial M for modem.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// LINEERR_OPERATIONFAILED if the modem fails
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineMakeCall(PLINEDEV pLineDev)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
// If we need a UI, start a dialog instance here
|
|
//
|
|
if ((GETOPTIONS(pLineDev->pDevCfg) & (TERMINAL_PRE | TERMINAL_POST | MANUAL_DIAL)) ||
|
|
(LINEMEDIAMODE_INTERACTIVEVOICE == pLineDev->dwCurMediaModes))
|
|
{
|
|
CreateMdmDlgInstance(pLineDev);
|
|
};
|
|
|
|
// If pre-dial terminal mode is set, go to terminal mode
|
|
//
|
|
if (GETOPTIONS(pLineDev->pDevCfg) & TERMINAL_PRE)
|
|
{
|
|
switch (pLineDev->DevState)
|
|
{
|
|
case DEVST_PORTLISTENINIT:
|
|
|
|
pLineDev->DevState = DEVST_PORTSTARTPRETERMINAL;
|
|
|
|
return pLineDev->dwPendingID;
|
|
|
|
case DEVST_PORTLISTENING:
|
|
|
|
Sleep(100);
|
|
|
|
case DEVST_DISCONNECTED:
|
|
|
|
pLineDev->DevState = DEVST_PORTSTARTPRETERMINAL;
|
|
|
|
if (MdmAsyncContinue(pLineDev, MDM_SUCCESS) == ERROR_SUCCESS)
|
|
{
|
|
return pLineDev->dwPendingID;
|
|
};
|
|
|
|
default:
|
|
DestroyMdmDlgInstance(pLineDev);
|
|
return LINEERR_OPERATIONFAILED;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// Start dialing procedure
|
|
//
|
|
switch (pLineDev->DevState)
|
|
{
|
|
|
|
case DEVST_PORTLISTENINIT:
|
|
//
|
|
// Wait until the current modem initialization to finish,
|
|
// then start dialing automatically.
|
|
//
|
|
pLineDev->DevState = DEVST_PORTCONNECTINIT;
|
|
dwRet = pLineDev->dwPendingID;
|
|
break;
|
|
|
|
|
|
case DEVST_PORTLISTENING:
|
|
//
|
|
// The modem is listening. It was already initialized.
|
|
// Stop monitoring immediately.
|
|
// When the monitoring stops, it will start dialing automatically.
|
|
//
|
|
|
|
//
|
|
// BUGBUG: To prevent the init or dial strings from stomping the
|
|
// monitor command, we will wait briefly here
|
|
//
|
|
//
|
|
Sleep(100);
|
|
|
|
if (pLineDev->InitStringsAreValid) {
|
|
|
|
pLineDev->DevState = DEVST_PORTCONNECTINIT;
|
|
dwRet = pLineDev->dwPendingID;
|
|
MdmAsyncContinue (pLineDev, MDM_SUCCESS);
|
|
break;
|
|
|
|
}
|
|
//
|
|
// LineSetDevConfig was called and changes the settings, need to rebuild the
|
|
// init strings to reflect this
|
|
//
|
|
//
|
|
// Fall on through
|
|
//
|
|
//
|
|
|
|
case DEVST_DISCONNECTED:
|
|
|
|
// The modem is disconnected. Initialize it before dialing.
|
|
//
|
|
pLineDev->DevState = DEVST_PORTCONNECTINIT;
|
|
|
|
switch (UnimodemInit(pLineDev))
|
|
{
|
|
case ERROR_SUCCESS:
|
|
ASSERT(0); // We do not expect a success return
|
|
|
|
case ERROR_IO_PENDING:
|
|
dwRet = pLineDev->dwPendingID;
|
|
break;
|
|
|
|
default:
|
|
pLineDev->DevState = DEVST_DISCONNECTED;
|
|
DestroyMdmDlgInstance(pLineDev);
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
break;
|
|
};
|
|
break;
|
|
|
|
default:
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineDial(PLINEDEV)
|
|
//
|
|
// Function: Dial M for modem.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// LINEERR_OPERATIONFAILED if the modem fails
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineDial(PLINEDEV pLineDev)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
// Kick start the modem state machine
|
|
//
|
|
if (MdmAsyncContinue(pLineDev, MDM_SUCCESS) != ERROR_SUCCESS)
|
|
{
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
}
|
|
else
|
|
{
|
|
dwRet = ERROR_SUCCESS;
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineAnswer (PLINEDEV)
|
|
//
|
|
// Function: Answer an offered call.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// LINEERR_INVALCALLSTATE if the call was not offerred.
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineAnswer (PLINEDEV pLineDev)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (pLineDev->DevState != DEVST_PORTLISTENOFFER)
|
|
return LINEERR_INVALCALLSTATE;
|
|
|
|
// Kill RING timer
|
|
KillMdmTimer((DWORD)pLineDev, NULL);
|
|
|
|
// Advance the call state and return pending
|
|
//
|
|
pLineDev->DevState = DEVST_PORTLISTENANSWER;
|
|
|
|
// Get modem to answer the call
|
|
//
|
|
switch (UnimodemAnswer(pLineDev))
|
|
{
|
|
case ERROR_SUCCESS:
|
|
ASSERT(0); // We do not expect a success return
|
|
|
|
case ERROR_IO_PENDING:
|
|
dwRet = pLineDev->dwPendingID;
|
|
break;
|
|
|
|
default:
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
break;
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineDrop (PLINEDEV, BOOL)
|
|
//
|
|
// Function: Disconnect the call synchronous or asynchronously.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// LINEERR_INVALCALLSTATE if the call was not offerred.
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineDrop (PLINEDEV pLineDev, BOOL fSync)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
// Synchronously terminate all the dangling UI windows
|
|
//
|
|
DestroyTalkDropDialog(pLineDev);
|
|
DestroyManualDialog(pLineDev);
|
|
DestroyTerminalDialog(pLineDev);
|
|
DestroyMdmDlgInstance(pLineDev);
|
|
|
|
// Do we need to do a hangup?
|
|
//
|
|
if (LINECALLSTATE_IDLE == pLineDev->dwCallState &&
|
|
DEVST_DISCONNECTED == pLineDev->DevState)
|
|
{
|
|
// The call is idle and the modem is disconnected,
|
|
// just notify the completion.
|
|
//
|
|
(*(gfnCompletionCallback))(pLineDev->dwPendingID, 0L);
|
|
pLineDev->dwPendingID = INVALID_PENDINGID;
|
|
pLineDev->dwPendingType = INVALID_PENDINGOP;
|
|
dwRet = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
if (pLineDev->DevState == DEVST_CONNECTED) {
|
|
|
|
// Cancel the outstanding remote disconnection detection
|
|
//
|
|
UnimodemCancelMonitorDisconnect(pLineDev);
|
|
}
|
|
|
|
if (DEVST_PORTLISTENOFFER == pLineDev->DevState) {
|
|
//
|
|
// the call was offered and then droped without answering, need to kill timer
|
|
//
|
|
KillMdmTimer((DWORD)pLineDev, NULL);
|
|
}
|
|
|
|
|
|
if (DEVST_DISCONNECTING == pLineDev->DevState) {
|
|
|
|
TSPPRINTF("DevLineDrop: re-entered, waiting for drop to complete");
|
|
|
|
RELEASE_LINEDEV(pLineDev);
|
|
|
|
WaitForSingleObject(
|
|
pLineDev->DroppingEvent,
|
|
30*1000
|
|
);
|
|
|
|
CLAIM_LINEDEV(pLineDev);
|
|
|
|
TSPPRINTF("DevLineDrop: re-entered, Done waiting");
|
|
|
|
dwRet = ERROR_SUCCESS;
|
|
|
|
} else {
|
|
|
|
TSPPRINTF1(
|
|
"DevLineDrop: Warning. DevState was %lu. Forcing to DISCONNECTING",
|
|
pLineDev->DevState
|
|
);
|
|
|
|
//
|
|
// 7/12/96 JosephJ BUGBUG
|
|
// We will simply clobber any existing command being sent out here,
|
|
// because we call UnimodemHangup which eventually cancels any pending
|
|
// I/O and calls purgecomm. End result is that the command being
|
|
// sent out can get truncated and the next command we send out gets
|
|
// concatenated to the previously-truncated command. Sometimes this
|
|
// results in ATE0V1 (truncated to AT) being combined with ATZ to
|
|
// form ATATZ, causing some modems to go off hook.
|
|
//
|
|
// Fix will to fix the state diagram so that previously executing
|
|
// commands are allowed to complete and response to be properly
|
|
// read. However this is a hack workaround in the (fSync) case...
|
|
// We sleep.
|
|
// We specifically exclude those states which are known to be OK
|
|
// (no pending I/O.)
|
|
if (fSync)
|
|
{
|
|
switch (pLineDev->DevState)
|
|
{
|
|
case DEVST_PORTLISTENING: // Fall through
|
|
case DEVST_PORTLISTENOFFER: // Fall through
|
|
case DEVST_PORTCONNECTWAITFORLINEDIAL: // Fall through
|
|
case DEVST_PORTCONNECTING: // Fall through
|
|
case DEVST_DISCONNECTED: // Fall through
|
|
case DEVST_CONNECTED: // Do Nothing.
|
|
break;
|
|
|
|
default:
|
|
Sleep(150);
|
|
break;
|
|
}
|
|
}
|
|
|
|
pLineDev->DevState = DEVST_DISCONNECTING;
|
|
|
|
ResetEvent(
|
|
pLineDev->DroppingEvent
|
|
);
|
|
|
|
// Make a direct call to unimodem to drop the line
|
|
//
|
|
switch (UnimodemHangup(pLineDev, fSync))
|
|
{
|
|
case ERROR_SUCCESS:
|
|
pLineDev->DevState = DEVST_DISCONNECTED;
|
|
case ERROR_IO_PENDING:
|
|
dwRet = ERROR_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0); // This should not happen whatsoever!!!
|
|
pLineDev->DevState = DEVST_DISCONNECTED;
|
|
dwRet = LINEERR_OPERATIONFAILED;
|
|
break;
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// LONG DevlineClose (PLINEDEV)
|
|
//
|
|
// Function: Close the modem.
|
|
//
|
|
// Returns: ERROR_SUCCESS always
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
LONG DevlineClose (PLINEDEV pLineDev)
|
|
{
|
|
// If the device is listening, we need to drop the line first
|
|
//
|
|
if (pLineDev->DevState != DEVST_DISCONNECTED)
|
|
{
|
|
DevlineDrop(pLineDev, TRUE);
|
|
};
|
|
|
|
DestroyMdmDlgInstance(pLineDev);
|
|
|
|
// Close the comm port
|
|
//
|
|
if (pLineDev->hDevice != INVALID_DEVICE)
|
|
{
|
|
if(pLineDev->hLights != NULL)
|
|
{
|
|
TerminateModemLight(pLineDev->hLights);
|
|
pLineDev->hLights = NULL;
|
|
};
|
|
|
|
CloseModem(pLineDev);
|
|
pLineDev->hDevice = INVALID_DEVICE;
|
|
};
|
|
|
|
return ERROR_SUCCESS ;
|
|
}
|