2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
47 #ifdef HAVE_SYS_FILIO_H
48 # include <sys/filio.h>
50 #include <sys/ioctl.h>
53 #include "wine/winuser16.h"
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
64 #include "server/request.h"
72 DEFAULT_DEBUG_CHANNEL(comm)
75 #define TIOCINQ FIONREAD
77 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
80 struct DosDeviceStruct COM[MAX_PORTS];
81 struct DosDeviceStruct LPT[MAX_PORTS];
82 /* pointers to unknown(==undocumented) comm structure */
83 LPCVOID *unknown[MAX_PORTS];
84 /* save terminal states */
85 static struct termios m_stat[MAX_PORTS];
90 char option[10], temp[256], *btemp;
93 for (x=0; x!=MAX_PORTS; x++) {
94 strcpy(option,"COMx");
98 PROFILE_GetWineIniString( "serialports", option, "*",
100 if (!strcmp(temp, "*") || *temp == '\0')
101 COM[x].devicename = NULL;
103 btemp = strchr(temp,',');
106 COM[x].baudrate = atoi(btemp);
108 COM[x].baudrate = -1;
111 if (!S_ISCHR(st.st_mode))
112 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
114 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
115 WARN(comm,"Can't malloc for device info!\n");
118 strcpy(COM[x].devicename, temp);
120 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
123 strcpy(option, "LPTx");
127 PROFILE_GetWineIniString( "parallelports", option, "*",
128 temp, sizeof(temp) );
129 if (!strcmp(temp, "*") || *temp == '\0')
130 LPT[x].devicename = NULL;
133 if (!S_ISCHR(st.st_mode))
134 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
136 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
137 WARN(comm,"Can't malloc for device info!\n");
140 strcpy(LPT[x].devicename, temp);
142 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
149 struct DosDeviceStruct *GetDeviceStruct_fd(int fd)
153 for (x=0; x!=MAX_PORTS; x++) {
163 struct DosDeviceStruct *GetDeviceStruct(int fd)
165 if ((fd&0x7F)<=MAX_PORTS) {
166 if (!(fd&FLAG_LPT)) {
178 int GetCommPort_fd(int fd)
182 for (x=0; x<MAX_PORTS; x++) {
190 int ValidCOMPort(int x)
192 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
195 int ValidLPTPort(int x)
197 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
202 TRACE(comm, "errno = %d\n", errno);
209 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
211 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
212 + ptr->ibuf_head - ptr->ibuf_tail;
215 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
217 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
218 + ptr->obuf_head - ptr->obuf_tail;
221 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
223 unsigned int mstat, okay;
224 okay = ioctl(fd, TIOCMGET, &mstat);
225 if (okay) return okay;
226 if (andy) mstat &= andy;
228 return ioctl(fd, TIOCMSET, &mstat);
231 static void comm_notification(int fd,void*private)
233 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
234 int prev, bleft, len;
236 int cid = GetCommPort_fd(fd);
238 TRACE(comm, "async notification\n");
239 /* read data from comm port */
240 prev = comm_inbuf(ptr);
242 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
244 len = read(fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
247 ptr->commerror = CE_RXOVER;
249 /* check for events */
250 if ((ptr->eventmask & EV_RXFLAG) &&
251 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, bleft)) {
252 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
255 if (ptr->eventmask & EV_RXCHAR) {
256 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
259 /* advance buffer position */
260 ptr->ibuf_head += len;
261 if (ptr->ibuf_head >= ptr->ibuf_size)
266 /* check for notification */
267 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
268 (comm_inbuf(ptr)>=ptr->n_read)) {
269 /* passed the receive notification threshold */
273 /* write any TransmitCommChar character */
275 len = write(fd, &(ptr->xmit), 1);
276 if (len > 0) ptr->xmit = -1;
278 /* write from output queue */
279 prev = comm_outbuf(ptr);
281 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
283 len = bleft ? write(fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
285 ptr->obuf_tail += len;
286 if (ptr->obuf_tail >= ptr->obuf_size)
289 if ((ptr->obuf_tail == ptr->obuf_head) && (ptr->eventmask & EV_TXEMPTY)) {
290 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
295 /* check for notification */
296 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
297 (comm_outbuf(ptr)<ptr->n_write)) {
298 /* passed the transmit notification threshold */
302 /* send notifications, if any */
303 if (ptr->wnd && mask) {
304 TRACE(comm, "notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
305 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
309 /**************************************************************************
310 * BuildCommDCB (USER.213)
312 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
314 /* "COM1:9600,n,8,1" */
317 char *ptr, temp[256];
319 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
321 if (!lstrncmpiA(device,"COM",3)) {
322 port = device[3] - '0';
326 ERR(comm, "BUG ! COM0 can't exist!.\n");
330 if (!ValidCOMPort(port)) {
334 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
341 if (*(device+4) != ':')
344 strcpy(temp,device+5);
345 ptr = strtok(temp, ", ");
347 if (COM[port].baudrate > 0)
348 lpdcb->BaudRate = COM[port].baudrate;
350 lpdcb->BaudRate = atoi(ptr);
351 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
353 ptr = strtok(NULL, ", ");
355 *ptr = toupper(*ptr);
357 TRACE(comm,"parity (%c)\n", *ptr);
358 lpdcb->fParity = TRUE;
361 lpdcb->Parity = NOPARITY;
362 lpdcb->fParity = FALSE;
365 lpdcb->Parity = EVENPARITY;
368 lpdcb->Parity = MARKPARITY;
371 lpdcb->Parity = ODDPARITY;
374 WARN(comm,"Unknown parity `%c'!\n", *ptr);
378 ptr = strtok(NULL, ", ");
379 TRACE(comm, "charsize (%c)\n", *ptr);
380 lpdcb->ByteSize = *ptr - '0';
382 ptr = strtok(NULL, ", ");
383 TRACE(comm, "stopbits (%c)\n", *ptr);
386 lpdcb->StopBits = ONESTOPBIT;
389 lpdcb->StopBits = TWOSTOPBITS;
392 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
400 /*****************************************************************************
401 * OpenComm (USER.200)
403 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
407 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
409 port = device[3] - '0';
412 ERR(comm, "BUG ! COM0 or LPT0 don't exist !\n");
414 if (!lstrncmpiA(device,"COM",3)) {
416 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
418 if (!ValidCOMPort(port))
424 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
426 ERR(comm, "error=%d\n", errno);
429 unknown[port] = SEGPTR_ALLOC(40);
430 bzero(unknown[port],40);
432 COM[port].commerror = 0;
433 COM[port].eventmask = 0;
434 COM[port].evtchar = 0; /* FIXME: default? */
435 /* save terminal state */
436 tcgetattr(fd,&m_stat[port]);
437 /* set default parameters */
438 if(COM[port].baudrate>-1){
440 GetCommState16(port, &dcb);
441 dcb.BaudRate=COM[port].baudrate;
443 * databits, parity, stopbits
445 SetCommState16( &dcb);
447 /* init priority characters */
448 COM[port].unget = -1;
450 /* allocate buffers */
451 COM[port].ibuf_size = cbInQueue;
452 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
453 COM[port].obuf_size = cbOutQueue;
454 COM[port].obuf_head = COM[port].obuf_tail = 0;
456 COM[port].inbuf = malloc(cbInQueue);
457 if (COM[port].inbuf) {
458 COM[port].outbuf = malloc(cbOutQueue);
459 if (!COM[port].outbuf)
460 free(COM[port].inbuf);
461 } else COM[port].outbuf = NULL;
462 if (!COM[port].outbuf) {
463 /* not enough memory */
464 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
466 ERR(comm, "out of memory");
470 /* enable async notifications */
471 ASYNC_RegisterFD(COM[port].fd,comm_notification,&COM[port]);
472 /* bootstrap notifications, just in case */
473 comm_notification(COM[port].fd,&COM[port]);
478 if (!lstrncmpiA(device,"LPT",3)) {
480 if (!ValidLPTPort(port))
486 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
491 LPT[port].commerror = 0;
492 LPT[port].eventmask = 0;
493 return port|FLAG_LPT;
499 /*****************************************************************************
500 * CloseComm (USER.207)
502 INT16 WINAPI CloseComm16(INT16 cid)
504 struct DosDeviceStruct *ptr;
506 TRACE(comm,"cid=%d\n", cid);
507 if ((ptr = GetDeviceStruct(cid)) == NULL) {
510 if (!(cid&FLAG_LPT)) {
512 SEGPTR_FREE(unknown[cid]); /* [LW] */
514 /* disable async notifications */
515 ASYNC_UnregisterFD(COM[cid].fd,comm_notification);
520 /* reset modem lines */
521 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
524 if (close(ptr->fd) == -1) {
525 ptr->commerror = WinError();
526 /* FIXME: should we clear ptr->fd here? */
535 /*****************************************************************************
536 * SetCommBreak (USER.210)
538 INT16 WINAPI SetCommBreak16(INT16 cid)
540 struct DosDeviceStruct *ptr;
542 TRACE(comm,"cid=%d\n", cid);
543 if ((ptr = GetDeviceStruct(cid)) == NULL) {
552 /*****************************************************************************
553 * ClearCommBreak (USER.211)
555 INT16 WINAPI ClearCommBreak16(INT16 cid)
557 struct DosDeviceStruct *ptr;
559 TRACE(comm,"cid=%d\n", cid);
560 if ((ptr = GetDeviceStruct(cid)) == NULL) {
569 /*****************************************************************************
570 * EscapeCommFunction (USER.214)
572 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
575 struct DosDeviceStruct *ptr;
578 TRACE(comm,"cid=%d, function=%d\n", cid, nFunction);
579 if ((ptr = GetDeviceStruct(cid)) == NULL) {
582 if (tcgetattr(ptr->fd,&port) == -1) {
583 ptr->commerror=WinError();
592 for (max = MAX_PORTS;!COM[max].devicename;max--)
598 for (max = MAX_PORTS;!LPT[max].devicename;max--)
600 return FLAG_LPT + max;
605 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
609 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
614 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
619 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
623 port.c_iflag |= IXOFF;
627 port.c_iflag |= IXON;
631 WARN(comm,"(cid=%d,nFunction=%d): Unknown function\n",
636 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
637 ptr->commerror = WinError();
645 /*****************************************************************************
646 * FlushComm (USER.215)
648 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
651 struct DosDeviceStruct *ptr;
653 TRACE(comm,"cid=%d, queue=%d\n", cid, fnQueue);
654 if ((ptr = GetDeviceStruct(cid)) == NULL) {
660 ptr->obuf_tail = ptr->obuf_head;
664 ptr->ibuf_head = ptr->ibuf_tail;
667 WARN(comm,"(cid=%d,fnQueue=%d):Unknown queue\n",
671 if (tcflush(ptr->fd, queue)) {
672 ptr->commerror = WinError();
680 /********************************************************************
681 * GetCommError (USER.203)
683 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
686 struct DosDeviceStruct *ptr;
690 if ((ptr = GetDeviceStruct(cid)) == NULL) {
694 WARN(comm," cid %d not comm port\n",cid);
697 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
698 ioctl(ptr->fd,TIOCMGET,&mstat);
699 if( mstat&TIOCM_CAR )
707 lpStat->cbOutQue = comm_outbuf(ptr);
708 lpStat->cbInQue = comm_inbuf(ptr);
710 TRACE(comm, "cid %d, error %d, lpStat %d %d %d stol %x\n",
711 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
712 lpStat->cbOutQue, *stol);
715 TRACE(comm, "cid %d, error %d, lpStat NULL stol %x\n",
716 cid, ptr->commerror, *stol);
718 /* Return any errors and clear it */
719 temperror = ptr->commerror;
724 /*****************************************************************************
725 * SetCommEventMask (USER.208)
727 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
729 struct DosDeviceStruct *ptr;
734 TRACE(comm,"cid %d,mask %d\n",cid,fuEvtMask);
735 if ((ptr = GetDeviceStruct(cid)) == NULL)
738 ptr->eventmask = fuEvtMask;
740 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
741 WARN(comm," cid %d not comm port\n",cid);
744 /* it's a COM port ? -> modify flags */
745 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
746 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
747 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
748 if ((mstat&TIOCM_CAR))
753 TRACE(comm," modem dcd construct %x\n",*stol);
754 return SEGPTR_GET(unknown[cid]);
757 /*****************************************************************************
758 * GetCommEventMask (USER.209)
760 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
762 struct DosDeviceStruct *ptr;
765 TRACE(comm, "cid %d, mask %d\n", cid, fnEvtClear);
766 if ((ptr = GetDeviceStruct(cid)) == NULL)
769 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
770 WARN(comm," cid %d not comm port\n",cid);
774 events = *(WORD*)(unknown[cid]) & fnEvtClear;
775 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
779 /*****************************************************************************
780 * SetCommState16 (USER.201)
782 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
785 struct DosDeviceStruct *ptr;
787 TRACE(comm, "cid %d, ptr %p\n", lpdcb->Id, lpdcb);
788 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
791 if (tcgetattr(ptr->fd, &port) == -1) {
792 ptr->commerror = WinError();
797 port.c_cc[VTIME] = 1;
800 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
802 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
804 port.c_iflag |= (IGNBRK);
806 port.c_oflag &= ~(OPOST);
808 port.c_cflag &= ~(HUPCL);
809 port.c_cflag |= CLOCAL | CREAD;
811 port.c_lflag &= ~(ICANON|ECHO|ISIG);
812 port.c_lflag |= NOFLSH;
814 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
816 port.c_cflag &= ~CBAUD;
817 switch (lpdcb->BaudRate) {
820 port.c_cflag |= B110;
824 port.c_cflag |= B300;
828 port.c_cflag |= B600;
832 port.c_cflag |= B1200;
836 port.c_cflag |= B2400;
840 port.c_cflag |= B4800;
844 port.c_cflag |= B9600;
848 port.c_cflag |= B19200;
852 port.c_cflag |= B38400;
856 port.c_cflag |= B57600;
861 port.c_cflag |= B115200;
865 ptr->commerror = IE_BAUDRATE;
868 #elif !defined(__EMX__)
869 switch (lpdcb->BaudRate) {
872 port.c_ospeed = B110;
876 port.c_ospeed = B300;
880 port.c_ospeed = B600;
884 port.c_ospeed = B1200;
888 port.c_ospeed = B2400;
892 port.c_ospeed = B4800;
896 port.c_ospeed = B9600;
900 port.c_ospeed = B19200;
904 port.c_ospeed = B38400;
907 ptr->commerror = IE_BAUDRATE;
910 port.c_ispeed = port.c_ospeed;
912 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
913 port.c_cflag &= ~CSIZE;
914 switch (lpdcb->ByteSize) {
928 ptr->commerror = IE_BYTESIZE;
932 TRACE(comm,"fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
933 port.c_cflag &= ~(PARENB | PARODD);
935 port.c_iflag |= INPCK;
937 port.c_iflag &= ~INPCK;
938 switch (lpdcb->Parity) {
942 port.c_cflag |= (PARENB | PARODD);
945 port.c_cflag |= PARENB;
948 ptr->commerror = IE_BYTESIZE;
953 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
955 switch (lpdcb->StopBits) {
957 port.c_cflag &= ~CSTOPB;
960 port.c_cflag |= CSTOPB;
963 ptr->commerror = IE_BYTESIZE;
968 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
969 port.c_cflag |= CRTSCTS;
971 if (lpdcb->fDtrDisable)
972 port.c_cflag &= ~CRTSCTS;
975 port.c_iflag |= IXON;
977 port.c_iflag &= ~IXON;
979 port.c_iflag |= IXOFF;
981 port.c_iflag &= ~IXOFF;
983 ptr->evtchar = lpdcb->EvtChar;
985 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
986 ptr->commerror = WinError();
994 /*****************************************************************************
995 * GetCommState (USER.202)
997 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
999 struct DosDeviceStruct *ptr;
1000 struct termios port;
1002 TRACE(comm,"cid %d, ptr %p\n", cid, lpdcb);
1003 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1006 if (tcgetattr(ptr->fd, &port) == -1) {
1007 ptr->commerror = WinError();
1013 switch (port.c_cflag & CBAUD) {
1015 switch (port.c_ospeed) {
1018 lpdcb->BaudRate = 110;
1021 lpdcb->BaudRate = 300;
1024 lpdcb->BaudRate = 600;
1027 lpdcb->BaudRate = 1200;
1030 lpdcb->BaudRate = 2400;
1033 lpdcb->BaudRate = 4800;
1036 lpdcb->BaudRate = 9600;
1039 lpdcb->BaudRate = 19200;
1042 lpdcb->BaudRate = 38400;
1046 lpdcb->BaudRate = 57600;
1051 lpdcb->BaudRate = 57601;
1056 switch (port.c_cflag & CSIZE) {
1058 lpdcb->ByteSize = 5;
1061 lpdcb->ByteSize = 6;
1064 lpdcb->ByteSize = 7;
1067 lpdcb->ByteSize = 8;
1071 if(port.c_iflag & INPCK)
1072 lpdcb->fParity = TRUE;
1074 lpdcb->fParity = FALSE;
1075 switch (port.c_cflag & (PARENB | PARODD)) {
1077 lpdcb->Parity = NOPARITY;
1080 lpdcb->Parity = EVENPARITY;
1082 case (PARENB | PARODD):
1083 lpdcb->Parity = ODDPARITY;
1087 if (port.c_cflag & CSTOPB)
1088 lpdcb->StopBits = TWOSTOPBITS;
1090 lpdcb->StopBits = ONESTOPBIT;
1092 lpdcb->RlsTimeout = 50;
1093 lpdcb->CtsTimeout = 50;
1094 lpdcb->DsrTimeout = 50;
1098 lpdcb->fDtrDisable = 0;
1102 if (port.c_cflag & CRTSCTS) {
1103 lpdcb->fDtrflow = 1;
1104 lpdcb->fRtsflow = 1;
1105 lpdcb->fOutxCtsFlow = 1;
1106 lpdcb->fOutxDsrFlow = 1;
1109 lpdcb->fDtrDisable = 1;
1111 if (port.c_iflag & IXON)
1116 if (port.c_iflag & IXOFF)
1125 lpdcb->XoffLim = 10;
1127 lpdcb->EvtChar = ptr->evtchar;
1133 /*****************************************************************************
1134 * TransmitCommChar (USER.206)
1136 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1138 struct DosDeviceStruct *ptr;
1140 TRACE(comm, "cid %d, data %d \n", cid, chTransmit);
1141 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1145 if (ptr->suspended) {
1146 ptr->commerror = IE_HARDWARE;
1150 if (ptr->xmit >= 0) {
1151 /* character already queued */
1152 /* FIXME: which error would Windows return? */
1153 ptr->commerror = CE_TXFULL;
1157 if (ptr->obuf_head == ptr->obuf_tail) {
1158 /* transmit queue empty, try to transmit directly */
1159 if (write(ptr->fd, &chTransmit, 1) == -1) {
1160 /* didn't work, queue it */
1161 ptr->xmit = chTransmit;
1164 /* data in queue, let this char be transmitted next */
1165 ptr->xmit = chTransmit;
1172 /*****************************************************************************
1173 * UngetCommChar (USER.212)
1175 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1177 struct DosDeviceStruct *ptr;
1179 TRACE(comm,"cid %d (char %d)\n", cid, chUnget);
1180 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1184 if (ptr->suspended) {
1185 ptr->commerror = IE_HARDWARE;
1189 if (ptr->unget>=0) {
1190 /* character already queued */
1191 /* FIXME: which error would Windows return? */
1192 ptr->commerror = CE_RXOVER;
1196 ptr->unget = chUnget;
1202 /*****************************************************************************
1203 * ReadComm (USER.204)
1205 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1208 struct DosDeviceStruct *ptr;
1209 LPSTR orgBuf = lpvBuf;
1211 TRACE(comm, "cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1212 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1216 if (ptr->suspended) {
1217 ptr->commerror = IE_HARDWARE;
1221 /* read unget character */
1222 if (ptr->unget>=0) {
1223 *lpvBuf++ = ptr->unget;
1230 /* read from receive buffer */
1231 while (length < cbRead) {
1232 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1233 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1235 if ((cbRead - length) < status)
1236 status = cbRead - length;
1238 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1239 ptr->ibuf_tail += status;
1240 if (ptr->ibuf_tail >= ptr->ibuf_size)
1246 TRACE(comm,"%.*s\n", length, orgBuf);
1251 /*****************************************************************************
1252 * WriteComm (USER.205)
1254 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1257 struct DosDeviceStruct *ptr;
1259 TRACE(comm,"cid %d, ptr %p, length %d\n",
1260 cid, lpvBuf, cbWrite);
1261 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1265 if (ptr->suspended) {
1266 ptr->commerror = IE_HARDWARE;
1270 TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
1273 while (length < cbWrite) {
1274 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1275 /* no data queued, try to write directly */
1276 status = write(ptr->fd, lpvBuf, cbWrite - length);
1283 /* can't write directly, put into transmit buffer */
1284 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1285 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1287 if ((cbWrite - length) < status)
1288 status = cbWrite - length;
1289 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1290 ptr->obuf_head += status;
1291 if (ptr->obuf_head >= ptr->obuf_size)
1301 /***********************************************************************
1302 * EnableCommNotification (USER.246)
1304 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1305 INT16 cbWriteNotify, INT16 cbOutQueue )
1307 struct DosDeviceStruct *ptr;
1309 TRACE(comm, "(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1310 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1311 ptr->commerror = IE_BADID;
1315 ptr->n_read = cbWriteNotify;
1316 ptr->n_write = cbOutQueue;
1321 /**************************************************************************
1322 * BuildCommDCBA (KERNEL32.14)
1324 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1326 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1329 /**************************************************************************
1330 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1332 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1333 LPCOMMTIMEOUTS lptimeouts)
1338 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1340 if (!lstrncmpiA(device,"COM",3)) {
1343 ERR(comm,"BUG! COM0 can't exists!.\n");
1346 if (!ValidCOMPort(port))
1348 if (*(device+4)!=':')
1350 temp=(LPSTR)(device+5);
1354 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1356 lpdcb->DCBlength = sizeof(DCB);
1357 if (strchr(temp,',')) { /* old style */
1360 char last=temp[strlen(temp)-1];
1362 ret=BuildCommDCB16(device,&dcb16);
1365 lpdcb->BaudRate = dcb16.BaudRate;
1366 lpdcb->ByteSize = dcb16.ByteSize;
1367 lpdcb->fBinary = dcb16.fBinary;
1368 lpdcb->Parity = dcb16.Parity;
1369 lpdcb->fParity = dcb16.fParity;
1370 lpdcb->fNull = dcb16.fNull;
1371 lpdcb->StopBits = dcb16.StopBits;
1374 lpdcb->fOutX = TRUE;
1375 lpdcb->fOutxCtsFlow = FALSE;
1376 lpdcb->fOutxDsrFlow = FALSE;
1377 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1378 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1379 } else if (last=='p') {
1380 lpdcb->fInX = FALSE;
1381 lpdcb->fOutX = FALSE;
1382 lpdcb->fOutxCtsFlow = TRUE;
1383 lpdcb->fOutxDsrFlow = TRUE;
1384 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1385 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1387 lpdcb->fInX = FALSE;
1388 lpdcb->fOutX = FALSE;
1389 lpdcb->fOutxCtsFlow = FALSE;
1390 lpdcb->fOutxDsrFlow = FALSE;
1391 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1392 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1394 lpdcb->XonChar = dcb16.XonChar;
1395 lpdcb->XoffChar = dcb16.XoffChar;
1396 lpdcb->ErrorChar= dcb16.PeChar;
1397 lpdcb->fErrorChar= dcb16.fPeChar;
1398 lpdcb->EofChar = dcb16.EofChar;
1399 lpdcb->EvtChar = dcb16.EvtChar;
1400 lpdcb->XonLim = dcb16.XonLim;
1401 lpdcb->XoffLim = dcb16.XoffLim;
1404 ptr=strtok(temp," ");
1409 if (!strncmp("baud=",ptr,5)) {
1410 if (!sscanf(ptr+5,"%ld",&x))
1411 WARN(comm,"Couldn't parse %s\n",ptr);
1412 lpdcb->BaudRate = x;
1415 if (!strncmp("stop=",ptr,5)) {
1416 if (!sscanf(ptr+5,"%ld",&x))
1417 WARN(comm,"Couldn't parse %s\n",ptr);
1418 lpdcb->StopBits = x;
1421 if (!strncmp("data=",ptr,5)) {
1422 if (!sscanf(ptr+5,"%ld",&x))
1423 WARN(comm,"Couldn't parse %s\n",ptr);
1424 lpdcb->ByteSize = x;
1427 if (!strncmp("parity=",ptr,7)) {
1428 lpdcb->fParity = TRUE;
1431 lpdcb->fParity = FALSE;
1432 lpdcb->Parity = NOPARITY;
1435 lpdcb->Parity = EVENPARITY;
1438 lpdcb->Parity = ODDPARITY;
1441 lpdcb->Parity = MARKPARITY;
1447 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
1448 ptr=strtok(NULL," ");
1450 if (lpdcb->BaudRate==110)
1451 lpdcb->StopBits = 2;
1455 /**************************************************************************
1456 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1458 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1459 LPCOMMTIMEOUTS lptimeouts )
1464 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1465 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1466 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1467 HeapFree( GetProcessHeap(), 0, devidA );
1471 /**************************************************************************
1472 * BuildCommDCBW (KERNEL32.17)
1474 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1476 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1479 /*****************************************************************************
1481 * returns a file descriptor for reading from or writing to
1482 * mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
1483 * the handle afterwards!
1485 int COMM_Handle2fd(HANDLE handle, int mode) {
1486 struct get_read_fd_request r_req;
1487 struct get_write_fd_request w_req;
1490 w_req.handle = r_req.handle = handle;
1494 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
1497 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
1500 ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
1503 CLIENT_WaitReply( NULL, &fd, 0 );
1508 /* FIXME: having these global for win32 for now */
1509 int commerror=0,eventmask=0;
1511 /*****************************************************************************
1512 * SetCommBreak (KERNEL32.449)
1514 BOOL WINAPI SetCommBreak(HANDLE handle)
1516 FIXME(comm,"handle %d, stub!\n", handle);
1520 /*****************************************************************************
1521 * ClearCommBreak (KERNEL32.20)
1523 BOOL WINAPI ClearCommBreak(HANDLE handle)
1525 FIXME(comm,"handle %d, stub!\n", handle);
1529 /*****************************************************************************
1530 * EscapeCommFunction (KERNEL32.214)
1532 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1535 struct termios port;
1537 TRACE(comm,"handle %d, function=%d\n", handle, nFunction);
1538 fd = COMM_Handle2fd(handle, GENERIC_WRITE);
1542 if (tcgetattr(fd,&port) == -1) {
1543 commerror=WinError();
1548 switch (nFunction) {
1554 port.c_cflag &= TIOCM_DTR;
1560 port.c_cflag &= TIOCM_RTS;
1566 port.c_cflag |= CRTSCTS;
1570 port.c_cflag |= CRTSCTS;
1575 port.c_iflag |= IXOFF;
1579 port.c_iflag |= IXON;
1582 FIXME(comm,"setbreak, stub\n");
1583 /* ptr->suspended = 1; */
1586 FIXME(comm,"clrbreak, stub\n");
1587 /* ptr->suspended = 0; */
1590 WARN(comm,"(handle=%d,nFunction=%d): Unknown function\n",
1595 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1596 commerror = WinError();
1606 /********************************************************************
1607 * PurgeComm (KERNEL32.557)
1609 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1613 TRACE(comm,"handle %d, flags %lx\n", handle, flags);
1615 fd = COMM_Handle2fd(handle, GENERIC_WRITE);
1620 ** not exactly sure how these are different
1621 ** Perhaps if we had our own internal queues, one flushes them
1622 ** and the other flushes the kernel's buffers.
1624 if(flags&PURGE_TXABORT)
1626 tcflush(fd,TCOFLUSH);
1628 if(flags&PURGE_RXABORT)
1630 tcflush(fd,TCIFLUSH);
1632 if(flags&PURGE_TXCLEAR)
1634 tcflush(fd,TCOFLUSH);
1636 if(flags&PURGE_RXCLEAR)
1638 tcflush(fd,TCIFLUSH);
1645 /*****************************************************************************
1646 * ClearCommError (KERNEL32.21)
1648 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1652 fd=COMM_Handle2fd(handle,GENERIC_READ);
1662 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1663 WARN(comm, "ioctl returned error\n");
1665 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1666 WARN(comm, "ioctl returned error\n");
1671 TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
1680 ** After an asynchronous write opperation, the
1681 ** app will call ClearCommError to see if the
1682 ** results are ready yet. It waits for ERROR_IO_PENDING
1684 commerror = ERROR_IO_PENDING;
1689 /*****************************************************************************
1690 * SetupComm (KERNEL32.676)
1692 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1696 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1697 fd=COMM_Handle2fd(handle,GENERIC_WRITE);
1706 /*****************************************************************************
1707 * GetCommMask (KERNEL32.156)
1709 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1713 TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
1714 if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
1719 *evtmask = eventmask;
1723 /*****************************************************************************
1724 * SetCommMask (KERNEL32.451)
1726 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1730 TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
1731 if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
1735 eventmask = evtmask;
1739 /*****************************************************************************
1740 * SetCommState (KERNEL32.452)
1742 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1744 struct termios port;
1746 struct get_write_fd_request req;
1748 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1750 req.handle = handle;
1751 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
1752 CLIENT_WaitReply( NULL, &fd, 0 );
1757 if (tcgetattr(fd,&port) == -1) {
1758 commerror = WinError();
1762 port.c_cc[VMIN] = 0;
1763 port.c_cc[VTIME] = 1;
1766 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1768 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1770 port.c_iflag |= (IGNBRK);
1772 port.c_oflag &= ~(OPOST);
1774 port.c_cflag &= ~(HUPCL);
1775 port.c_cflag |= CLOCAL | CREAD;
1777 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1778 port.c_lflag |= NOFLSH;
1781 ** MJM - removed default baudrate settings
1782 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1785 port.c_cflag &= ~CBAUD;
1786 switch (lpdcb->BaudRate) {
1789 port.c_cflag |= B110;
1793 port.c_cflag |= B300;
1797 port.c_cflag |= B600;
1801 port.c_cflag |= B1200;
1805 port.c_cflag |= B2400;
1809 port.c_cflag |= B4800;
1813 port.c_cflag |= B9600;
1817 port.c_cflag |= B19200;
1821 port.c_cflag |= B38400;
1824 commerror = IE_BAUDRATE;
1827 #elif !defined(__EMX__)
1828 switch (lpdcb->BaudRate) {
1831 port.c_ospeed = B110;
1835 port.c_ospeed = B300;
1839 port.c_ospeed = B600;
1843 port.c_ospeed = B1200;
1847 port.c_ospeed = B2400;
1851 port.c_ospeed = B4800;
1855 port.c_ospeed = B9600;
1859 port.c_ospeed = B19200;
1863 port.c_ospeed = B38400;
1866 commerror = IE_BAUDRATE;
1869 port.c_ispeed = port.c_ospeed;
1871 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1872 port.c_cflag &= ~CSIZE;
1873 switch (lpdcb->ByteSize) {
1875 port.c_cflag |= CS5;
1878 port.c_cflag |= CS6;
1881 port.c_cflag |= CS7;
1884 port.c_cflag |= CS8;
1887 commerror = IE_BYTESIZE;
1891 TRACE(comm,"fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
1892 port.c_cflag &= ~(PARENB | PARODD);
1894 port.c_iflag |= INPCK;
1896 port.c_iflag &= ~INPCK;
1897 switch (lpdcb->Parity) {
1901 port.c_cflag |= (PARENB | PARODD);
1904 port.c_cflag |= PARENB;
1907 commerror = IE_BYTESIZE;
1912 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1913 switch (lpdcb->StopBits) {
1915 port.c_cflag &= ~CSTOPB;
1918 port.c_cflag |= CSTOPB;
1921 commerror = IE_BYTESIZE;
1925 if ( lpdcb->fOutxCtsFlow ||
1926 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1927 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1929 port.c_cflag |= CRTSCTS;
1930 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1931 port.c_cflag &= ~CRTSCTS;
1935 port.c_iflag |= IXON;
1937 port.c_iflag &= ~IXON;
1939 port.c_iflag |= IXOFF;
1941 port.c_iflag &= ~IXOFF;
1943 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1944 commerror = WinError();
1953 /*****************************************************************************
1954 * GetCommState (KERNEL32.159)
1956 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
1958 struct termios port;
1960 struct get_read_fd_request req;
1962 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1963 req.handle = handle;
1964 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
1965 CLIENT_WaitReply( NULL, &fd, 0 );
1970 if (tcgetattr(fd, &port) == -1) {
1971 TRACE(comm,"tcgetattr(%d, ...) returned -1",fd);
1972 commerror = WinError();
1977 switch (port.c_cflag & CBAUD) {
1979 switch (port.c_ospeed) {
1982 lpdcb->BaudRate = 110;
1985 lpdcb->BaudRate = 300;
1988 lpdcb->BaudRate = 600;
1991 lpdcb->BaudRate = 1200;
1994 lpdcb->BaudRate = 2400;
1997 lpdcb->BaudRate = 4800;
2000 lpdcb->BaudRate = 9600;
2003 lpdcb->BaudRate = 19200;
2006 lpdcb->BaudRate = 38400;
2010 switch (port.c_cflag & CSIZE) {
2012 lpdcb->ByteSize = 5;
2015 lpdcb->ByteSize = 6;
2018 lpdcb->ByteSize = 7;
2021 lpdcb->ByteSize = 8;
2025 if(port.c_iflag & INPCK)
2026 lpdcb->fParity = TRUE;
2028 lpdcb->fParity = FALSE;
2029 switch (port.c_cflag & (PARENB | PARODD)) {
2031 lpdcb->Parity = NOPARITY;
2034 lpdcb->Parity = EVENPARITY;
2036 case (PARENB | PARODD):
2037 lpdcb->Parity = ODDPARITY;
2041 if (port.c_cflag & CSTOPB)
2042 lpdcb->StopBits = TWOSTOPBITS;
2044 lpdcb->StopBits = ONESTOPBIT;
2051 if (port.c_cflag & CRTSCTS) {
2052 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2053 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2054 lpdcb->fOutxCtsFlow = 1;
2055 lpdcb->fOutxDsrFlow = 1;
2059 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2060 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2062 if (port.c_iflag & IXON)
2067 if (port.c_iflag & IXOFF)
2076 lpdcb->XoffLim = 10;
2085 /*****************************************************************************
2086 * TransmitCommChar (KERNEL32.535)
2088 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2090 struct DosDeviceStruct *ptr;
2092 FIXME(comm,"(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2093 if ((ptr = GetDeviceStruct(cid)) == NULL) {
2097 if (ptr->suspended) {
2098 ptr->commerror = IE_HARDWARE;
2101 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2102 ptr->commerror = WinError();
2110 /*****************************************************************************
2111 * GetCommTimeouts (KERNEL32.160)
2113 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
2115 FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
2119 /*****************************************************************************
2120 * SetCommTimeouts (KERNEL32.453)
2122 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2123 FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
2127 /***********************************************************************
2128 * GetCommModemStatus (KERNEL32.285)
2130 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2132 FIXME(comm, "(%d %p)\n",hFile,lpModemStat );
2135 /***********************************************************************
2136 * WaitCommEvent (KERNEL32.719)
2138 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2140 FIXME(comm, "(%d %p %p )\n",hFile, eventmask,overlapped);
2144 /***********************************************************************
2145 * GetCommProperties (KERNEL32.???)
2147 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2149 FIXME(comm, "(%d %p )\n",hFile,dcb);
2153 /***********************************************************************
2154 * SetCommProperties (KERNEL32.???)
2156 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2158 FIXME(comm, "(%d %p )\n",hFile,dcb);