home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 3 Comm
/
03-Comm.zip
/
RXCOMM.ZIP
/
RXCOMM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-23
|
34KB
|
965 lines
/* 09-27-90 Mark Smith */
/*************************************************************************/
/* RxComm.c */
/* Purpose: Handle COMM port through REXX/SAA. This package is loaded */
/* as a REXX extension, and therefore the following lines MUST */
/* be executed in REXX before they may be used: */
/* */
/* call RxFuncAdd 'RxCommOpen' , 'RXCOMM', 'RXCOMMOPEN' */
/* call RxFuncAdd 'RxCommClose' , 'RXCOMM', 'RXCOMMCLOSE' */
/* call RxFuncAdd 'RxCommPut' , 'RXCOMM', 'RXCOMMPUT' */
/* call RxFuncAdd 'RxCommGet' , 'RXCOMM', 'RXCOMMGET' */
/* call RxFuncAdd 'RxCommGetParams', 'RXCOMM', 'RXCOMMGETPARAMS' */
/* call RxFuncAdd 'RxCommSetParams', 'RXCOMM', 'RXCOMMSETPARAMS' */
/* call RxFuncAdd 'RxCommSendBreak', 'RXCOMM', 'RXCOMMSENDBREAK' */
/* call RxFuncAdd 'RxCommCheck' , 'RXCOMM', 'RXCOMMCHECK' */
/* call RxFuncAdd 'RxCommSetDTR' , 'RXCOMM', 'RXCOMMSETDTR' */
/* call RxFuncAdd 'RxCommFlush' , 'RXCOMM', 'RXCOMMFLUSH' */
/* call RxFuncAdd 'RxGetChar' , 'RXCOMM', 'RXGETCHAR' */
/* call RxFuncAdd 'RxSay' , 'RXCOMM', 'RXSAY' */
/* */
/* NOTE: This code has been released into the Public Domain by the */
/* author. This code has NOT been extensivly tested, being a */
/* 3 hour development project that was abandoned due to the speed */
/* of the REXX interpreter under OS/2. If you find any bugs, */
/* or would like to contact the author, he can be reached at: */
/* */
/* Copyright (c) 1990 by: Mark C. Smith */
/* 2638 Marrietta */
/* Farmersvilles, Tx 75234 */
/* */
/* 214/484-4470 */
/* */
/*************************************************************************/
#define INCL_BASE
#include <os2.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <rexxsaa.h>
/* Define our error return codes */
#define OK 0
#define INCORRECT_NUM_PARAMS -1
#define UNABLE_TO_FIND_COM -2
#define IOCTL_ERROR -3
/* Structure to define each port opened by REXX */
struct OPEN_PORTS {
CHAR *Name; /* Name of this COM port */
USHORT handle; /* handle to this COM port */
struct OPEN_PORTS *Next; /* Pointer to next COMM port */
struct OPEN_PORTS *Prev; /* Pointer to prev COMM port */
};
static struct OPEN_PORTS *Top = NULL; /* This is the 1st COMM port opened */
/* Function prototypes for internal functions */
static struct OPEN_PORTS *FindCOM(RXSTRING);
/*************************************************************************/
/* RxCommFlush: flush the input queue of all characters */
/*************************************************************************/
SHORT APIENTRY RxCommFlush(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
SHORT rc;
USHORT zero = 0;
struct OPEN_PORTS *curr;
rc = OK; /* System return code */
retval->strlength = 0;
retval->strptr = NULL;
rc = INCORRECT_NUM_PARAMS;
switch(argc) {
case 0: break;
case 1:
rc = UNABLE_TO_FIND_COM;
if ((curr = FindCOM(argv[0])) != NULL) {
rc = DosDevIOCtl(0L,
&zero,
DEV_FLUSHINPUT,
IOCTL_GENERAL,
curr->handle);
if (rc)
rc = IOCTL_ERROR;
}
break;
default: break;
}
return(rc);
}
/*************************************************************************/
/* RxCommSetDTR: Set the DTR value - returns old DTR value */
/*************************************************************************/
SHORT APIENTRY RxCommSetDTR(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
PSZ tmp;
SHORT rc;
SHORT cc;
USHORT cset;
PSZ data;
MODEMSTATUS ms;
struct OPEN_PORTS *curr;
rc = OK; /* System return code */
cc = 0; /* IOCTL return code */
retval->strlength = 0;
switch(argc) {
case 0:
rc = INCORRECT_NUM_PARAMS;
break;
case 1:
case 2:
rc = UNABLE_TO_FIND_COM;
if ((curr = FindCOM(argv[0])) != NULL) {
rc = OK;
cc = DosDevIOCtl(&cset,
0L,
ASYNC_GETMODEMOUTPUT,
IOCTL_ASYNC,
curr->handle);
_fmemcpy(retval->strptr,(((cset&DTR_ON)==0) ? "OFF\0" : "ON \0"),4);
retval->strlength = _fstrlen(retval->strptr);
if (argc > 1 && argv[1].strlength > 0) {
ms.fbModemOn = 0x00;
ms.fbModemOff = 0xFF;
if (!_fmemcmp(argv[1].strptr, "ON", 2))
ms.fbModemOn = DTR_ON;
else if (!_fmemcmp(argv[1].strptr, "OFF", 2))
ms.fbModemOff = DTR_OFF;
cc = DosDevIOCtl(&cset,
&ms,
ASYNC_SETMODEMCTRL,
IOCTL_ASYNC,
curr->handle);
}
}
break;
default:
rc = INCORRECT_NUM_PARAMS;
break;
}
if (cc)
rc = IOCTL_ERROR;
return(rc);
}
/***************************************************************************/
/* RxCommSendBreak: send the break signal out the COMM port for (n) msecs. */
/***************************************************************************/
SHORT APIENTRY RxCommSendBreak(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
SHORT rc;
USHORT err;
ULONG msec;
CHAR tmp[20];
struct OPEN_PORTS *curr;
msec = 0L;
rc = INCORRECT_NUM_PARAMS;
retval->strlength = 0;
retval->strptr = NULL;
switch(argc) {
case 0:
break;
case 1:
msec = 50L;
case 2:
rc = UNABLE_TO_FIND_COM;
if ((curr = FindCOM(argv[0])) != NULL) {
rc = OK;
if (!msec) {
_fmemset(tmp,'\0',sizeof(tmp));
_fmemcpy(tmp, argv[1].strptr, (USHORT)argv[1].strlength);
msec = atol(tmp);
}
rc = DosDevIOCtl(&err,
0L,
ASYNC_SETBREAKON,
IOCTL_ASYNC,
curr->handle);
DosSleep(msec);
rc += DosDevIOCtl(&err,
0L,
ASYNC_SETBREAKOFF,
IOCTL_ASYNC,
curr->handle);
if(rc)
rc = IOCTL_ERROR;
}
break;
default:
break;
}
return(rc);
}
/*************************************************************************/
/* RxCommSetParams: set the baud rate for the specified COMM port */
/*************************************************************************/
SHORT APIENTRY RxCommSetParams(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
SHORT rc;
SHORT brc;
SHORT lrc;
USHORT baud;
USHORT words;
USHORT bits;
CHAR tmp[20];
struct OPEN_PORTS *curr;
LINECONTROL lc;
retval->strlength = 0;
retval->strptr = NULL;
rc = INCORRECT_NUM_PARAMS;
switch(argc) {
case 0: break;
default:
rc = UNABLE_TO_FIND_COM;
if ((curr = FindCOM(argv[0])) != NULL) {
DosDevIOCtl(&lc,
0L,
ASYNC_GETLINECTRL,
IOCTL_ASYNC,
curr->handle);
rc = OK;
if (argc >= 2) {
_fmemset(tmp,'\0', sizeof(tmp));
_fmemcpy(tmp, argv[1].strptr, (USHORT)argv[1].strlength);
baud = atoi(tmp);
if (baud == 110 ||
baud == 150 ||
baud == 300 ||
baud == 600 ||
baud == 1200 ||
baud == 2400 ||
baud == 4800 ||
baud == 9600 ||
baud == 19200)
brc = DosDevIOCtl(0L,
&baud,
ASYNC_SETBAUDRATE,
IOCTL_ASYNC,
curr->handle);
}
if (argc >= 3) {
lrc = DosDevIOCtl(&lc,
0L,
ASYNC_GETLINECTRL,
IOCTL_ASYNC,
curr->handle);
_fmemset(tmp,'\0', sizeof(tmp));
_fmemcpy(tmp, argv[2].strptr, (USHORT)argv[2].strlength);
words = atoi(tmp);
if (words > 4 && words < 9)
lc.bDataBits = words;
}
if (argc >= 4) {
if (!_fmemcmp(argv[3].strptr, "NONE",1))
lc.bParity = 0x0;
else if (!_fmemcmp(argv[3].strptr, "EVEN",1))
lc.bParity = 0x02;
else if (!_fmemcmp(argv[3].strptr, "ODD",1))
lc.bParity = 0x01;
else if (!_fmemcmp(argv[3].strptr, "MARK",1))
lc.bParity = 0x03;
else if (!_fmemcmp(argv[3].strptr, "SPACE",1))
lc.bParity = 0x04;
}
if (argc >= 5) {
_fmemset(tmp,'\0', sizeof(tmp));
_fmemcpy(tmp, argv[4].strptr, (USHORT)argv[4].strlength);
bits = atoi(tmp);
switch(bits) {
case 1: lc.bStopBits = 0x00;
case 2: lc.bStopBits = 0x02;
}
}
if (argc >= 3)
lrc = DosDevIOCtl(0L,
&lc,
ASYNC_SETLINECTRL,
IOCTL_ASYNC,
curr->handle);
}
}
return(rc);
}
/**************************************************************************/
/* RxCommGetParams: get the line statistics */
/* */
/* Return codes 0 - Ok */
/* -1 - invalid number of parameters */
/* -2 - Unable to find comm port */
/* -3 - IOCTL error */
/**************************************************************************/
SHORT APIENTRY RxCommGetParams(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
SHORT rc;
SHORT brc;
SHORT trc;
SHORT mirc;
SHORT morc;
USHORT baud;
USHORT inputp;
USHORT outputp;
USHORT stopbits;
CHAR parity[20];
PSZ data;
LINECONTROL lc;
struct OPEN_PORTS *curr;
retval->strlength = 0;
rc = INCORRECT_NUM_PARAMS;
switch(argc) {
case 0: break;
case 1:
rc = UNABLE_TO_FIND_COM;
if ((curr = FindCOM(argv[0])) != NULL) {
rc = OK;
brc = DosDevIOCtl(&baud,
0L,
ASYNC_GETBAUDRATE,
IOCTL_ASYNC,
curr->handle);
brc += DosDevIOCtl(&lc,
0L,
ASYNC_GETLINECTRL,
IOCTL_ASYNC,
curr->handle);
brc += DosDevIOCtl(&inputp,
0L,
ASYNC_GETMODEMINPUT,
IOCTL_ASYNC,
curr->handle);
brc += DosDevIOCtl(&outputp,
0L,
ASYNC_GETMODEMOUTPUT,
IOCTL_ASYNC,
curr->handle);
if (!brc) {
rc = 0;
brc = inputp & CTS_ON;
trc = inputp & DSR_ON;
mirc = inputp & RI_ON;
morc = inputp & DCD_ON;
inputp = outputp & DTR_ON;
outputp = outputp & RTS_ON;
switch(lc.bParity) {
case 0x00: strcpy(parity, "NONE"); break;
case 0x01: strcpy(parity, "ODD"); break;
case 0x02: strcpy(parity, "EVEN"); break;
case 0x03: strcpy(parity, "MARK"); break;
case 0x04: strcpy(parity, "SPACE"); break;
default: strcpy(parity, "UNKNOWN"); break;
}
strcat(parity, "\0");
switch(lc.bStopBits) {
case 0x00: stopbits = 1;
case 0x01: stopbits = 1;
case 0x02: stopbits = 2;
default: stopbits = 0;
}
data = (PSZ) retval->strptr;
retval->strlength = sprintf(data,
"BAUD=%d PARITY=%s DATABITS=%d STOPBITS=%d CTS=%s DSR=%s RI=%s CD=%s DTR=%s RTS=%s",
baud, parity, lc.bDataBits, stopbits,
((brc > 0) ? "ON" : "OFF"),
((trc > 0) ? "ON" : "OFF"),
((mirc > 0) ? "ON" : "OFF"),
((morc > 0) ? "ON" : "OFF"),
((inputp > 0) ? "ON" : "OFF"),
((outputp > 0) ? "ON" : "OFF"));
}
else
rc = IOCTL_ERROR;
}
default: break;
}
return(rc);
}
/**************************************************************************/
/* RxCommOpen: execute an open on a COMM port */
/* */
/* return codes: 0 - Ok */
/* -1 - Incorrect number of arguments */
/* -2 - COMM port not found / already open */
/**************************************************************************/
SHORT APIENTRY RxCommOpen(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
SHORT rc;
USHORT handle;
USHORT act;
char *comp;
struct OPEN_PORTS *tmp;
struct OPEN_PORTS *curr;
retval->strlength = 0;
retval->strptr = NULL;
rc = INCORRECT_NUM_PARAMS;
switch (argc) {
case 0: break;
case 1:
rc = UNABLE_TO_FIND_COM;
if (FindCOM(argv[0]) == NULL) {
comp = malloc((USHORT)argv[0].strlength+1);
_fmemset(comp, '\0', (USHORT)argv[0].strlength+1);
_fmemcpy(comp, argv[0].strptr, (USHORT)argv[0].strlength);
rc = DosOpen(comp,
&handle,
&act,
0L,
0,
0x01,
0x0012,
0L);
free(comp);
if (rc == 0) {
tmp = malloc(sizeof(struct OPEN_PORTS));
if (tmp == NULL)
rc = IOCTL_ERROR;
else {
rc = OK;
tmp->Next = NULL;
tmp->Prev = NULL;
tmp->Name = malloc((USHORT)argv[0].strlength);
_fmemcpy(tmp->Name, argv[0].strptr, (USHORT)argv[0].strlength);
tmp->handle = handle;
curr = Top;
if (curr == NULL)
Top = tmp;
else {
while (curr->Next != NULL)
curr = curr->Next;
curr->Next = tmp;
tmp->Prev = curr;
}
}
}
else
rc = IOCTL_ERROR;
}
default: break;
}
return(rc);
}
/**************************************************************************/
/* RxCommClose: execute a close on a COMM port */
/* */
/* Return codes: 0 - Ok */
/* -1 - incorrect # of args */
/* -2 - port not found */
/**************************************************************************/
SHORT APIENTRY RxCommClose(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
SHORT rc;
struct OPEN_PORTS *tmp;
struct OPEN_PORTS *curr;
rc = INCORRECT_NUM_PARAMS;
retval->strlength = 0;
retval->strptr = NULL;
switch(argc) {
case 0: break;
case 1:
rc = UNABLE_TO_FIND_COM;
if (( curr = FindCOM(argv[0])) != NULL) {
DosClose(curr->handle);
if (curr == Top)
Top = curr->Next;
if (curr->Prev != NULL)
curr->Prev->Next = curr->Next;
free(curr->Name);
free(curr);
rc = OK;
}
default: break;
}
return(rc);
}
/*************************************************************************/
/* RxCommCheck: return the number of characters available from COMM port */
/* */
/* Return codes xx - number of characters available */
/* -1 - wrong # of args */
/* -2 - unable to find COM port */
/*************************************************************************/
SHORT APIENTRY RxCommCheck(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
char Param[20];
struct OPEN_PORTS *curr;
RXQUEUE ccount;
SHORT rc;
retval->strlength = 0;
rc = INCORRECT_NUM_PARAMS;
switch(argc) {
case 0: break;
case 1:
rc = UNABLE_TO_FIND_COM;
if (( curr = FindCOM(argv[0])) != NULL) {
rc = DosDevIOCtl(&ccount,
0L,
ASYNC_GETINQUECOUNT,
IOCTL_ASYNC,
curr->handle);
if (rc == 0) {
itoa(ccount.cch, retval->strptr, 10);
retval->strlength = _fstrlen(retval->strptr);
}
else
rc = IOCTL_ERROR;
}
default: break;
}
return(rc);
}
/**************************************************************************/
/* RxCommGet: execute a getc on a COMM port */
/* */
/* Return codes xx - number of characters returned */
/* 0 - no characters available */
/* -1 - wrong # of args */
/* -2 - unable to find COM port */
/* -3 - IOCTL error */
/**************************************************************************/
SHORT APIENTRY RxCommGet(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
USHORT bytes;
USHORT rc;
PSZ ptr1;
char *ptr;
char *buff;
RXQUEUE ccount;
struct OPEN_PORTS *curr;
rc = INCORRECT_NUM_PARAMS;
retval->strlength = 0;
switch(argc) {
case 0: break;
case 1:
rc = UNABLE_TO_FIND_COM;
if (( curr = FindCOM(argv[0])) != NULL) {
rc = IOCTL_ERROR;
bytes = DosDevIOCtl(&ccount,
0L,
ASYNC_GETINQUECOUNT,
IOCTL_ASYNC,
curr->handle);
if ((bytes == 0) && (ccount.cch > 0)) {
rc = OK;
DosRead(curr->handle,
retval->strptr,
ccount.cch,
&bytes);
retval->strlength = bytes;
}
else
rc = OK;
}
break;
default: break;
}
return(rc);
}
/**************************************************************************/
/* RxCommPut: execute a putc on a COMM port */
/* */
/* Return codes 0 - Ok */
/* -1 - wrong # of args */
/* -2 - Unable to find COM port */
/**************************************************************************/
SHORT APIENTRY RxCommPut(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
USHORT bytes;
SHORT rc;
PSZ data;
struct OPEN_PORTS *curr;
rc = INCORRECT_NUM_PARAMS;
retval->strlength = 0;
retval->strptr = NULL;
switch(argc) {
case 0: break;
case 1: break;
case 2:
rc = INCORRECT_NUM_PARAMS;
if (argv[1].strlength > 0) {
rc = UNABLE_TO_FIND_COM;
if (( curr = FindCOM(argv[0])) != NULL) {
data = malloc((USHORT)argv[1].strlength + 1);
if (data != NULL) {
rc = OK;
_fmemset(data, '\0', (USHORT)argv[1].strlength+1);
_fmemcpy(data, argv[1].strptr, (USHORT)argv[1].strlength);
DosWrite(curr->handle,
data,
strlen(data),
&bytes);
free(data);
}
}
}
break;
default: break;
}
return(rc);
}
/**************************************************************************/
/* FindCOM - find the com port in the list */
/* Internal routine */
/**************************************************************************/
static struct OPEN_PORTS *FindCOM(RXSTRING var)
{
struct OPEN_PORTS *curr;
if (var.strlength == 0L)
return(NULL);
curr = Top;
while(curr != NULL) {
if (_fmemcmp(curr->Name, var.strptr, (USHORT)var.strlength) == 0)
return(curr);
curr = curr->Next;
}
return(NULL);
}
/**************************************************************************/
/* RxGetChar: get a character from the keyboard - wait for it */
/* */
/* Return codes 0 - Ok */
/**************************************************************************/
SHORT APIENTRY RxGetChar(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
USHORT bytes;
PSZ data;
INT ch;
ch = getch();
switch(argc) {
case 0: if (ch != 0x00) putchar(ch); break;
default: break;
}
if (ch == 0x00 | ch == 0xE0)
{
ch = getch();
switch(ch)
{
case 0x3b: strcpy(retval->strptr, "F1");
retval->strlength = 2;
break;
case 0x3c: strcpy(retval->strptr, "F2");
retval->strlength = 2;
break;
case 0x3d: strcpy(retval->strptr, "F3");
retval->strlength = 2;
break;
case 0x3e: strcpy(retval->strptr, "F4");
retval->strlength = 2;
break;
case 0x3f: strcpy(retval->strptr, "F5");
retval->strlength = 2;
break;
case 0x40: strcpy(retval->strptr, "F6");
retval->strlength = 2;
break;
case 0x41: strcpy(retval->strptr, "F7");
retval->strlength = 2;
break;
case 0x42: strcpy(retval->strptr, "F8");
retval->strlength = 2;
break;
case 0x43: strcpy(retval->strptr, "F9");
retval->strlength = 2;
break;
case 0x44: strcpy(retval->strptr, "F10");
retval->strlength = 3;
break;
case 0x47: strcpy(retval->strptr, "HOME");
retval->strlength = 4;
break;
case 0x48: strcpy(retval->strptr, "UP");
retval->strlength = 2;
break;
case 0x49: strcpy(retval->strptr, "PGUP");
retval->strlength = 4;
break;
case 0x4b: strcpy(retval->strptr, "LEFT");
retval->strlength = 4;
break;
case 0x4d: strcpy(retval->strptr, "RIGHT");
retval->strlength = 5;
break;
case 0x52: strcpy(retval->strptr, "INSERT");
retval->strlength = 6;
break;
case 0x53: strcpy(retval->strptr, "DEL");
retval->strlength = 3;
break;
default: strcpy(retval->strptr, "UNKNOWN");
retval->strlength = 7;
break;
}
}
else
retval->strlength = sprintf(retval->strptr, "%c", ch);
return(0);
}
/**************************************************************************/
/* RxSay: output a string at the current cursor location w/o cr-lf. */
/* */
/* Return codes 0 - Ok */
/**************************************************************************/
SHORT APIENTRY RxSay(
PSZ szName, /* name function called as */
USHORT argc, /* argument count */
PRXSTRING argv, /* argument list */
PSZ szQueue, /* current active queue */
PRXSTRING retval) /* return value */
{
char *p;
unsigned long count;
if (argc > 0)
{
count = argv[0].strlength;
p = argv[0].strptr;
while (count--)
putchar(*p++);
}
return(0);
}