home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boldly Go Collection
/
version40.iso
/
TS
/
17A
/
DRWIN101.ZIP
/
SERUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-23
|
60KB
|
1,387 lines
/****************************************************************************/
/* MODULE serutil.c */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This module contains support files for use with RS232 serial port */
/* communications. Both reception and transmission are interrupt-driven, */
/* so overhead is low. All functions (accessible to the user) begin with */
/* the three letters "ser". The function prototypes are listed in the */
/* file serutil.h, along with brief descriptions. */
/* An error code, sererr, is set whenever an error occurs (usually */
/* indicated by a 0 or NULL return value from a serXXXX() function). */
/*-----------------------------Constraints/Gotchas--------------------------*/
/* These functions require the use of an 8251 or 8250B serial i/o chip. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code, version 1.00 */
/****************************************************************************/
#include <stdio.h>
#include <dos.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "strutil.h"
#include "bufutil.h"
#include "serutil.h"
void interrupt serint1(void);
void interrupt serint2(void);
void interrupt serint3(void);
void interrupt serint4(void);
volatile PORT serp[MAXPORTS]={
{ COM1, NULL, NULL, serint1, NULL, SER_COM1INT, SER_COM1IMR },
{ COM2, NULL, NULL, serint2, NULL, SER_COM2INT, SER_COM2IMR },
{ COM3, NULL, NULL, serint3, NULL, SER_COM3INT, SER_COM3IMR },
{ COM4, NULL, NULL, serint4, NULL, SER_COM4INT, SER_COM4IMR }
};
char serstr[256];
char *sercomstr[8]={ "COM1","COM2","COM3","COM4",NULL };
int sererr=SER_NONE;
WORD far *seriobase=(WORD far *)0x00000400; /*pointer to COM port list*/
/****************************************************************************/
/* serintX */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* The following functions are the interrupt drivers for each of the four */
/* COM ports currently supported. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* Don't screw with these functions unless you know what you're doing. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
void interrupt serint1(void)
{
static int c;
static int ityp; /*interrupt type -- RX or TX*/
static WORD iop; /*uart base port*/
static volatile PORT *p; /*pointer to port record*/
disable(); /*turn off interrupts*/
iop=seriobase[COM1]; /*uart chip base register i/o addr*/
p=&serp[COM1]; /*our struct*/
ityp=inp(iop+SIO_IIR) & SIO_INTID; /*get interrupt type*/
if (inp(iop+SIO_LSR) & SIO_DR) { /*check data ready*/
c=inp(iop+SIO_RBR); /*read data from rec buffer register*/
if (!bufputc(p->rx,c)) sererr=SER_RXOVER; /*if full, note error*/
}
if (inp(iop+SIO_LSR) & SIO_THRE) { /*check transmit holding register*/
if (!bufempty(p->tx)) /*if more chars to add..*/
outp(iop+SIO_THR,bufgetc(p->tx)); /*..add one*/
}
outp(IOP_PIC,0x20); /*tell PIC end of interrupt*/
enable(); /*reinstate interrupts*/
} /*serint1*/
void interrupt serint2(void)
{
static int c;
static int ityp; /*interrupt type -- RX or TX*/
static WORD iop; /*uart base port*/
static volatile PORT *p; /*pointer to port record*/
disable(); /*turn off interrupts*/
iop=seriobase[COM2]; /*uart chip base register i/o addr*/
p=&serp[COM2]; /*our struct*/
ityp=inp(iop+SIO_IIR) & SIO_INTID; /*get interrupt type*/
if (inp(iop+SIO_LSR) & SIO_DR) {
c=inp(iop+SIO_RBR);
if (!bufputc(p->rx,c)) sererr=SER_RXOVER;
}
if (inp(iop+SIO_LSR) & SIO_THRE) {
if (!bufempty(p->tx))
outp(iop+SIO_THR,bufgetc(p->tx));
}
outp(IOP_PIC,0x20); /*tell PIC end of interrupt*/
enable(); /*reinstate interrupts*/
} /*serint2*/
void interrupt serint3(void)
{
static int c;
static int ityp; /*interrupt type -- RX or TX*/
static WORD iop; /*uart base port*/
static volatile PORT *p; /*pointer to port record*/
disable(); /*turn off interrupts*/
iop=seriobase[COM3]; /*uart chip base register i/o addr*/
p=&serp[COM3]; /*our struct*/
ityp=inp(iop+SIO_IIR) & SIO_INTID; /*get interrupt type*/
if (inp(iop+SIO_LSR) & SIO_DR) {
c=inp(iop+SIO_RBR);
if (!bufputc(p->rx,c)) sererr=SER_RXOVER;
}
if (inp(iop+SIO_LSR) & SIO_THRE) {
if (!bufempty(p->tx))
outp(iop+SIO_THR,bufgetc(p->tx));
}
outp(IOP_PIC,0x20); /*tell PIC end of interrupt*/
enable(); /*reinstate interrupts*/
} /*serint3*/
void interrupt serint4(void)
{
static int c;
static int ityp; /*interrupt type -- RX or TX*/
static WORD iop; /*uart base port*/
static volatile PORT *p; /*pointer to port record*/
disable(); /*turn off interrupts*/
iop=seriobase[COM4]; /*uart chip base register i/o addr*/
p=&serp[COM4]; /*our struct*/
ityp=inp(iop+SIO_IIR) & SIO_INTID; /*get interrupt type*/
if (inp(iop+SIO_LSR) & SIO_DR) {
c=inp(iop+SIO_RBR);
if (!bufputc(p->rx,c)) sererr=SER_RXOVER;
}
if (inp(iop+SIO_LSR) & SIO_THRE) {
if (!bufempty(p->tx))
outp(iop+SIO_THR,bufgetc(p->tx));
}
outp(IOP_PIC,0x20); /*tell PIC end of interrupt*/
enable(); /*reinstate interrupts*/
} /*serint4*/
/****************************************************************************/
/* serbad */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function does a quick check of the PORT pointer parameter to see */
/* if it really points to a PORT structure. It sets sererr on error. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p pointer to check */
/*-----------------------------Return value---------------------------------*/
/* 1 if the pointer was bad, 0 if it seemed ok. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int serbad(PORT *p)
{
if (p==NULL) return sererr=SER_BADPORT;
if (p->rx==NULL) return sererr=SER_UNINIT;
if (p->com>=MAXPORTS) return sererr=SER_BADCOM;
return sererr=0;
} /*serbad*/
/****************************************************************************/
/* setdtr, setrts, setbrk */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions set the RS232 control lines for the given COM port. */
/* If the value passed is 0, the RS232 control line is reset (logical 0), */
/* but if the value passed is nonzero, the RS232 line is set to an active */
/* state. Note that these are logic levels, and not voltages, since some */
/* active levels are at lower voltages. */
/* The output lines are Data Terminal Ready (setdtr()), Request To Send */
/* (setrts()) and Break (setbrk()). */
/*-----------------------------Arguments------------------------------------*/
/* WORD p COM port (NOT a PORT pointer), 0=COM1, 1=COM2, etc. */
/* int <val> value, 0=inactive, nonzero=active */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* These are low-level routines, which do NOT take PORT* arguments. For */
/* normal use, use the corresponding sersetXXX() functions. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int setdtr(WORD p,int dtr)
{
p=seriobase[p];
if (!p) return 0;
if (dtr)
outp(p+SIO_MCR,inp(p+SIO_MCR) | SIO_DTR);
else
outp(p+SIO_MCR,inp(p+SIO_MCR) & ~SIO_DTR);
return 0;
} /*setdtr*/
int setrts(WORD p,int rts)
{
p=seriobase[p];
if (!p) return 0;
if (rts)
outp(p+SIO_MCR,inp(p+SIO_MCR) | SIO_RTS);
else
outp(p+SIO_MCR,inp(p+SIO_MCR) & ~SIO_RTS);
return 0;
} /*setrts*/
int setbrk(WORD p,int brk)
{
p=seriobase[p];
if (!p) return 0;
if (brk)
outp(p+SIO_LCR,inp(p+SIO_LCR) | SIO_SBRK);
else
outp(p+SIO_LCR,inp(p+SIO_LCR) & ~SIO_SBRK);
return 1;
} /*setbrk*/
/****************************************************************************/
/* getdtr, getrts, getbrk, getcts, getdsr */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions get the current settings of the RS232 control lines. */
/* The DTR, RTS and BRK values (returned by getdtr(), getrts() and */
/* getbrk()) are the current values on the output of the chip (under the */
/* user's control). The Clear To Send (getcts()) and Data Set Ready */
/* (getdsr()) values are those present as inputs to the chip. */
/*-----------------------------Arguments------------------------------------*/
/* WORD p COM port (NOT a PORT pointer), 0=COM1, 1=COM2, etc. */
/*-----------------------------Return value---------------------------------*/
/* 1 if value is logically set (active), 0 if reset (inactive) */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* These are low-level routines, which do NOT take PORT* arguments. For */
/* normal use, use the corresponding sergetXXX() functions. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int getdtr(WORD p)
{
p=seriobase[p];
if (!p) return 0;
return (inp(p+SIO_MCR) & SIO_DTR)!=0;
} /*getdtr*/
int getrts(WORD p)
{
p=seriobase[p];
if (!p) return 0;
return (inp(p+SIO_MCR) & SIO_RTS)!=0;
} /*getrts*/
int getbrk(WORD p)
{
p=seriobase[p];
if (!p) return 0;
return (inp(p+SIO_LCR) & SIO_SBRK)!=0;
} /*getbrk*/
int getcts(WORD p)
{
p=seriobase[p];
if (!p) return 0;
return (inp(p+SIO_MSR) & SIO_CTS)!=0;
} /*getcts*/
int getdsr(WORD p)
{
p=seriobase[p];
if (!p) return 0;
return (inp(p+SIO_MSR) & SIO_DSR)!=0;
} /*getdsr*/
/****************************************************************************/
/* baudofbits, paryofbits, dataofbits, stopofbits */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions convert from the low-level register values that the */
/* serial interface chip requires, to high-level values which are easily */
/* recognized by the user. These functions are not accessible to the */
/* user, but are used but higher-level functions after reading values */
/* from the chip's registers. */
/*-----------------------------Arguments------------------------------------*/
/* WORD bits bits (value) read from the serial i/o chip */
/*-----------------------------Return value---------------------------------*/
/* for baudofbits, an unsigned int equal to the baud rate */
/* for paryofbits, 'N' for None, 'O' for Odd and 'E' for even parity */
/* for dataofbits, '5', '6', '7' or '8' data bits (Word Length Setting) */
/* for stopofbits, '1' or '2' stop bits */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
WORD baudofbits(WORD bits)
{
switch(bits) {
case SER_BAUD_300: return 300;
case SER_BAUD_600: return 600;
case SER_BAUD_1200: return 1200;
case SER_BAUD_2400: return 2400;
case SER_BAUD_4800: return 4800;
case SER_BAUD_9600: return 9600;
case SER_BAUD_19200: return 19200;
default: return 0;
} /*switch*/
} /*baudofbits*/
char paryofbits(WORD bits)
{
switch(bits & SIO_PAR) {
case SIO_PARN: return 'N';
case SIO_PARO: return 'O';
case SIO_PARE: return 'E';
default: return 0;
} /*switch*/
} /*paryofbits*/
char dataofbits(WORD bits)
{
switch(bits & SIO_DAT) {
case SIO_DAT5: return '5';
case SIO_DAT6: return '6';
case SIO_DAT7: return '7';
case SIO_DAT8: return '8';
default: return 0;
} /*switch*/
} /*dataofbits*/
char stopofbits(WORD bits)
{
switch(bits & SIO_STB) {
case SIO_STB1: return '1';
case SIO_STB2: return '2';
default: return 0;
} /*switch*/
} /*stopofbits*/
/****************************************************************************/
/* bitsofbaud, bitsofpary, bitsofdata, bitsofstop */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions convert from high-level, easily-recognizable, values */
/* for the given configuration elements, to low-level, register-settable */
/* bit-values for subsequent writing (setting). */
/*-----------------------------Arguments------------------------------------*/
/* for bitsofbaud, one of the SER_BAUD_XXXX constants below */
/* for bitsofpary, 'N' for None, 'O' for Odd and 'E' for even parity */
/* for bitsofdata, '5', '6', '7' or '8' data bits (Word Length Setting) */
/* for bitsofstop, '1' or '2' stop bits */
/*-----------------------------Return value---------------------------------*/
/* WORD bits bits (value) read from the serial i/o chip */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
WORD bitsofbaud(WORD baud)
{
switch(baud) {
case 300: return SER_BAUD_300;
case 600: return SER_BAUD_600;
case 1200: return SER_BAUD_1200;
case 2400: return SER_BAUD_2400;
case 4800: return SER_BAUD_4800;
case 9600: return SER_BAUD_9600;
case 19200: return SER_BAUD_19200;
default: return 0;
} /*switch*/
} /*bitsofbaud*/
WORD bitsofpary(char pary)
{
switch(pary) {
case 'N': return SIO_PARN;
case 'O': return SIO_PARO;
case 'E': return SIO_PARE;
default: return SIO_PARN;
} /*switch*/
} /*bitsofpary*/
WORD bitsofdata(char data)
{
switch(data) {
case '5': return SIO_DAT5;
case '6': return SIO_DAT6;
case '7': return SIO_DAT7;
case '8': return SIO_DAT8;
default: return SIO_DAT8;
} /*switch*/
} /*bitsofdata*/
WORD bitsofstop(char stop)
{
switch(stop) {
case '1': return SIO_STB1;
case '2': return SIO_STB2;
default: return SIO_STB1;
} /*switch*/
} /*bitsofstop*/
/****************************************************************************/
/* setbaud, setpary, setdata, setstop */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions set various transmission parameters, using low-level */
/* bit-masks. */
/*-----------------------------Arguments------------------------------------*/
/* WORD p COM port, 0=COM1, 1=COM2, etc. */
/* WORD bits appropriate bit-mask for function */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* The argument p is NOT a PORT pointer, but is a COM port number. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int setbaud(WORD p,WORD bits)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
outp(iop+SIO_LCR,inp(iop+SIO_LCR) | SIO_DLAB);
outp(iop+SIO_DLL,(bits & 0xFF));
outp(iop+SIO_DLM,(bits >> 8));
outp(iop+SIO_LCR,inp(iop+SIO_LCR) & ~SIO_DLAB);
return 1;
} /*setbaud*/
int setpary(WORD p,WORD bits)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
outp(iop+SIO_LCR,MSKVAL(inp(iop+SIO_LCR),SIO_PAR,bits));
return 1;
} /*setpary*/
int setdata(WORD p,WORD bits)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
outp(iop+SIO_LCR,MSKVAL(inp(iop+SIO_LCR),SIO_DAT,bits));
return 1;
} /*setdata*/
int setstop(WORD p,WORD bits)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
outp(iop+SIO_LCR,MSKVAL(inp(iop+SIO_LCR),SIO_STB,bits));
return 1;
} /*setstop*/
/****************************************************************************/
/* getbaud, getpary, getdata, getstop */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions set various transmission parameters, using low-level */
/* bit-masks. */
/*-----------------------------Arguments------------------------------------*/
/* WORD p COM port, 0=COM1, 1=COM2, etc. */
/*-----------------------------Return value---------------------------------*/
/* Returns the current bit-mask value from the serial interface chip for */
/* the specified configuration element. The return value needs to be */
/* translated from a bit-mask into a more readable form, by way of */
/* XXXXofbits() functions above. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* The argument p is NOT a PORT pointer, but is a COM port number. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
WORD getbaud(WORD p)
{
WORD iop;
WORD bits;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
outp(iop+SIO_LCR,inp(iop+SIO_LCR) | SIO_DLAB);
bits=(inp(iop+SIO_DLM)<<8)+inp(iop+SIO_DLL);
outp(iop+SIO_LCR,inp(iop+SIO_LCR) & ~SIO_DLAB);
return bits;
} /*getbaud*/
WORD getpary(WORD p)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
return inp(iop+SIO_LCR) & SIO_PAR;
} /*getpary*/
WORD getdata(WORD p)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
return inp(iop+SIO_LCR) & SIO_DAT;
} /*getdata*/
WORD getstop(WORD p)
{
WORD iop;
if (p>=MAXPORTS) return 0;
iop=seriobase[p];
if (!iop) return 0;
return inp(iop+SIO_LCR) & SIO_STB;
} /*getstop*/
/****************************************************************************/
/* sersetdtr, sersetrts, sersetbrk */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions set the RS232 control lines for the serial PORT */
/* indicated by the argument p. If the second argument passed is 0, the */
/* RS232 control line is reset (logical 0), but if the value passed is */
/* nonzero, the RS232 line is set to an active level. Note that these */
/* are logic levels, and not voltages, since some active levels are at */
/* lower voltages. */
/* The output lines are Data Terminal Ready (setdtr()), Request To Send */
/* (setrts()) and Break (setbrk()). */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p pointer to PORT structure, as return by seropen() */
/* int <val> value, 0=inactive, nonzero=active */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int sersetdtr(PORT *p,int dtr)
{
if (serbad(p)) return 0;
setdtr(p->com,dtr);
return 1;
} /*sersetdtr*/
int sersetrts(PORT *p,int rts)
{
if (serbad(p)) return 0;
setrts(p->com,rts);
return 1;
} /*sersetrts*/
int sersetbrk(PORT *p,int brk)
{
if (serbad(p)) return 0;
setbrk(p->com,brk);
return 1;
} /*sersetbrk*/
/****************************************************************************/
/* sergetdtr, sergetrts, sergetbrk, sergetrts, sergetdsr */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions read the status of the RS232 control lines for the */
/* serial PORT indicated by the argument p. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p pointer to PORT structure, as return by seropen() */
/*-----------------------------Return value---------------------------------*/
/* Values returned are logic levels: 1 for TRUE (active) and 0 for FALSE. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int sergetdtr(PORT *p)
{
if (serbad(p)) return 0;
return getdtr(p->com);
} /*sergetdtr*/
int sergetrts(PORT *p)
{
if (serbad(p)) return 0;
return getrts(p->com);
} /*sergetrts*/
int sergetbrk(PORT *p)
{
if (serbad(p)) return 0;
return getbrk(p->com);
} /*sergetbrk*/
int sergetcts(PORT *p)
{
if (serbad(p)) return 0;
return getcts(p->com);
} /*sergetcts*/
int sergetdsr(PORT *p)
{
if (serbad(p)) return 0;
return getdsr(p->com);
} /*sergetdsr*/
/****************************************************************************/
/* sersetbaud, sersetpary, sersetdata, sersetstop */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions set various transmission parameters of the serial port */
/* indicated by the PORT *p argument. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p serial port pointer, returned by seropen() */
/* The second argument depends on the element being set: */
/* for sersetbaud(), int val is an int baud rate (300, 1200, 9600, etc) */
/* for sersetpary(), char val is 'N'=none, 'O'=odd, 'E'=even parity */
/* for sersetdata(), char val is '5', '6', '7' or '8' data bits */
/* for sersetstop(), char val is '1' or '2' stop bits */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int sersetbaud(PORT *p,int val)
{
if (serbad(p)) return 0;
setbaud(p->com,bitsofbaud(val));
return 1;
} /*sersetbaud*/
int sersetpary(PORT *p,char val)
{
if (serbad(p)) return 0;
setpary(p->com,bitsofpary(val));
return 1;
} /*sersetpary*/
int sersetdata(PORT *p,char val)
{
if (serbad(p)) return 0;
setdata(p->com,bitsofdata(val));
return 1;
} /*sersetdata*/
int sersetstop(PORT *p,char val)
{
if (serbad(p)) return 0;
setstop(p->com,bitsofstop(val));
return 1;
} /*sersetstop*/
/****************************************************************************/
/* sergetbaud, sergetpary, sergetdata, sergetstop */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions read various transmission parameters of the serial */
/* port indicated by the PORT *p argument. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p serial port pointer, returned by seropen() */
/*-----------------------------Return value---------------------------------*/
/* The return value depends on the element being set: */
/* for sersetbaud(), an int baud rate (300, 1200, 9600, etc) */
/* for sersetpary(), 'N'=none, 'O'=odd, 'E'=even parity */
/* for sersetdata(), '5', '6', '7' or '8' data bits */
/* for sersetstop(), '1' or '2' stop bits */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int sergetbaud(PORT *p)
{
if (serbad(p)) return 0;
return baudofbits(getbaud(p->com));
} /*sergetbaud*/
char sergetpary(PORT *p)
{
if (serbad(p)) return 0;
return paryofbits(getpary(p->com));
} /*sergetpary*/
char sergetdata(PORT *p)
{
if (serbad(p)) return 0;
return dataofbits(getdata(p->com));
} /*sergetdata*/
char sergetstop(PORT *p)
{
if (serbad(p)) return 0;
return stopofbits(getstop(p->com));
} /*sergetstop*/
/****************************************************************************/
/* serscancfg */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function scans its string argument, looking for configuration */
/* switches. The string argument must already have its values loaded via */
/* sprintf() before serscancfg() is called (see sersetcfg() and seropen(), */
/* below). The cfg string may contain any of the following fields, in */
/* any order: */
/* c<com-port> <com-port> is 0 for COM1, 1 for COM2, etc */
/* b<baud-rate> <baud-rate> is 300,600,1200,2400,4800,9600,19200 */
/* p<parity> <parity> is N=none, O=odd or E=even parity */
/* d<data-bits> <data-bits> is 5, 6, 7 or 8 data bits */
/* s<stop-bits> <stop-bits> is 1 or 2 stop bits */
/* r<recv-size> <recv-size> is the receive buffer size, in bytes */
/* t<xmit-size> <xmit-size> is the transmit buffer size, in bytes */
/* D<DTR> <DTR> is 0=inactive, 1=active state for DTR */
/* R<RTS> <RTS> is 0=inactive, 1=active for RTS */
/* B<Break> <Break> is 0=inactive, 1=active for Break */
/* serscancfg() returns the settings in the locations pointed to by its */
/* many arguments. */
/*-----------------------------Arguments------------------------------------*/
/* char *cfg pointer to configuration string to scan */
/* All the remaining arguments point to data values to be set, if their */
/* corresponding switches are found in the cfg string. */
/* WORD *c for COM port, 0=COM1, 1=COM2, etc. */
/* WORD *b for baud rate, 300,600,1200,2400,4800,9600,19200 */
/* char *p for parity, 'N', 'O', 'E' */
/* char *d for data bits, '5', '6', '7', '8' */
/* char *s for stop bits, '1', '2' */
/* WORD *r for receive buffer size */
/* WORD *t for transmit buffer size */
/* char *D for DTR value, '0', '1' */
/* char *R for RTS value, '0', '1' */
/* char *B for Break value, '0', '1' */
/*-----------------------------Return value---------------------------------*/
/* 1 if scan was successful, 0 if an error was encountered */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int serscancfg(
char *cfg, /*configuration string*/
WORD *c, /*pointer to COM port*/
WORD *b,char *p,char *d,char *s, /*to baud, parity, data & stop bits*/
WORD *r,WORD *t, /*to receive and transmit buff sizes*/
char *D,char *R,char *B /*to DTR, RTS and Break settings*/
)
{
if (cfg==NULL) return 1;
while (*cfg) {
while (*cfg && isspace(*cfg)) cfg++; /*skip white space*/
switch (*cfg++) {
case 0: return 1;
case 'c':
switch(*cfg++) {
case '0': *c=COM1; break;
case '1': *c=COM2; break;
case '2': *c=COM3; break;
case '3': *c=COM4; break;
default: sererr=SER_ILLEGALCOM; return 0;
} /*switch on COM port*/
break;
case 'b':
*b=atoi(cfg);
switch(*b) {
case 300:
case 600:
case 1200:
case 2400:
case 4800:
case 9600:
case 19200:
while (*cfg && !isspace(*cfg)) cfg++;
break;
default:
sererr=SER_ILLEGALBAUD;
return 0;
} /*switch on baud*/
break;
case 'p':
*p=*cfg++;
switch(*p) {
case 'N':
case 'E':
case 'O':
break;
default:
sererr=SER_ILLEGALPARY;
return 0;
} /*switch on parity*/
break;
case 'd':
*d=*cfg++;
switch(*d) {
case '5':
case '6':
case '7':
case '8':
break;
default:
sererr=SER_ILLEGALDATA;
return 0;
} /*switch on data*/
break;
case 's':
*s=*cfg++;
switch(*s) {
case '1':
case '2':
break;
default:
sererr=SER_ILLEGALSTOP;
return 0;
} /*switch on data*/
break;
case 'r':
*r=atoi(cfg);
if (*r<=0) {
sererr=SER_ILLEGALRSIZE;
return 0;
}
while (*cfg && !isspace(*cfg)) cfg++;
break;
case 't':
*t=atoi(cfg);
if (*t<=0) {
sererr=SER_ILLEGALTSIZE;
return 0;
}
while (*cfg && !isspace(*cfg)) cfg++;
break;
case 'D':
*D=*cfg++;
switch(*D) {
case '0':
case '1':
break;
default:
*D=0;
sererr=SER_ILLEGALDTR;
return 0;
} /*switch on baud*/
break;
case 'R':
*R=*cfg++;
switch(*R) {
case '0':
case '1':
break;
default:
*R=0;
sererr=SER_ILLEGALRTS;
return 0;
} /*switch on baud*/
break;
case 'B':
*B=*cfg++;
switch(*B) {
case '0':
case '1':
break;
default:
*B=0;
sererr=SER_ILLEGALBRK;
return 0;
} /*switch on baud*/
break;
default:
sererr=SER_ILLEGALSPEC;
return 0;
} /*switch*/
} /*while*/
return 1;
} /*serscancfg*/
/****************************************************************************/
/* seropen */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function opens (initializes) a port, returning a handle to the */
/* calling function. The returned handle is a pointer to a serial port */
/* structure, PORT, which holds information about the port. The pointer */
/* is used on subsequent calls to the serXXXXX() functions. */
/* A configuration may be specified: */
/* c<com-port> <com-port> is 0 for COM1, 1 for COM2, etc */
/* b<baud-rate> <baud-rate> is 300,600,1200,2400,4800,9600,19200 */
/* p<parity> <parity> is N=none, O=odd or E=even parity */
/* d<data-bits> <data-bits> is 5, 6, 7 or 8 data bits */
/* s<stop-bits> <stop-bits> is 1 or 2 stop bits */
/* r<recv-size> <recv-size> is the receive buffer size, in bytes */
/* t<xmit-size> <xmit-size> is the transmit buffer size, in bytes */
/* D<DTR> <DTR> is 0=inactive, 1=active state for DTR */
/* R<RTS> <RTS> is 0=inactive, 1=active for RTS */
/* B<Break> <Break> is 0=inactive, 1=active for Break */
/*-----------------------------Arguments------------------------------------*/
/* char *cfg configuration/format string for port */
/* The cfg string may contain printf()-type format specifiers, in which */
/* case extra arguments should be provided. For example: */
/* p=seropen("c%d b%d pN d8 s1",COM2,1200); */
/* will open the COM2 port, with 1200 baud, N81. */
/*-----------------------------Return value---------------------------------*/
/* Returns NULL on error (check sererr), otherwise returns a PORT pointer */
/* which is to be used on subsequent calls to the serXXXX() functions. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
PORT *seropen(char *cfg,...)
{
va_list va;
PORT *p;
WORD baud,com;
WORD rsiz,tsiz;
char pary,data,stop;
char dtr,rts,brk;
WORD iop;
va_start(va,cfg);
if (cfg) vsprintf(serstr,cfg,va); else serstr[0]=0;
va_end(va);
baud=SER_DEF_BAUD;
com=SER_DEF_COM;
rsiz=SER_DEF_RSIZ;
tsiz=SER_DEF_TSIZ;
pary=SER_DEF_PARY;
data=SER_DEF_DATA;
stop=SER_DEF_STOP;
dtr=SER_DEF_DTR;
rts=SER_DEF_RTS;
brk=SER_DEF_BRK;
for (com=0;com<MAXPORTS;com++) {
if (seriobase[com] && (serp[com].rx==NULL)) break;
} /*for*/
if (com>=MAXPORTS) { sererr=SER_NOAVAILABLE; return NULL; }
if (!serscancfg(serstr,&com,&baud,&pary,&data,&stop,&rsiz,&tsiz,
&dtr,&rts,&brk)) return NULL;
if (com>=MAXPORTS) return NULL;
if ((serp[com].rx!=NULL) || !seriobase[com]) {
sererr=SER_NOAVAILABLE;
return 0;
}
p=(PORT *) &serp[com];
p->com=com; /*just in case*/
p->rx=bufopen(rsiz);
p->tx=bufopen(tsiz);
if ((p->rx==NULL) || (p->tx==NULL)) {
sererr=SER_NOBUFMEM;
bufclose(p->rx);
bufclose(p->tx);
p->rx=NULL;
p->tx=NULL;
return 0;
}
setbaud(p->com,bitsofbaud(baud));
setpary(p->com,bitsofpary(pary));
setdata(p->com,bitsofdata(data));
setstop(p->com,bitsofstop(stop));
if (dtr) setdtr(p->com,dtr-'0');
if (rts) setrts(p->com,rts-'0');
if (brk) setbrk(p->com,brk-'0');
iop=seriobase[p->com];
outp(iop+SIO_LCR,inp(iop+SIO_LCR) & ~SIO_DLAB); /*make sure not baud*/
outp(iop+SIO_IER,SIO_ERBFI+SIO_ETBEI);
outp(iop+SIO_MCR,inp(iop+SIO_MCR) | SIO_EINTS);
p->serold=getvect(p->intnum);
setvect(p->intnum,p->serint);
outp(IOP_IMR,(~p->intimr) & inp(IOP_IMR)); /*enable by resetting*/
inp(iop+SIO_RBR);
inp(iop+SIO_RBR);
inp(iop+SIO_IIR); /*clear stray int id's*/
return p;
} /*seropen*/
/****************************************************************************/
/* serclose */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function closes a serial port and frees the memory being used by */
/* it. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p serial port pointer returned by seropen() */
/*-----------------------------Return value---------------------------------*/
/* Returns 1 if successful, 0 on error. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int serclose(PORT *p)
{
WORD iop;
if (serbad(p)) return 0;
iop=seriobase[p->com];
outp(IOP_IMR,inp(IOP_IMR) | p->intimr);
outp(iop+SIO_MCR,inp(iop+SIO_MCR) & (~SIO_EINTS) & (~SIO_DTR));
outp(iop+SIO_IER,0);
setvect(p->intnum,p->serold);
bufclose(p->rx); p->rx=NULL;
bufclose(p->tx); p->tx=NULL;
return 1;
} /*serclose*/
/****************************************************************************/
/* serputc */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function sends a character out the specified serial port. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p handle for serial port over which to send the char */
/* int c character (passed as int) to send */
/*-----------------------------Return value---------------------------------*/
/* Returns 1 on success, 0 on error. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int serputc(PORT *p,int c)
{
WORD iop;
if (serbad(p)) return 0;
iop=seriobase[p->com];
if (buffull(p->tx)) {
sererr=SER_TXFULL;
return 0;
}
bufputc(p->tx,c);
if ((inp(iop+SIO_LSR)&SIO_THRE)!=0) /*if not currently transmitting*/
outp(iop+SIO_THR,bufgetc(p->tx)); /*write to transmit holding reg*/
return 1;
} /*serputc*/
/****************************************************************************/
/* serputs, serputns, serprintf */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This functions send string out the serial port by calling serputc() */
/* until all the desired characters have been placed in the output buffer. */
/* serputs() puts each character out until a 0 is found, serputns() puts */
/* n characters out, and serprintf() puts printf()-type formatted output. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p handle of serial port to use, returned by seropen() */
/* char *s (serputs() and serputns()) pointer to string to put */
/* int n (serputns()) number of bytes (chars) to output */
/* char *fmt (serprintf()) format specifier for formatted output */
/*-----------------------------Return value---------------------------------*/
/* Returns 1 on success, 0 on error. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int serputs(PORT *p,char *s)
{
sererr=0;
while (*s && !sererr) serputc(p,*s++);
return sererr==0;
} /*serputs*/
int serputns(PORT *p,char *s,int n)
{
if (serbad(p)) return 0;
while ((n-->0) && !sererr) serputc(p,*s++);
return sererr==0;
} /*serputns*/
int serprintf(PORT *p,char *fmt,...)
{
va_list va;
int n;
va_start(va,fmt);
n=vsprintf(serstr,fmt,va);
va_end(va);
serputns(p,serstr,n);
return sererr==0;
} /*serprintf*/
/****************************************************************************/
/* sergetc, sergets */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions receive characters from the serial port receive buffer. */
/* sergetc() gets a single character, and sergets() returns an ASCII-Z */
/* string (0-terminated), from the first character in the buffer, up to */
/* the first newline character ('\n'), which is NOT included. */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p handle of port to use, as returned by seropen() */
/* char *s (sergets()) pointer to hold received string */
/* int n (sergets()) maximum chars to get, including final 0 */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int sergetc(PORT *p)
{
if (serbad(p)) return 0;
if (bufempty(p->rx)) {
sererr=SER_RXEMPTY;
return 0;
}
return bufgetc(p->rx);
} /*sergetc*/
int sergets(PORT *p,char *s,int n)
{
sererr=0;
while ((--n>0) && !sererr) {
*s=sergetc(p);
if (*s==(p->rx)->trm) { *s=0; return 1; }
s++;
} /*while*/
*s=0;
return (sererr==0);
} /*sergets*/
/****************************************************************************/
/* sersetcfg */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function reconfigures the serial port, but allowing more than one */
/* element to be changed in a single call (as opposed to the sersetXXX() */
/* functions). The new configuration values are specified just as in */
/* seropen(): */
/* b<baud-rate> <baud-rate> is 300,600,1200,2400,4800,9600,19200 */
/* p<parity> <parity> is N=none, O=odd or E=even parity */
/* d<data-bits> <data-bits> is 5, 6, 7 or 8 data bits */
/* s<stop-bits> <stop-bits> is 1 or 2 stop bits */
/* D<DTR> <DTR> is 0=inactive, 1=active state for DTR */
/* R<RTS> <RTS> is 0=inactive, 1=active for RTS */
/* B<Break> <Break> is 0=inactive, 1=active for Break */
/* Note that the receive and transmit buffer sizes cannot be changed, nor */
/* can the serial port (COM1, COM2, etc). */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p handle for serial port, as returned by seropen() */
/* char *cfg configuration/format string for port */
/* The cfg string may contain printf()-type format specifiers, in which */
/* case extra arguments should be provided. For example: */
/* p=sersetcfg("b%d p%c d7 s1",1200,'E'); */
/* will reconfigure port p, with 1200 baud, E71. */
/*-----------------------------Return value---------------------------------*/
/* Returns 1 on success, 0 on error. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
int sersetcfg(PORT *p,char *cfg,...)
{
va_list va;
WORD baud=0,com=0,rsiz=0,tsiz=0;
char pary=0,data=0,stop=0;
char dtr=0,rts=0,brk=0;
WORD iop;
va_start(va,cfg);
if (cfg!=NULL) vsprintf(serstr,cfg,va); else serstr[0]=0;
va_end(va);
if (serbad(p)) return 0;
if (!serscancfg(serstr,&com,&baud,&pary,&data,&stop,
&rsiz,&tsiz,&dtr,&rts,&brk)) return 0;
if (com!=p->com) { sererr=SER_NOCOMSWITCH; return 0; }
iop=seriobase[p->com];
if (iop==0) { sererr=SER_NOAVAILABLE; return 0; }
if (baud) sersetbaud(p,baud);
if (pary) sersetpary(p,pary);
if (data) sersetdata(p,data);
if (stop) sersetstop(p,stop);
if (dtr) sersetdtr(p,dtr-'0');
if (rts) sersetrts(p,rts-'0');
if (brk) sersetbrk(p,brk-'0');
if (rsiz || tsiz) {
sererr=SER_NOBUFCHANGE;
return 0;
}
return 1;
} /*sersetcfg*/
/****************************************************************************/
/* sergetcfg */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function loads a string with a displayable description of the */
/* given ports configuration. Note that the string is NOT commpatible */
/* with setsetcfg() nor seropen(). */
/*-----------------------------Arguments------------------------------------*/
/* PORT *p handle of serial port, as returned by seropen() */
/* char *s destination location for configuration description */
/* int n maximum length of string, including final 0 */
/*-----------------------------Return value---------------------------------*/
/* Returns s, as passed. Returns NULL on error. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* The string produced by this function is NOT compatible with those */
/* required by sersetcfg() and seropen(). The string is meant only to be */
/* displayed and easily read. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
char *sergetcfg(PORT *p,char *s,int n)
{
if (serbad(p)) return NULL;
sprintf(
serstr,
"%s %u %c%c%c (r%u t%u)",
sercomstr[p->com],sergetbaud(p),
sergetpary(p),sergetdata(p),sergetstop(p),
(p->rx)->siz,(p->tx)->siz
);
strncpy(s,serstr,n-1);
s[n-1]=0;
return s;
} /*sergetcfg*/
/****************************************************************************/
/* sererrmsg */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function returns a pointer to an error message corresponding to */
/* the error code passed. The error codes are possible values held by */
/* the int variable sererr. */
/*-----------------------------Arguments------------------------------------*/
/* int ec error code for which a message is desired, sererr */
/*-----------------------------Return value---------------------------------*/
/* Returns a pointer to a constant error message string. */
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.07.12 D. Rogers initial code */
/****************************************************************************/
char *sererrmsg(int ec)
{
switch (ec) {
case SER_NONE: return "no error";
case SER_BADPORT: return "port pointer was NULL";
case SER_UNINIT: return "port not yet initialized";
case SER_BADCOM: return "port pointer way off: com field bad";
case SER_ILLEGALSPEC: return "bad cfg specifier";
case SER_ILLEGALCOM: return "bad cfg COM value, c";
case SER_ILLEGALBAUD: return "bad cfg baud rate value, b";
case SER_ILLEGALPARY: return "bad cfg parity value, p";
case SER_ILLEGALDATA: return "bad cfg data bits value, d";
case SER_ILLEGALSTOP: return "bad cfg stop bits value, s";
case SER_ILLEGALRSIZE: return "bad cfg rx buffer size value, r";
case SER_ILLEGALTSIZE: return "bad cfg tx buffer size value, t";
case SER_ILLEGALDTR: return "bad cfg DTR value";
case SER_ILLEGALRTS: return "bad cfg RTS value";
case SER_ILLEGALBRK: return "bad cfg Break value";
case SER_NOAVAILABLE: return "com port not available";
case SER_NOBUFMEM: return "could not allocate serial buffers";
case SER_RXOVER: return "receive buffer overflow";
case SER_TXFULL: return "transmit buffer full";
case SER_RXEMPTY: return "receive buffer empty";
case SER_NOCOMSWITCH: return "COM port switching not allowed";
case SER_NOBUFCHANGE: return "no buffer size changes allowed";
default: return "unknown serial error";
} /*switch*/
} /*sererrmsg*/