reman3/Rayman_X/cpa/tempgrp/NET/l0modem.c

2247 lines
81 KiB
C
Raw Blame History

/*
* universal multiplayer library level 0 implementation file
* transport layer: modem PC-windows 95
*/
/*
* Author: Christophe Roguet
*
* Modification Date: 09/07/96
*
* The modem layer uses most of the functionalities of the serial layer.
* The differences reside in this file and concern the processes of connection and deconnection.
*
* lots of restrictions:
* - the modem uses a special serial channel (the last one) instead of the channel associated
* to its COM port
* - only one call at a time is allowed (gets confused if many applications try to connect ...)
* - parts of the code are written as if many modem channels could coexist, for an eventual future
* version
*
* REMARKS:
*
* - in order for the modem events to be properly dispatched,
* the application must dispatch window messages
* - to avoid problems, the vL0PCWin95ModemExitTAPI() function must be called whenever the
* application is left
* - thread problem ??? the thread in which lineInitialize() is called is the
* thread that receives the callback ... it must pump windows messages ...
*
*/
#include "warnings.h"
#define TAPI_CURRENT_VERSION 0x00010004
#include <tapi.h>
#include <mcx.h>
#include <NET\Netdebug.h>
#ifdef NET_USE_DEBUG
#include <stdio.h>
#endif
/*
* we need this one to fill the interface structure
* with pointers to the correct functions
*/
#include "PrivL0modem.h"
#include "PrivNetDef.h"
#include "L0GlDef.h"
#include "NetMemCo.h"
#define MODEM_WINDOW 20
#define MODEM_RATE XXXXX
#define MODEM_TIMEOUT 1000
#define MODEM_LINKNUMBER 100/*2*MODEM_WINDOW*/
/* typedefs necessary for parameters to lineSetDevConfig for Unimodem ... */
/* (refer to "comm/datamodem" */
/* Device setting information*/
typedef struct tagDEVCFGDR {
DWORD dwSize;
DWORD dwVersion;
WORD fwOptions;
WORD wWaitBong;
} DEVCFGHDR;
typedef struct tagDEVCFG {
DEVCFGHDR dfgHdr;
COMMCONFIG commconfig;
} DEVCFG, *PDEVCFG, FAR* LPDEVCFG;
/* local functions declaration */
void L0PCWin95ModemDoLineCallState(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
void L0PCWin95ModemDoLineClose(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
void L0PCWin95ModemDoLineDevState(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
void L0PCWin95ModemDoLineReply(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
void L0PCWin95ModemDoLineCreate(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
void vL0PCWin95ModemExitTAPI();
void vL0PCWin95ModemConnect();
void vL0PCWin95ModemDisconnect();
void vL0PCWin95ModemAnswer(HCALL);
void vL0PCWin95ModemRelease(HCALL);
void vL0PCWin95ModemCloseChannel(tduwNetChannel);
void vL0PCWin95ModemCloseProtocol(void);
/* array of descriptors to access a physical channel. */
/* problem there: should be the static array defined in level0_Serial_PCWin95.cpp ... */
#define C_uw_Net_L0PCWin95Serial_PortNumber ((unsigned short)5)
#undef extern /* what is this define for ???? */
extern tdstL0PCWin95SerialChannel gs_a_stL0PCWin95SerialChannels[C_uw_Net_L0PCWin95Serial_PortNumber];
extern long lSerialChannelsOnceInitialized;
/* the last serial channel is dedicated to the modem */
#define C_ModemSpecialChannel (C_uw_Net_L0PCWin95Serial_PortNumber-1)
/* global variables */
static HINSTANCE gs_hInstance; /* application instance handle */
static tdfnvModemCallback gs_tdfnvModemCallback; /* pointer to the application callback function */
static HLINEAPP gs_hLineApp; /* TAPI application ID */
static DWORD gs_dwNumDevs; /* number of available line devices */
static HLINE gs_hLine; /* line ID */
static HCALL gs_hCall; /* call ID */
static LINECALLPARAMS *lpCallParams; /* parameters for the call; could be local ??? */
static gs_cModemAnswerMode; /* boolean: upon reception of incoming call, reject it or accept it ? */
static HANDLE gs_hWaitForRelease; /* synchronization object for call deallocation */
static COMMCONFIG *gs_pstCommConfig; /* modem configuration */
static unsigned long gs_ulCommConfigSize;
static DWORD gs_dwInitialiserThreadId; /* Id of the thread that initialized the protocol */
static char gs_bL0PCWin95ModemInitState;
static unsigned long gs_ulL0PCWin95ModemBaudRate;
/*******************************************************************/
#ifdef NET_USE_DEBUG
void vL0PCWin95ModemDisplayModemOptions(DWORD ModemOptions)
{
char acString[200];
int pos;
pos=0;
pos+=sprintf(acString, "( ");
if(ModemOptions & MDM_BLIND_DIAL)
pos+=sprintf(acString+pos, "BLIND_DIAL ");
if(ModemOptions & MDM_CCITT_OVERRIDE)
pos+=sprintf(acString+pos, "CCITT_OVERRIDE ");
if(ModemOptions & MDM_CELLULAR)
pos+=sprintf(acString+pos, "CELLULAR ");
if(ModemOptions & MDM_COMPRESSION)
pos+=sprintf(acString+pos, "COMPRESSION ");
if(ModemOptions & MDM_ERROR_CONTROL)
pos+=sprintf(acString+pos, "ERROR_CONTROL ");
if(ModemOptions & MDM_FLOWCONTROL_HARD)
pos+=sprintf(acString+pos, "FLOWCONTROL_HARD ");
if(ModemOptions & MDM_FLOWCONTROL_SOFT)
pos+=sprintf(acString+pos, "FLOWCONTROL_SOFT ");
if(ModemOptions & MDM_FORCED_EC)
pos+=sprintf(acString+pos, "FORCED_EC ");
if(ModemOptions & MDM_SPEED_ADJUST)
pos+=sprintf(acString+pos, "SPEED_ADJUST ");
if(ModemOptions & MDM_TONE_DIAL)
pos+=sprintf(acString+pos, "TONE_DIAL ");
if(ModemOptions & MDM_V23_OVERRIDE)
pos+=sprintf(acString+pos, "V23_OVERRIDE ");
pos+=sprintf(acString+pos, ")");
vDebugS(Net_C_Debug_Modem, acString);
}
void vL0PCWin95ModemDisplayModemSettings(MODEMSETTINGS *pModemSettings)
{
vDebugFormat(Net_C_Debug_Modem, "dwActualSize:\t%d", pModemSettings->dwActualSize);
vDebugFormat(Net_C_Debug_Modem, "dwRequiredSize:\t%d", pModemSettings->dwRequiredSize);
vDebugFormat(Net_C_Debug_Modem, "dwDevSpecificSize:\t%d", pModemSettings->dwDevSpecificSize);
vDebugFormat(Net_C_Debug_Modem, "dwCallSetupFailTimer:\t%d", pModemSettings->dwCallSetupFailTimer);
vDebugFormat(Net_C_Debug_Modem, "dwInactivityTimeout:\t%d", pModemSettings->dwInactivityTimeout);
vDebugFormat(Net_C_Debug_Modem, "dwSpeakerVolume:\t0x%08x", pModemSettings->dwSpeakerVolume);
vDebugFormat(Net_C_Debug_Modem, "dwSpeakerMode:\t0x%08x", pModemSettings->dwSpeakerMode);
vDebugFormat(Net_C_Debug_Modem, "dwPreferredModemOptions:\t0x%08x", pModemSettings->dwPreferredModemOptions);
vL0PCWin95ModemDisplayModemOptions(pModemSettings->dwPreferredModemOptions);
vDebugFormat(Net_C_Debug_Modem, "dwNegotiatedModemOptions:\t0x%08x", pModemSettings->dwNegotiatedModemOptions);
vL0PCWin95ModemDisplayModemOptions(pModemSettings->dwNegotiatedModemOptions);
vDebugFormat(Net_C_Debug_Modem, "dwNegotiatedDCERate:\t%d", pModemSettings->dwNegotiatedDCERate);
}
#endif /* NET_USE_DEBUG */
/*******************************************************************/
#ifdef NET_USE_DEBUG
void vL0PCWin95ModemDisplayModemDevCaps(MODEMDEVCAPS *pModemDevCaps)
{
#define STRING_MAX_SIZE 80
char string[STRING_MAX_SIZE];
vDebugFormat(Net_C_Debug_Modem, "dwActualSize:\t%d", pModemDevCaps->dwActualSize);
vDebugFormat(Net_C_Debug_Modem, "dwRequiredSize:\t%d", pModemDevCaps->dwRequiredSize);
vDebugFormat(Net_C_Debug_Modem, "dwDevSpecificOffset:\t%d", pModemDevCaps->dwDevSpecificOffset);
vDebugFormat(Net_C_Debug_Modem, "dwDevSpecificSize:\t%d", pModemDevCaps->dwDevSpecificSize);
vDebugFormat(Net_C_Debug_Modem, "dwModemProviderVersion:\t%d", pModemDevCaps->dwModemProviderVersion);
vDebugFormat(Net_C_Debug_Modem, "dwModemManufacturerOffset:\t%d", pModemDevCaps->dwModemManufacturerOffset);
vDebugFormat(Net_C_Debug_Modem, "dwModemManufacturerSize:\t%d", pModemDevCaps->dwModemManufacturerSize);
vDebugFormat(Net_C_Debug_Modem, "dwModemModelOffset:\t%d", pModemDevCaps->dwModemModelOffset);
vDebugFormat(Net_C_Debug_Modem, "dwModemModelSize:\t%d", pModemDevCaps->dwModemModelSize);
vDebugFormat(Net_C_Debug_Modem, "dwModemVersionOffset:\t%d", pModemDevCaps->dwModemVersionOffset);
vDebugFormat(Net_C_Debug_Modem, "dwModemVersionSize:\t%d", pModemDevCaps->dwModemVersionSize);
vDebugFormat(Net_C_Debug_Modem, "dwDialOptions:\t0x%08x", pModemDevCaps->dwDialOptions);
vDebugFormat(Net_C_Debug_Modem, "dwCallSetupFailTimer:\t%d", pModemDevCaps->dwCallSetupFailTimer);
vDebugFormat(Net_C_Debug_Modem, "dwInactivityTimeout:\t%d", pModemDevCaps->dwInactivityTimeout);
vDebugFormat(Net_C_Debug_Modem, "dwSpeakerVolume:\t0x%08x", pModemDevCaps->dwSpeakerVolume);
vDebugFormat(Net_C_Debug_Modem, "dwSpeakerMode:\t0x%08x", pModemDevCaps->dwSpeakerMode);
vDebugFormat(Net_C_Debug_Modem, "dwModemOptions:\t0x%08x", pModemDevCaps->dwModemOptions);
vDebugFormat(Net_C_Debug_Modem, "dwMaxDTERate:\t%d", pModemDevCaps->dwMaxDTERate);
vDebugFormat(Net_C_Debug_Modem, "dwMaxDCERate:\t%d", pModemDevCaps->dwMaxDCERate);
if(pModemDevCaps->dwModemManufacturerOffset!=0) {
if(pModemDevCaps->dwModemManufacturerSize>=STRING_MAX_SIZE) {
memcpy(string, ((char *)pModemDevCaps)+pModemDevCaps->dwModemManufacturerOffset,
STRING_MAX_SIZE-1);
string[STRING_MAX_SIZE-1]='\0';
} else {
memcpy(string, ((char *)pModemDevCaps)+pModemDevCaps->dwModemManufacturerOffset,
pModemDevCaps->dwModemManufacturerSize);
string[pModemDevCaps->dwModemManufacturerSize]='\0';
}
vDebugFormat(Net_C_Debug_Modem, "ModemManufacturer: %s", string);
}
if(pModemDevCaps->dwModemModelOffset!=0) {
if(pModemDevCaps->dwModemModelSize>=STRING_MAX_SIZE) {
memcpy(string, ((char *)pModemDevCaps)+pModemDevCaps->dwModemModelOffset,
STRING_MAX_SIZE-1);
string[STRING_MAX_SIZE-1]='\0';
} else {
memcpy(string, ((char *)pModemDevCaps)+pModemDevCaps->dwModemModelOffset,
pModemDevCaps->dwModemModelSize);
string[pModemDevCaps->dwModemModelSize]='\0';
}
vDebugFormat(Net_C_Debug_Modem, "ModemModel: %s", string);
}
if(pModemDevCaps->dwModemVersionOffset!=0) {
if(pModemDevCaps->dwModemVersionSize>=STRING_MAX_SIZE) {
memcpy(string, ((char *)pModemDevCaps)+pModemDevCaps->dwModemVersionOffset,
STRING_MAX_SIZE-1);
string[STRING_MAX_SIZE-1]='\0';
} else {
memcpy(string, ((char *)pModemDevCaps)+pModemDevCaps->dwModemVersionOffset,
pModemDevCaps->dwModemVersionSize);
string[pModemDevCaps->dwModemVersionSize]='\0';
}
vDebugFormat(Net_C_Debug_Modem, "ModemVersion: %s", string);
}
}
#endif /* NET_USE_DEBUG */
/*******************************************************************/
#ifdef NET_USE_DEBUG
void vL0PCWin95ModemDisplayCommTimeouts(LPCOMMTIMEOUTS pcto)
{
vDebugFormat(Net_C_Debug_Modem, "ReadIntervalTimeout: %d", pcto->ReadIntervalTimeout);
vDebugFormat(Net_C_Debug_Modem, "ReadTotalTimeoutMultiplier: %d", pcto->ReadTotalTimeoutMultiplier);
vDebugFormat(Net_C_Debug_Modem, "ReadTotalTimeoutConstant: %d", pcto->ReadTotalTimeoutConstant);
vDebugFormat(Net_C_Debug_Modem, "WriteTotalTimeoutMultiplier: %d", pcto->WriteTotalTimeoutMultiplier);
vDebugFormat(Net_C_Debug_Modem, "WriteTotalTimeoutConstant: %d", pcto->WriteTotalTimeoutConstant);
}
#endif /* NET_USE_DEBUG */
/*******************************************************************/
void vL0PCWin95ModemInitializeCommConfig(COMMCONFIG *pCommConfig)
{
MODEMSETTINGS *pModemSettings;
DCB *pDcb;
/* initialize the COM port part of the commconfig */
pDcb=&pCommConfig->dcb;
pDcb->BaudRate= gs_ulL0PCWin95ModemBaudRate;
pDcb->fBinary = TRUE; /* not text transfer */
pDcb->ByteSize = 8; /* 8 bit chars */
pDcb->fParity = FALSE; /* no parity checking */
pDcb->Parity = NOPARITY; /* no parity checking (redundant ?) */
pDcb->StopBits = ONESTOPBIT;
pDcb->fErrorChar = FALSE; /* do not replace bad chars */
pDcb->fAbortOnError = FALSE; /* do not replace bad chars */
pDcb->fOutxCtsFlow = TRUE; /* hardware flow control */
pDcb->fOutxDsrFlow = FALSE; /* hardware flow control */
pDcb->fDtrControl = DTR_CONTROL_ENABLE; /* hardware flow control */
pDcb->fDsrSensitivity = FALSE; /* hardware flow control */
pDcb->fRtsControl = RTS_CONTROL_HANDSHAKE; /* hardware flow control */
/* no software flow control */
pDcb->fOutX = FALSE;
pDcb->fInX = FALSE;
pDcb->fNull = FALSE;
/* initialize the modem part of the commconfig */
pModemSettings=(MODEMSETTINGS *)pCommConfig->wcProviderData;
#ifdef NET_USE_DEBUG
vL0PCWin95ModemDisplayModemSettings(pModemSettings);
#endif /* NET_USE_DEBUG */
pModemSettings->dwCallSetupFailTimer=35; /* thirty five seconds */
pModemSettings->dwInactivityTimeout=MAXDWORD; /* can remain inactive 'forever' ?*/
pModemSettings->dwSpeakerVolume=MDMVOL_MEDIUM;
pModemSettings->dwSpeakerMode=MDMSPKR_CALLSETUP;
pModemSettings->dwPreferredModemOptions|=
MDM_FLOWCONTROL_HARD /* harware flow control */
/* | MDM_COMPRESSION /* hardware data compression */
| MDM_BLIND_DIAL /* do not wait for dial tone */
/* | MDM_TONE_DIAL /* use tone dialing */
;
pModemSettings->dwPreferredModemOptions&=
~MDM_COMPRESSION /* no compression */
& ~MDM_FLOWCONTROL_SOFT; /* no software flow control */
;
}
/*******************************************************************/
void vL0PCWin95ModemInitializeCommTimeouts(LPCOMMTIMEOUTS pcto)
{
/* timeouts should be tailored to baud rate and/or vNetEngine() call frequency */
pcto->ReadIntervalTimeout = 0; /* no timeout */
pcto->ReadTotalTimeoutMultiplier = 0 ;
pcto->ReadTotalTimeoutConstant = 200/*MAXDWORD*/ ;
pcto->WriteTotalTimeoutMultiplier = 0 ;
pcto->WriteTotalTimeoutConstant = MAXDWORD;
}
/*****************************************************************************
*
* Description: uwL0PCWin95ModemStartChannelScan
*
* returns the identification number of the first channel for the protocol
*
*****************************************************************************
*
* Input: none
*
* Output: identification of the channel
*
*****************************************************************************
* Creation Date: April 15, 1996 Author: Christophe Roguet
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
tduwNetChannel uwL0PCWin95ModemStartChannelScan(void)
{
tduwNetChannel uwCurrentChannel;
/* scan the array of channel definitions */
for (uwCurrentChannel = 0; uwCurrentChannel < C_uw_Net_L0PCWin95Serial_PortNumber; uwCurrentChannel ++)
/* if the slot is used, and can transmit data to another individual player */
if
(
gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotInUse
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotForModem
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotConnected
)
/* return its index value */
return uwCurrentChannel;
/* else no slot is in use */
return C_uwNetInvalidChannel ;
}
/*****************************************************************************
*
* Description: uwL0PCWin95ModemNextChannel
*
* returns the identification number of the channel following the last
*
*****************************************************************************
*
* Input: uwLastScannedChannel, index returned by the previous call
*
* Output: identification of the channel following the specified one
*
*****************************************************************************
* Creation Date: April 15, 1996 Author: Christophe Roguet
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
tduwNetChannel uwL0PCWin95ModemNextChannel(tduwNetChannel uwLastScannedChannel)
{
tduwNetChannel uwCurrentChannel;
/*
* scan the array of channel definitions, starting with the channel following
* the last channel returned
*/
for
(
uwCurrentChannel = (tduwNetChannel)(uwLastScannedChannel + 1);
uwCurrentChannel < C_uw_Net_L0PCWin95Serial_PortNumber;
uwCurrentChannel ++
)
/* if the slot is used, and can transmit data to another individual player */
if
(
gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotInUse
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotForModem
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotConnected
)
/* return its index value */
return uwCurrentChannel;
/* else no slot is in use */
return C_uwNetInvalidChannel;
}
/*****************************************************************************
*
* Description: uwL0PCWin95ModemStartBroadcastChannelScan
*
* returns the identification number of the first broadcast channel
* for the protocol
*
*****************************************************************************
*
* Input: none
*
* Output: identification of the channel
*
*****************************************************************************
* Creation Date: April 15, 1996 Author: Christophe Roguet
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
tduwNetChannel uwL0PCWin95ModemStartBroadcastChannelScan(void)
{
tduwNetChannel uwCurrentChannel;
/* scan the array of channel definitions */
for (uwCurrentChannel = 0; uwCurrentChannel < C_uw_Net_L0PCWin95Serial_PortNumber; uwCurrentChannel ++)
/* if the slot is used, and the channel can send broadcast data */
if
(
gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotInUse
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotForModem
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotConnected
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsBroadcast
)
/* return its index value */
return uwCurrentChannel;
/* else no slot is in use */
return C_uwNetInvalidChannel;
}
/*****************************************************************************
*
* Description: uwL0PCWin95ModemNextBroadcastChannel
*
* returns the identification number of the broadcast channel following
* the specified one
*
*****************************************************************************
*
* Input: uwLastScannedChannel, index returned by the previous call
*
* Output: identification of the channel following the specified one
*
*****************************************************************************
* Creation Date: April 15, 1996 Author: Christophe Roguet
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
tduwNetChannel uwL0PCWin95ModemNextBroadcastChannel(tduwNetChannel uwLastScannedChannel)
{
tduwNetChannel uwCurrentChannel;
/*
* scan the array of channel definitions, starting with the channel following
* the last channel returned
*/
for
(
uwCurrentChannel = (tduwNetChannel)(uwLastScannedChannel + 1);
uwCurrentChannel < C_uw_Net_L0PCWin95Serial_PortNumber;
uwCurrentChannel ++
)
/* if the slot is used, and can transmit broadcast data */
if
(
gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotInUse
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotForModem
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotConnected
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsBroadcast
)
/* return its index value */
return uwCurrentChannel;
/* else no slot is in use */
return C_uwNetInvalidChannel;
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : void vModemCallback
////////////////////////////////////////////////////////////////////////////////
Input :
read the SDK ...
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
Creation date : July 9,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
void CALLBACK vL0PCWin95ModemCallback(DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "\nModemCallback:\nDev:0x%08x, Msg:%ld, CallbackInstance:%ld, "
"P1:0x%08x, P2:0x%08x, P3:0x%08x",
dwDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3);
#endif /* NET_USE_DEBUG */
/* All we do is dispatch the dwMsg to the correct handler.*/
switch(dwMsg)
{
case LINE_CALLSTATE:
L0PCWin95ModemDoLineCallState(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
case LINE_CLOSE:
L0PCWin95ModemDoLineClose(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
case LINE_LINEDEVSTATE:
L0PCWin95ModemDoLineDevState(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
case LINE_REPLY:
L0PCWin95ModemDoLineReply(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
case LINE_CREATE:
L0PCWin95ModemDoLineCreate(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
default:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "message non interprete");
#endif /* NET_USE_DEBUG */
;
}
}
/*************************************************************/
void L0PCWin95ModemDoLineCallState(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
#ifdef NET_USE_DEBUG
LPSTR pszReasonDisconnected;
#endif
long lDisconnectCause;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINE_CALLSTATE");
#endif /* NET_USE_DEBUG */
if ((HCALL)dwDevice != gs_hCall)
{
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINE_CALLSTATE: Unknown device ID '0x%lx' (new call ?).\n", dwDevice);
#endif
}
/* dwParam3 contains changes to LINECALLPRIVILEGE, if there are any.*/
switch (dwParam3)
{
case 0:
break; /* no change to call state*/
case LINECALLPRIVILEGE_MONITOR:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "line given monitor privilege");
#endif /* NET_USE_DEBUG */
return;
/* close line if we are made owner. Shouldn't happen!*/
case LINECALLPRIVILEGE_OWNER:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "line given owner privilege");
#endif /* NET_USE_DEBUG */
break;
default: /* Shouldn't happen! All cases handled.*/
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Unknown LINECALLPRIVILEGE message: closing");
#endif /* NET_USE_DEBUG */
return;
}
/* dwParam1 is the specific CALLSTATE change that is occurring.*/
switch (dwParam1)
{
case LINECALLSTATE_DIALTONE:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Dial Tone");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_DIALTONE, 0);
break;
case LINECALLSTATE_DIALING:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Dialing");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_DIALING, 0);
break;
case LINECALLSTATE_PROCEEDING:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Proceeding");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_PROCEEDING, 0);
break;
case LINECALLSTATE_RINGBACK:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "RingBack");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_RINGBACK, 0);
break;
case LINECALLSTATE_BUSY:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Line busy");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_BUSY, 0);
break;
case LINECALLSTATE_IDLE:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Line idle");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_IDLE, 0);
/* deallocate the call handle */
vL0PCWin95ModemRelease((HCALL)dwDevice);
break;
case LINECALLSTATE_SPECIALINFO:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Special Info, probably couldn't dial number");
#endif /* NET_USE_DEBUG */
break;
case LINECALLSTATE_DISCONNECTED:
{
lDisconnectCause=Netlib_E_mdc_UNKNOWN;
#ifdef NET_USE_DEBUG
switch (dwParam2)
{
case LINEDISCONNECTMODE_NORMAL:
pszReasonDisconnected = "Remote Party Disconnected";
lDisconnectCause=Netlib_E_mdc_NORMAL;
break;
case LINEDISCONNECTMODE_UNKNOWN:
pszReasonDisconnected = "Disconnected: Unknown reason";
lDisconnectCause=Netlib_E_mdc_UNKNOWN;
break;
case LINEDISCONNECTMODE_REJECT:
pszReasonDisconnected = "Remote Party rejected call";
lDisconnectCause=Netlib_E_mdc_REJECT;
break;
case LINEDISCONNECTMODE_PICKUP:
pszReasonDisconnected =
"Disconnected: Local phone picked up";
lDisconnectCause=Netlib_E_mdc_PICKUP;
break;
case LINEDISCONNECTMODE_FORWARDED:
pszReasonDisconnected = "Disconnected: Forwarded";
lDisconnectCause=Netlib_E_mdc_FORWARDED;
break;
case LINEDISCONNECTMODE_BUSY:
pszReasonDisconnected = "Disconnected: Busy";
lDisconnectCause=Netlib_E_mdc_BUSY;
break;
case LINEDISCONNECTMODE_NOANSWER:
pszReasonDisconnected = "Disconnected: No Answer";
lDisconnectCause=Netlib_E_mdc_NOANSWER;
break;
case LINEDISCONNECTMODE_BADADDRESS:
pszReasonDisconnected = "Disconnected: Bad Address";
lDisconnectCause=Netlib_E_mdc_BADADDRESS;
break;
case LINEDISCONNECTMODE_UNREACHABLE:
pszReasonDisconnected = "Disconnected: Unreachable";
lDisconnectCause=Netlib_E_mdc_UNREACHABLE;
break;
case LINEDISCONNECTMODE_CONGESTION:
pszReasonDisconnected = "Disconnected: Congestion";
lDisconnectCause=Netlib_E_mdc_CONGESTION;
break;
case LINEDISCONNECTMODE_INCOMPATIBLE:
pszReasonDisconnected = "Disconnected: Incompatible";
lDisconnectCause=Netlib_E_mdc_INCOMPATIBLE;
break;
case LINEDISCONNECTMODE_UNAVAIL:
pszReasonDisconnected = "Disconnected: Unavail";
lDisconnectCause=Netlib_E_mdc_UNAVAIL;
break;
case LINEDISCONNECTMODE_NODIALTONE:
pszReasonDisconnected = "Disconnected: No Dial Tone";
lDisconnectCause=Netlib_E_mdc_NODIALTONE;
break;
default:
pszReasonDisconnected =
"Disconnected: LINECALLSTATE; Bad Reason";
lDisconnectCause=-1;
break;
}
vDebugFormat(Net_C_Debug_Modem, pszReasonDisconnected);
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_DISCONNECTED, lDisconnectCause);
vL0PCWin95ModemDisconnect();
break;
}
case LINECALLSTATE_CONNECTED: /* CONNECTED!!!*/
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINECALLSTATE_CONNECTED !!!");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_CONNECTED,0);
vL0PCWin95ModemConnect();
break;
case LINECALLSTATE_OFFERING:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINECALLSTATE_OFFERING");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_OFFERING, 0);
vL0PCWin95ModemAnswer((HCALL)dwDevice);
break;
case LINECALLSTATE_ACCEPTED:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINECALLSTATE_ACCEPTED");
#endif /* NET_USE_DEBUG */
if(gs_tdfnvModemCallback)
gs_tdfnvModemCallback(Netlib_E_mcs_ACCEPTED, 0);
break;
default:
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "Unhandled LINECALLSTATE message");
#endif /* NET_USE_DEBUG */
break;
}
}
/*************************************************************/
void L0PCWin95ModemDoLineClose(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINE_CLOSE");
#endif /* NET_USE_DEBUG */
}
/*************************************************************/
void L0PCWin95ModemDoLineDevState(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINE_LINEDEVSTATE");
switch(dwParam1)
{
case LINEDEVSTATE_RINGING:
vDebugFormat(Net_C_Debug_Modem, "Line Ringing.");
break;
case LINEDEVSTATE_REINIT:
/* This is an important case! Usually means that a service provider*/
/* has changed in such a way that requires TAPI to REINIT.*/
/* Note that there are both 'soft' REINITs and 'hard' REINITs.*/
/* Soft REINITs don't actually require a full shutdown but is instead*/
/* just an informational change that historically required a REINIT*/
/* to force the application to deal with. TAPI API Version 1.3 apps*/
/* will still need to do a full REINIT for both hard and soft REINITs.*/
switch(dwParam2)
{
/* This is the hard REINIT. No reason given, just REINIT.*/
/* TAPI is waiting for everyone to shutdown.*/
/* Our response is to immediately shutdown any calls,*/
/* shutdown our use of TAPI and notify the user.*/
case 0:
vDebugFormat(Net_C_Debug_Modem, "Tapi line configuration has changed.");
break;
case LINE_CREATE:
vDebugFormat(Net_C_Debug_Modem, "Soft REINIT: LINE_CREATE.");
break;
case LINE_LINEDEVSTATE:
vDebugFormat(Net_C_Debug_Modem, "Soft REINIT: LINE_LINEDEVSTATE.");
break;
/* There might be other reasons to send a soft reinit.*/
/* No need to to shutdown for these.*/
default:
vDebugFormat(Net_C_Debug_Modem, "Ignoring soft REINIT");
break;
}
break;
case LINEDEVSTATE_OUTOFSERVICE:
vDebugFormat(Net_C_Debug_Modem, "Line selected is now Out of Service.");
break;
case LINEDEVSTATE_DISCONNECTED:
vDebugFormat(Net_C_Debug_Modem, "Line selected is now disconnected.");
break;
case LINEDEVSTATE_MAINTENANCE:
vDebugFormat(Net_C_Debug_Modem, "Line selected is now out for maintenance.");
break;
case LINEDEVSTATE_TRANSLATECHANGE:
break;
case LINEDEVSTATE_REMOVED:
vDebugFormat(Net_C_Debug_Modem, "A Line device has been removed");
break;
default:
vDebugFormat(Net_C_Debug_Modem, "Unhandled LINEDEVSTATE message");
}
#endif /* NET_USE_DEBUG */
}
/*************************************************************/
void L0PCWin95ModemDoLineReply(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINE_REPLY, Request ID: %ld", dwParam1);
#endif /* NET_USE_DEBUG */
if(dwParam2==0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "OK");
#endif /* NET_USE_DEBUG */
} else {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "erreur: %x", dwParam2);
#endif /* NET_USE_DEBUG */
}
}
/*************************************************************/
void L0PCWin95ModemDoLineCreate(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "LINE_CREATE");
#endif /* NET_USE_DEBUG */
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : NetLib_tdeErrorStatus eL0PCWin95ModemScan
////////////////////////////////////////////////////////////////////////////////
Input :
cStart - flag indicating whether to step to the next modem or to restart from the beginning
dwCallerDeviceID - address of a long where the functions stores the next modem's device ID
acName - array of char where the functions stores the next modem's name
usNameLength - size of the previous array of char
////////////////////////////////////////////////////////////////////////////////
Output :
a NetLib_tdeErrorStatus
////////////////////////////////////////////////////////////////////////////////
Creation date : July 9,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95ModemScan(char cStart, long *dwCallerDeviceID, char *acName, unsigned short usNameLength)
{
long lErrorCode;
static DWORD dwDeviceID;
DWORD dwAPIVersion;
LINEEXTENSIONID ExtensionID;
LINEDEVCAPS *pLineDevCaps;
long lNeededSize;
/* make certain TAPI has been initialized */
if(!(gs_bL0PCWin95ModemInitState&0x01))
return NetLib_E_es_ProtocolNotInitialized;
/* allocate a LINEDEVCAPS structure */
pLineDevCaps=(LINEDEVCAPS *)pMalloc(sizeof(LINEDEVCAPS));
pLineDevCaps->dwTotalSize=sizeof(LINEDEVCAPS);
if(cStart)
dwDeviceID=0;
else
dwDeviceID++;
/* clear the user data */
memset(acName, '\0', usNameLength);
*dwCallerDeviceID=-1;
/* scan the list of installed connectoids */
for(; dwDeviceID<gs_dwNumDevs; dwDeviceID++) {
lErrorCode=lineNegotiateAPIVersion(gs_hLineApp, dwDeviceID,
0x00000000, 0x000A0000, /* ??? */
&dwAPIVersion, &ExtensionID);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineNegotiate(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
continue;
}
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "dwAPIVersion: 0x%08x\n", dwAPIVersion);
#endif /* NET_USE_DEBUG */
lErrorCode=lineGetDevCaps(gs_hLineApp, dwDeviceID/* device id */,
dwAPIVersion, 0 /* ext. version */,
pLineDevCaps);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineGetDevCaps(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
continue;
}
/* if the device has modem capabilities, retrieve its name */
if( pLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE
&& pLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM
&& pLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "%d: modem, voix, appel ok", dwDeviceID);
vDebugFormat(Net_C_Debug_Modem, "dwMaxRate:%d", pLineDevCaps->dwMaxRate);
#endif /* NET_USE_DEBUG */
/* we may need to reallocate the LINEDEVCAPS structure */
if(pLineDevCaps->dwTotalSize<pLineDevCaps->dwNeededSize) {
lNeededSize=pLineDevCaps->dwNeededSize;
vFree((tdpPointer)pLineDevCaps);
pLineDevCaps=(LINEDEVCAPS *)pMalloc(lNeededSize);
if((tdpPointer)pLineDevCaps==C_pNull)
continue;
pLineDevCaps->dwTotalSize=lNeededSize;
lErrorCode=lineGetDevCaps(gs_hLineApp, dwDeviceID/* device id */,
dwAPIVersion, 0 /* ext. version */,
pLineDevCaps);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineGetDevCaps(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
continue;
}
}
if(pLineDevCaps->dwLineNameOffset==0)
strncpy(acName, "Unknown", usNameLength-1);
else {
/* copy just the required number of chars */
/* but don't forget to leave a null character at the end of the string */
if(pLineDevCaps->dwLineNameSize<usNameLength)
usNameLength=(unsigned short)(pLineDevCaps->dwLineNameSize+1);
strncpy(acName, (char*)pLineDevCaps+pLineDevCaps->dwLineNameOffset, usNameLength-1);
}
break;
}
}
/* return the new device ID */
if(dwDeviceID==gs_dwNumDevs) { /* we reached the end of the list of installed connectoids */
*dwCallerDeviceID=(unsigned long)-1;
dwDeviceID=(unsigned long)-1; /* loop back from the beginning */
} else
*dwCallerDeviceID=dwDeviceID;
/* free the allocated LINEDEVCAPS structure */
vFree((tdpPointer)pLineDevCaps);
return NetLib_E_es_NoError;
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : NetLib_tdeErrorStatus eL0PCWin95ModemAddPort
////////////////////////////////////////////////////////////////////////////////
Input :
none (use the first modem in the system list of communication devices)
////////////////////////////////////////////////////////////////////////////////
Output :
a NetLib_tdeErrorStatus
////////////////////////////////////////////////////////////////////////////////
Creation date : July 9,96
Author : Christophe Roguet, part of code adapted from eL0PCWin95SerialAddPort
////////////////////////////////////////////////////////////////////////////////
*/
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95ModemAddPort(long dwDeviceID)
{
long lErrorCode;
DWORD dwAPIVersion;
LINEEXTENSIONID ExtensionID;
LINEDEVCAPS LineDevCaps;
VARSTRING *pDeviceConfig;
VARSTRING *pDeviceID;
tduwNetChannel uwChannelToInit;
long lNeededSize;
HANDLE hCom;
/* COMMPROP *pCommProp;
*/
#define DEVNAMEMAXSIZE 100
char szDeviceName[DEVNAMEMAXSIZE];
/* verify the validity of the device ID */
if(dwDeviceID>=(long)gs_dwNumDevs) { /* not a valid line device ID*/
return NetLib_E_es_InvalidPortNumber; /* trouver un autre num<75>ro d'erreur */
}
lErrorCode=lineNegotiateAPIVersion(gs_hLineApp, dwDeviceID,
0x00000000, 0x000A0000, /* ??? */
&dwAPIVersion, &ExtensionID);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineNegotiate(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber; /* trouver un autre num<75>ro d'erreur */;
}
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "dwAPIVersion: 0x%08x\n", dwAPIVersion);
#endif /* NET_USE_DEBUG */
LineDevCaps.dwTotalSize=sizeof(LineDevCaps);
lErrorCode=lineGetDevCaps(gs_hLineApp, dwDeviceID/* device id */,
dwAPIVersion, 0 /* ext. version */,
&LineDevCaps);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineGetDevCaps(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber; /* trouver un autre num<75>ro d'erreur */;
}
if(!( LineDevCaps.dwBearerModes & LINEBEARERMODE_VOICE
&& LineDevCaps.dwMediaModes & LINEMEDIAMODE_DATAMODEM
&& LineDevCaps.dwLineFeatures & LINEFEATURE_MAKECALL) ) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemAddPort: device ID %d is not a modem", dwDeviceID);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber; /* trouver un autre num<75>ro d'erreur */;
}
/* reset the answer flag */
gs_cModemAnswerMode=0;
/* configure the modem */
pDeviceConfig=(VARSTRING *)pMalloc(sizeof(VARSTRING)+sizeof(DEVCFGHDR)+sizeof(COMMCONFIG)+sizeof(MODEMSETTINGS));
if(pDeviceConfig==(VARSTRING *)C_pNull) {
return NetLib_E_es_NotEnoughMemory;
}
pDeviceConfig->dwTotalSize=sizeof(VARSTRING)+sizeof(DEVCFGHDR)+sizeof(COMMCONFIG)+sizeof(MODEMSETTINGS);
lErrorCode=lineGetDevConfig(dwDeviceID, pDeviceConfig, "comm/datamodem");
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineGetDevConfig(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber;
}
vL0PCWin95ModemInitializeCommConfig(
&(((DEVCFG *)((char *)pDeviceConfig+pDeviceConfig->dwStringOffset))->commconfig));
lErrorCode=lineSetDevConfig(dwDeviceID, (char *)pDeviceConfig+pDeviceConfig->dwStringOffset, pDeviceConfig->dwStringSize, "comm/datamodem");
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineSetDevConfig(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber;
}
lErrorCode=lineOpen(gs_hLineApp, dwDeviceID, &gs_hLine,
dwAPIVersion, 0 /* dwExtVersion */, 0 /* dwCallbackInstance */,
LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM, 0);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineOpen(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber;
}
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineOpen()->hLine: 0x%08x\n", gs_hLine);
#endif /* NET_USE_DEBUG */
/* request notification of state changes */
lErrorCode=lineSetStatusMessages(
gs_hLine,
/* DWORD dwLineStates */
LINEDEVSTATE_RINGING |
LINEDEVSTATE_CONNECTED | /* Important state!*/
LINEDEVSTATE_DISCONNECTED | /* Important state!*/
LINEDEVSTATE_OUTOFSERVICE | /* Important state!*/
LINEDEVSTATE_MAINTENANCE | /* Important state!*/
LINEDEVSTATE_REINIT /* Not allowed to disable this.*/
,
/*DWORD dwAddressStates */
0
);
if(lErrorCode!=0) {
lineClose(gs_hLine);
gs_hLine=0;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineSetStatusMessage(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_InvalidPortNumber;
}
/* retrieve the associated device ID */
/* allocate a memory block for a VARSTRING structure plus 30 bytes of data */
pDeviceID=(VARSTRING *)pMalloc(30+sizeof(VARSTRING));
if(pDeviceID==(VARSTRING *)C_pNull) {
lineClose(gs_hLine);
gs_hLine=0;
return NetLib_E_es_NotEnoughMemory;
}
pDeviceID->dwTotalSize=30+sizeof(VARSTRING);
lErrorCode=lineGetID(gs_hLine, 0 /*dwAddressID ignore*/ , 0 /*hCall ignore */,
LINECALLSELECT_LINE, pDeviceID, "comm/datamodem");
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineGetID(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
lineClose(gs_hLine);
gs_hLine=0;
return NetLib_E_es_InvalidPortNumber;
}
/* we may need to reallocate the VARSTRING structure */
if(pDeviceID->dwTotalSize<pDeviceID->dwNeededSize) {
lNeededSize=pDeviceID->dwNeededSize;
vFree((tdpPointer)pDeviceID);
pDeviceID=(VARSTRING *)pMalloc(lNeededSize);
pDeviceID->dwTotalSize=lNeededSize;
lErrorCode=lineGetID(gs_hLine, 0 /*dwAddressID ignore*/ , 0 /*hCall ignore */,
LINECALLSELECT_LINE, pDeviceID, "comm/datamodem");
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineGetID(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
lineClose(gs_hLine);
gs_hLine=0;
return NetLib_E_es_InvalidPortNumber;
}
}
if(pDeviceID->dwStringFormat!=STRINGFORMAT_BINARY) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "pDeviceID->dwStringFormat!=STRINGFORMAT_BINARY ??");
#endif /* NET_USE_DEBUG */
lineClose(gs_hLine);
gs_hLine=0;
return NetLib_E_es_InvalidPortNumber;
}
/* retrieve the associated communication port handle */
hCom=*(HANDLE*)(((char *)pDeviceID)+pDeviceID->dwStringOffset);
strncpy(szDeviceName, (((char *)pDeviceID)+pDeviceID->dwStringOffset+sizeof(HANDLE)), DEVNAMEMAXSIZE);
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "%d: %s", dwDeviceID, szDeviceName);
#endif /* NET_USE_DEBUG */
vFree((tdpPointer)pDeviceID);
/* now that we have a COM port, initialize a channel with it */
/* how to find the index of the com port associated to the modem ???*/
/* as for now, we use the last serial channel, which is reserved for the modem */
uwChannelToInit = C_ModemSpecialChannel;
/* any failure will cause the channel to be marked as unavailable */
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].ubf1IsSlotInUse = 0;
if(gs_a_stL0PCWin95SerialChannels[uwChannelToInit].hCom == INVALID_HANDLE_VALUE)
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].hCom = hCom;
else { /* the modem slot is already used ??? */
lineClose(gs_hLine);
gs_hLine=0;
return NetLib_E_es_SerialFileCreationFailure; /* new modem error code ? */
}
/* this is a channel usable to send broadcast messages */
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].ubf1IsBroadcast = 1;
/* this is a channel for the modem layer */
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].ubf1IsSlotForModem= 1;
/* the modem line is not connected to a remote end yet */
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].ubf1IsSlotConnected= 0;
/* line baud rate setting : POSTPONED until I understand how exactly it works ... */
/* the modem rate should be no more than the serial port rate */
/* the modems negotiate the rate they use at connect time */
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].eChannelStatus = E_ts_OK;
gs_a_stL0PCWin95SerialChannels[uwChannelToInit].ubf1IsSlotInUse = 1;
/* copy the configuration into the channel structure */
/* (but the modemsettings gets lost) */
memcpy(&gs_a_stL0PCWin95SerialChannels[uwChannelToInit].stChannelStatus,
&(((DEVCFG *)((char *)pDeviceConfig+pDeviceConfig->dwStringOffset))->commconfig.dcb), sizeof(DCB));
/* now we can free the device structure */
vFree((tdpPointer)pDeviceConfig);
gs_bL0PCWin95ModemInitState = gs_bL0PCWin95ModemInitState | (char)0x04;
return NetLib_E_es_NoError;
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : void vL0PCWin95ModemAnswer
////////////////////////////////////////////////////////////////////////////////
Input :
handle to the call to be answered
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
Creation date : July 10,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
void vL0PCWin95ModemAnswer(HCALL hCallToAnswer)
{
long lErrorCode;
/* if there is no call in progress and we should accept incoming calls, */
/* then accept the incoming call, else reject it */
if(!gs_hCall && gs_cModemAnswerMode) {
lErrorCode=lineAnswer(hCallToAnswer, NULL, 0);
if(lErrorCode<0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemAnswer(): lineAnswer(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return;
}
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemAnswer(): lineAnswer(): -->Request ID: %d", lErrorCode);
#endif /* NET_USE_DEBUG */
gs_hCall=hCallToAnswer;
} else {
lErrorCode=lineDrop(hCallToAnswer, NULL, 0);
if(lErrorCode<0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemAnswer(): lineDrop(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
}
}
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : void vL0PCWin95ModemConnect
////////////////////////////////////////////////////////////////////////////////
Input :
none
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
Creation date : July 10,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
void vL0PCWin95ModemConnect()
{
long lErrorCode;
tduwNetChannel uwChannelToInit; /* index of channel to init */
tdstL0PCWin95SerialChannel *pstChannel; /* pointer to channel to init */
COMMTIMEOUTS cto; /* communication timeouts */
int iNotOk; /* flag: has a problem occured so far ?*/
/* as for now, the modem uses the last serial channel */
uwChannelToInit=C_ModemSpecialChannel;
pstChannel=&gs_a_stL0PCWin95SerialChannels[uwChannelToInit];
/* the connection has been established: */
/* the channel can be used to communicate */
/* allocate handles and buffers, and mark channel as connected */
/* set transmission timeouts */
#ifdef MODEM_DEBUG
if(GetCommTimeouts(pstChannel->hCom, &cto)==FALSE) {
lErrorCode=GetLastError();
fprintf(stderr, "GetCommTimeouts(): %d\n", lErrorCode);
}
DisplayCommTimeouts(&cto);
puts("---------------------------------");
#endif /* MODEM_DEBUG */
if(SetupComm(pstChannel->hCom, 500, 2*sizeof(tdstPacket))==FALSE) {
lErrorCode=GetLastError();
#ifdef MODEM_DEBUG
fprintf(stderr, "GetCommTimeouts(): %d\n", lErrorCode);
#endif /* MODEM_DEBUG */
}
vL0PCWin95ModemInitializeCommTimeouts(&cto);
if(SetCommTimeouts(pstChannel->hCom, &cto)==FALSE) {
lErrorCode=GetLastError();
#ifdef MODEM_DEBUG
printf("SetCommTimeouts(): %d\n", lErrorCode);
#endif /* MODEM_DEBUG */
}
#ifdef MODEM_DEBUG
DisplayCommTimeouts(&cto);
puts("---------------------------------");
#endif /* MODEM_DEBUG */
/* purge transmission channel from any extraneous lingering data */
if (!PurgeComm(pstChannel->hCom, PURGE_RXCLEAR | PURGE_TXCLEAR)) {
lErrorCode=GetLastError();
/* close the handle */
CloseHandle(pstChannel->hCom);
pstChannel->hCom = INVALID_HANDLE_VALUE;
pstChannel->eChannelStatus = E_ts_ChannelUnitialized; /* ? */
/* CLOSE AND DEALLOCATE THE CALL ??? ModemRelease ?? */
return /* NetLib_E_es_SerialInitFailure */;
}
ClearCommBreak(pstChannel->hCom);
iNotOk=0;
/* initialize the low level emission/reception buffers */
vInitWindow(&pstChannel->stSendWindow, MODEM_WINDOW, MODEM_TIMEOUT);
vInitWindow(&pstChannel->stRecvWindow, MODEM_WINDOW, 0);
pstChannel->ucSeqn=0;
pstChannel->ulReadPos=0;
vInitRingBuffer(&pstChannel->stSendBuffer);
vInitLinkBuffer(&pstChannel->stRecvBuffer, MODEM_LINKNUMBER);
pstChannel->hBufferEmpty=CreateEvent(NULL, TRUE, FALSE, NULL);
pstChannel->hSlotsEmpty=CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&pstChannel->stSendBufferAccess);
InitializeCriticalSection(&pstChannel->stRecvBufferAccess);
/* no operation in progress yet */
pstChannel->ubf1ReadInProgress
= pstChannel->ubf1WriteInProgress = 0;
/* no byte received or sent in any I/O operation yet */
pstChannel->ulBytesInReadBuffer = 0;
/* allocate buffer for reception */
pstChannel->pCurrentReceivingBuffer = pMalloc(C_uwMaxAsyncLength);
if(pstChannel->pCurrentReceivingBuffer!=C_pNull) {
/* register with the threada controller */
vAddThreadClient(uwChannelToInit);
/* start the ball rolling: signal the read event */
if(SetEvent(pstChannel->stOverlappedRead.hEvent)==TRUE) {
pstChannel->pCurrentReceivedMessage=C_pNull;
pstChannel->pCurrentMessageIncomingPoint=C_pNull;
pstChannel->ulBytesToCompleteIncomingMessage=0L;
pstChannel->ubf1IsSlotConnected= 1;
} else {
iNotOk=1;
/* deregister from the thread controller */
vRemoveThreadClient(uwChannelToInit);
}
} else iNotOk=1; /* NetLib_E_es_NotEnoughMemory */
if(iNotOk) {
/* close the handle */
CloseHandle(pstChannel->hCom);
pstChannel->hCom = INVALID_HANDLE_VALUE;
DeleteCriticalSection(&pstChannel->stSendBufferAccess);
DeleteCriticalSection(&pstChannel->stRecvBufferAccess);
CloseHandle(pstChannel->hBufferEmpty);
CloseHandle(pstChannel->hSlotsEmpty);
vDeleteLinkBuffer(&pstChannel->stRecvBuffer);
vDeleteWindow(&pstChannel->stRecvWindow);
vDeleteWindow(&pstChannel->stSendWindow);
pstChannel->eChannelStatus = E_ts_ChannelUnitialized; /* ? */
}
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : void vL0PCWin95ModemDisconnect
////////////////////////////////////////////////////////////////////////////////
Input :
none
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
This function is called when the line gets disconnected.
Creation date : July 14,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
void vL0PCWin95ModemDisconnect()
{
tduwNetChannel uwChannelToClose; /* index of channel disconnected */
tdstL0PCWin95SerialChannel *pstChannel; /* pointer to this channel */
/* as for now, the modem uses the last serial channel */
uwChannelToClose=C_ModemSpecialChannel;
pstChannel=&gs_a_stL0PCWin95SerialChannels[uwChannelToClose];
/* the connection has been broken: */
vL0PCWin95SerialCloseChannel(uwChannelToClose);
/* the resources held by the channel are deallocated when the line becomes idle */
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : void vL0PCWin95ModemRelease
////////////////////////////////////////////////////////////////////////////////
Input :
none
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
This function is called when the line becomes idle.
Creation date : July 14,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
void vL0PCWin95ModemRelease(HCALL hCallToRelease)
{
long lErrorCode;
tduwNetChannel uwChannelToClose; /* index of channel disconnected */
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemRelease()");
#endif /* NET_USE_DEBUG */
/* the line has become idle : deallocate what needs to be deallocated */
/* is this a call that we rejected ? */
if(hCallToRelease!=gs_hCall) {
/* yes: simply deallocate the call */
lErrorCode=lineDeallocateCall(hCallToRelease);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemRelease():lineDeallocateCall()1: 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
} else {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemRelease():lineDeallocateCall()1: OK");
#endif /* NET_USE_DEBUG */
}
return;
}
/* deallocate the call used by the previous connection */
/* as for now, the modem uses the last serial channel */
/* because of the I/O thread, we can't just close the handle ... we have to close the channel */
uwChannelToClose=C_ModemSpecialChannel;
vL0PCWin95SerialCloseChannel(uwChannelToClose);
lErrorCode=lineDeallocateCall(gs_hCall);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemRelease():lineDeallocateCall()2: 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return;
} else {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemRelease():lineDeallocateCall()2: OK");
#endif /* NET_USE_DEBUG */
}
gs_hCall=0;
if(gs_hWaitForRelease!=INVALID_HANDLE_VALUE)
SetEvent(gs_hWaitForRelease);
else {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemRelease(): ?? hWaitForRelease invalide");
#endif /* NET_USE_DEBUG */
}
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : void vL0PCWin95ModemExitTAPI
////////////////////////////////////////////////////////////////////////////////
Input :
none
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
Creation date : July 10,96
Author : Christophe Roguet
This function closes the line, if needed, and detaches from the TAPI, if needed.
IT MUST BE CALLED WHENEVER THE APPLICATION IS LEFT, if not, TAPI gets stuck() ...
Modification log:
Date: Author
8/11/96 Christophe Roguet
moved part of code into ModemCloseProtocol()
////////////////////////////////////////////////////////////////////////////////
*/
void vL0PCWin95ModemExitTAPI()
{
long lErrorCode;
/* if the line is still open, close it */
/* (if there was no call in progress, ModemCloseChannel did not close the line) */
if(gs_hLine) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "avant lineClose(%lx)", gs_hLine);
#endif /* NET_USE_DEBUG */
lErrorCode=lineClose(gs_hLine);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineClose(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
} else
gs_hLine=0L;
}
if(gs_hLineApp) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "avant lineShutdown(%lx)", gs_hLineApp);
#endif /* NET_USE_DEBUG */
lErrorCode=lineShutdown(gs_hLineApp);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineShutdown(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
} else
gs_hLineApp=0L;
}
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "fin de vL0PCWin95ModemExitTAPI");
#endif /* NET_USE_DEBUG */
}
/*****************************************************************************
*
* Description: eL0PCWin95ModemDial
*
* dials a phone call and initiates connection
*
*****************************************************************************
*
* Input: telephone number represented as a string
*
* Output: an error code
*
*****************************************************************************
* Creation Date: July 10, 1996 Author: Christophe ROGUET
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95ModemDial(char *pcNumberString)
{
int iNumberLength;
long lErrorCode;
long RequestID;
/* should test the validity of hLine etc ... */
/* should avoid reentering calls */
iNumberLength=1+strlen(pcNumberString);
/* allocate a block for holding the call parameters plus the string that contains */
/* the called number */
lpCallParams=(LINECALLPARAMS *)pMalloc(iNumberLength + sizeof( LINECALLPARAMS ));
memset(lpCallParams, 0, iNumberLength + sizeof( LINECALLPARAMS ));
lpCallParams -> dwTotalSize = iNumberLength + sizeof( LINECALLPARAMS );
/* This is where we configure the line for DATAMODEM usage.*/
lpCallParams -> dwBearerMode = LINEBEARERMODE_VOICE;
lpCallParams -> dwMediaMode = LINEMEDIAMODE_DATAMODEM;
/* This specifies that we want to use only IDLE calls and*/
/* don't want to cut into a call that might not be IDLE (ie, in use).*/
lpCallParams -> dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
/* if there are multiple addresses on line, use first anyway.*/
/* It will take a more complex application than a simple tty app*/
/* to use multiple addresses on a line anyway.*/
lpCallParams -> dwAddressMode = LINEADDRESSMODE_ADDRESSID;
lpCallParams -> dwAddressID = 0;
/* Since we don't know where we originated, leave these blank.*/
lpCallParams -> dwOrigAddressSize = 0;
lpCallParams -> dwOrigAddressOffset = 0;
/* Unimodem ignores these values.*/
(lpCallParams -> DialParams) . dwDialSpeed = 0;
(lpCallParams -> DialParams) . dwDigitDuration = 0;
(lpCallParams -> DialParams) . dwDialPause = 0;
(lpCallParams -> DialParams) . dwWaitForDialtone = 0;
/* Address we are dialing.*/
lpCallParams -> dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
lpCallParams -> dwDisplayableAddressSize = iNumberLength;
strcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS), pcNumberString);
/* baud rate range ???*/
lpCallParams -> dwMinRate= 0;
lpCallParams -> dwMaxRate= 0;
lErrorCode=lineMakeCall(gs_hLine, &gs_hCall, pcNumberString,0 /* dwCountryCode */, lpCallParams );
if(lErrorCode<0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineMakeCall(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return NetLib_E_es_UnknownError; /* add a new error code */
} else RequestID=lErrorCode;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "lineMakeCall()->RequestID: %d\n", RequestID);
#endif /* NET_USE_DEBUG */
vFree((tdpPointer)lpCallParams);
return NetLib_E_es_NoError;
}
/*****************************************************************************
*
* Description: eL0PCWin95ModemAnswerMode
*
* this function indicates whether incoming calls should be accepted or rejected
*
*****************************************************************************
*
* Input: boolean: non zero means 'answer any incoming call'
*
* Output: none
*
*****************************************************************************
* Creation Date: August 5, 1996 Author: Christophe ROGUET
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
void _NET_CALLING_CONV_ vL0PCWin95ModemAnswerMode(char cMode)
{
gs_cModemAnswerMode=cMode;
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : vL0PCWin95ModemCloseChannel
////////////////////////////////////////////////////////////////////////////////
Input :
the channel to close - not actually used yet. the modem must be on the last serial channel
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
Creation date : July 17,96
Author : Christophe Roguet
////////////////////////////////////////////////////////////////////////////////
*/
void vL0PCWin95ModemCloseChannel(tduwNetChannel uwChannel)
{
long lErrorCode;
DWORD dwWaitResult;
int bBreak;
unsigned long ulStopTime;
MSG msg;
/* as for now, the modem uses the last serial channel */
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(%d)", uwChannel);
#endif /* NET_USE_DEBUG */
if(uwChannel!=C_ModemSpecialChannel) /* refuse to close a channel but the last one */
return;
/* close the communication port */
vL0PCWin95SerialCloseChannel(uwChannel);
/* hang up the phone */
lErrorCode=0;
if(gs_hCall) {
gs_hWaitForRelease=CreateEvent(NULL, TRUE, FALSE, NULL);
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): lineDrop()");
#endif /* NET_USE_DEBUG */
lErrorCode=lineDrop(gs_hCall, NULL/* user to user info */, 0);
}
if(lErrorCode<0) {
CloseHandle(gs_hWaitForRelease);
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): lineDrop(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return;
} else if(lErrorCode>0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): lineDrop()-->RequestID: %d", lErrorCode);
#endif /* NET_USE_DEBUG */
/* leave time for the asynchronous call deallocation */
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): WaitForRelease");
#endif /* NET_USE_DEBUG */
if(gs_hWaitForRelease==NULL) {
lErrorCode=GetLastError();
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): CreateEvent(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return;
}
/* if the closing thread is not the same thread that initialized the protocol */
/* then simply wait for the deinitialisation to proceed */
/* else process windows messages until deinitialisation is done */
if(GetCurrentThreadId()!=gs_dwInitialiserThreadId)
dwWaitResult=WaitForSingleObject(gs_hWaitForRelease, 3000);
else {
bBreak=0;
ulStopTime=GetTickCount()+3000;
do {
dwWaitResult=MsgWaitForMultipleObjects(1, &gs_hWaitForRelease, FALSE, 50, QS_ALLINPUT);
switch(dwWaitResult) {
case WAIT_OBJECT_0:
bBreak=1;
break;
case WAIT_OBJECT_0+1:
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
case WAIT_ABANDONED_0:
bBreak=1;
break;
case WAIT_TIMEOUT:
if(GetTickCount()>ulStopTime)
bBreak=1;
break;
}
} while(!bBreak);
}
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): deblocage lineDrop()");
#endif /* NET_USE_DEBUG */
CloseHandle(gs_hWaitForRelease);
gs_hWaitForRelease=INVALID_HANDLE_VALUE;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel(): retour WaitForRelease: %ld", dwWaitResult);
#endif /* NET_USE_DEBUG */
} else {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel():lineDrop()-->0 ????");
#endif /* NET_USE_DEBUG */
}
/* close the line (if it hasn't been asynchronously deallocated) */
if(gs_hLine) {
lErrorCode=lineClose(gs_hLine);
if(lErrorCode!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "CloseChannel():lineClose(): 0x%08x", lErrorCode);
#endif /* NET_USE_DEBUG */
return;
}
gs_hLine=0;
}
/* we have to reset the overlapped IO operations events here, because they seem to get signaled after lineClose() */
if(ResetEvent(gs_a_stL0PCWin95SerialChannels[uwChannel].stOverlappedRead.hEvent)==FALSE)
lErrorCode=GetLastError();
if(ResetEvent(gs_a_stL0PCWin95SerialChannels[uwChannel].stOverlappedWrite.hEvent)==FALSE)
lErrorCode=GetLastError();
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "sortie CloseChannel(%d)", uwChannel);
#endif /* NET_USE_DEBUG */
}
/*
////////////////////////////////////////////////////////////////////////////////
Description : vL0PCWin95ModemClosePort
////////////////////////////////////////////////////////////////////////////////
Input :
none
////////////////////////////////////////////////////////////////////////////////
Output :
none
////////////////////////////////////////////////////////////////////////////////
Creation date : July 27,96
Author : Christophe Roguet
remark:
This is an interface function to close a particular modem. As long as the library
manages only one modem channel, this function takes no parameter.
////////////////////////////////////////////////////////////////////////////////
*/
void _NET_CALLING_CONV_ vL0PCWin95ModemClosePort(void)
{
vL0PCWin95ModemCloseChannel(C_ModemSpecialChannel);
}
/*****************************************************************************
*
* Description: vL0PCWin95ModemSetCallback
*
* sets the global variable used to store the callback function through which
* the application that uses the library gets notified of the progress of the
* connection process
*
*****************************************************************************
*
* Input: a pointer to the callback function
*
* Output: none
*
*****************************************************************************
* Creation Date: November 6th, 1996 Author: Christophe ROGUET
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
void _NET_CALLING_CONV_ vL0PCWin95ModemSetCallback(tdfnvModemCallback CallbackFunction)
{
/* register the function's address */
gs_tdfnvModemCallback=CallbackFunction;
/* initialize the state to idle */
CallbackFunction(Netlib_E_mcs_IDLE, 0);
}
/*****************************************************************************
*
* Description: eL0PCWin95InitModem
*
* initializes the TAPI
*
*****************************************************************************
*
* Input: none
*
* Output: an error code
*
*****************************************************************************
* Creation Date: July 9, 1996 Author: Christophe ROGUET
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95InitModem(void)
{
long lErrorCode;
/* global variables */
gs_dwNumDevs=0; /* number of available line devices */
gs_hLine=0; /* line ID */
gs_hCall=0; /* call ID */
lpCallParams=0; /* parameters for a call */
gs_hWaitForRelease=INVALID_HANDLE_VALUE; /* Event for synchronization of call deallocation */
gs_pstCommConfig=0; /* modem configuration */
gs_ulCommConfigSize=0;
gs_cModemAnswerMode=0; /* reject incoming calls */
gs_tdfnvModemCallback=(tdfnvModemCallback)0; /* no callback function */
if((lErrorCode=lineInitialize(&gs_hLineApp, gs_hInstance, vL0PCWin95ModemCallback,
"NetLib", &gs_dwNumDevs))!=0) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "InitModem(): lineInitialize() -> %lx", lErrorCode);
#endif
return NetLib_E_es_InitialisationModemError;
}
gs_bL0PCWin95ModemInitState = gs_bL0PCWin95ModemInitState | (char)0x02;
return NetLib_E_es_NoError;
}
/*****************************************************************************
*
* Description: void vL0PCWin95ModemOpenProtocol
*
* initialize the specified interface structure with the correct function
* pointers to enable a protocol-independent data transmission process.
*
*****************************************************************************
*
* Input: p_stProtocolInterface, pointer to the interface structure
*
* Output: none
*
*****************************************************************************
* Creation Date: July 9, 1996 Author: Christophe ROGUET
*****************************************************************************
*
* Modification log:
*
* Date: Author:
*
****************************************************************************/
void _NET_CALLING_CONV_ vL0PCWin95ModemOpenProtocol(HINSTANCE hInstance, unsigned long ulRate)
{
tdstNetProtocolInterface *p_stProtocolInterface;
/* first, test whether the protocol has already been opened */
/* so as not to open it twice */
/* TO WRITE */
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "ModemOpenProtocol()");
#endif
gs_hInstance=hInstance;
gs_bL0PCWin95ModemInitState = 0x00;
gs_ulL0PCWin95ModemBaudRate=ulRate;
/* initialize TAPI() */
if(eL0PCWin95InitModem()!=NetLib_E_es_NoError)
return;
/* store the current thread ID */
gs_dwInitialiserThreadId=GetCurrentThreadId();
p_stProtocolInterface=pstLevel1AddProtocol();
/* logical identification of the protocol */
p_stProtocolInterface->eProtocol = E_Net_pr_Windows95ModemProtocol;
/* setup the function pointers */
p_stProtocolInterface->fn_uwStartChannelScan = uwL0PCWin95ModemStartChannelScan;
p_stProtocolInterface->fn_uwStartBroadcastChannelScan= uwL0PCWin95ModemStartBroadcastChannelScan;
p_stProtocolInterface->fn_uwNextChannel= uwL0PCWin95ModemNextChannel;
p_stProtocolInterface->fn_uwNextBroadcastChannel= uwL0PCWin95ModemNextBroadcastChannel;
p_stProtocolInterface->fn_eReadData= eL0PCWin95SerialReadData;
p_stProtocolInterface->fn_eSendData= eL0PCWin95SerialSendData;
p_stProtocolInterface->fn_eQueryChannelStatus= eL0PCWin95SerialQueryChannelStatus;
p_stProtocolInterface->fn_vLevel0NetEngine = vL0PCWin95SerialNetEngine;
p_stProtocolInterface->fn_vCloseChannel = (tdfn_vCloseChannel)C_pNull;
p_stProtocolInterface->fn_vLevel0CloseProtocol = vL0PCWin95ModemCloseProtocol;
p_stProtocolInterface->eIsInternet = 0;
/* the channel array is initialized by the serial layer */
gs_bL0PCWin95ModemInitState = gs_bL0PCWin95ModemInitState | (char)0x01;
}
/*****************************************************************************
*
* Description: void vL0PCWin95ModemCloseProtocol();
*
* frees system resources used by the modem
*
*****************************************************************************
*
* Input: none
*
* Output: none
*
*****************************************************************************
* Creation Date: July 23, 1996 Author: Christophe ROGUET
*****************************************************************************
*
* Modification log:
*
* Date: Author:
* 8/11/96 Christophe Roguet
* moved some code from ExitTAPI() into this function
****************************************************************************/
void vL0PCWin95ModemCloseProtocol()
{
tduwNetChannel uwCurrentChannel;
if(lSerialChannelsOnceInitialized) {
/* close 'all' channels */
uwCurrentChannel=C_ModemSpecialChannel;
if( gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotInUse
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotForModem
&& gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].hCom!=INVALID_HANDLE_VALUE)
vL0PCWin95ModemCloseChannel(uwCurrentChannel);
/* release the critical sections used to synchronize channel access, */
/* as well as the communication overlapped operation structures */
if(gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].ubf1IsSlotForModem) {
DeleteCriticalSection(&gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].stChannelAccess);
CloseHandle(gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].stOverlappedRead.hEvent);
CloseHandle(gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].stOverlappedWrite.hEvent);
gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].stOverlappedRead.hEvent=INVALID_HANDLE_VALUE;
gs_a_stL0PCWin95SerialChannels[uwCurrentChannel].stOverlappedWrite.hEvent=INVALID_HANDLE_VALUE;
}
} else
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_Modem, "pas de fermeture de canal");
#endif
vL0PCWin95ModemExitTAPI();
vLevel1RemoveProtocol(E_Net_pr_Windows95ModemProtocol);
}