Move 16-bit COMM stuff to USER, where it belongs
Dmitry Timoshkov
dmitry at baikal.ru
Mon Jun 18 00:04:17 CDT 2001
Hello.
Changelog:
Dmitry Timoshkov <dmitry at codeweavers.com>
Move 16-bit COMM stuff to USER, where it belongs.
diff -u cvs/hq/wine/dlls/kernel/comm.c wine/dlls/kernel/comm.c
--- cvs/hq/wine/dlls/kernel/comm.c Thu Jun 14 13:59:48 2001
+++ wine/dlls/kernel/comm.c Mon Jun 18 12:54:47 2001
@@ -64,7 +64,6 @@
#include "wine/port.h"
#include "server.h"
#include "winerror.h"
-#include "services.h"
#include "callback.h"
#include "file.h"
=20
@@ -113,30 +112,6 @@
=20
static struct DosDeviceStruct COM[MAX_PORTS];
static struct DosDeviceStruct LPT[MAX_PORTS];
-/* pointers to unknown(=3D=3Dundocumented) comm structure */=20
-static LPCVOID *unknown[MAX_PORTS];
-/* save terminal states */
-static struct termios m_stat[MAX_PORTS];
-
-/* update window's semi documented modem status register */
-/* see knowledge base Q101417 */
-static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
-{
- UCHAR tmpmsr=3D0;
-#ifdef TIOCM_CTS
- if(mstat & TIOCM_CTS) tmpmsr |=3D MSR_CTS;
-#endif
-#ifdef TIOCM_DSR
- if(mstat & TIOCM_DSR) tmpmsr |=3D MSR_DSR;
-#endif
-#ifdef TIOCM_RI
- if(mstat & TIOCM_RI) tmpmsr |=3D MSR_RI;
-#endif
-#ifdef TIOCM_CAR
- if(mstat & TIOCM_CAR) tmpmsr |=3D MSR_RLSD;
-#endif
- *pMsr =3D (*pMsr & ~MSR_MASK) | tmpmsr;
-}
=20
void COMM_Init(void)
{
@@ -199,45 +174,11 @@
}
}
=20
-
-static struct DosDeviceStruct *GetDeviceStruct(int fd)
-{
- if ((fd&0x7F)<=3DMAX_PORTS) {
- if (!(fd&FLAG_LPT)) {
- if (COM[fd].fd)
- return &COM[fd];
- } else {
- fd &=3D 0x7f;
- if (LPT[fd].fd)
- return &LPT[fd];
- }
- }
-
- return NULL;
-}
-
-static int GetCommPort_fd(int fd)
-{
- int x;
- =20
- for (x=3D0; x<MAX_PORTS; x++) {
- if (COM[x].fd =3D=3D fd)
- return x;
- }
- =20
- return -1;
-}=20
-
static int ValidCOMPort(int x)
{
return(x < MAX_PORTS ? (int) COM[x].devicename : 0);=20
}
=20
-static int ValidLPTPort(int x)
-{
- return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);=20
-}
-
static int WinError(void)
{
TRACE("errno =3D %d\n", errno);
@@ -247,18 +188,6 @@
}
}
=20
-static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
-{
- return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
- + ptr->ibuf_head - ptr->ibuf_tail;
-}
-
-static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
-{
- return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
- + ptr->obuf_head - ptr->obuf_tail;
-}
-
static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie=
)
{
unsigned int mstat, okay;
@@ -269,1259 +198,6 @@
return ioctl(fd, TIOCMSET, &mstat);
}
=09
-static void CALLBACK comm_notification( ULONG_PTR private )
-{
- struct DosDeviceStruct *ptr =3D (struct DosDeviceStruct *)private;
- int prev, bleft, len;
- WORD mask =3D 0;
- int cid =3D GetCommPort_fd(ptr->fd);
-
- TRACE("async notification\n");
- /* read data from comm port */
- prev =3D comm_inbuf(ptr);
- do {
- bleft =3D ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : =
ptr->ibuf_size)
- - ptr->ibuf_head;
- len =3D read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
- if (len > 0) {
- if (!bleft) {
- ptr->commerror =3D CE_RXOVER;
- } else {
- /* check for events */
- if ((ptr->eventmask & EV_RXFLAG) &&
- memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
- *(WORD*)(unknown[cid]) |=3D EV_RXFLAG;
- mask |=3D CN_EVENT;
- }
- if (ptr->eventmask & EV_RXCHAR) {
- *(WORD*)(unknown[cid]) |=3D EV_RXCHAR;
- mask |=3D CN_EVENT;
- }
- /* advance buffer position */
- ptr->ibuf_head +=3D len;
- if (ptr->ibuf_head >=3D ptr->ibuf_size)
- ptr->ibuf_head =3D 0;
- }
- }
- } while (len > 0);
- /* check for notification */
- if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
- (comm_inbuf(ptr)>=3Dptr->n_read)) {
- /* passed the receive notification threshold */
- mask |=3D CN_RECEIVE;
- }
-
- /* write any TransmitCommChar character */
- if (ptr->xmit>=3D0) {
- len =3D write(ptr->fd, &(ptr->xmit), 1);
- if (len > 0) ptr->xmit =3D -1;
- }
- /* write from output queue */
- prev =3D comm_outbuf(ptr);
- do {
- bleft =3D ((ptr->obuf_tail <=3D ptr->obuf_head) ? ptr->obuf_head : p=
tr->obuf_size)
- - ptr->obuf_tail;
- len =3D bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) =
: 0;
- if (len > 0) {
- ptr->obuf_tail +=3D len;
- if (ptr->obuf_tail >=3D ptr->obuf_size)
- ptr->obuf_tail =3D 0;
- /* flag event */
- if (ptr->obuf_tail =3D=3D ptr->obuf_head) {
- if (ptr->s_write) {
- SERVICE_Delete( ptr->s_write );
- ptr->s_write =3D INVALID_HANDLE_VALUE;
- }
- if (ptr->eventmask & EV_TXEMPTY) {
- *(WORD*)(unknown[cid]) |=3D EV_TXEMPTY;
- mask |=3D CN_EVENT;
- }
- }
- }
- } while (len > 0);
- /* check for notification */
- if (ptr->wnd && (ptr->n_write>0) && (prev>=3Dptr->n_write) &&
- (comm_outbuf(ptr)<ptr->n_write)) {
- /* passed the transmit notification threshold */
- mask |=3D CN_TRANSMIT;
- }
-
- /* send notifications, if any */
- if (ptr->wnd && mask) {
- TRACE("notifying %04x: cid=3D%d, mask=3D%02x\n", ptr->wnd, cid, mask=
);
- if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTI=
FY, cid, mask);
- }
-}
-
-static void comm_waitread(struct DosDeviceStruct *ptr)
-{
- if (ptr->s_read !=3D INVALID_HANDLE_VALUE) return;
- ptr->s_read =3D SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
- GENERIC_READ | SYNCHRONIZE ),
- comm_notification,
- (ULONG_PTR)ptr );
-}
-
-static void comm_waitwrite(struct DosDeviceStruct *ptr)
-{
- if (ptr->s_write !=3D INVALID_HANDLE_VALUE) return;
- ptr->s_write =3D SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
- GENERIC_WRITE | SYNCHRONIZE ),
- comm_notification,
- (ULONG_PTR)ptr );
-}
-
-/***********************************************************************=
***
- * BuildCommDCB16 (USER.213)
- *
- * According to the ECMA-234 (368.3) the function will return FALSE on=20
- * success, otherwise it will return -1.=20
- * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeou=
tsA
- * NEEDS TO BE FIXED
- */
-INT16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
-{
- /* "COM1:96,n,8,1" */
- /* 012345 */
- int port;
- char *ptr, temp[256];
-
- TRACE("(%s), ptr %p\n", device, lpdcb);
-
- if (!strncasecmp(device,"COM",3)) {
- port =3D device[3] - '0';
-=09
-
- if (port-- =3D=3D 0) {
- ERR("BUG ! COM0 can't exist!\n");
- return -1;
- }
-
- if (!ValidCOMPort(port)) {
- FIXME("invalid COM port %d?\n",port);
- return -1;
- }
- =09
- memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
-
- lpdcb->Id =3D port;
- =09
- if (!*(device+4))
- return 0;
-
- if (*(device+4) !=3D ':')
- return -1;
- =09
- strcpy(temp,device+5);
- ptr =3D strtok(temp, ", ");=20
-
- if (COM[port].baudrate > 0)
- lpdcb->BaudRate =3D COM[port].baudrate;
- else
- {
- int rate;
- /* DOS/Windows only compares the first two numbers
- * and assigns an appropriate baud rate.
- * You can supply 961324245, it still returns 9600 ! */
- if (strlen(ptr) < 2)
- {
- WARN("Unknown baudrate string '%s' !\n", ptr);
- return -1; /* error: less than 2 chars */
- }
- ptr[2] =3D '\0';
- rate =3D atoi(ptr);
-
- switch (rate) {
- case 11:
- case 30:
- case 60:
- rate *=3D 10;
- break;
- case 12:
- case 24:
- case 48:
- case 96:
- rate *=3D 100;
- break;
- case 19:
- rate =3D 19200;
- break;
- default:
- WARN("Unknown baudrate indicator %d !\n", rate);
- return -1;
- }
- =09
- lpdcb->BaudRate =3D rate;
- }
- TRACE("baudrate (%d)\n", lpdcb->BaudRate);
-
- ptr =3D strtok(NULL, ", ");
- if (islower(*ptr))
- *ptr =3D toupper(*ptr);
-
- TRACE("parity (%c)\n", *ptr);
- lpdcb->fParity =3D TRUE;
- switch (*ptr) {
- case 'N':
- lpdcb->Parity =3D NOPARITY;
- lpdcb->fParity =3D FALSE;
- break; =09
- case 'E':
- lpdcb->Parity =3D EVENPARITY;
- break; =09
- case 'M':
- lpdcb->Parity =3D MARKPARITY;
- break; =09
- case 'O':
- lpdcb->Parity =3D ODDPARITY;
- break; =09
- default:
- WARN("Unknown parity `%c'!\n", *ptr);
- return -1;
- }
-
- ptr =3D strtok(NULL, ", ");=20
- TRACE("charsize (%c)\n", *ptr);
- lpdcb->ByteSize =3D *ptr - '0';
-
- ptr =3D strtok(NULL, ", ");
- TRACE("stopbits (%c)\n", *ptr);
- switch (*ptr) {
- case '1':
- lpdcb->StopBits =3D ONESTOPBIT;
- break; =09
- case '2':
- lpdcb->StopBits =3D TWOSTOPBITS;
- break; =09
- default:
- WARN("Unknown # of stopbits `%c'!\n", *ptr);
- return -1;
- }
- }=09
-
- return 0;
-}
-
-/***********************************************************************=
******
- * OpenComm16 (USER.200)
- */
-INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue=
)
-{
- int port,fd;
-
- TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
-
- if (strlen(device) < 4)
- return IE_BADID;
-
- port =3D device[3] - '0';
-
- if (port-- =3D=3D 0)
- ERR("BUG ! COM0 or LPT0 don't exist !\n");
-
- if (!strncasecmp(device,"COM",3)) {
- =09
- TRACE("%s =3D %s\n", device, COM[port].devicename);
-
- if (!ValidCOMPort(port))
- return IE_BADID;
-
- if (COM[port].fd)
- return IE_OPEN;
-
- fd =3D open(COM[port].devicename, O_RDWR | O_NONBLOCK);
- if (fd =3D=3D -1) {
- ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno=
));
- return IE_HARDWARE;
- } else {
- unknown[port] =3D SEGPTR_ALLOC(40);
- memset(unknown[port], 0, 40);
- COM[port].fd =3D fd;
- COM[port].commerror =3D 0;
- COM[port].eventmask =3D 0;
- COM[port].evtchar =3D 0; /* FIXME: default? */
- /* save terminal state */
- tcgetattr(fd,&m_stat[port]);
- /* set default parameters */
- if(COM[port].baudrate>-1){
- DCB16 dcb;
- GetCommState16(port, &dcb);
- dcb.BaudRate=3DCOM[port].baudrate;
- /* more defaults:
- * databits, parity, stopbits
- */
- SetCommState16( &dcb);
- }
- /* init priority characters */
- COM[port].unget =3D -1;
- COM[port].xmit =3D -1;
- /* allocate buffers */
- COM[port].ibuf_size =3D cbInQueue;
- COM[port].ibuf_head =3D COM[port].ibuf_tail =3D 0;
- COM[port].obuf_size =3D cbOutQueue;
- COM[port].obuf_head =3D COM[port].obuf_tail =3D 0;
-
- COM[port].inbuf =3D malloc(cbInQueue);
- if (COM[port].inbuf) {
- COM[port].outbuf =3D malloc(cbOutQueue);
- if (!COM[port].outbuf)
- free(COM[port].inbuf);
- } else COM[port].outbuf =3D NULL;
- if (!COM[port].outbuf) {
- /* not enough memory */
- tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
- close(COM[port].fd);
- ERR("out of memory\n");
- return IE_MEMORY;
- }
-
- COM[port].s_read =3D INVALID_HANDLE_VALUE;
- COM[port].s_write =3D INVALID_HANDLE_VALUE;
- comm_waitread( &COM[port] );
- return port;
- }
- }=20
- else=20
- if (!strncasecmp(device,"LPT",3)) {
-=09
- if (!ValidLPTPort(port))
- return IE_BADID;
-
- if (LPT[port].fd)
- return IE_OPEN;
-
- fd =3D open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
- if (fd =3D=3D -1) {
- return IE_HARDWARE;
- } else {
- LPT[port].fd =3D fd;
- LPT[port].commerror =3D 0;
- LPT[port].eventmask =3D 0;
- return port|FLAG_LPT;
- }
- }
- return IE_BADID;
-}
-
-/***********************************************************************=
******
- * CloseComm16 (USER.207)
- */
-INT16 WINAPI CloseComm16(INT16 cid)
-{
- struct DosDeviceStruct *ptr;
- =20
- TRACE("cid=3D%d\n", cid);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no cid=3D%d found!\n", cid);
- return -1;
- }
- if (!(cid&FLAG_LPT)) {
- /* COM port */
- SEGPTR_FREE(unknown[cid]); /* [LW] */
-
- SERVICE_Delete( COM[cid].s_write );
- SERVICE_Delete( COM[cid].s_read );
- /* free buffers */
- free(ptr->outbuf);
- free(ptr->inbuf);
-
- /* reset modem lines */
- tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
- }
-
- if (close(ptr->fd) =3D=3D -1) {
- ptr->commerror =3D WinError();
- /* FIXME: should we clear ptr->fd here? */
- return -1;
- } else {
- ptr->commerror =3D 0;
- ptr->fd =3D 0;
- return 0;
- }
-}
-
-/***********************************************************************=
******
- * SetCommBreak16 (USER.210)
- */
-INT16 WINAPI SetCommBreak16(INT16 cid)
-{
- struct DosDeviceStruct *ptr;
-
- TRACE("cid=3D%d\n", cid);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no cid=3D%d found!\n", cid);
- return -1;
- }
-
- ptr->suspended =3D 1;
- ptr->commerror =3D 0;
- return 0;
-}
-
-/***********************************************************************=
******
- * ClearCommBreak16 (USER.211)
- */
-INT16 WINAPI ClearCommBreak16(INT16 cid)
-{
- struct DosDeviceStruct *ptr;
-
- TRACE("cid=3D%d\n", cid);
- if (!(ptr =3D GetDeviceStruct(cid))) {
- FIXME("no cid=3D%d found!\n", cid);
- return -1;
- }
- ptr->suspended =3D 0;
- ptr->commerror =3D 0;
- return 0;
-}
-
-/***********************************************************************=
******
- * EscapeCommFunction16 (USER.214)
- */
-LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
-{
- int max;
- struct DosDeviceStruct *ptr;
- struct termios port;
-
- TRACE("cid=3D%d, function=3D%d\n", cid, nFunction);
- if ((nFunction !=3D GETMAXCOM) && (nFunction !=3D GETMAXLPT)) {
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no cid=3D%d found!\n", cid);
- return -1;
- }
- if (tcgetattr(ptr->fd,&port) =3D=3D -1) {
- TRACE("tcgetattr failed\n");
- ptr->commerror=3DWinError();=09
- return -1;
- }
- } else ptr =3D NULL;
-
- switch (nFunction) {
- case RESETDEV:
- TRACE("RESETDEV\n");
- break; =09
-
- case GETMAXCOM:
- TRACE("GETMAXCOM\n");=20
- for (max =3D MAX_PORTS;!COM[max].devicename;max--)
- ;
- return max;
- break;
-
- case GETMAXLPT:
- TRACE("GETMAXLPT\n");=20
- for (max =3D MAX_PORTS;!LPT[max].devicename;max--)
- ;
- return FLAG_LPT + max;
- break;
-
- case GETBASEIRQ:
- TRACE("GETBASEIRQ\n");=20
- /* FIXME: use tables */
- /* just fake something for now */
- if (cid & FLAG_LPT) {
- /* LPT1: irq 7, LPT2: irq 5 */
- return (cid & 0x7f) ? 5 : 7;
- } else {
- /* COM1: irq 4, COM2: irq 3,
- COM3: irq 4, COM4: irq 3 */
- return 4 - (cid & 1);
- }
- break;
-
- case CLRDTR:
- TRACE("CLRDTR\n");=20
-#ifdef TIOCM_DTR
- return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
-#endif
- case CLRRTS:
- TRACE("CLRRTS\n");=20
-#ifdef TIOCM_RTS
- return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
-#endif
-=09
- case SETDTR:
- TRACE("SETDTR\n");=20
-#ifdef TIOCM_DTR
- return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
-#endif
-
- case SETRTS:
- TRACE("SETRTS\n");=20
-#ifdef TIOCM_RTS =09
- return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
-#endif
-
- case SETXOFF:
- TRACE("SETXOFF\n");=20
- port.c_iflag |=3D IXOFF;
- break;
-
- case SETXON:
- TRACE("SETXON\n");=20
- port.c_iflag |=3D IXON;
- break;
-
- default:
- WARN("(cid=3D%d,nFunction=3D%d): Unknown function\n",=20
- cid, nFunction);
- break; =09
- }
-=09
- if (tcsetattr(ptr->fd, TCSADRAIN, &port) =3D=3D -1) {
- ptr->commerror =3D WinError();
- return -1;=09
- } else {
- ptr->commerror =3D 0;
- return 0;
- }
-}
-
-/***********************************************************************=
******
- * FlushComm16 (USER.215)
- */
-INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
-{
- int queue;
- struct DosDeviceStruct *ptr;
-
- TRACE("cid=3D%d, queue=3D%d\n", cid, fnQueue);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no cid=3D%d found!\n", cid);
- return -1;
- }
- switch (fnQueue) {
- case 0:
- queue =3D TCOFLUSH;
- ptr->obuf_tail =3D ptr->obuf_head;
- break;
- case 1:
- queue =3D TCIFLUSH;
- ptr->ibuf_head =3D ptr->ibuf_tail;
- break;
- default:
- WARN("(cid=3D%d,fnQueue=3D%d):Unknown queue\n",=20
- cid, fnQueue);
- return -1;
- }
- if (tcflush(ptr->fd, queue)) {
- ptr->commerror =3D WinError();
- return -1;=09
- } else {
- ptr->commerror =3D 0;
- return 0;
- }
-} =20
-
-/********************************************************************
- * GetCommError16 (USER.203)
- */
-INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
-{
- int temperror;
- struct DosDeviceStruct *ptr;
- unsigned char *stol;
- unsigned int mstat;
-
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
- if (cid&FLAG_LPT) {
- WARN(" cid %d not comm port\n",cid);
- return CE_MODE;
- }
- stol =3D (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
- ioctl(ptr->fd,TIOCMGET,&mstat);
- COMM_MSRUpdate( stol, mstat);
-
- if (lpStat) {
- lpStat->status =3D 0;
-
- lpStat->cbOutQue =3D comm_outbuf(ptr);
- lpStat->cbInQue =3D comm_inbuf(ptr);
-
- TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
- cid, ptr->commerror, lpStat->status, lpStat->cbInQue,=20
- lpStat->cbOutQue, *stol);
- }
- else
- TRACE("cid %d, error %d, lpStat NULL stol %x\n",
- cid, ptr->commerror, *stol);
-
- /* Return any errors and clear it */
- temperror =3D ptr->commerror;
- ptr->commerror =3D 0;
- return(temperror);
-}
-
-/***********************************************************************=
******
- * SetCommEventMask16 (USER.208)
- */
-SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
-{
- struct DosDeviceStruct *ptr;
- unsigned char *stol;
- int repid;
- unsigned int mstat;
-
- TRACE("cid %d,mask %d\n",cid,fuEvtMask);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return (SEGPTR)NULL;
- }
-
- ptr->eventmask =3D fuEvtMask;
-
- if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
- WARN(" cid %d not comm port\n",cid);
- return (SEGPTR)NULL;
- }
- /* it's a COM port ? -> modify flags */
- stol =3D (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
- repid =3D ioctl(ptr->fd,TIOCMGET,&mstat);
- TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
- COMM_MSRUpdate( stol, mstat);
-
- TRACE(" modem dcd construct %x\n",*stol);
- return SEGPTR_GET(unknown[cid]);
-}
-
-/***********************************************************************=
******
- * GetCommEventMask16 (USER.209)
- */
-UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
-{
- struct DosDeviceStruct *ptr;
- WORD events;
-
- TRACE("cid %d, mask %d\n", cid, fnEvtClear);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return 0;
- }
-
- if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
- WARN(" cid %d not comm port\n",cid);
- return 0;
- }
-
- events =3D *(WORD*)(unknown[cid]) & fnEvtClear;
- *(WORD*)(unknown[cid]) &=3D ~fnEvtClear;
- return events;
-}
-
-/***********************************************************************=
******
- * SetCommState16 (USER.201)
- */
-INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
-{
- struct termios port;
- struct DosDeviceStruct *ptr;
- int bytesize, stopbits;
- int fail=3D0;
-
- TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
- if ((ptr =3D GetDeviceStruct(lpdcb->Id)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",lpdcb->Id);
- return -1;
- }
- if (tcgetattr(ptr->fd, &port) =3D=3D -1) {
- ptr->commerror =3D WinError();=09
- return -1;
- }
-
- port.c_cc[VMIN] =3D 0;
- port.c_cc[VTIME] =3D 1;
-
-#ifdef IMAXBEL
- port.c_iflag &=3D ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
-#else
- port.c_iflag &=3D ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
-#endif
- port.c_iflag |=3D (IGNBRK);
-
- port.c_oflag &=3D ~(OPOST);
-
- port.c_cflag &=3D ~(HUPCL);
- port.c_cflag |=3D CLOCAL | CREAD;
-
- port.c_lflag &=3D ~(ICANON|ECHO|ISIG);
- port.c_lflag |=3D NOFLSH;
-
- TRACE("baudrate %d\n",lpdcb->BaudRate);
-#ifdef CBAUD
- port.c_cflag &=3D ~CBAUD;
- switch (lpdcb->BaudRate) {
- case 110:
- case CBR_110:
- port.c_cflag |=3D B110;
- break; =09
- case 300:
- case CBR_300:
- port.c_cflag |=3D B300;
- break; =09
- case 600:
- case CBR_600:
- port.c_cflag |=3D B600;
- break; =09
- case 1200:
- case CBR_1200:
- port.c_cflag |=3D B1200;
- break; =09
- case 2400:
- case CBR_2400:
- port.c_cflag |=3D B2400;
- break; =09
- case 4800:
- case CBR_4800:
- port.c_cflag |=3D B4800;
- break; =09
- case 9600:
- case CBR_9600:
- port.c_cflag |=3D B9600;
- break; =09
- case 19200:
- case CBR_19200:
- port.c_cflag |=3D B19200;
- break; =09
- case 38400:
- case CBR_38400:
- port.c_cflag |=3D B38400;
- break; =09
-#ifdef B57600
- case 57600:
- port.c_cflag |=3D B57600;
- break; =09
-#endif
-#ifdef B115200
- case 57601:
- port.c_cflag |=3D B115200;
- break; =09
-#endif
- default:
- ptr->commerror =3D IE_BAUDRATE;
- fail=3D1;
- }
-#elif !defined(__EMX__)
- switch (lpdcb->BaudRate) {
- case 110:
- case CBR_110:
- port.c_ospeed =3D B110;
- break;
- case 300:
- case CBR_300:
- port.c_ospeed =3D B300;
- break;
- case 600:
- case CBR_600:
- port.c_ospeed =3D B600;
- break;
- case 1200:
- case CBR_1200:
- port.c_ospeed =3D B1200;
- break;
- case 2400:
- case CBR_2400:
- port.c_ospeed =3D B2400;
- break;
- case 4800:
- case CBR_4800:
- port.c_ospeed =3D B4800;
- break;
- case 9600:
- case CBR_9600:
- port.c_ospeed =3D B9600;
- break;
- case 19200:
- case CBR_19200:
- port.c_ospeed =3D B19200;
- break;
- case 38400:
- case CBR_38400:
- port.c_ospeed =3D B38400;
- break;
- default:
- ptr->commerror =3D IE_BAUDRATE;
- fail=3D1;
- }
- port.c_ispeed =3D port.c_ospeed;
-#endif
- bytesize=3Dlpdcb->ByteSize;
- stopbits=3Dlpdcb->StopBits;
-
- TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
-#ifdef CMSPAR
- port.c_cflag &=3D ~(PARENB | PARODD | CMSPAR);
-#else
- port.c_cflag &=3D ~(PARENB | PARODD);
-#endif
- if (lpdcb->fParity)
- port.c_iflag |=3D INPCK;
- else
- port.c_iflag &=3D ~INPCK;
- switch (lpdcb->Parity) {
- case NOPARITY:
- break;
- case ODDPARITY:
- port.c_cflag |=3D (PARENB | PARODD);
- break;
- case EVENPARITY:
- port.c_cflag |=3D PARENB;
- break;
-#ifdef CMSPAR
- /* Linux defines mark/space (stick) parity */
- case MARKPARITY:
- port.c_cflag |=3D (PARENB | CMSPAR);
- break;
- case SPACEPARITY:
- port.c_cflag |=3D (PARENB | PARODD | CMSPAR);
- break;
-#else
- /* try the POSIX way */
- case MARKPARITY:
- if( stopbits =3D=3D ONESTOPBIT) {
- stopbits =3D TWOSTOPBITS;
- port.c_iflag &=3D ~INPCK;
- } else {
- ptr->commerror =3D IE_BYTESIZE;
- fail=3D1;
- }
- break;
- case SPACEPARITY:
- if( bytesize < 8) {
- bytesize +=3D1;
- port.c_iflag &=3D ~INPCK;
- } else {
- ptr->commerror =3D IE_BYTESIZE;
- fail=3D1;
- }
- break;
-#endif
- default:
- ptr->commerror =3D IE_BYTESIZE;
- fail=3D1;
- }
-=09
- TRACE("bytesize %d\n",bytesize);
- port.c_cflag &=3D ~CSIZE;
- switch (bytesize) {
- case 5:
- port.c_cflag |=3D CS5;
- break;
- case 6:
- port.c_cflag |=3D CS6;
- break;
- case 7:
- port.c_cflag |=3D CS7;
- break;
- case 8:
- port.c_cflag |=3D CS8;
- break;
- default:
- ptr->commerror =3D IE_BYTESIZE;
- fail=3D1;
- }
-
- TRACE("stopbits %d\n",stopbits);
-
- switch (stopbits) {
- case ONESTOPBIT:
- port.c_cflag &=3D ~CSTOPB;
- break;
- case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
- case TWOSTOPBITS:
- port.c_cflag |=3D CSTOPB;
- break;
- default:
- ptr->commerror =3D IE_BYTESIZE;
- fail=3D1;
- }
-#ifdef CRTSCTS
-
- if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
- port.c_cflag |=3D CRTSCTS;
-
- if (lpdcb->fDtrDisable)=20
- port.c_cflag &=3D ~CRTSCTS;
-#endif=09
- if (lpdcb->fInX)
- port.c_iflag |=3D IXON;
- else
- port.c_iflag &=3D ~IXON;
- if (lpdcb->fOutX)
- port.c_iflag |=3D IXOFF;
- else
- port.c_iflag &=3D ~IXOFF;
-
- ptr->evtchar =3D lpdcb->EvtChar;
-
- if(fail)
- return -1;
- =20
- if (tcsetattr(ptr->fd, TCSADRAIN, &port) =3D=3D -1) {
- ptr->commerror =3D WinError();=09
- return -1;
- } else {
- ptr->commerror =3D 0;
- return 0;
- }
-}
-
-/***********************************************************************=
******
- * GetCommState16 (USER.202)
- */
-INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
-{
- int speed;
- struct DosDeviceStruct *ptr;
- struct termios port;
-
- TRACE("cid %d, ptr %p\n", cid, lpdcb);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
- if (tcgetattr(ptr->fd, &port) =3D=3D -1) {
- ptr->commerror =3D WinError();=09
- return -1;
- }
- lpdcb->Id =3D cid;
-#ifndef __EMX__
-#ifdef CBAUD
- speed =3D port.c_cflag & CBAUD;
-#else
- speed =3D port.c_ospeed;
-#endif
- switch(speed) {
- case B110:
- lpdcb->BaudRate =3D 110;
- break;
- case B300:
- lpdcb->BaudRate =3D 300;
- break;
- case B600:
- lpdcb->BaudRate =3D 600;
- break;
- case B1200:
- lpdcb->BaudRate =3D 1200;
- break;
- case B2400:
- lpdcb->BaudRate =3D 2400;
- break;
- case B4800:
- lpdcb->BaudRate =3D 4800;
- break;
- case B9600:
- lpdcb->BaudRate =3D 9600;
- break;
- case B19200:
- lpdcb->BaudRate =3D 19200;
- break;
- case B38400:
- lpdcb->BaudRate =3D 38400;
- break;
-#ifdef B57600
- case B57600:
- lpdcb->BaudRate =3D 57600;
- break;
-#endif
-#ifdef B115200
- case B115200:
- lpdcb->BaudRate =3D 57601;
- break;
-#endif
- }
-#endif
- switch (port.c_cflag & CSIZE) {
- case CS5:
- lpdcb->ByteSize =3D 5;
- break;
- case CS6:
- lpdcb->ByteSize =3D 6;
- break;
- case CS7:
- lpdcb->ByteSize =3D 7;
- break;
- case CS8:
- lpdcb->ByteSize =3D 8;
- break;
- }=09
-=09
- if(port.c_iflag & INPCK)
- lpdcb->fParity =3D TRUE;
- else
- lpdcb->fParity =3D FALSE;
-#ifdef CMSPAR
- switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
-#else
- switch (port.c_cflag & (PARENB | PARODD))
-#endif
- {
- case 0:
- lpdcb->Parity =3D NOPARITY;
- break;
- case PARENB:
- lpdcb->Parity =3D EVENPARITY;
- break;
- case (PARENB | PARODD):
- lpdcb->Parity =3D ODDPARITY; =09
- break;
-#ifdef CMSPAR
- case (PARENB | CMSPAR):
- lpdcb->Parity =3D MARKPARITY; =09
- break;
- case (PARENB | PARODD | CMSPAR):
- lpdcb->Parity =3D SPACEPARITY; =09
- break;
-#endif
- }
-
- if (port.c_cflag & CSTOPB)
- if(lpdcb->ByteSize =3D=3D 5)
- lpdcb->StopBits =3D ONE5STOPBITS;
- else
- lpdcb->StopBits =3D TWOSTOPBITS;
- else
- lpdcb->StopBits =3D ONESTOPBIT;
-
- lpdcb->RlsTimeout =3D 50;
- lpdcb->CtsTimeout =3D 50;=20
- lpdcb->DsrTimeout =3D 50;
- lpdcb->fNull =3D 0;
- lpdcb->fChEvt =3D 0;
- lpdcb->fBinary =3D 1;
- lpdcb->fDtrDisable =3D 0;
-
-#ifdef CRTSCTS
-
- if (port.c_cflag & CRTSCTS) {
- lpdcb->fDtrflow =3D 1;
- lpdcb->fRtsflow =3D 1;
- lpdcb->fOutxCtsFlow =3D 1;
- lpdcb->fOutxDsrFlow =3D 1;
- } else=20
-#endif
- lpdcb->fDtrDisable =3D 1;
-
- if (port.c_iflag & IXON)
- lpdcb->fInX =3D 1;
- else
- lpdcb->fInX =3D 0;
-
- if (port.c_iflag & IXOFF)
- lpdcb->fOutX =3D 1;
- else
- lpdcb->fOutX =3D 0;
-/*
- lpdcb->XonChar =3D=20
- lpdcb->XoffChar =3D=20
- */
- lpdcb->XonLim =3D 10;
- lpdcb->XoffLim =3D 10;
-
- lpdcb->EvtChar =3D ptr->evtchar;
-
- ptr->commerror =3D 0;
- return 0;
-}
-
-/***********************************************************************=
******
- * TransmitCommChar16 (USER.206)
- */
-INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
-{
- struct DosDeviceStruct *ptr;
-
- TRACE("cid %d, data %d \n", cid, chTransmit);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
-
- if (ptr->suspended) {
- ptr->commerror =3D IE_HARDWARE;
- return -1;
- }=09
-
- if (ptr->xmit >=3D 0) {
- /* character already queued */
- /* FIXME: which error would Windows return? */
- ptr->commerror =3D CE_TXFULL;
- return -1;
- }
-
- if (ptr->obuf_head =3D=3D ptr->obuf_tail) {
- /* transmit queue empty, try to transmit directly */
- if (write(ptr->fd, &chTransmit, 1) =3D=3D -1) {
- /* didn't work, queue it */
- ptr->xmit =3D chTransmit;
- comm_waitwrite(ptr);
- }
- } else {
- /* data in queue, let this char be transmitted next */
- ptr->xmit =3D chTransmit;
- comm_waitwrite(ptr);
- }
-
- ptr->commerror =3D 0;
- return 0;
-}
-
-/***********************************************************************=
******
- * UngetCommChar16 (USER.212)
- */
-INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
-{
- struct DosDeviceStruct *ptr;
-
- TRACE("cid %d (char %d)\n", cid, chUnget);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
-
- if (ptr->suspended) {
- ptr->commerror =3D IE_HARDWARE;
- return -1;
- }=09
-
- if (ptr->unget>=3D0) {
- /* character already queued */
- /* FIXME: which error would Windows return? */
- ptr->commerror =3D CE_RXOVER;
- return -1;
- }
-
- ptr->unget =3D chUnget;
-
- ptr->commerror =3D 0;
- return 0;
-}
-
-/***********************************************************************=
******
- * ReadComm16 (USER.204)
- */
-INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
-{
- int status, length;
- struct DosDeviceStruct *ptr;
- LPSTR orgBuf =3D lpvBuf;
-
- TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
-
- if (ptr->suspended) {
- ptr->commerror =3D IE_HARDWARE;
- return -1;
- }=09
-
- /* read unget character */
- if (ptr->unget>=3D0) {
- *lpvBuf++ =3D ptr->unget;
- ptr->unget =3D -1;
-
- length =3D 1;
- } else
- length =3D 0;
-
- /* read from receive buffer */
- while (length < cbRead) {
- status =3D ((ptr->ibuf_head < ptr->ibuf_tail) ?
- ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
- if (!status) break;
- if ((cbRead - length) < status)
- status =3D cbRead - length;
-
- memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
- ptr->ibuf_tail +=3D status;
- if (ptr->ibuf_tail >=3D ptr->ibuf_size)
- ptr->ibuf_tail =3D 0;
- lpvBuf +=3D status;
- length +=3D status;
- }
-
- TRACE("%.*s\n", length, orgBuf);
- ptr->commerror =3D 0;
- return length;
-}
-
-/***********************************************************************=
******
- * WriteComm16 (USER.205)
- */
-INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
-{
- int status, length;
- struct DosDeviceStruct *ptr;
-
- TRACE("cid %d, ptr %p, length %d\n",=20
- cid, lpvBuf, cbWrite);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
-
- if (ptr->suspended) {
- ptr->commerror =3D IE_HARDWARE;
- return -1;
- }=09
-=09
- TRACE("%.*s\n", cbWrite, lpvBuf );
-
- length =3D 0;
- while (length < cbWrite) {
- if ((ptr->obuf_head =3D=3D ptr->obuf_tail) && (ptr->xmit < 0)) {
- /* no data queued, try to write directly */
- status =3D write(ptr->fd, lpvBuf, cbWrite - length);
- if (status > 0) {
- lpvBuf +=3D status;
- length +=3D status;
- continue;
- }
- }
- /* can't write directly, put into transmit buffer */
- status =3D ((ptr->obuf_tail > ptr->obuf_head) ?
- (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
- if (!status) break;
- if ((cbWrite - length) < status)
- status =3D cbWrite - length;
- memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
- ptr->obuf_head +=3D status;
- if (ptr->obuf_head >=3D ptr->obuf_size)
- ptr->obuf_head =3D 0;
- lpvBuf +=3D status;
- length +=3D status;
- comm_waitwrite(ptr);
- }
-
- ptr->commerror =3D 0;=09
- return length;
-}
-
-/***********************************************************************
- * EnableCommNotification (USER.245)
- */
-BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
- INT16 cbWriteNotify, INT16 cbOutQu=
eue )
-{
- struct DosDeviceStruct *ptr;
-
- TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
- if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
- FIXME("no handle for cid =3D %0x!\n",cid);
- return -1;
- }
- ptr->wnd =3D hwnd;
- ptr->n_read =3D cbWriteNotify;
- ptr->n_write =3D cbOutQueue;
- return TRUE;
-}
-
-
/***********************************************************************=
***
* BuildCommDCBA (KERNEL32.@)
*
diff -u cvs/hq/wine/dlls/user/Makefile.in wine/dlls/user/Makefile.in
--- cvs/hq/wine/dlls/user/Makefile.in Sat Jun 2 17:22:50 2001
+++ wine/dlls/user/Makefile.in Mon Jun 18 12:24:07 2001
@@ -10,6 +10,7 @@
C_SRCS =3D \
bidi16.c \
cache.c \
+ comm.c \
ddeml.c \
display.c \
exticon.c \
diff -u cvs/hq/wine/dlls/user/comm.c wine/dlls/user/comm.c
--- /dev/null Wed May 6 05:32:27 1998
+++ wine/dlls/user/comm.c Mon Jun 18 12:54:03 2001
@@ -0,0 +1,1457 @@
+/*
+ * DEC 93 Erik Bos <erik at xs4all.nl>
+ *
+ * Copyright 1996 Marcus Meissner
+ *
+ * Mar 31, 1999. Ove K=E5ven <ovek at arcticnet.no>
+ * - Implemented buffers and EnableCommNotification.
+ *
+ * Apr 3, 1999. Lawson Whitney <lawson_whitney at juno.com>
+ * - Fixed the modem control part of EscapeCommFunction16.
+ *
+ * Mar 3, 1999. Ove K=E5ven <ovek at arcticnet.no>
+ * - Use port indices instead of unixfds for win16
+ * - Moved things around (separated win16 and win32 routines)
+ * - Added some hints on how to implement buffers and EnableCommNotifica=
tion.
+ *
+ * May 26, 1997. Fixes and comments by Rick Richardson <rick at dgii.com> =
[RER]
+ * - ptr->fd wasn't getting cleared on close.
+ * - GetCommEventMask() and GetCommError() didn't do much of anything.
+ * IMHO, they are still wrong, but they at least implement the RXCHAR
+ * event and return I/O queue sizes, which makes the app I'm intereste=
d
+ * in (analog devices EZKIT DSP development system) work.
+ *
+ * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
+ * <lawson_whitney at juno.com>
+ * July 6, 1998. Fixes and comments by Valentijn Sessink
+ * <vsessink at ic.uva.nl> [V]
+ * Oktober 98, Rein Klazes [RHK]
+ * A program that wants to monitor the modem status line (RLSD/DCD) may
+ * poll the modem status register in the commMask structure. I update th=
e bit
+ * in GetCommError, waiting for an implementation of communication event=
s.
+ *=20
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#include <errno.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/poll.h>
+
+#include "windef.h"
+#ifdef HAVE_SYS_MODEM_H
+# include <sys/modem.h>
+#endif
+#ifdef HAVE_SYS_STRTIO_H
+# include <sys/strtio.h>
+#endif
+#include "heap.h"
+#include "winerror.h"
+#include "services.h"
+#include "callback.h"
+#include "file.h"
+
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(comm);
+
+#if !defined(TIOCINQ) && defined(FIONREAD)
+#define TIOCINQ FIONREAD
+#endif
+
+/* window's semi documented modem status register */
+#define COMM_MSR_OFFSET 35
+#define MSR_CTS 0x10
+#define MSR_DSR 0x20
+#define MSR_RI 0x40
+#define MSR_RLSD 0x80
+#define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
+
+#define FLAG_LPT 0x80
+
+#ifdef linux
+#define CMSPAR 0x40000000 /* stick parity */
+#endif
+
+#define MAX_PORTS 9
+
+struct DosDeviceStruct {
+ char *devicename; /* /dev/ttyS0 */
+ int fd;
+ int suspended;
+ int unget,xmit;
+ int baudrate;
+ int evtchar;
+ /* events */
+ int commerror, eventmask;
+ /* buffers */
+ char *inbuf,*outbuf;
+ unsigned ibuf_size,ibuf_head,ibuf_tail;
+ unsigned obuf_size,obuf_head,obuf_tail;
+ /* notifications */
+ int wnd, n_read, n_write;
+ HANDLE s_read, s_write;
+};
+
+
+static struct DosDeviceStruct COM[MAX_PORTS];
+static struct DosDeviceStruct LPT[MAX_PORTS];
+/* pointers to unknown(=3D=3Dundocumented) comm structure */=20
+static LPCVOID *unknown[MAX_PORTS];
+/* save terminal states */
+static struct termios m_stat[MAX_PORTS];
+
+/* update window's semi documented modem status register */
+/* see knowledge base Q101417 */
+static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
+{
+ UCHAR tmpmsr=3D0;
+#ifdef TIOCM_CTS
+ if(mstat & TIOCM_CTS) tmpmsr |=3D MSR_CTS;
+#endif
+#ifdef TIOCM_DSR
+ if(mstat & TIOCM_DSR) tmpmsr |=3D MSR_DSR;
+#endif
+#ifdef TIOCM_RI
+ if(mstat & TIOCM_RI) tmpmsr |=3D MSR_RI;
+#endif
+#ifdef TIOCM_CAR
+ if(mstat & TIOCM_CAR) tmpmsr |=3D MSR_RLSD;
+#endif
+ *pMsr =3D (*pMsr & ~MSR_MASK) | tmpmsr;
+}
+
+static struct DosDeviceStruct *GetDeviceStruct(int fd)
+{
+ if ((fd&0x7F)<=3DMAX_PORTS) {
+ if (!(fd&FLAG_LPT)) {
+ if (COM[fd].fd)
+ return &COM[fd];
+ } else {
+ fd &=3D 0x7f;
+ if (LPT[fd].fd)
+ return &LPT[fd];
+ }
+ }
+
+ return NULL;
+}
+
+static int GetCommPort_fd(int fd)
+{
+ int x;
+ =20
+ for (x=3D0; x<MAX_PORTS; x++) {
+ if (COM[x].fd =3D=3D fd)
+ return x;
+ }
+ =20
+ return -1;
+}=20
+
+static int ValidCOMPort(int x)
+{
+ return(x < MAX_PORTS ? (int) COM[x].devicename : 0);=20
+}
+
+static int ValidLPTPort(int x)
+{
+ return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);=20
+}
+
+static int WinError(void)
+{
+ TRACE("errno =3D %d\n", errno);
+ switch (errno) {
+ default:
+ return CE_IOE;
+ }
+}
+
+static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
+{
+ return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
+ + ptr->ibuf_head - ptr->ibuf_tail;
+}
+
+static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
+{
+ return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
+ + ptr->obuf_head - ptr->obuf_tail;
+}
+
+static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie=
)
+{
+ unsigned int mstat, okay;
+ okay =3D ioctl(fd, TIOCMGET, &mstat);
+ if (okay) return okay;
+ if (andy) mstat &=3D andy;
+ mstat |=3D orrie;
+ return ioctl(fd, TIOCMSET, &mstat);
+}
+=09
+static void CALLBACK comm_notification( ULONG_PTR private )
+{
+ struct DosDeviceStruct *ptr =3D (struct DosDeviceStruct *)private;
+ int prev, bleft, len;
+ WORD mask =3D 0;
+ int cid =3D GetCommPort_fd(ptr->fd);
+
+ TRACE("async notification\n");
+ /* read data from comm port */
+ prev =3D comm_inbuf(ptr);
+ do {
+ bleft =3D ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : =
ptr->ibuf_size)
+ - ptr->ibuf_head;
+ len =3D read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
+ if (len > 0) {
+ if (!bleft) {
+ ptr->commerror =3D CE_RXOVER;
+ } else {
+ /* check for events */
+ if ((ptr->eventmask & EV_RXFLAG) &&
+ memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
+ *(WORD*)(unknown[cid]) |=3D EV_RXFLAG;
+ mask |=3D CN_EVENT;
+ }
+ if (ptr->eventmask & EV_RXCHAR) {
+ *(WORD*)(unknown[cid]) |=3D EV_RXCHAR;
+ mask |=3D CN_EVENT;
+ }
+ /* advance buffer position */
+ ptr->ibuf_head +=3D len;
+ if (ptr->ibuf_head >=3D ptr->ibuf_size)
+ ptr->ibuf_head =3D 0;
+ }
+ }
+ } while (len > 0);
+ /* check for notification */
+ if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
+ (comm_inbuf(ptr)>=3Dptr->n_read)) {
+ /* passed the receive notification threshold */
+ mask |=3D CN_RECEIVE;
+ }
+
+ /* write any TransmitCommChar character */
+ if (ptr->xmit>=3D0) {
+ len =3D write(ptr->fd, &(ptr->xmit), 1);
+ if (len > 0) ptr->xmit =3D -1;
+ }
+ /* write from output queue */
+ prev =3D comm_outbuf(ptr);
+ do {
+ bleft =3D ((ptr->obuf_tail <=3D ptr->obuf_head) ? ptr->obuf_head : p=
tr->obuf_size)
+ - ptr->obuf_tail;
+ len =3D bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) =
: 0;
+ if (len > 0) {
+ ptr->obuf_tail +=3D len;
+ if (ptr->obuf_tail >=3D ptr->obuf_size)
+ ptr->obuf_tail =3D 0;
+ /* flag event */
+ if (ptr->obuf_tail =3D=3D ptr->obuf_head) {
+ if (ptr->s_write) {
+ SERVICE_Delete( ptr->s_write );
+ ptr->s_write =3D INVALID_HANDLE_VALUE;
+ }
+ if (ptr->eventmask & EV_TXEMPTY) {
+ *(WORD*)(unknown[cid]) |=3D EV_TXEMPTY;
+ mask |=3D CN_EVENT;
+ }
+ }
+ }
+ } while (len > 0);
+ /* check for notification */
+ if (ptr->wnd && (ptr->n_write>0) && (prev>=3Dptr->n_write) &&
+ (comm_outbuf(ptr)<ptr->n_write)) {
+ /* passed the transmit notification threshold */
+ mask |=3D CN_TRANSMIT;
+ }
+
+ /* send notifications, if any */
+ if (ptr->wnd && mask) {
+ TRACE("notifying %04x: cid=3D%d, mask=3D%02x\n", ptr->wnd, cid, mask=
);
+ if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTI=
FY, cid, mask);
+ }
+}
+
+static void comm_waitread(struct DosDeviceStruct *ptr)
+{
+ if (ptr->s_read !=3D INVALID_HANDLE_VALUE) return;
+ ptr->s_read =3D SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
+ GENERIC_READ | SYNCHRONIZE ),
+ comm_notification,
+ (ULONG_PTR)ptr );
+}
+
+static void comm_waitwrite(struct DosDeviceStruct *ptr)
+{
+ if (ptr->s_write !=3D INVALID_HANDLE_VALUE) return;
+ ptr->s_write =3D SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
+ GENERIC_WRITE | SYNCHRONIZE ),
+ comm_notification,
+ (ULONG_PTR)ptr );
+}
+
+/***********************************************************************=
***
+ * BuildCommDCB16 (USER.213)
+ *
+ * According to the ECMA-234 (368.3) the function will return FALSE on=20
+ * success, otherwise it will return -1.=20
+ * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeou=
tsA
+ * NEEDS TO BE FIXED
+ */
+INT16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
+{
+ /* "COM1:96,n,8,1" */
+ /* 012345 */
+ int port;
+ char *ptr, temp[256];
+
+ TRACE("(%s), ptr %p\n", device, lpdcb);
+
+ if (!strncasecmp(device,"COM",3)) {
+ port =3D device[3] - '0';
+=09
+
+ if (port-- =3D=3D 0) {
+ ERR("BUG ! COM0 can't exist!\n");
+ return -1;
+ }
+
+ if (!ValidCOMPort(port)) {
+ FIXME("invalid COM port %d?\n",port);
+ return -1;
+ }
+ =09
+ memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
+
+ lpdcb->Id =3D port;
+ =09
+ if (!*(device+4))
+ return 0;
+
+ if (*(device+4) !=3D ':')
+ return -1;
+ =09
+ strcpy(temp,device+5);
+ ptr =3D strtok(temp, ", ");=20
+
+ if (COM[port].baudrate > 0)
+ lpdcb->BaudRate =3D COM[port].baudrate;
+ else
+ {
+ int rate;
+ /* DOS/Windows only compares the first two numbers
+ * and assigns an appropriate baud rate.
+ * You can supply 961324245, it still returns 9600 ! */
+ if (strlen(ptr) < 2)
+ {
+ WARN("Unknown baudrate string '%s' !\n", ptr);
+ return -1; /* error: less than 2 chars */
+ }
+ ptr[2] =3D '\0';
+ rate =3D atoi(ptr);
+
+ switch (rate) {
+ case 11:
+ case 30:
+ case 60:
+ rate *=3D 10;
+ break;
+ case 12:
+ case 24:
+ case 48:
+ case 96:
+ rate *=3D 100;
+ break;
+ case 19:
+ rate =3D 19200;
+ break;
+ default:
+ WARN("Unknown baudrate indicator %d !\n", rate);
+ return -1;
+ }
+ =09
+ lpdcb->BaudRate =3D rate;
+ }
+ TRACE("baudrate (%d)\n", lpdcb->BaudRate);
+
+ ptr =3D strtok(NULL, ", ");
+ if (islower(*ptr))
+ *ptr =3D toupper(*ptr);
+
+ TRACE("parity (%c)\n", *ptr);
+ lpdcb->fParity =3D TRUE;
+ switch (*ptr) {
+ case 'N':
+ lpdcb->Parity =3D NOPARITY;
+ lpdcb->fParity =3D FALSE;
+ break; =09
+ case 'E':
+ lpdcb->Parity =3D EVENPARITY;
+ break; =09
+ case 'M':
+ lpdcb->Parity =3D MARKPARITY;
+ break; =09
+ case 'O':
+ lpdcb->Parity =3D ODDPARITY;
+ break; =09
+ default:
+ WARN("Unknown parity `%c'!\n", *ptr);
+ return -1;
+ }
+
+ ptr =3D strtok(NULL, ", ");=20
+ TRACE("charsize (%c)\n", *ptr);
+ lpdcb->ByteSize =3D *ptr - '0';
+
+ ptr =3D strtok(NULL, ", ");
+ TRACE("stopbits (%c)\n", *ptr);
+ switch (*ptr) {
+ case '1':
+ lpdcb->StopBits =3D ONESTOPBIT;
+ break; =09
+ case '2':
+ lpdcb->StopBits =3D TWOSTOPBITS;
+ break; =09
+ default:
+ WARN("Unknown # of stopbits `%c'!\n", *ptr);
+ return -1;
+ }
+ }=09
+
+ return 0;
+}
+
+/***********************************************************************=
******
+ * OpenComm16 (USER.200)
+ */
+INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue=
)
+{
+ int port,fd;
+
+ TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
+
+ if (strlen(device) < 4)
+ return IE_BADID;
+
+ port =3D device[3] - '0';
+
+ if (port-- =3D=3D 0)
+ ERR("BUG ! COM0 or LPT0 don't exist !\n");
+
+ if (!strncasecmp(device,"COM",3)) {
+ =09
+ TRACE("%s =3D %s\n", device, COM[port].devicename);
+
+ if (!ValidCOMPort(port))
+ return IE_BADID;
+
+ if (COM[port].fd)
+ return IE_OPEN;
+
+ fd =3D open(COM[port].devicename, O_RDWR | O_NONBLOCK);
+ if (fd =3D=3D -1) {
+ ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno=
));
+ return IE_HARDWARE;
+ } else {
+ unknown[port] =3D SEGPTR_ALLOC(40);
+ memset(unknown[port], 0, 40);
+ COM[port].fd =3D fd;
+ COM[port].commerror =3D 0;
+ COM[port].eventmask =3D 0;
+ COM[port].evtchar =3D 0; /* FIXME: default? */
+ /* save terminal state */
+ tcgetattr(fd,&m_stat[port]);
+ /* set default parameters */
+ if(COM[port].baudrate>-1){
+ DCB16 dcb;
+ GetCommState16(port, &dcb);
+ dcb.BaudRate=3DCOM[port].baudrate;
+ /* more defaults:
+ * databits, parity, stopbits
+ */
+ SetCommState16( &dcb);
+ }
+ /* init priority characters */
+ COM[port].unget =3D -1;
+ COM[port].xmit =3D -1;
+ /* allocate buffers */
+ COM[port].ibuf_size =3D cbInQueue;
+ COM[port].ibuf_head =3D COM[port].ibuf_tail =3D 0;
+ COM[port].obuf_size =3D cbOutQueue;
+ COM[port].obuf_head =3D COM[port].obuf_tail =3D 0;
+
+ COM[port].inbuf =3D malloc(cbInQueue);
+ if (COM[port].inbuf) {
+ COM[port].outbuf =3D malloc(cbOutQueue);
+ if (!COM[port].outbuf)
+ free(COM[port].inbuf);
+ } else COM[port].outbuf =3D NULL;
+ if (!COM[port].outbuf) {
+ /* not enough memory */
+ tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
+ close(COM[port].fd);
+ ERR("out of memory\n");
+ return IE_MEMORY;
+ }
+
+ COM[port].s_read =3D INVALID_HANDLE_VALUE;
+ COM[port].s_write =3D INVALID_HANDLE_VALUE;
+ comm_waitread( &COM[port] );
+ return port;
+ }
+ }=20
+ else=20
+ if (!strncasecmp(device,"LPT",3)) {
+=09
+ if (!ValidLPTPort(port))
+ return IE_BADID;
+
+ if (LPT[port].fd)
+ return IE_OPEN;
+
+ fd =3D open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
+ if (fd =3D=3D -1) {
+ return IE_HARDWARE;
+ } else {
+ LPT[port].fd =3D fd;
+ LPT[port].commerror =3D 0;
+ LPT[port].eventmask =3D 0;
+ return port|FLAG_LPT;
+ }
+ }
+ return IE_BADID;
+}
+
+/***********************************************************************=
******
+ * CloseComm16 (USER.207)
+ */
+INT16 WINAPI CloseComm16(INT16 cid)
+{
+ struct DosDeviceStruct *ptr;
+ =20
+ TRACE("cid=3D%d\n", cid);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no cid=3D%d found!\n", cid);
+ return -1;
+ }
+ if (!(cid&FLAG_LPT)) {
+ /* COM port */
+ SEGPTR_FREE(unknown[cid]); /* [LW] */
+
+ SERVICE_Delete( COM[cid].s_write );
+ SERVICE_Delete( COM[cid].s_read );
+ /* free buffers */
+ free(ptr->outbuf);
+ free(ptr->inbuf);
+
+ /* reset modem lines */
+ tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
+ }
+
+ if (close(ptr->fd) =3D=3D -1) {
+ ptr->commerror =3D WinError();
+ /* FIXME: should we clear ptr->fd here? */
+ return -1;
+ } else {
+ ptr->commerror =3D 0;
+ ptr->fd =3D 0;
+ return 0;
+ }
+}
+
+/***********************************************************************=
******
+ * SetCommBreak16 (USER.210)
+ */
+INT16 WINAPI SetCommBreak16(INT16 cid)
+{
+ struct DosDeviceStruct *ptr;
+
+ TRACE("cid=3D%d\n", cid);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no cid=3D%d found!\n", cid);
+ return -1;
+ }
+
+ ptr->suspended =3D 1;
+ ptr->commerror =3D 0;
+ return 0;
+}
+
+/***********************************************************************=
******
+ * ClearCommBreak16 (USER.211)
+ */
+INT16 WINAPI ClearCommBreak16(INT16 cid)
+{
+ struct DosDeviceStruct *ptr;
+
+ TRACE("cid=3D%d\n", cid);
+ if (!(ptr =3D GetDeviceStruct(cid))) {
+ FIXME("no cid=3D%d found!\n", cid);
+ return -1;
+ }
+ ptr->suspended =3D 0;
+ ptr->commerror =3D 0;
+ return 0;
+}
+
+/***********************************************************************=
******
+ * EscapeCommFunction16 (USER.214)
+ */
+LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
+{
+ int max;
+ struct DosDeviceStruct *ptr;
+ struct termios port;
+
+ TRACE("cid=3D%d, function=3D%d\n", cid, nFunction);
+ if ((nFunction !=3D GETMAXCOM) && (nFunction !=3D GETMAXLPT)) {
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no cid=3D%d found!\n", cid);
+ return -1;
+ }
+ if (tcgetattr(ptr->fd,&port) =3D=3D -1) {
+ TRACE("tcgetattr failed\n");
+ ptr->commerror=3DWinError();=09
+ return -1;
+ }
+ } else ptr =3D NULL;
+
+ switch (nFunction) {
+ case RESETDEV:
+ TRACE("RESETDEV\n");
+ break; =09
+
+ case GETMAXCOM:
+ TRACE("GETMAXCOM\n");=20
+ for (max =3D MAX_PORTS;!COM[max].devicename;max--)
+ ;
+ return max;
+ break;
+
+ case GETMAXLPT:
+ TRACE("GETMAXLPT\n");=20
+ for (max =3D MAX_PORTS;!LPT[max].devicename;max--)
+ ;
+ return FLAG_LPT + max;
+ break;
+
+ case GETBASEIRQ:
+ TRACE("GETBASEIRQ\n");=20
+ /* FIXME: use tables */
+ /* just fake something for now */
+ if (cid & FLAG_LPT) {
+ /* LPT1: irq 7, LPT2: irq 5 */
+ return (cid & 0x7f) ? 5 : 7;
+ } else {
+ /* COM1: irq 4, COM2: irq 3,
+ COM3: irq 4, COM4: irq 3 */
+ return 4 - (cid & 1);
+ }
+ break;
+
+ case CLRDTR:
+ TRACE("CLRDTR\n");=20
+#ifdef TIOCM_DTR
+ return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
+#endif
+ case CLRRTS:
+ TRACE("CLRRTS\n");=20
+#ifdef TIOCM_RTS
+ return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
+#endif
+=09
+ case SETDTR:
+ TRACE("SETDTR\n");=20
+#ifdef TIOCM_DTR
+ return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
+#endif
+
+ case SETRTS:
+ TRACE("SETRTS\n");=20
+#ifdef TIOCM_RTS =09
+ return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
+#endif
+
+ case SETXOFF:
+ TRACE("SETXOFF\n");=20
+ port.c_iflag |=3D IXOFF;
+ break;
+
+ case SETXON:
+ TRACE("SETXON\n");=20
+ port.c_iflag |=3D IXON;
+ break;
+
+ default:
+ WARN("(cid=3D%d,nFunction=3D%d): Unknown function\n",=20
+ cid, nFunction);
+ break; =09
+ }
+=09
+ if (tcsetattr(ptr->fd, TCSADRAIN, &port) =3D=3D -1) {
+ ptr->commerror =3D WinError();
+ return -1;=09
+ } else {
+ ptr->commerror =3D 0;
+ return 0;
+ }
+}
+
+/***********************************************************************=
******
+ * FlushComm16 (USER.215)
+ */
+INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
+{
+ int queue;
+ struct DosDeviceStruct *ptr;
+
+ TRACE("cid=3D%d, queue=3D%d\n", cid, fnQueue);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no cid=3D%d found!\n", cid);
+ return -1;
+ }
+ switch (fnQueue) {
+ case 0:
+ queue =3D TCOFLUSH;
+ ptr->obuf_tail =3D ptr->obuf_head;
+ break;
+ case 1:
+ queue =3D TCIFLUSH;
+ ptr->ibuf_head =3D ptr->ibuf_tail;
+ break;
+ default:
+ WARN("(cid=3D%d,fnQueue=3D%d):Unknown queue\n",=20
+ cid, fnQueue);
+ return -1;
+ }
+ if (tcflush(ptr->fd, queue)) {
+ ptr->commerror =3D WinError();
+ return -1;=09
+ } else {
+ ptr->commerror =3D 0;
+ return 0;
+ }
+} =20
+
+/********************************************************************
+ * GetCommError16 (USER.203)
+ */
+INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
+{
+ int temperror;
+ struct DosDeviceStruct *ptr;
+ unsigned char *stol;
+ unsigned int mstat;
+
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+ if (cid&FLAG_LPT) {
+ WARN(" cid %d not comm port\n",cid);
+ return CE_MODE;
+ }
+ stol =3D (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
+ ioctl(ptr->fd,TIOCMGET,&mstat);
+ COMM_MSRUpdate( stol, mstat);
+
+ if (lpStat) {
+ lpStat->status =3D 0;
+
+ lpStat->cbOutQue =3D comm_outbuf(ptr);
+ lpStat->cbInQue =3D comm_inbuf(ptr);
+
+ TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
+ cid, ptr->commerror, lpStat->status, lpStat->cbInQue,=20
+ lpStat->cbOutQue, *stol);
+ }
+ else
+ TRACE("cid %d, error %d, lpStat NULL stol %x\n",
+ cid, ptr->commerror, *stol);
+
+ /* Return any errors and clear it */
+ temperror =3D ptr->commerror;
+ ptr->commerror =3D 0;
+ return(temperror);
+}
+
+/***********************************************************************=
******
+ * SetCommEventMask16 (USER.208)
+ */
+SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
+{
+ struct DosDeviceStruct *ptr;
+ unsigned char *stol;
+ int repid;
+ unsigned int mstat;
+
+ TRACE("cid %d,mask %d\n",cid,fuEvtMask);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return (SEGPTR)NULL;
+ }
+
+ ptr->eventmask =3D fuEvtMask;
+
+ if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
+ WARN(" cid %d not comm port\n",cid);
+ return (SEGPTR)NULL;
+ }
+ /* it's a COM port ? -> modify flags */
+ stol =3D (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
+ repid =3D ioctl(ptr->fd,TIOCMGET,&mstat);
+ TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
+ COMM_MSRUpdate( stol, mstat);
+
+ TRACE(" modem dcd construct %x\n",*stol);
+ return SEGPTR_GET(unknown[cid]);
+}
+
+/***********************************************************************=
******
+ * GetCommEventMask16 (USER.209)
+ */
+UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
+{
+ struct DosDeviceStruct *ptr;
+ WORD events;
+
+ TRACE("cid %d, mask %d\n", cid, fnEvtClear);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return 0;
+ }
+
+ if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
+ WARN(" cid %d not comm port\n",cid);
+ return 0;
+ }
+
+ events =3D *(WORD*)(unknown[cid]) & fnEvtClear;
+ *(WORD*)(unknown[cid]) &=3D ~fnEvtClear;
+ return events;
+}
+
+/***********************************************************************=
******
+ * SetCommState16 (USER.201)
+ */
+INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
+{
+ struct termios port;
+ struct DosDeviceStruct *ptr;
+ int bytesize, stopbits;
+ int fail=3D0;
+
+ TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
+ if ((ptr =3D GetDeviceStruct(lpdcb->Id)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",lpdcb->Id);
+ return -1;
+ }
+ if (tcgetattr(ptr->fd, &port) =3D=3D -1) {
+ ptr->commerror =3D WinError();=09
+ return -1;
+ }
+
+ port.c_cc[VMIN] =3D 0;
+ port.c_cc[VTIME] =3D 1;
+
+#ifdef IMAXBEL
+ port.c_iflag &=3D ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
+#else
+ port.c_iflag &=3D ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
+#endif
+ port.c_iflag |=3D (IGNBRK);
+
+ port.c_oflag &=3D ~(OPOST);
+
+ port.c_cflag &=3D ~(HUPCL);
+ port.c_cflag |=3D CLOCAL | CREAD;
+
+ port.c_lflag &=3D ~(ICANON|ECHO|ISIG);
+ port.c_lflag |=3D NOFLSH;
+
+ TRACE("baudrate %d\n",lpdcb->BaudRate);
+#ifdef CBAUD
+ port.c_cflag &=3D ~CBAUD;
+ switch (lpdcb->BaudRate) {
+ case 110:
+ case CBR_110:
+ port.c_cflag |=3D B110;
+ break; =09
+ case 300:
+ case CBR_300:
+ port.c_cflag |=3D B300;
+ break; =09
+ case 600:
+ case CBR_600:
+ port.c_cflag |=3D B600;
+ break; =09
+ case 1200:
+ case CBR_1200:
+ port.c_cflag |=3D B1200;
+ break; =09
+ case 2400:
+ case CBR_2400:
+ port.c_cflag |=3D B2400;
+ break; =09
+ case 4800:
+ case CBR_4800:
+ port.c_cflag |=3D B4800;
+ break; =09
+ case 9600:
+ case CBR_9600:
+ port.c_cflag |=3D B9600;
+ break; =09
+ case 19200:
+ case CBR_19200:
+ port.c_cflag |=3D B19200;
+ break; =09
+ case 38400:
+ case CBR_38400:
+ port.c_cflag |=3D B38400;
+ break; =09
+#ifdef B57600
+ case 57600:
+ port.c_cflag |=3D B57600;
+ break; =09
+#endif
+#ifdef B115200
+ case 57601:
+ port.c_cflag |=3D B115200;
+ break; =09
+#endif
+ default:
+ ptr->commerror =3D IE_BAUDRATE;
+ fail=3D1;
+ }
+#elif !defined(__EMX__)
+ switch (lpdcb->BaudRate) {
+ case 110:
+ case CBR_110:
+ port.c_ospeed =3D B110;
+ break;
+ case 300:
+ case CBR_300:
+ port.c_ospeed =3D B300;
+ break;
+ case 600:
+ case CBR_600:
+ port.c_ospeed =3D B600;
+ break;
+ case 1200:
+ case CBR_1200:
+ port.c_ospeed =3D B1200;
+ break;
+ case 2400:
+ case CBR_2400:
+ port.c_ospeed =3D B2400;
+ break;
+ case 4800:
+ case CBR_4800:
+ port.c_ospeed =3D B4800;
+ break;
+ case 9600:
+ case CBR_9600:
+ port.c_ospeed =3D B9600;
+ break;
+ case 19200:
+ case CBR_19200:
+ port.c_ospeed =3D B19200;
+ break;
+ case 38400:
+ case CBR_38400:
+ port.c_ospeed =3D B38400;
+ break;
+ default:
+ ptr->commerror =3D IE_BAUDRATE;
+ fail=3D1;
+ }
+ port.c_ispeed =3D port.c_ospeed;
+#endif
+ bytesize=3Dlpdcb->ByteSize;
+ stopbits=3Dlpdcb->StopBits;
+
+ TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
+#ifdef CMSPAR
+ port.c_cflag &=3D ~(PARENB | PARODD | CMSPAR);
+#else
+ port.c_cflag &=3D ~(PARENB | PARODD);
+#endif
+ if (lpdcb->fParity)
+ port.c_iflag |=3D INPCK;
+ else
+ port.c_iflag &=3D ~INPCK;
+ switch (lpdcb->Parity) {
+ case NOPARITY:
+ break;
+ case ODDPARITY:
+ port.c_cflag |=3D (PARENB | PARODD);
+ break;
+ case EVENPARITY:
+ port.c_cflag |=3D PARENB;
+ break;
+#ifdef CMSPAR
+ /* Linux defines mark/space (stick) parity */
+ case MARKPARITY:
+ port.c_cflag |=3D (PARENB | CMSPAR);
+ break;
+ case SPACEPARITY:
+ port.c_cflag |=3D (PARENB | PARODD | CMSPAR);
+ break;
+#else
+ /* try the POSIX way */
+ case MARKPARITY:
+ if( stopbits =3D=3D ONESTOPBIT) {
+ stopbits =3D TWOSTOPBITS;
+ port.c_iflag &=3D ~INPCK;
+ } else {
+ ptr->commerror =3D IE_BYTESIZE;
+ fail=3D1;
+ }
+ break;
+ case SPACEPARITY:
+ if( bytesize < 8) {
+ bytesize +=3D1;
+ port.c_iflag &=3D ~INPCK;
+ } else {
+ ptr->commerror =3D IE_BYTESIZE;
+ fail=3D1;
+ }
+ break;
+#endif
+ default:
+ ptr->commerror =3D IE_BYTESIZE;
+ fail=3D1;
+ }
+=09
+ TRACE("bytesize %d\n",bytesize);
+ port.c_cflag &=3D ~CSIZE;
+ switch (bytesize) {
+ case 5:
+ port.c_cflag |=3D CS5;
+ break;
+ case 6:
+ port.c_cflag |=3D CS6;
+ break;
+ case 7:
+ port.c_cflag |=3D CS7;
+ break;
+ case 8:
+ port.c_cflag |=3D CS8;
+ break;
+ default:
+ ptr->commerror =3D IE_BYTESIZE;
+ fail=3D1;
+ }
+
+ TRACE("stopbits %d\n",stopbits);
+
+ switch (stopbits) {
+ case ONESTOPBIT:
+ port.c_cflag &=3D ~CSTOPB;
+ break;
+ case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
+ case TWOSTOPBITS:
+ port.c_cflag |=3D CSTOPB;
+ break;
+ default:
+ ptr->commerror =3D IE_BYTESIZE;
+ fail=3D1;
+ }
+#ifdef CRTSCTS
+
+ if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
+ port.c_cflag |=3D CRTSCTS;
+
+ if (lpdcb->fDtrDisable)=20
+ port.c_cflag &=3D ~CRTSCTS;
+#endif=09
+ if (lpdcb->fInX)
+ port.c_iflag |=3D IXON;
+ else
+ port.c_iflag &=3D ~IXON;
+ if (lpdcb->fOutX)
+ port.c_iflag |=3D IXOFF;
+ else
+ port.c_iflag &=3D ~IXOFF;
+
+ ptr->evtchar =3D lpdcb->EvtChar;
+
+ if(fail)
+ return -1;
+ =20
+ if (tcsetattr(ptr->fd, TCSADRAIN, &port) =3D=3D -1) {
+ ptr->commerror =3D WinError();=09
+ return -1;
+ } else {
+ ptr->commerror =3D 0;
+ return 0;
+ }
+}
+
+/***********************************************************************=
******
+ * GetCommState16 (USER.202)
+ */
+INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
+{
+ int speed;
+ struct DosDeviceStruct *ptr;
+ struct termios port;
+
+ TRACE("cid %d, ptr %p\n", cid, lpdcb);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+ if (tcgetattr(ptr->fd, &port) =3D=3D -1) {
+ ptr->commerror =3D WinError();=09
+ return -1;
+ }
+ lpdcb->Id =3D cid;
+#ifndef __EMX__
+#ifdef CBAUD
+ speed =3D port.c_cflag & CBAUD;
+#else
+ speed =3D port.c_ospeed;
+#endif
+ switch(speed) {
+ case B110:
+ lpdcb->BaudRate =3D 110;
+ break;
+ case B300:
+ lpdcb->BaudRate =3D 300;
+ break;
+ case B600:
+ lpdcb->BaudRate =3D 600;
+ break;
+ case B1200:
+ lpdcb->BaudRate =3D 1200;
+ break;
+ case B2400:
+ lpdcb->BaudRate =3D 2400;
+ break;
+ case B4800:
+ lpdcb->BaudRate =3D 4800;
+ break;
+ case B9600:
+ lpdcb->BaudRate =3D 9600;
+ break;
+ case B19200:
+ lpdcb->BaudRate =3D 19200;
+ break;
+ case B38400:
+ lpdcb->BaudRate =3D 38400;
+ break;
+#ifdef B57600
+ case B57600:
+ lpdcb->BaudRate =3D 57600;
+ break;
+#endif
+#ifdef B115200
+ case B115200:
+ lpdcb->BaudRate =3D 57601;
+ break;
+#endif
+ }
+#endif
+ switch (port.c_cflag & CSIZE) {
+ case CS5:
+ lpdcb->ByteSize =3D 5;
+ break;
+ case CS6:
+ lpdcb->ByteSize =3D 6;
+ break;
+ case CS7:
+ lpdcb->ByteSize =3D 7;
+ break;
+ case CS8:
+ lpdcb->ByteSize =3D 8;
+ break;
+ }=09
+=09
+ if(port.c_iflag & INPCK)
+ lpdcb->fParity =3D TRUE;
+ else
+ lpdcb->fParity =3D FALSE;
+#ifdef CMSPAR
+ switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
+#else
+ switch (port.c_cflag & (PARENB | PARODD))
+#endif
+ {
+ case 0:
+ lpdcb->Parity =3D NOPARITY;
+ break;
+ case PARENB:
+ lpdcb->Parity =3D EVENPARITY;
+ break;
+ case (PARENB | PARODD):
+ lpdcb->Parity =3D ODDPARITY; =09
+ break;
+#ifdef CMSPAR
+ case (PARENB | CMSPAR):
+ lpdcb->Parity =3D MARKPARITY; =09
+ break;
+ case (PARENB | PARODD | CMSPAR):
+ lpdcb->Parity =3D SPACEPARITY; =09
+ break;
+#endif
+ }
+
+ if (port.c_cflag & CSTOPB)
+ if(lpdcb->ByteSize =3D=3D 5)
+ lpdcb->StopBits =3D ONE5STOPBITS;
+ else
+ lpdcb->StopBits =3D TWOSTOPBITS;
+ else
+ lpdcb->StopBits =3D ONESTOPBIT;
+
+ lpdcb->RlsTimeout =3D 50;
+ lpdcb->CtsTimeout =3D 50;=20
+ lpdcb->DsrTimeout =3D 50;
+ lpdcb->fNull =3D 0;
+ lpdcb->fChEvt =3D 0;
+ lpdcb->fBinary =3D 1;
+ lpdcb->fDtrDisable =3D 0;
+
+#ifdef CRTSCTS
+
+ if (port.c_cflag & CRTSCTS) {
+ lpdcb->fDtrflow =3D 1;
+ lpdcb->fRtsflow =3D 1;
+ lpdcb->fOutxCtsFlow =3D 1;
+ lpdcb->fOutxDsrFlow =3D 1;
+ } else=20
+#endif
+ lpdcb->fDtrDisable =3D 1;
+
+ if (port.c_iflag & IXON)
+ lpdcb->fInX =3D 1;
+ else
+ lpdcb->fInX =3D 0;
+
+ if (port.c_iflag & IXOFF)
+ lpdcb->fOutX =3D 1;
+ else
+ lpdcb->fOutX =3D 0;
+/*
+ lpdcb->XonChar =3D=20
+ lpdcb->XoffChar =3D=20
+ */
+ lpdcb->XonLim =3D 10;
+ lpdcb->XoffLim =3D 10;
+
+ lpdcb->EvtChar =3D ptr->evtchar;
+
+ ptr->commerror =3D 0;
+ return 0;
+}
+
+/***********************************************************************=
******
+ * TransmitCommChar16 (USER.206)
+ */
+INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
+{
+ struct DosDeviceStruct *ptr;
+
+ TRACE("cid %d, data %d \n", cid, chTransmit);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+
+ if (ptr->suspended) {
+ ptr->commerror =3D IE_HARDWARE;
+ return -1;
+ }=09
+
+ if (ptr->xmit >=3D 0) {
+ /* character already queued */
+ /* FIXME: which error would Windows return? */
+ ptr->commerror =3D CE_TXFULL;
+ return -1;
+ }
+
+ if (ptr->obuf_head =3D=3D ptr->obuf_tail) {
+ /* transmit queue empty, try to transmit directly */
+ if (write(ptr->fd, &chTransmit, 1) =3D=3D -1) {
+ /* didn't work, queue it */
+ ptr->xmit =3D chTransmit;
+ comm_waitwrite(ptr);
+ }
+ } else {
+ /* data in queue, let this char be transmitted next */
+ ptr->xmit =3D chTransmit;
+ comm_waitwrite(ptr);
+ }
+
+ ptr->commerror =3D 0;
+ return 0;
+}
+
+/***********************************************************************=
******
+ * UngetCommChar16 (USER.212)
+ */
+INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
+{
+ struct DosDeviceStruct *ptr;
+
+ TRACE("cid %d (char %d)\n", cid, chUnget);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+
+ if (ptr->suspended) {
+ ptr->commerror =3D IE_HARDWARE;
+ return -1;
+ }=09
+
+ if (ptr->unget>=3D0) {
+ /* character already queued */
+ /* FIXME: which error would Windows return? */
+ ptr->commerror =3D CE_RXOVER;
+ return -1;
+ }
+
+ ptr->unget =3D chUnget;
+
+ ptr->commerror =3D 0;
+ return 0;
+}
+
+/***********************************************************************=
******
+ * ReadComm16 (USER.204)
+ */
+INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
+{
+ int status, length;
+ struct DosDeviceStruct *ptr;
+ LPSTR orgBuf =3D lpvBuf;
+
+ TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+
+ if (ptr->suspended) {
+ ptr->commerror =3D IE_HARDWARE;
+ return -1;
+ }=09
+
+ /* read unget character */
+ if (ptr->unget>=3D0) {
+ *lpvBuf++ =3D ptr->unget;
+ ptr->unget =3D -1;
+
+ length =3D 1;
+ } else
+ length =3D 0;
+
+ /* read from receive buffer */
+ while (length < cbRead) {
+ status =3D ((ptr->ibuf_head < ptr->ibuf_tail) ?
+ ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
+ if (!status) break;
+ if ((cbRead - length) < status)
+ status =3D cbRead - length;
+
+ memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
+ ptr->ibuf_tail +=3D status;
+ if (ptr->ibuf_tail >=3D ptr->ibuf_size)
+ ptr->ibuf_tail =3D 0;
+ lpvBuf +=3D status;
+ length +=3D status;
+ }
+
+ TRACE("%.*s\n", length, orgBuf);
+ ptr->commerror =3D 0;
+ return length;
+}
+
+/***********************************************************************=
******
+ * WriteComm16 (USER.205)
+ */
+INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
+{
+ int status, length;
+ struct DosDeviceStruct *ptr;
+
+ TRACE("cid %d, ptr %p, length %d\n",=20
+ cid, lpvBuf, cbWrite);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+
+ if (ptr->suspended) {
+ ptr->commerror =3D IE_HARDWARE;
+ return -1;
+ }=09
+=09
+ TRACE("%.*s\n", cbWrite, lpvBuf );
+
+ length =3D 0;
+ while (length < cbWrite) {
+ if ((ptr->obuf_head =3D=3D ptr->obuf_tail) && (ptr->xmit < 0)) {
+ /* no data queued, try to write directly */
+ status =3D write(ptr->fd, lpvBuf, cbWrite - length);
+ if (status > 0) {
+ lpvBuf +=3D status;
+ length +=3D status;
+ continue;
+ }
+ }
+ /* can't write directly, put into transmit buffer */
+ status =3D ((ptr->obuf_tail > ptr->obuf_head) ?
+ (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
+ if (!status) break;
+ if ((cbWrite - length) < status)
+ status =3D cbWrite - length;
+ memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
+ ptr->obuf_head +=3D status;
+ if (ptr->obuf_head >=3D ptr->obuf_size)
+ ptr->obuf_head =3D 0;
+ lpvBuf +=3D status;
+ length +=3D status;
+ comm_waitwrite(ptr);
+ }
+
+ ptr->commerror =3D 0;=09
+ return length;
+}
+
+/***********************************************************************
+ * EnableCommNotification (USER.245)
+ */
+BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
+ INT16 cbWriteNotify, INT16 cbOutQu=
eue )
+{
+ struct DosDeviceStruct *ptr;
+
+ TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
+ if ((ptr =3D GetDeviceStruct(cid)) =3D=3D NULL) {
+ FIXME("no handle for cid =3D %0x!\n",cid);
+ return -1;
+ }
+ ptr->wnd =3D hwnd;
+ ptr->n_read =3D cbWriteNotify;
+ ptr->n_write =3D cbOutQueue;
+ return TRUE;
+}
More information about the wine-patches
mailing list