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