You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1835 lines
44 KiB
1835 lines
44 KiB
/* com.c -- High level com routines
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 15 $
|
|
* $Date: 7/08/02 6:40p $
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
// #define DEBUGSTR
|
|
#include <time.h>
|
|
|
|
#include "stdtyp.h"
|
|
#include "session.h"
|
|
#include "cnct.h"
|
|
#include "assert.h"
|
|
#include "mc.h"
|
|
#include "cloop.h"
|
|
#include "tdll.h"
|
|
#include "sf.h"
|
|
#include "htchar.h"
|
|
#include "com.h"
|
|
#include "comdev.h"
|
|
#include "com.hh"
|
|
#include <comstd\comstd.hh> // Drivers are linked directly in in this vers.
|
|
#if defined(INCL_WINSOCK)
|
|
#include <comwsock\comwsock.hh>
|
|
#endif // defined(INCL_WINSOCK)
|
|
#include "XFER_MSC.HH" // XD_TYPE
|
|
|
|
int WINAPI WsckDeviceInitialize(HCOM hCom,
|
|
unsigned nInterfaceVersion,
|
|
void **ppvDriverData);
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComCreateHandle
|
|
*
|
|
* DESCRIPTION:
|
|
* Creates a communications handle to be used with subsequent Com calls.
|
|
* The resulting com handle will not be associated with any actual device
|
|
* or port initially.
|
|
*
|
|
* ARGUMENTS:
|
|
* hSession -- Session handle of session creating com handle
|
|
* hwndNotify -- Window to receive Com notifications
|
|
* phcom -- pointer to a var. of type HCOM to receive new com handle
|
|
*
|
|
* RETURNS:
|
|
* COM_OK
|
|
* COM_NOT_ENOUGH_MEMORY if there is insufficient memory
|
|
* COM_FAILED if resources could not be obtained
|
|
* COM_INVALID_HANDLE if handle to Com is invalid
|
|
*/
|
|
int ComCreateHandle(const HSESSION hSession, HCOM *phcom)
|
|
{
|
|
int iRet = COM_OK;
|
|
HCOM pstCom;
|
|
|
|
DBGOUT_NORMAL("+ComCreateHandle for session %08lX\r\n", hSession,0,0,0,0);
|
|
|
|
assert(phcom);
|
|
if (phcom)
|
|
{
|
|
pstCom = *phcom;
|
|
|
|
if(pstCom && ComValidHandle(pstCom))
|
|
{
|
|
// Disconnect from driver
|
|
ComFreeDevice(pstCom);
|
|
|
|
if (pstCom->hRcvEvent)
|
|
{
|
|
ResetEvent(pstCom->hRcvEvent);
|
|
CloseHandle(pstCom->hRcvEvent);
|
|
pstCom->hRcvEvent = NULL;
|
|
}
|
|
if (pstCom->hSndReady)
|
|
{
|
|
ResetEvent(pstCom->hSndReady);
|
|
CloseHandle(pstCom->hSndReady);
|
|
pstCom->hSndReady = NULL;
|
|
}
|
|
*phcom = NULL;
|
|
}
|
|
}
|
|
|
|
// See if we can get memory for a handle
|
|
if ((pstCom = malloc(sizeof(*pstCom))) == NULL)
|
|
{
|
|
// This error can't be reported by ComReportError because no
|
|
// Com Handle exists yet.
|
|
//* utilReportError(hSession, RE_ERROR | RE_OK, NM_NEED_MEM,
|
|
//* strldGet(mGetStrldHdl(hSession), NM_CREATE_SESSION));
|
|
DBGOUT_NORMAL("-ComCreateHandle returning COM_NOT_ENOUGH_MEMORY",
|
|
0,0,0,0,0);
|
|
iRet = COM_NOT_ENOUGH_MEMORY;
|
|
goto Checkout;
|
|
}
|
|
|
|
// Initialize to all zeros just to be on the safe side
|
|
memset(pstCom, 0, sizeof(*pstCom));
|
|
|
|
// ComInitHdl will initialize most values. We must pre-initialize
|
|
// enough so that ComInitHdl knows if it needs to shut anything down.
|
|
pstCom->hSession = hSession;
|
|
pstCom->hDriverModule = (HANDLE)0;
|
|
pstCom->fPortActive = FALSE;
|
|
pstCom->nGuard = COM_VERSION;
|
|
|
|
pstCom->hRcvEvent = NULL;
|
|
pstCom->hSndReady = NULL;
|
|
pstCom->hRcvEvent = CreateEvent(NULL,
|
|
TRUE, // must be manually reset
|
|
FALSE, // create unsignalled
|
|
NULL); // unnamed
|
|
if (pstCom->hRcvEvent == NULL)
|
|
{
|
|
iRet = COM_FAILED;
|
|
goto Checkout;
|
|
}
|
|
|
|
pstCom->hSndReady = CreateEvent(NULL,
|
|
TRUE, // must be manually reset
|
|
FALSE, // create unsignalled
|
|
NULL); // unnamed
|
|
if (pstCom->hSndReady == NULL)
|
|
{
|
|
CloseHandle(pstCom->hRcvEvent);
|
|
pstCom->hRcvEvent = NULL;
|
|
iRet = COM_FAILED;
|
|
goto Checkout;
|
|
}
|
|
|
|
if ((iRet = ComInitHdl(pstCom)) != COM_OK)
|
|
{
|
|
goto Checkout;
|
|
}
|
|
|
|
|
|
Checkout:
|
|
|
|
if (iRet == COM_OK)
|
|
{
|
|
*phcom = (HCOM)pstCom;
|
|
}
|
|
else
|
|
{
|
|
*phcom = NULL;
|
|
if (pstCom)
|
|
{
|
|
if (pstCom->hRcvEvent)
|
|
{
|
|
ResetEvent(pstCom->hRcvEvent);
|
|
CloseHandle(pstCom->hRcvEvent);
|
|
pstCom->hRcvEvent = NULL;
|
|
}
|
|
if (pstCom->hSndReady)
|
|
{
|
|
ResetEvent(pstCom->hSndReady);
|
|
CloseHandle(pstCom->hSndReady);
|
|
pstCom->hSndReady = NULL;
|
|
}
|
|
free(pstCom);
|
|
pstCom = NULL;
|
|
}
|
|
}
|
|
|
|
DBGOUT_NORMAL("ComCreateHandle returning %d, pstCom == %08lX\r\n",
|
|
iRet, pstCom, 0,0,0);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComDestroyHandle
|
|
*
|
|
* DESCRIPTION:
|
|
* Shuts down an existing com handle and frees all resources assigned to it.
|
|
*
|
|
* ARGUMENTS:
|
|
* hCom -- A com handle returned from an earlier call to ComCreateHandle
|
|
* (or ComCreateWudgeHandle)
|
|
*
|
|
* RETURNS:
|
|
* COM_OK
|
|
*/
|
|
int ComDestroyHandle(HCOM *phCom)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
HCOM pstCom;
|
|
|
|
DBGOUT_NORMAL("+ComDestroyHandle(%#08lx)\r\n", *phCom,0,0,0,0);
|
|
assert(phCom);
|
|
|
|
// OK to pass null handle to this function
|
|
if (*phCom == NULL)
|
|
{
|
|
DBGOUT_NORMAL("-ComDestroyHandle returning COM_OK\r\n", 0,0,0,0,0);
|
|
return COM_OK;
|
|
}
|
|
|
|
pstCom = *phCom;
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
// Disconnect from driver
|
|
ComFreeDevice(pstCom);
|
|
|
|
if (pstCom->hRcvEvent)
|
|
{
|
|
ResetEvent(pstCom->hRcvEvent);;
|
|
CloseHandle(pstCom->hRcvEvent);
|
|
pstCom->hRcvEvent = NULL;
|
|
}
|
|
if (pstCom->hSndReady)
|
|
{
|
|
ResetEvent(pstCom->hSndReady);
|
|
CloseHandle(pstCom->hSndReady);
|
|
pstCom->hSndReady = NULL;
|
|
}
|
|
|
|
free(pstCom);
|
|
*phCom = NULL;
|
|
DBGOUT_NORMAL("-ComDestroyHandle returned %d\r\n",
|
|
usRetVal,0,0,0,0);
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* ComInitHdl
|
|
*
|
|
* DESCRIPTION:
|
|
* Called to initialize the Com handle to its default state. Calling this
|
|
* function will clear any existing settings or states and reset for a
|
|
* new session.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- Pointer to our handle data.
|
|
*
|
|
* RETURNS:
|
|
* COM_OK if all is well.
|
|
*/
|
|
int ComInitHdl(const HCOM pstCom)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
// Make sure we're disconnected from any driver loaded earlier
|
|
ComFreeDevice(pstCom);
|
|
|
|
// Fill in default values in exported com structure
|
|
pstCom->stComCntrl.puchRBData = &pstCom->chDummy;
|
|
pstCom->stComCntrl.puchRBDataLimit = &pstCom->chDummy;
|
|
|
|
// Fill in default values for user-settable fields
|
|
pstCom->stWorkSettings.szDeviceFile[0] = TEXT('\0');
|
|
pstCom->stWorkSettings.szPortName[0] = TEXT('\0');
|
|
pstCom->stFileSettings = pstCom->stWorkSettings;
|
|
|
|
// Fill in default values in private com structure
|
|
pstCom->fPortActive = FALSE;
|
|
pstCom->fErrorReported = FALSE;
|
|
pstCom->hDriverModule = (HANDLE)0;
|
|
pstCom->szDeviceName[0]= (TCHAR)0;
|
|
pstCom->chDummy = (TCHAR)0;
|
|
pstCom->afOverride = 0;
|
|
|
|
//
|
|
// Free the send bufers prior to setting to NULL so we don't have
|
|
// a memory leak when the buffers get malloc'd. REV: 02/27/2001.
|
|
//
|
|
if (pstCom->puchSendBufr1)
|
|
{
|
|
free(pstCom->puchSendBufr1);
|
|
pstCom->puchSendBufr1 = NULL;
|
|
}
|
|
if (pstCom->puchSendBufr2)
|
|
{
|
|
free(pstCom->puchSendBufr2);
|
|
pstCom->puchSendBufr2 = NULL;
|
|
}
|
|
|
|
pstCom->puchSendBufr = pstCom->puchSendBufr1;
|
|
pstCom->puchSendPut = pstCom->puchSendBufr1;
|
|
|
|
pstCom->nSBufrSize = 0;
|
|
pstCom->nSendCount = 0;
|
|
pstCom->fUserCalled = FALSE;
|
|
pstCom->pfUserFunction = ComSendDefaultStatusFunction;
|
|
|
|
// fill in defaults for driver functions
|
|
|
|
pstCom->pfDeviceClose = ComDefDoNothing;
|
|
pstCom->pfDeviceDialog = ComDefDeviceDialog;
|
|
pstCom->pfDeviceGetCommon = ComDefDeviceGetCommon;
|
|
pstCom->pfDeviceSetCommon = ComDefDeviceSetCommon;
|
|
pstCom->pfDeviceSpecial = ComDefDeviceSpecial;
|
|
pstCom->pfDeviceLoadHdl = ComDefDeviceLoadSaveHdl;
|
|
pstCom->pfDeviceSaveHdl = ComDefDeviceLoadSaveHdl;
|
|
pstCom->pfPortConfigure = ComDefDoNothing;
|
|
pstCom->pfPortPreconnect = ComDefPortPreconnect;
|
|
pstCom->pfPortActivate = ComDefPortActivate;
|
|
pstCom->pfPortDeactivate = ComDefDoNothing;
|
|
|
|
pstCom->pfPortConnected = ComDefDoNothing;
|
|
pstCom->pfRcvRefill = ComDefBufrRefill;
|
|
pstCom->pfRcvClear = ComDefDoNothing;
|
|
pstCom->pfSndBufrSend = ComDefSndBufrSend;
|
|
pstCom->pfSndBufrIsBusy = ComDefSndBufrBusy;
|
|
pstCom->pfSndBufrClear = ComDefSndBufrClear;
|
|
pstCom->pfSndBufrQuery = ComDefSndBufrQuery;
|
|
pstCom->pfSendXon = ComDefDoNothing;
|
|
|
|
pstCom->pvDriverData = NULL;
|
|
|
|
if (pstCom->hRcvEvent)
|
|
{
|
|
ResetEvent(pstCom->hRcvEvent);
|
|
}
|
|
if (pstCom->hSndReady)
|
|
{
|
|
ResetEvent(pstCom->hSndReady);
|
|
}
|
|
|
|
// Normally, we would load the port type and port name values from the session file and set them,
|
|
// but since we inherit such things from TAPI, just call ComSetDeviceFromFile with a dummy
|
|
// name to get the proper initialization of the com driver.
|
|
ComSetDeviceFromFile((HCOM)pstCom, "comstd.dll");
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* ComLoadHdl
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComLoadHdl(const HCOM pstCom)
|
|
{
|
|
const SF_HANDLE sfHdl = sessQuerySysFileHdl(pstCom->hSession);
|
|
int (WINAPI *pfDeviceLoadHdl)(void *pvDevData, SF_HANDLE sfHdl);
|
|
int iRetVal;
|
|
|
|
pfDeviceLoadHdl = DeviceLoadHdl;
|
|
iRetVal = (*pfDeviceLoadHdl)(pstCom->pvDriverData, sfHdl);
|
|
|
|
#if defined(INCL_WINSOCK)
|
|
if (iRetVal == SF_OK)
|
|
{
|
|
pfDeviceLoadHdl = WsckDeviceLoadHdl;
|
|
iRetVal = (*pfDeviceLoadHdl)(pstCom->pvDriverData, sfHdl);
|
|
}
|
|
#endif // defined(INCL_WINSOCK)
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* ComSaveHdl
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSaveHdl(const HCOM pstCom)
|
|
{
|
|
const SF_HANDLE sfHdl = sessQuerySysFileHdl(pstCom->hSession);
|
|
int (WINAPI *pfDeviceSaveHdl)(void *pvDevData, SF_HANDLE sfHdl);
|
|
int iRetVal;
|
|
|
|
pfDeviceSaveHdl = DeviceSaveHdl;
|
|
iRetVal = (*pfDeviceSaveHdl)(pstCom->pvDriverData, sfHdl);
|
|
|
|
#if defined(INCL_WINSOCK)
|
|
if (iRetVal == SF_OK)
|
|
{
|
|
pfDeviceSaveHdl = WsckDeviceSaveHdl;
|
|
iRetVal = (*pfDeviceSaveHdl)(pstCom->pvDriverData, sfHdl);
|
|
}
|
|
#endif // defined(INCL_WINSOCK)
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetDeviceFromFile(const HCOM pstCom, const TCHAR * const pszFileName)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
int (WINAPI *pfDeviceInit)(HCOM, unsigned, void **);
|
|
|
|
if (pstCom->pvDriverData)
|
|
return COM_OK;
|
|
|
|
// If loadable com drivers were actually implemented, we wouldl load the proper .DLL module here
|
|
// and initialize it. In this version, though, we have only one com driver and it is linked right
|
|
// in. So rather than doing GetProcAddress calls to link to the driver, we can simply load function
|
|
// addresses right into function pointers.
|
|
//
|
|
// Not true anymore! We now have two com drivers to support. But since
|
|
// we still don't load from DLLs, we just let the two drivers share the
|
|
// driver data structure, and each initializes its own specific members.
|
|
// - jmh 02-22-96
|
|
pstCom->hDriverModule = (HANDLE)1; // Set this to fake value so we can close
|
|
pfDeviceInit = DeviceInitialize;
|
|
|
|
if ((iRetVal = (*pfDeviceInit)(pstCom, COM_VERSION,
|
|
&pstCom->pvDriverData)) != COM_OK)
|
|
{
|
|
// The device driver cannot report errors itself until it has
|
|
// been initialized. So we must report any errors it encountered.
|
|
//* if (iRetVal == COM_DEVICE_VERSION_ERROR)
|
|
//* ComReportError(pstCom, CM_ERR_WRONG_VERSION, pszFileName, TRUE);
|
|
//* else
|
|
//* ComReportError(pstCom, CM_ERR_CANT_INIT, pszFileName, TRUE);
|
|
|
|
DBGOUT_NORMAL(" ComSetDevice: *pfDeviceInit failed\r\n",0,0,0,0,0);
|
|
goto Checkout;
|
|
}
|
|
|
|
#if defined(INCL_WINSOCK)
|
|
// Initialize the driver data structure members specific to WinSock.
|
|
//
|
|
pfDeviceInit = WsckDeviceInitialize;
|
|
|
|
if ((iRetVal = (*pfDeviceInit)(pstCom, COM_VERSION,
|
|
&pstCom->pvDriverData)) != COM_OK)
|
|
{
|
|
goto Checkout;
|
|
}
|
|
#endif // defined(INCL_WINSOCK)
|
|
|
|
pstCom->pfDeviceClose = DeviceClose;
|
|
pstCom->pfDeviceDialog = DeviceDialog;
|
|
pstCom->pfDeviceGetCommon = DeviceGetCommon;
|
|
pstCom->pfDeviceSetCommon = DeviceSetCommon;
|
|
pstCom->pfDeviceSpecial = DeviceSpecial;
|
|
pstCom->pfPortConfigure = PortConfigure;
|
|
//pstCom->pfPortPreconnect = PortPreconnect;
|
|
pstCom->pfPortPreconnect = ComDefPortPreconnect;
|
|
pstCom->pfPortActivate = PortActivate;
|
|
|
|
Checkout:
|
|
// if something went wrong, set comm to invalid driver state and return err
|
|
if (iRetVal != COM_OK)
|
|
ComFreeDevice(pstCom);
|
|
|
|
DBGOUT_NORMAL("-ComSetDevice returning %d\r\n", iRetVal,0,0,0,0);
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetDeviceName
|
|
*
|
|
* DESCRIPTION:
|
|
* Returns name of device associated with a com handle
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- com handle returned from earlier call to ComCreateHandle
|
|
* pszName -- pointer to buffer to receive device name (may be NULL)
|
|
* pusLen -- pointer length variable. If pszName is not NULL, this variable
|
|
* should contain the size of the buffer pointed to by pszName.
|
|
* In either case, *pusLen will be set to the size of the
|
|
* device name to be returned.
|
|
*
|
|
* RETURNS:
|
|
* COM_OK
|
|
* COM_INVALID_HANDLE
|
|
*/
|
|
int ComGetDeviceName(const HCOM pstCom,
|
|
TCHAR * const pszName,
|
|
int * const pnLen)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
int nTheirLen;
|
|
|
|
DBGOUT_NORMAL("+ComGetDevice(%#08lx)\r\n", pstCom,0,0,0,0);
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pnLen);
|
|
|
|
nTheirLen = *pnLen;
|
|
*pnLen = StrCharGetByteCount(pstCom->szDeviceName);
|
|
|
|
if (pszName)
|
|
{
|
|
assert(nTheirLen >= (*pnLen + 1));
|
|
if (nTheirLen >= (*pnLen + 1))
|
|
StrCharCopyN(pszName, pstCom->szDeviceName, *pnLen);
|
|
DBGOUT_NORMAL(" ComGetDevice: providing name (%s)\r\n", pszName,0,0,0,0);
|
|
}
|
|
DBGOUT_NORMAL("-ComGetDevice returning %d\r\n", iRetVal,0,0,0,0);
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* ComGetRcvEvent
|
|
*
|
|
* DESCRIPTION:
|
|
* Returns a handle to an event object that can be used to wait for
|
|
* received data to be available from the com routines.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- com handle returned from earlier call to ComCreateHandle
|
|
*
|
|
* RETURNS:
|
|
* The Receive event object
|
|
*/
|
|
HANDLE ComGetRcvEvent(HCOM pstCom)
|
|
{
|
|
return pstCom->hRcvEvent;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetSession
|
|
*
|
|
* DESCRIPTION:
|
|
* Returns Session Handle associated with a Com handle
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- com handle returned from earlier call to ComCreateHandle
|
|
* phSession -- pointer to session handle to receive result
|
|
*
|
|
* RETURNS:
|
|
* always returns COM_OK
|
|
*/
|
|
int ComGetSession(const HCOM pstCom, HSESSION * const phSession)
|
|
{
|
|
assert(ComValidHandle(pstCom));
|
|
assert(phSession);
|
|
|
|
*phSession = pstCom->hSession;
|
|
return COM_OK;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComNotify
|
|
*
|
|
* DESCRIPTION:
|
|
* Called by driver modules to notify com routines of significant events
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void ComNotify(const HCOM pstCom, enum COM_EVENTS event)
|
|
{
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
switch (event)
|
|
{
|
|
case CONNECT:
|
|
cnctComEvent(sessQueryCnctHdl(pstCom->hSession), CONNECT);
|
|
//
|
|
// Set the send and recieve events so we'll wake the COM thread
|
|
// and start sending and/or receiving data. REV: 08/27/2001
|
|
//
|
|
SetEvent(pstCom->hSndReady);
|
|
SetEvent(pstCom->hRcvEvent);
|
|
break;
|
|
|
|
case DATA_RECEIVED:
|
|
SetEvent(pstCom->hRcvEvent);
|
|
CLoopRcvControl(sessQueryCLoopHdl(pstCom->hSession), CLOOP_RESUME,
|
|
CLOOP_RB_NODATA);
|
|
break;
|
|
|
|
case NODATA:
|
|
ResetEvent(pstCom->hRcvEvent);
|
|
break;
|
|
|
|
case SEND_STARTED:
|
|
// NotifyClient(pstCom->hSession, EVENT_LED_SD_ON, 0);
|
|
//DbgOutStr("Send started\n",0,0,0,0,0);
|
|
ResetEvent(pstCom->hSndReady);
|
|
break;
|
|
|
|
case SEND_DONE:
|
|
// NotifyClient(pstCom->hSession, EVENT_LED_SD_OFF, 0);
|
|
//DbgOutStr("Send done\n",0,0,0,0,0);
|
|
SetEvent(pstCom->hSndReady);
|
|
break;
|
|
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComIsActive
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComIsActive(const HCOM pstCom)
|
|
{
|
|
int iRet = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (pstCom == NULL || !pstCom->fPortActive)
|
|
{
|
|
iRet = COM_PORT_NOT_OPEN;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSetPortName
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetPortName(const HCOM pstCom, const TCHAR * const pszPortName)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
|
|
DBGOUT_NORMAL("+ComSetPortName(%#08lx, %s)\r\n", pstCom, pszPortName,0,0,0);
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (!pszPortName)
|
|
iRetVal = COM_PORT_INVALID_NAME;
|
|
|
|
else if (ComIsActive(pstCom) == COM_OK)
|
|
iRetVal = COM_PORT_IN_USE;
|
|
|
|
if (StrCharCmp(pszPortName, pstCom->stWorkSettings.szPortName) != 0)
|
|
{
|
|
//* TODO: call driver to check validity of name
|
|
StrCharCopyN(pstCom->stWorkSettings.szPortName, pszPortName, COM_MAX_PORT_NAME);
|
|
}
|
|
|
|
DBGOUT_NORMAL("-ComSetPortName returned %u\r\n", iRetVal, 0,0,0,0);
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetPortName
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComGetPortName(const HCOM pstCom, TCHAR * const pszName, int nLen)
|
|
{
|
|
int iRetVal = COM_INVALID_HANDLE;
|
|
|
|
DBGOUT_NORMAL("+ComGetPortName(%#08lx)\r\n", pstCom, 0,0,0,0);
|
|
|
|
if (pstCom && ComValidHandle(pstCom))
|
|
{
|
|
if (pszName)
|
|
{
|
|
if (nLen > StrCharGetStrLength(pstCom->stWorkSettings.szPortName))
|
|
{
|
|
iRetVal = COM_OK;
|
|
StrCharCopyN(pszName, pstCom->stWorkSettings.szPortName, nLen);
|
|
}
|
|
else
|
|
{
|
|
iRetVal = COM_NOT_ENOUGH_MEMORY;
|
|
pszName[0] = TEXT('\0');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iRetVal = COM_PORT_INVALID_NAME;
|
|
pszName[0] = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
DBGOUT_NORMAL("-ComGetPortName returning %u, size = %u, name = %s\r\n",
|
|
iRetVal, nLen, pszName ? pszName : " ",0,0);
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetAutoDetect
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComGetAutoDetect(HCOM pstCom, int *pfAutoDetect)
|
|
{
|
|
int iRet = COM_OK;
|
|
struct s_common stCommon;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pfAutoDetect);
|
|
|
|
if (pstCom->pfDeviceGetCommon == NULL)
|
|
iRet = COM_NOT_SUPPORTED;
|
|
else if ((*pstCom->pfDeviceGetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
iRet = COM_DEVICE_ERROR;
|
|
else if (!bittest(stCommon.afItem, COM_AUTO))
|
|
iRet = COM_NOT_SUPPORTED;
|
|
else if (pfAutoDetect)
|
|
*pfAutoDetect = stCommon.fAutoDetect;
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSetAutoDetect
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetAutoDetect(HCOM pstCom, int fAutoDetect)
|
|
{
|
|
struct s_common stCommon;
|
|
int fDummy;
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (ComGetAutoDetect(pstCom, &fDummy) == COM_NOT_SUPPORTED)
|
|
{
|
|
iRetVal = COM_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
stCommon.afItem = COM_AUTO;
|
|
stCommon.fAutoDetect = fAutoDetect;
|
|
|
|
if ((*pstCom->pfDeviceSetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
{
|
|
iRetVal = COM_DEVICE_ERROR;
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetBaud
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComGetBaud(const HCOM pstCom, long * const plBaud)
|
|
{
|
|
ST_COMMON stCommon;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
assert(plBaud);
|
|
|
|
if (pstCom->pfDeviceGetCommon == NULL)
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
if ((*pstCom->pfDeviceGetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
return COM_DEVICE_ERROR;
|
|
|
|
if (!bittest(stCommon.afItem, COM_BAUD))
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
*plBaud = stCommon.lBaud;
|
|
return COM_OK;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSetBaud
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetBaud(const HCOM pstCom, const long lBaud)
|
|
{
|
|
ST_COMMON stCommon;
|
|
long lDummy;
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (ComGetBaud(pstCom, &lDummy) == COM_NOT_SUPPORTED)
|
|
{
|
|
iRetVal = COM_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
stCommon.afItem = COM_BAUD;
|
|
stCommon.lBaud = lBaud;
|
|
|
|
if ((*pstCom->pfDeviceSetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
{
|
|
iRetVal = COM_DEVICE_ERROR;
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetDataBits
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComGetDataBits(const HCOM pstCom, int * const pnDataBits)
|
|
{
|
|
ST_COMMON stCommon;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pnDataBits);
|
|
|
|
if (pstCom->pfDeviceGetCommon == NULL)
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
if ((*pstCom->pfDeviceGetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
return COM_DEVICE_ERROR;
|
|
|
|
if (!bittest(stCommon.afItem, COM_DATABITS))
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
*pnDataBits = stCommon.nDataBits;
|
|
return COM_OK;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSetDataBits
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetDataBits(const HCOM pstCom, const int nDataBits)
|
|
{
|
|
ST_COMMON stCommon;
|
|
int nDummy;
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (ComGetDataBits(pstCom, &nDummy) == COM_NOT_SUPPORTED)
|
|
{
|
|
iRetVal = COM_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
stCommon.afItem = COM_DATABITS;
|
|
stCommon.nDataBits = nDataBits;
|
|
|
|
if ((*pstCom->pfDeviceSetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
{
|
|
iRetVal = COM_DEVICE_ERROR;
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetStopBits
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComGetStopBits(const HCOM pstCom, int * const pnStopBits)
|
|
{
|
|
ST_COMMON stCommon;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pnStopBits);
|
|
|
|
if (pstCom->pfDeviceGetCommon == NULL)
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
if ((*pstCom->pfDeviceGetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
return COM_DEVICE_ERROR;
|
|
|
|
if (!bittest(stCommon.afItem, COM_STOPBITS))
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
*pnStopBits = stCommon.nStopBits;
|
|
return COM_OK;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSetStopBits
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetStopBits(const HCOM pstCom, const int nStopBits)
|
|
{
|
|
ST_COMMON stCommon;
|
|
int nDummy;
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (ComGetStopBits(pstCom, &nDummy) == COM_NOT_SUPPORTED)
|
|
{
|
|
iRetVal = COM_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
stCommon.afItem = COM_STOPBITS;
|
|
stCommon.nStopBits = nStopBits;
|
|
|
|
if ((*pstCom->pfDeviceSetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
{
|
|
iRetVal = COM_DEVICE_ERROR;
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComGetParity
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComGetParity(const HCOM pstCom, int * const pnParity)
|
|
{
|
|
ST_COMMON stCommon;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pnParity);
|
|
|
|
if (pstCom->pfDeviceGetCommon == NULL)
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
if ((*pstCom->pfDeviceGetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
return COM_DEVICE_ERROR;
|
|
|
|
if (!bittest(stCommon.afItem, COM_PARITY))
|
|
return COM_NOT_SUPPORTED;
|
|
|
|
*pnParity = stCommon.nParity;
|
|
return COM_OK;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSetParity
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSetParity(const HCOM pstCom, const int nParity)
|
|
{
|
|
ST_COMMON stCommon;
|
|
int nDummy;
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (ComGetParity(pstCom, &nDummy) == COM_NOT_SUPPORTED)
|
|
{
|
|
iRetVal = COM_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
stCommon.afItem = COM_PARITY;
|
|
stCommon.nParity = nParity;
|
|
|
|
if ((*pstCom->pfDeviceSetCommon)(pstCom->pvDriverData, &stCommon) != COM_OK)
|
|
{
|
|
iRetVal = COM_DEVICE_ERROR;
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComPreconnect
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called just before a connection is attempted. It is
|
|
* called at a point in the connection process when user interaction is
|
|
* straight-forward. Certain devices may need to interact with the user
|
|
* in order to work (having user insert a card, or select from a pool of
|
|
* devices, etc.). User interaction may not be possible at the time that
|
|
* ComActivatePort is called, so it should be done here. This routine
|
|
* may lay claim to a resource and hold it pending the call to
|
|
* ComActivatePort. Once this routine is called, ComActivatePort will
|
|
* usually be called (but not necessarily always); ComDeactivatePort will
|
|
* always be called.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- a com handle as returned by ComCreateHandle
|
|
*
|
|
* RETURNS:
|
|
* COM_OK -- if the connection attempt should continue
|
|
* COM_FAILED -- if the connection attempt should be abandoned. (in this
|
|
* case, it is up to the driver to display the reason
|
|
* before returning)
|
|
*/
|
|
int ComPreconnect(const HCOM pstCom)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
iRetVal = (*pstCom->pfPortPreconnect)(pstCom->pvDriverData,
|
|
pstCom->stWorkSettings.szPortName, sessQueryHwnd(pstCom->hSession));
|
|
|
|
if (iRetVal != COM_OK)
|
|
{
|
|
iRetVal = COM_FAILED;
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComActivatePort
|
|
*
|
|
* DESCRIPTION:
|
|
* Attempts to activate the port associated with a com handle. This call
|
|
* will not necessarily attempt to complete a connection.
|
|
* Note: this function will display an error messages for all errors except
|
|
* COM_PORT_IN_USE. If a COM_PORT_IN_USE error is encountered and
|
|
* is not rectified by borrowing or changing ports, the error message
|
|
* should be displayed by the calling routine.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- a com handle as returned by ComCreateHandle
|
|
*
|
|
* RETURNS:
|
|
* COM_OK
|
|
* COM_PORT_IN_USE -- Port is in use by another process.
|
|
* or error code as defined in COM.H
|
|
*/
|
|
int ComActivatePort(const HCOM pstCom, DWORD_PTR dwMediaHdl)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
|
|
// This function (or the functions it calls) should report all errors
|
|
// except for COM_PORT_IN_USE. Higher level routines may want to
|
|
// try some recovery techniques before reporting an unavailable port
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
DBGOUT_NORMAL("+ComActivatePort(%#08x)\r\n", pstCom, 0,0,0,0);
|
|
if (ComIsActive(pstCom) != COM_OK)
|
|
{
|
|
//* TODO: this is temporary until we resolve how driver and program
|
|
// decide on size of send buffers.
|
|
pstCom->nSBufrSize = 128;
|
|
|
|
//
|
|
// Free the send bufers prior to setting to malloc so we don't
|
|
// have a memory leak. REV: 02/27/2001.
|
|
//
|
|
if (pstCom->puchSendBufr1)
|
|
{
|
|
free(pstCom->puchSendBufr1);
|
|
pstCom->puchSendBufr1 = NULL;
|
|
}
|
|
if (pstCom->puchSendBufr2)
|
|
{
|
|
free(pstCom->puchSendBufr2);
|
|
pstCom->puchSendBufr2 = NULL;
|
|
}
|
|
|
|
// Allocate ComSend buffers
|
|
if ((pstCom->puchSendBufr1 =
|
|
malloc((size_t)pstCom->nSBufrSize)) == NULL ||
|
|
(pstCom->puchSendBufr2 =
|
|
malloc((size_t)pstCom->nSBufrSize)) == NULL)
|
|
{
|
|
DBGOUT_NORMAL(" ComActivatePort -- no memory for send buffers\r\n",
|
|
0,0,0,0,0);
|
|
//* ComReportError(pstCom, NM_NEED_MEMFOR,
|
|
//* strldGet(mGetStrldHdl(pstCom->hSession), CM_NM_COMDRIVER), TRUE);
|
|
iRetVal = COM_NOT_ENOUGH_MEMORY;
|
|
goto checkout;
|
|
}
|
|
|
|
pstCom->puchSendBufr = pstCom->puchSendPut = pstCom->puchSendBufr1;
|
|
pstCom->nSendCount = 0;
|
|
pstCom->fUserCalled = FALSE;
|
|
pstCom->pfUserFunction = ComSendDefaultStatusFunction;
|
|
|
|
// Now call on driver code to activate the physical device
|
|
if ((iRetVal = (*pstCom->pfPortActivate)(pstCom->pvDriverData,
|
|
pstCom->stWorkSettings.szPortName, dwMediaHdl)) == COM_OK)
|
|
{
|
|
//
|
|
// Reset the transfer's loss of carrier flag. REV: 08/23/2001
|
|
//
|
|
XD_TYPE* pX = (XD_TYPE*)sessQueryXferHdl(pstCom->hSession);
|
|
|
|
if (pX != NULL)
|
|
{
|
|
pX->nCarrierLost = FALSE;
|
|
}
|
|
|
|
pstCom->fPortActive = TRUE;
|
|
}
|
|
}
|
|
|
|
checkout:
|
|
if (iRetVal != COM_OK)
|
|
{
|
|
ComDeactivatePort(pstCom);
|
|
}
|
|
DBGOUT_NORMAL("-ComActivatePort returning %u\r\n", iRetVal, 0,0,0,0);
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComDeactivatePort
|
|
*
|
|
* DESCRIPTION:
|
|
* Attempts to deactivate the port associated with a com handle. This call
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- a com handle as returned by ComCreateHandle
|
|
*
|
|
* RETURNS:
|
|
* COM_OK
|
|
* or error code as defined in COM.H
|
|
*/
|
|
int ComDeactivatePort(const HCOM pstCom)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
int iPortConnected = COM_PORT_NOT_OPEN;
|
|
|
|
DBGOUT_NORMAL("+ComDeactivatePort(%#08x)\r\n", pstCom,0,0,0,0);
|
|
|
|
if (ComValidHandle(pstCom) == FALSE || pstCom == NULL)
|
|
{
|
|
assert(0);
|
|
return COM_INVALID_HANDLE;
|
|
}
|
|
|
|
if (pstCom->pvDriverData != NULL)
|
|
{
|
|
iPortConnected = (*pstCom->pfPortConnected)(pstCom->pvDriverData);
|
|
}
|
|
|
|
if (pstCom->fPortActive || iPortConnected != COM_PORT_NOT_OPEN)
|
|
{
|
|
// Call on driver code to deactivate the physical device
|
|
if ((iRetVal =
|
|
(*pstCom->pfPortDeactivate)(pstCom->pvDriverData)) == COM_OK)
|
|
{
|
|
//
|
|
// Reset the transfer's loss of carrier flag. REV: 08/23/2001
|
|
//
|
|
XD_TYPE* pX = (XD_TYPE*)sessQueryXferHdl(pstCom->hSession);
|
|
|
|
if (pX != NULL)
|
|
{
|
|
pX->nCarrierLost = TRUE;
|
|
}
|
|
|
|
pstCom->fPortActive = FALSE;
|
|
}
|
|
}
|
|
|
|
if (pstCom->pfSndBufrClear)
|
|
{
|
|
// Call on driver code to clear the send buffer
|
|
iRetVal = (*pstCom->pfSndBufrClear)(pstCom->pvDriverData);
|
|
}
|
|
|
|
if (pstCom->hSndReady)
|
|
{
|
|
ResetEvent(pstCom->hSndReady);
|
|
}
|
|
|
|
if (pstCom->pfRcvClear)
|
|
{
|
|
// Call on driver code to clear the receive buffer
|
|
iRetVal = (*pstCom->pfRcvClear)(pstCom->pvDriverData);
|
|
}
|
|
|
|
if (pstCom->hRcvEvent)
|
|
{
|
|
ResetEvent(pstCom->hRcvEvent);
|
|
}
|
|
|
|
pstCom->pfPortDeactivate = ComDefDoNothing;
|
|
pstCom->pfPortConnected = ComDefDoNothing;
|
|
pstCom->pfRcvRefill = ComDefBufrRefill;
|
|
pstCom->pfRcvClear = ComDefDoNothing;
|
|
pstCom->pfSndBufrSend = ComDefSndBufrSend;
|
|
pstCom->pfSndBufrIsBusy = ComDefSndBufrBusy;
|
|
pstCom->pfSndBufrClear = ComDefSndBufrClear;
|
|
pstCom->pfSndBufrQuery = ComDefSndBufrQuery;
|
|
pstCom->pfSendXon = ComDefDoNothing;
|
|
|
|
if (pstCom->puchSendBufr1)
|
|
{
|
|
free(pstCom->puchSendBufr1);
|
|
pstCom->puchSendBufr1 = NULL;
|
|
}
|
|
if (pstCom->puchSendBufr2)
|
|
{
|
|
free(pstCom->puchSendBufr2);
|
|
pstCom->puchSendBufr2 = NULL;
|
|
}
|
|
|
|
pstCom->puchSendBufr = pstCom->puchSendPut = pstCom->puchSendBufr1;
|
|
pstCom->nSendCount = 0;
|
|
pstCom->nSBufrSize = 0;
|
|
pstCom->fUserCalled = FALSE;
|
|
|
|
DBGOUT_NORMAL("-ComDeactivatePort returned %u\r\n", iRetVal, 0,0,0,0);
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComOverride
|
|
*
|
|
* DESCRIPTION:
|
|
* Used to temporarily override the current com settings. Allows setting
|
|
* the com channel to support specific data transfer needs without
|
|
* specific knowledge of the current com device or its settings.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom Com handle returned by an call to CreateComHandle
|
|
* uiOptions Options which specify transfer requirements. Currently:
|
|
* COM_OVERRIDE_8BIT temporarily switchs port to
|
|
* 8 bit, no parity mode
|
|
* COM_OVERRIDE_RCVALL temporarily suspends any com
|
|
* settings that would prevent some
|
|
* characters from being received:
|
|
* typically suspends recognition
|
|
* of received XON/XOFF codes
|
|
* COM_OVERRIDE_SNDALL temporarily suspends any com
|
|
* settings that would prevent some
|
|
* characters from being sent.
|
|
* puiOldOptions Pointer to a unsigned variable to receive the options in
|
|
* force prior to this call. The value returned in this
|
|
* field should be used to restore the com driver when
|
|
* the override is no longer needed. If this value is not
|
|
* needed, puiOldOptions can be set to NULL.
|
|
*
|
|
* RETURNS:
|
|
* COM_OK if requested override is possible with the current com device
|
|
* COM_CANT_OVERRIDE if the current device cannot support the request
|
|
*
|
|
*/
|
|
int ComOverride(const HCOM pstCom,
|
|
const unsigned afOptions,
|
|
unsigned * const pafOldOptions)
|
|
{
|
|
unsigned afOldOverride;
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
afOldOverride = pstCom->afOverride;
|
|
if (pafOldOptions)
|
|
*pafOldOptions = afOldOverride;
|
|
pstCom->afOverride = afOptions;
|
|
|
|
if ((iRetVal = ComConfigurePort(pstCom)) == COM_CANT_OVERRIDE)
|
|
pstCom->afOverride = afOldOverride;
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComQueryOverride
|
|
*
|
|
* DESCRIPTION:
|
|
* Returns the value of the override flags as described in ComOverride
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom Com handle returned by an call to CreateComHandle
|
|
* pafOptions Pointer to UINT to receive copy of override option flags
|
|
*
|
|
* RETURNS:
|
|
* Always returns COM_OK
|
|
*/
|
|
int ComQueryOverride(HCOM pstCom, unsigned *pafOptions)
|
|
{
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pafOptions);
|
|
|
|
*pafOptions = pstCom->afOverride;
|
|
return COM_OK;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComConfigurePort
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComConfigurePort(const HCOM pstCom)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
|
|
DBGOUT_NORMAL("+ComconfigurePort(%#08x)\r\n", pstCom, 0,0,0,0);
|
|
assert(ComValidHandle(pstCom));
|
|
|
|
if (ComIsActive(pstCom) == COM_OK)
|
|
iRetVal = (*pstCom->pfPortConfigure)(pstCom->pvDriverData);
|
|
|
|
DBGOUT_NORMAL("-ComConfigurePort returning %u\r\n", iRetVal, 0,0,0,0);
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComRcvBufrRefill
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComRcvBufrRefill(const HCOM pstCom, TCHAR * const tc, const int fRemoveChar)
|
|
{
|
|
int iRetVal;
|
|
ST_COM_CONTROL *pstComCntrl = (ST_COM_CONTROL *)pstCom;
|
|
|
|
iRetVal = (*pstCom->pfRcvRefill)(pstCom->pvDriverData);
|
|
if (iRetVal)
|
|
{
|
|
if (tc)
|
|
*tc = *pstComCntrl->puchRBData;
|
|
if (fRemoveChar)
|
|
++pstComCntrl->puchRBData;
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComRcvBufrClear
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComRcvBufrClear(const HCOM pstCom)
|
|
{
|
|
return ((*pstCom->pfRcvClear)(pstCom->pvDriverData));
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSndBufrSend
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSndBufrSend(
|
|
const HCOM pstCom,
|
|
void * const pvBufr,
|
|
const int nCount,
|
|
const int nWait)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
assert(pvBufr);
|
|
if (nCount > 0)
|
|
{
|
|
if ((*pstCom->pfPortConnected)(pstCom->pvDriverData) == COM_PORT_NOT_OPEN)
|
|
{
|
|
iRetVal = COM_PORT_NOT_OPEN;
|
|
}
|
|
else if (ComSndBufrBusy(pstCom) == COM_BUSY &&
|
|
(!nWait || ComSndBufrWait(pstCom, nWait) != COM_OK))
|
|
iRetVal = COM_BUSY;
|
|
else
|
|
{
|
|
iRetVal = (*pstCom->pfSndBufrSend)(pstCom->pvDriverData,
|
|
pvBufr, nCount);
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSndBufrBusy
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSndBufrBusy(const HCOM pstCom)
|
|
{
|
|
int usResult;
|
|
|
|
usResult = (*pstCom->pfSndBufrIsBusy)(pstCom->pvDriverData);
|
|
|
|
return usResult;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSndBufrWait
|
|
*
|
|
* DESCRIPTION:
|
|
* Waits until the Com driver can transmit more data. The amount of time to
|
|
* wait can be specified. While waiting, a settable idle function is
|
|
* repeatedly called.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- Com handle
|
|
* nWait -- Time to wait in tenths of a second
|
|
*
|
|
* RETURNS:
|
|
* COM_OK if driver can accept new data within the timeout interval
|
|
* COM_BUSY if the transmitter is still not available after timeout interval
|
|
*/
|
|
int ComSndBufrWait(const HCOM pstCom, const int nWait)
|
|
{
|
|
int iRetVal = COM_OK;
|
|
DWORD dwRet;
|
|
|
|
//
|
|
// See if the port is currently connected. If not, then return an
|
|
// error stating the port is not connected. REV: 08/24/2001
|
|
//
|
|
if ((*pstCom->pfPortConnected)(pstCom->pvDriverData) == COM_PORT_NOT_OPEN)
|
|
{
|
|
iRetVal = COM_PORT_NOT_OPEN;
|
|
}
|
|
else if ((iRetVal = ComSndBufrBusy(pstCom)) != COM_OK && nWait)
|
|
{
|
|
//DbgOutStr("DBG_WRITE: %d Wait started\n",GetTickCount(),0,0,0,0);
|
|
dwRet = WaitForSingleObject(pstCom->hSndReady, nWait * 100);
|
|
if (dwRet != WAIT_OBJECT_0)
|
|
{
|
|
iRetVal = COM_BUSY;
|
|
}
|
|
else
|
|
{
|
|
iRetVal = COM_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//DbgOutStr("DBG_WRITE: %d No wait\n",GetTickCount(),0,0,0,0);
|
|
}
|
|
|
|
return iRetVal;
|
|
|
|
#if 0 // jmh 01-11-96 This was the previous method, which didn't block at all
|
|
int iRetVal = COM_OK;
|
|
DWORD dwTimer;
|
|
|
|
if ((iRetVal = ComSndBufrBusy(pstCom)) != COM_OK && nWait)
|
|
{
|
|
dwTimer = startinterval();
|
|
while (interval(dwTimer) < (DWORD)nWait)
|
|
{
|
|
//* With thread model, not sure we still need ComIdle
|
|
//* ComIdle(pstCom); // Keep from locking up the program
|
|
if (ComSndBufrBusy(pstCom) == COM_OK)
|
|
{
|
|
iRetVal = COM_OK;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return iRetVal;
|
|
#endif // 0
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSndBufrClear
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSndBufrClear(const HCOM pstCom)
|
|
{
|
|
return (*pstCom->pfSndBufrClear)(pstCom->pvDriverData);
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComSndBufrQuery
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComSndBufrQuery(const HCOM pstCom, unsigned * const pafStatus,
|
|
long * const plHandshakeDelay)
|
|
{
|
|
return (*pstCom->pfSndBufrQuery)(pstCom->pvDriverData, pafStatus,
|
|
plHandshakeDelay);
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComDeviceDialog
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComDeviceDialog(const HCOM pstCom, const HWND hwndParent)
|
|
{
|
|
int iRetVal;
|
|
|
|
assert(ComValidHandle(pstCom));
|
|
iRetVal = (*pstCom->pfDeviceDialog)(pstCom->pvDriverData, hwndParent);
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComDriverSpecial
|
|
*
|
|
* DESCRIPTION:
|
|
* Allows access to special features of specific Com Device Drivers using
|
|
* a common API.
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- A Com Handle
|
|
* pszInstructions -- A driver specific string providing instructions
|
|
* on what task a driver should carry out.
|
|
* pszResults -- A buffer to receive a driver specific result string.
|
|
* uiBufrSize -- The size (in bytes) of the pszResults buffer.
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int ComDriverSpecial(const HCOM pstCom, const TCHAR * const pszInstructions,
|
|
TCHAR * const pszResults, const int nBufrSize)
|
|
{
|
|
int iRetVal = COM_NOT_SUPPORTED;
|
|
|
|
if (pstCom == NULL)
|
|
return iRetVal;
|
|
|
|
if (pstCom->pfDeviceSpecial)
|
|
iRetVal = (*pstCom->pfDeviceSpecial)(pstCom->pvDriverData,
|
|
pszInstructions, pszResults, nBufrSize);
|
|
|
|
return iRetVal;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* --- Internal functions --- */
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComReportError
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void ComReportError(const HCOM pstCom, int iErrStr,
|
|
const TCHAR * const pszOptInfo, const int fFirstOnly)
|
|
{
|
|
if (!fFirstOnly || !pstCom->fErrorReported)
|
|
{
|
|
//* if (iErrStr == 0)
|
|
//* iErrStr = GM_TEST_FORMAT; // just %s
|
|
|
|
// Most error messages can be reported with a message error
|
|
// string and (maybe) an optional string field. The optional
|
|
// string is passed to utilReportError whether needed or not
|
|
// since it does no harm if it is not referenced.
|
|
|
|
//* utilReportError(pstCom->hSession, RE_ERROR | RE_OK,
|
|
//* iErrStr, pszOptInfo);
|
|
|
|
if (fFirstOnly)
|
|
pstCom->fErrorReported = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: ComFreeDevice
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void ComFreeDevice(const HCOM pstCom)
|
|
{
|
|
if (pstCom == NULL)
|
|
{
|
|
assert(FALSE);
|
|
return;
|
|
}
|
|
|
|
ComDeactivatePort(pstCom);
|
|
|
|
if (pstCom->hDriverModule != (HANDLE)0)
|
|
{
|
|
if (pstCom->pfDeviceClose)
|
|
{
|
|
(void)(*pstCom->pfDeviceClose)(pstCom->pvDriverData);
|
|
pstCom->pvDriverData = 0;
|
|
// FreeLibrary(pstCom->hDriverModule);
|
|
}
|
|
|
|
pstCom->hDriverModule = (HANDLE)0;
|
|
}
|
|
|
|
pstCom->pfDeviceClose = ComDefDoNothing;
|
|
pstCom->pfDeviceDialog = ComDefDeviceDialog;
|
|
pstCom->pfDeviceGetCommon = ComDefDeviceGetCommon;
|
|
pstCom->pfDeviceSetCommon = ComDefDeviceSetCommon;
|
|
pstCom->pfDeviceSpecial = ComDefDeviceSpecial;
|
|
pstCom->pfDeviceLoadHdl = ComDefDeviceLoadSaveHdl;
|
|
pstCom->pfDeviceSaveHdl = ComDefDeviceLoadSaveHdl;
|
|
pstCom->pfPortConfigure = ComDefDoNothing;
|
|
pstCom->pfPortPreconnect = ComDefPortPreconnect;
|
|
pstCom->pfPortActivate = ComDefPortActivate;
|
|
pstCom->pfPortDeactivate = ComDefDoNothing;
|
|
pstCom->fPortActive = FALSE;
|
|
pstCom->szDeviceName[0] = TEXT('\0');
|
|
pstCom->stWorkSettings.szDeviceFile[0] = TEXT('\0');
|
|
pstCom->stWorkSettings.szPortName[0] = TEXT('\0');
|
|
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* ComValidHandle
|
|
*
|
|
* DESCRIPTION:
|
|
* Tests whether a com handle points to a valid, initialize structure
|
|
*
|
|
* ARGUMENTS:
|
|
* pstCom -- com handle to be tested
|
|
*
|
|
* RETURNS:
|
|
* TRUE if com handle appears to be valid
|
|
* FALSE if com handle if NULL or points to an invalid structure
|
|
*/
|
|
BOOL ComValidHandle(HCOM pstCom)
|
|
{
|
|
BOOL bReturnValue = TRUE;
|
|
|
|
if (pstCom == NULL)
|
|
{
|
|
bReturnValue = FALSE;
|
|
}
|
|
#if !defined(NDEBUG)
|
|
else if (pstCom->nGuard != COM_VERSION)
|
|
{
|
|
bReturnValue = FALSE;
|
|
}
|
|
#endif //!defined(NDEBUG)
|
|
|
|
return bReturnValue;
|
|
}
|
|
|