?? utitech.c
字號:
/* $Header: "%n Ver=%v %f LastEdit=%w Locker=%l" */
/* "UDSERIAL.C Ver=4 25-Nov-97,17:08:20 LastEdit=JIMV Locker=***_NOBODY_***" */
/***********************************************************************\
* *
* Copyright Wonderware Software Development Corp. 1992-1997 *
* *
* ThisFileName="L:\ww\dde_serv\src\udsample\udserial\udserial.c" *
* LastEditDate="1997 Nov 25 17:08:00" *
* *
\***********************************************************************/
/******************************************/
/* >>>>>>>> Sample Serial Server <<<<<<<< */
/******************************************/
//#define SIMULATING /* enable I/O to simulated device */
#define LINT_ARGS
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if !defined(__MSC)
#include <conio.h>
#else
/* Note: BORLAND conio.h include is disabled for Windows apps. */
/* It includes prototypes for inp & outp which are OK for Windows, */
/* but the whole include file is disabled so these are copied here: */
int _Cdecl inport( int __portid );
void _Cdecl outport( int __portid, int __value );
/* These are in-line functions. These prototypes just clean up
some syntax checks and code generation.
*/
unsigned char _Cdecl __inportb__( int __portid );
unsigned int _Cdecl __inportw__( int __portid );
void _Cdecl __outportb__( int __portid, unsigned char __value );
void _Cdecl __outportw__( int __portid, unsigned int __value );
#define inportb __inportb__
#define inportw __inportw__
#define outportb __outportb__
#define outportw __outportw__
#define inp( portid ) inportb( portid )
#define outp( portid,v ) outportb( portid,v )
#define inpw( portid ) inportw( portid )
#define outpw( portid,v ) outportw( portid,v )
#endif
#include "ntconv.h"
#include "hmemcpy.h"
#include "chainmgr.h"
#include "Utitech.h"
#include "uddefs.h"
#include "config.h"
#include "ntsrvr.h"
#include "debug.h"
#include "tmpbuf.h"
#include "permissn.h"
#include "udgetstr.h"
#include "wwassert.h"
USES_ASSERT
BOOL bFlushOnError = TRUE; /* =TRUE if should flush port buffers
while processing an error */
static int WriteSimComm(int idComDev, const void FAR *lpvBuf, int cbWrite);
static int ReadSimComm(int idComDev, void FAR *lpvBuf, int cbRead);
/*加入一個函數用于切割讀回的字符串。該函數將有效的讀回數據寫入變量lpPort,并把有效的字符串長度寫入變量len。*/
static BYTE inQueBuf[8][INQSIZE];
int
WINAPI
Utitech_ReadComm(LPPORT lpPort)
{
static int qIdx = -1;
BOOL eof_wait;
BYTE cch,*pInQueBuf;
int i,idxQue;
LPSTAT lpTopic;
BYTE plcAddr;
static WORD len;
// next QUEUE stack
qIdx ++;
eof_wait = FALSE;
idxQue = 0;
pInQueBuf = (BYTE *)&inQueBuf[qIdx];
i = ReadComm(lpPort->mbCid,(LPSTR)pInQueBuf, INQSIZE);
if (i > 0) {
lpTopic = lpPort->mbCurTopic;
plcAddr = lpTopic->statTopic;
while (i--) {
cch = *pInQueBuf ++;
idxQue = lpPort->mbRspIndex;
lpPort->mbRspBuffer[idxQue] = cch;
switch (idxQue) {
case 0:
len = 1023;
if (cch == plcAddr) ++idxQue; // start
break;
case 2:
++ idxQue;
// if ERROR return
if (lpPort->mbRspBuffer[1] & 0x80) {
len = 5;
}
else {
switch (lpPort->mbRspBuffer[1]){
case 0x1:
case 0x2:
len = (BYTE)cch + 5;
break;
case 0x10:
case 0x0f:
case 0x05:
len = 8;
break;
default:
len = (WORD)cch + 5;
break;
}
}
break;
default:
/*
if ((cch == 10) || (cch == 13)) { // BCC
lpPort->mbRspExpLen = idxQue;
eof_wait = TRUE;
break;
}
*/
if (++ idxQue >= ( INQSIZE-1)) {
idxQue = 0; // out of QUEUE
break;
}
if (idxQue >= len) {
lpPort->mbRspExpLen = idxQue;
eof_wait = TRUE;
}
break;
} /* switch */
lpPort->mbRspIndex = idxQue;
if (idxQue >= lpPort->mbRspExpLen) break;
} /* while */
}
// release QUEUE stack
qIdx --;
return idxQue;
}
/***********************************************************************/
/** get COMPORT name corresponding to the port for indicated station **/
void
WINAPI
ExtractPortName (LPSTNPARAM lpStnParam, LPSTR lpName, int iMax)
{
int i;
/* get length of name */
i = lstrlen (lpStnParam->spChannelName);
/* ensure name will fit in target buffer */
if (i >= iMax)
i = iMax - 1;
/* copy name to destination */
_fstrncpy (lpName, lpStnParam->spChannelName, i);
lpName[i] = '\0';
} /* ExtractPortName */
/***********************************************************************/
/** Set up port configuration info for indicated station **/
void
WINAPI
SetPortConfigInfo (LPPORT lpPort, LPSTNPARAM lpStnParam)
{
/* copy COMPORT mode string to port structure */
lstrcpy (lpPort->mbConfigString, lpStnParam->spConfigString);
} /* SetPortConfigInfo */
/***********************************************************************/
/** This function checks the communications port for events and logs them. **/
void
WINAPI
checkEvents(LPPORT lpPort)
{
int events;
/* get and clear event mask for indicated COM port */
events = GetCommEventMask(lpPort->mbCid, EV_RXCHAR | EV_TXEMPTY);
if (!ShowingEvents)
/* not displaying events, just return */
return;
/* have logger display appropriate event string */
if ((events & (EV_RXCHAR | EV_TXEMPTY)) == (EV_RXCHAR | EV_TXEMPTY)) {
debug(GetString(STRUSER + 89) /* "RXCHAR and TXEMPTY" */ );
} else if ((events & (EV_RXCHAR | EV_TXEMPTY)) == EV_RXCHAR) {
debug(GetString(STRUSER + 90) /* "RXCHAR" */ );
} else if ((events & (EV_RXCHAR | EV_TXEMPTY)) == EV_TXEMPTY) {
debug(GetString(STRUSER + 91) /* "TXEMPTY" */ );
}
} /* checkEvents */
/***********************************************************************/
/** Check the communications port for serious errors
and print debug messages showing the problem.
return TRUE if event is a serious problem **/
BOOL
WINAPI
UdprotCheckErrors(LPPORT lpPort)
{
int ec;
BOOL serious;
/* get and clear COM error mask for indicated port */
if ((ec = GetCommError(lpPort->mbCid, (COMSTAT FAR *)NULL)) == 0)
/* no errors, just return */
return FALSE;
/* determine whether error is serious */
serious = (ec &
(CE_OVERRUN | CE_RXPARITY | CE_FRAME | CE_BREAK | CE_TXFULL)) != 0;
if (!ShowingErrors)
/* not displaying errors, just return indicator */
return serious;
/* formulate appropriate error message */
dbgBuf[0] = '\0';
if (ec & CE_MODE)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 92) /* "Bad comm port handle. " */ );
if (ec & CE_RXOVER)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 93) /* "Receive queue overflow. " */ );
if (ec & CE_OVERRUN)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 94) /* "Receive overrun. " */ );
if (ec & CE_RXPARITY)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 95) /* "Receive parity error. " */ );
if (ec & CE_FRAME)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 96) /* "Receive framing error. " */ );
if (ec & CE_BREAK)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 97) /* "Received BREAK. " */ );
#ifndef WIN32
if (ec & CE_CTSTO)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 98) /* "CTS timeout. " */ );
if (ec & CE_DSRTO)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 99) /* "DSR timeout. " */ );
if (ec & CE_RLSDTO)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 100) /* "DCD timeout. " */ );
#endif
if (ec & CE_TXFULL)
sprintf(&dbgBuf[strlen(dbgBuf)],
GetString(STRUSER + 101) /* "Transmit queue overflow. " */ );
/* output error message to logger */
debug(dbgBuf);
/* return indication of whether error is serious */
return serious;
} /* UdprotCheckErrors */
/***********************************************************************/
/** Report error code
Called when an OpenComm() fails.
Translates the error code into plain English. **/
void
WINAPI
UdprotReportOpenErrorCode (LPPORT lpPort)
{
/* select appropriate message */
switch (lpPort->mbCid) {
case IE_BADID:
/* "Failed to open device name (%Fs)" */
sprintf(dbgBuf, GetString(STRUSER + 56), lpPort->mbPortName);
break;
case IE_OPEN:
/* "Device already open (%Fs)" */
sprintf(dbgBuf, GetString(STRUSER + 57), lpPort->mbPortName);
break;
case IE_NOPEN:
/* "Device not open (%Fs)" */
sprintf(dbgBuf, GetString(STRUSER + 58), lpPort->mbPortName);
break;
case IE_MEMORY:
/* "Unable to allocate queues" */
strcpy(dbgBuf, GetString(STRUSER + 59));
break;
case IE_DEFAULT:
/* "Error in default parameters" */
strcpy(dbgBuf, GetString(STRUSER + 60));
break;
case IE_HARDWARE:
/* "Hardware not present or already allocated (%Fs)" */
sprintf(dbgBuf, GetString(STRUSER + 61), lpPort->mbPortName);
break;
case IE_BYTESIZE:
/* "Invalid byte size" */
strcpy(dbgBuf, GetString(STRUSER + 62) );
break;
case IE_BAUDRATE:
/* "Unsupported baud rate" */
strcpy(dbgBuf, GetString(STRUSER + 63) );
break;
default:
/* "Unknown error from OpenComm: 0x%x" */
sprintf(dbgBuf, GetString(STRUSER + 64), lpPort->mbCid);
break;
}
/* display message on screen */
MessageBox(hWndParent, dbgBuf, GetAppName(),
MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
} /* UdprotReportOpenErrorCode */
#ifndef SIMULATING
/***********************************************************************/
/* open indicated port */
BOOL
WINAPI
OpenPort (LPPORT lpPort)
{
DCB dcb;
BOOL Trick19200 = FALSE;
char ModeString [21], tempString [21];
char *baudPtr;
/* attempt to open COM port */
lpPort->mbCid = OpenComm(lpPort->mbPortName, INQSIZE, OUTQSIZE);
if (lpPort->mbCid < 0) {
/* OpenComm() failed, display error code */
UdprotReportOpenErrorCode(lpPort);
return FALSE;
}
/* initialize the DCB with current values */
if( NTSrvr_GetCommState(lpPort->mbCid, (DCB FAR *)&dcb) != 0) {
CloseComm(lpPort->mbCid);
return FALSE;
}
/*
* Translate the DOS MODE-style string into the corresponding fields
* in the DCB.
*/
/* copy the mode string to a local string */
lstrcpy (ModeString, lpPort->mbConfigString);
/* point to the baud rate */
baudPtr = strchr (ModeString, ':');
assert (baudPtr);
baudPtr++;
/* check whether the baud rate setting exceeds 4 characters */
if (strncmp (baudPtr, "19200", 5) == 0) {
/** Baud rate string is longer than BuildCommDCB can handle,
so substitute 9600 in the string and set up the DCB.
We will correct the baud rate in the DCB later. **/
Trick19200 = TRUE;
strncpy (baudPtr, " 9600 ", 5); /* Careful, string2 has to */
/* be longer than 5, or the */
/* function will insert a NULL */
strcpy (tempString, baudPtr+1); /* drop out leading space */
strcpy (baudPtr, tempString);
}
if (NTSrvr_BuildCommDCB(ModeString, (DCB FAR *) & dcb) == 0) {
/* Set up the port as needed for the driver's operation */
dcb.fBinary = 1; /* Binary operation */
/* enable RTS handshake, enable DTR */
NTSrvr_SetDCB_Rts( (DCB FAR *)&dcb, NTSrvr_RTS_ENABLE );
NTSrvr_SetDCB_Dtr( (DCB FAR *)&dcb, NTSrvr_DTR_ENABLE );
dcb.fParity = 0; /* No Parity checking */
dcb.fOutxCtsFlow = 0; /* No CTS output flow control */
dcb.fOutxDsrFlow = 0; /* No DSR output flow control */
dcb.fOutX = 0; /* XON/XOFF output flow control */
dcb.fInX = 0; /* No XON/XOFF input flow control */
dcb.fNull = 0; /* No null */
dcb.XonChar = 0x11; /* XON is ^Q */
dcb.XoffChar = 0x13; /* XOFF is ^S */
/* check whether baud rate trick was used */
if (Trick19200) {
/* yes, force DCB baud rate to correct value */
dcb.BaudRate = 19200;
}
/* Now set the port to the configuration in the DCB */
if (NTSrvr_SetCommState( lpPort->mbCid, (DCB FAR *) & dcb) != 0) {
/* unable to set COM port state, close COM port and exit */
CloseComm(lpPort->mbCid);
return FALSE;
}
} else {
/* Parsing of config string failed, close COM port and exit */
CloseComm(lpPort->mbCid);
return FALSE;
}
/* indicate success */
return TRUE;
} /* OpenPort */
/***********************************************************************/
/* shut down serial port */
void
WINAPI
ClosePort (LPPORT lpPort)
{
CloseComm(lpPort->mbCid);
} /* ClosePort */
#endif
/***********************************************************************/
/** Flush indicated port **/
void
WINAPI
FlushPort (LPPORT lpPort, LPSTR lpErrMsg)
{
#ifndef SIMULATING
/* flush COM port input and output buffers */
FlushComm(lpPort->mbCid, 0);
FlushComm(lpPort->mbCid, 1);
#endif
} /* FlushPort */
/***********************************************************************/
/** Read and discard any pending port input,
return TRUE if port is quiet **/
BOOL
WINAPI
WaitForQuietPort (LPPORT lpPort, LPSTR lpErrMsg)
{
int len;
/* read any incoming characters, check for errors */
#ifndef SIMULATING
len = ReadComm(lpPort->mbCid, (LPSTR) lpPort->mbRspBuffer, 1024);
#else
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -