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>
70 #include "debugtools.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("Can't use `%s' as %s !\n", temp, option);
114 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
115 WARN("Can't malloc for device info!\n");
118 strcpy(COM[x].devicename, temp);
120 TRACE("%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("Can't use `%s' as %s !\n", temp, option);
136 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
137 WARN("Can't malloc for device info!\n");
140 strcpy(LPT[x].devicename, temp);
142 TRACE("%s = %s\n", option, LPT[x].devicename);
149 static struct DosDeviceStruct *GetDeviceStruct(int fd)
151 if ((fd&0x7F)<=MAX_PORTS) {
152 if (!(fd&FLAG_LPT)) {
164 static int GetCommPort_fd(int fd)
168 for (x=0; x<MAX_PORTS; x++) {
176 static int ValidCOMPort(int x)
178 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
181 static int ValidLPTPort(int x)
183 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
186 static int WinError(void)
188 TRACE("errno = %d\n", errno);
195 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
197 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
198 + ptr->ibuf_head - ptr->ibuf_tail;
201 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
203 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
204 + ptr->obuf_head - ptr->obuf_tail;
207 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
209 unsigned int mstat, okay;
210 okay = ioctl(fd, TIOCMGET, &mstat);
211 if (okay) return okay;
212 if (andy) mstat &= andy;
214 return ioctl(fd, TIOCMSET, &mstat);
217 static void CALLBACK comm_notification( ULONG_PTR private )
219 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
220 int prev, bleft, len;
222 int cid = GetCommPort_fd(ptr->fd);
224 TRACE("async notification\n");
225 /* read data from comm port */
226 prev = comm_inbuf(ptr);
228 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
230 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
233 ptr->commerror = CE_RXOVER;
235 /* check for events */
236 if ((ptr->eventmask & EV_RXFLAG) &&
237 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
238 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
241 if (ptr->eventmask & EV_RXCHAR) {
242 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
245 /* advance buffer position */
246 ptr->ibuf_head += len;
247 if (ptr->ibuf_head >= ptr->ibuf_size)
252 /* check for notification */
253 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
254 (comm_inbuf(ptr)>=ptr->n_read)) {
255 /* passed the receive notification threshold */
259 /* write any TransmitCommChar character */
261 len = write(ptr->fd, &(ptr->xmit), 1);
262 if (len > 0) ptr->xmit = -1;
264 /* write from output queue */
265 prev = comm_outbuf(ptr);
267 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
269 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
271 ptr->obuf_tail += len;
272 if (ptr->obuf_tail >= ptr->obuf_size)
275 if ((ptr->obuf_tail == ptr->obuf_head) && (ptr->eventmask & EV_TXEMPTY)) {
276 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
281 /* check for notification */
282 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
283 (comm_outbuf(ptr)<ptr->n_write)) {
284 /* passed the transmit notification threshold */
288 /* send notifications, if any */
289 if (ptr->wnd && mask) {
290 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
291 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
295 /**************************************************************************
296 * BuildCommDCB (USER.213)
298 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
300 /* "COM1:9600,n,8,1" */
303 char *ptr, temp[256];
305 TRACE("(%s), ptr %p\n", device, lpdcb);
307 if (!lstrncmpiA(device,"COM",3)) {
308 port = device[3] - '0';
312 ERR("BUG ! COM0 can't exist!.\n");
316 if (!ValidCOMPort(port)) {
320 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
327 if (*(device+4) != ':')
330 strcpy(temp,device+5);
331 ptr = strtok(temp, ", ");
333 if (COM[port].baudrate > 0)
334 lpdcb->BaudRate = COM[port].baudrate;
336 lpdcb->BaudRate = atoi(ptr);
337 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
339 ptr = strtok(NULL, ", ");
341 *ptr = toupper(*ptr);
343 TRACE("parity (%c)\n", *ptr);
344 lpdcb->fParity = TRUE;
347 lpdcb->Parity = NOPARITY;
348 lpdcb->fParity = FALSE;
351 lpdcb->Parity = EVENPARITY;
354 lpdcb->Parity = MARKPARITY;
357 lpdcb->Parity = ODDPARITY;
360 WARN("Unknown parity `%c'!\n", *ptr);
364 ptr = strtok(NULL, ", ");
365 TRACE("charsize (%c)\n", *ptr);
366 lpdcb->ByteSize = *ptr - '0';
368 ptr = strtok(NULL, ", ");
369 TRACE("stopbits (%c)\n", *ptr);
372 lpdcb->StopBits = ONESTOPBIT;
375 lpdcb->StopBits = TWOSTOPBITS;
378 WARN("Unknown # of stopbits `%c'!\n", *ptr);
386 /*****************************************************************************
387 * OpenComm (USER.200)
389 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
393 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
395 if (strlen(device) < 4)
398 port = device[3] - '0';
401 ERR("BUG ! COM0 or LPT0 don't exist !\n");
403 if (!lstrncmpiA(device,"COM",3)) {
405 TRACE("%s = %s\n", device, COM[port].devicename);
407 if (!ValidCOMPort(port))
413 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
415 ERR("error=%d\n", errno);
418 unknown[port] = SEGPTR_ALLOC(40);
419 bzero(unknown[port],40);
421 COM[port].commerror = 0;
422 COM[port].eventmask = 0;
423 COM[port].evtchar = 0; /* FIXME: default? */
424 /* save terminal state */
425 tcgetattr(fd,&m_stat[port]);
426 /* set default parameters */
427 if(COM[port].baudrate>-1){
429 GetCommState16(port, &dcb);
430 dcb.BaudRate=COM[port].baudrate;
432 * databits, parity, stopbits
434 SetCommState16( &dcb);
436 /* init priority characters */
437 COM[port].unget = -1;
439 /* allocate buffers */
440 COM[port].ibuf_size = cbInQueue;
441 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
442 COM[port].obuf_size = cbOutQueue;
443 COM[port].obuf_head = COM[port].obuf_tail = 0;
445 COM[port].inbuf = malloc(cbInQueue);
446 if (COM[port].inbuf) {
447 COM[port].outbuf = malloc(cbOutQueue);
448 if (!COM[port].outbuf)
449 free(COM[port].inbuf);
450 } else COM[port].outbuf = NULL;
451 if (!COM[port].outbuf) {
452 /* not enough memory */
453 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
455 ERR("out of memory");
459 COM[port].service = SERVICE_AddObject( FILE_DupUnixHandle( COM[port].fd,
460 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE ),
462 (ULONG_PTR)&COM[port] );
463 /* bootstrap notifications, just in case */
464 comm_notification( (ULONG_PTR)&COM[port] );
469 if (!lstrncmpiA(device,"LPT",3)) {
471 if (!ValidLPTPort(port))
477 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
482 LPT[port].commerror = 0;
483 LPT[port].eventmask = 0;
484 return port|FLAG_LPT;
490 /*****************************************************************************
491 * CloseComm (USER.207)
493 INT16 WINAPI CloseComm16(INT16 cid)
495 struct DosDeviceStruct *ptr;
497 TRACE("cid=%d\n", cid);
498 if ((ptr = GetDeviceStruct(cid)) == NULL) {
501 if (!(cid&FLAG_LPT)) {
503 SEGPTR_FREE(unknown[cid]); /* [LW] */
505 SERVICE_Delete( COM[cid].service );
510 /* reset modem lines */
511 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
514 if (close(ptr->fd) == -1) {
515 ptr->commerror = WinError();
516 /* FIXME: should we clear ptr->fd here? */
525 /*****************************************************************************
526 * SetCommBreak (USER.210)
528 INT16 WINAPI SetCommBreak16(INT16 cid)
530 struct DosDeviceStruct *ptr;
532 TRACE("cid=%d\n", cid);
533 if ((ptr = GetDeviceStruct(cid)) == NULL) {
542 /*****************************************************************************
543 * ClearCommBreak (USER.211)
545 INT16 WINAPI ClearCommBreak16(INT16 cid)
547 struct DosDeviceStruct *ptr;
549 TRACE("cid=%d\n", cid);
550 if ((ptr = GetDeviceStruct(cid)) == NULL) {
559 /*****************************************************************************
560 * EscapeCommFunction (USER.214)
562 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
565 struct DosDeviceStruct *ptr;
568 TRACE("cid=%d, function=%d\n", cid, nFunction);
569 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
570 if ((ptr = GetDeviceStruct(cid)) == NULL) {
571 TRACE("GetDeviceStruct failed\n");
574 if (tcgetattr(ptr->fd,&port) == -1) {
575 TRACE("tcgetattr failed\n");
576 ptr->commerror=WinError();
587 TRACE("GETMAXCOM\n");
588 for (max = MAX_PORTS;!COM[max].devicename;max--)
594 TRACE("GETMAXLPT\n");
595 for (max = MAX_PORTS;!LPT[max].devicename;max--)
597 return FLAG_LPT + max;
601 TRACE("GETBASEIRQ\n");
602 /* FIXME: use tables */
603 /* just fake something for now */
604 if (cid & FLAG_LPT) {
605 /* LPT1: irq 7, LPT2: irq 5 */
606 return (cid & 0x7f) ? 5 : 7;
608 /* COM1: irq 4, COM2: irq 3,
609 COM3: irq 4, COM4: irq 3 */
610 return 4 - (cid & 1);
617 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
622 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
628 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
634 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
639 port.c_iflag |= IXOFF;
644 port.c_iflag |= IXON;
648 WARN("(cid=%d,nFunction=%d): Unknown function\n",
653 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
654 ptr->commerror = WinError();
662 /*****************************************************************************
663 * FlushComm (USER.215)
665 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
668 struct DosDeviceStruct *ptr;
670 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
671 if ((ptr = GetDeviceStruct(cid)) == NULL) {
677 ptr->obuf_tail = ptr->obuf_head;
681 ptr->ibuf_head = ptr->ibuf_tail;
684 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
688 if (tcflush(ptr->fd, queue)) {
689 ptr->commerror = WinError();
697 /********************************************************************
698 * GetCommError (USER.203)
700 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
703 struct DosDeviceStruct *ptr;
707 if ((ptr = GetDeviceStruct(cid)) == NULL) {
711 WARN(" cid %d not comm port\n",cid);
714 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
715 ioctl(ptr->fd,TIOCMGET,&mstat);
716 if( mstat&TIOCM_CAR )
724 lpStat->cbOutQue = comm_outbuf(ptr);
725 lpStat->cbInQue = comm_inbuf(ptr);
727 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
728 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
729 lpStat->cbOutQue, *stol);
732 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
733 cid, ptr->commerror, *stol);
735 /* Return any errors and clear it */
736 temperror = ptr->commerror;
741 /*****************************************************************************
742 * SetCommEventMask (USER.208)
744 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
746 struct DosDeviceStruct *ptr;
751 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
752 if ((ptr = GetDeviceStruct(cid)) == NULL)
755 ptr->eventmask = fuEvtMask;
757 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
758 WARN(" cid %d not comm port\n",cid);
761 /* it's a COM port ? -> modify flags */
762 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
763 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
764 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
765 if ((mstat&TIOCM_CAR))
770 TRACE(" modem dcd construct %x\n",*stol);
771 return SEGPTR_GET(unknown[cid]);
774 /*****************************************************************************
775 * GetCommEventMask (USER.209)
777 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
779 struct DosDeviceStruct *ptr;
782 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
783 if ((ptr = GetDeviceStruct(cid)) == NULL)
786 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
787 WARN(" cid %d not comm port\n",cid);
791 events = *(WORD*)(unknown[cid]) & fnEvtClear;
792 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
796 /*****************************************************************************
797 * SetCommState16 (USER.201)
799 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
802 struct DosDeviceStruct *ptr;
804 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
805 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
808 if (tcgetattr(ptr->fd, &port) == -1) {
809 ptr->commerror = WinError();
814 port.c_cc[VTIME] = 1;
817 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
819 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
821 port.c_iflag |= (IGNBRK);
823 port.c_oflag &= ~(OPOST);
825 port.c_cflag &= ~(HUPCL);
826 port.c_cflag |= CLOCAL | CREAD;
828 port.c_lflag &= ~(ICANON|ECHO|ISIG);
829 port.c_lflag |= NOFLSH;
831 TRACE("baudrate %d\n",lpdcb->BaudRate);
833 port.c_cflag &= ~CBAUD;
834 switch (lpdcb->BaudRate) {
837 port.c_cflag |= B110;
841 port.c_cflag |= B300;
845 port.c_cflag |= B600;
849 port.c_cflag |= B1200;
853 port.c_cflag |= B2400;
857 port.c_cflag |= B4800;
861 port.c_cflag |= B9600;
865 port.c_cflag |= B19200;
869 port.c_cflag |= B38400;
873 port.c_cflag |= B57600;
878 port.c_cflag |= B115200;
882 ptr->commerror = IE_BAUDRATE;
885 #elif !defined(__EMX__)
886 switch (lpdcb->BaudRate) {
889 port.c_ospeed = B110;
893 port.c_ospeed = B300;
897 port.c_ospeed = B600;
901 port.c_ospeed = B1200;
905 port.c_ospeed = B2400;
909 port.c_ospeed = B4800;
913 port.c_ospeed = B9600;
917 port.c_ospeed = B19200;
921 port.c_ospeed = B38400;
924 ptr->commerror = IE_BAUDRATE;
927 port.c_ispeed = port.c_ospeed;
929 TRACE("bytesize %d\n",lpdcb->ByteSize);
930 port.c_cflag &= ~CSIZE;
931 switch (lpdcb->ByteSize) {
945 ptr->commerror = IE_BYTESIZE;
949 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
950 port.c_cflag &= ~(PARENB | PARODD);
952 port.c_iflag |= INPCK;
954 port.c_iflag &= ~INPCK;
955 switch (lpdcb->Parity) {
959 port.c_cflag |= (PARENB | PARODD);
962 port.c_cflag |= PARENB;
965 ptr->commerror = IE_BYTESIZE;
970 TRACE("stopbits %d\n",lpdcb->StopBits);
972 switch (lpdcb->StopBits) {
974 port.c_cflag &= ~CSTOPB;
977 port.c_cflag |= CSTOPB;
980 ptr->commerror = IE_BYTESIZE;
985 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
986 port.c_cflag |= CRTSCTS;
988 if (lpdcb->fDtrDisable)
989 port.c_cflag &= ~CRTSCTS;
992 port.c_iflag |= IXON;
994 port.c_iflag &= ~IXON;
996 port.c_iflag |= IXOFF;
998 port.c_iflag &= ~IXOFF;
1000 ptr->evtchar = lpdcb->EvtChar;
1002 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1003 ptr->commerror = WinError();
1011 /*****************************************************************************
1012 * GetCommState (USER.202)
1014 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1016 struct DosDeviceStruct *ptr;
1017 struct termios port;
1019 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1020 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1023 if (tcgetattr(ptr->fd, &port) == -1) {
1024 ptr->commerror = WinError();
1030 switch (port.c_cflag & CBAUD) {
1032 switch (port.c_ospeed) {
1035 lpdcb->BaudRate = 110;
1038 lpdcb->BaudRate = 300;
1041 lpdcb->BaudRate = 600;
1044 lpdcb->BaudRate = 1200;
1047 lpdcb->BaudRate = 2400;
1050 lpdcb->BaudRate = 4800;
1053 lpdcb->BaudRate = 9600;
1056 lpdcb->BaudRate = 19200;
1059 lpdcb->BaudRate = 38400;
1063 lpdcb->BaudRate = 57600;
1068 lpdcb->BaudRate = 57601;
1073 switch (port.c_cflag & CSIZE) {
1075 lpdcb->ByteSize = 5;
1078 lpdcb->ByteSize = 6;
1081 lpdcb->ByteSize = 7;
1084 lpdcb->ByteSize = 8;
1088 if(port.c_iflag & INPCK)
1089 lpdcb->fParity = TRUE;
1091 lpdcb->fParity = FALSE;
1092 switch (port.c_cflag & (PARENB | PARODD)) {
1094 lpdcb->Parity = NOPARITY;
1097 lpdcb->Parity = EVENPARITY;
1099 case (PARENB | PARODD):
1100 lpdcb->Parity = ODDPARITY;
1104 if (port.c_cflag & CSTOPB)
1105 lpdcb->StopBits = TWOSTOPBITS;
1107 lpdcb->StopBits = ONESTOPBIT;
1109 lpdcb->RlsTimeout = 50;
1110 lpdcb->CtsTimeout = 50;
1111 lpdcb->DsrTimeout = 50;
1115 lpdcb->fDtrDisable = 0;
1119 if (port.c_cflag & CRTSCTS) {
1120 lpdcb->fDtrflow = 1;
1121 lpdcb->fRtsflow = 1;
1122 lpdcb->fOutxCtsFlow = 1;
1123 lpdcb->fOutxDsrFlow = 1;
1126 lpdcb->fDtrDisable = 1;
1128 if (port.c_iflag & IXON)
1133 if (port.c_iflag & IXOFF)
1142 lpdcb->XoffLim = 10;
1144 lpdcb->EvtChar = ptr->evtchar;
1150 /*****************************************************************************
1151 * TransmitCommChar (USER.206)
1153 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1155 struct DosDeviceStruct *ptr;
1157 TRACE("cid %d, data %d \n", cid, chTransmit);
1158 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1162 if (ptr->suspended) {
1163 ptr->commerror = IE_HARDWARE;
1167 if (ptr->xmit >= 0) {
1168 /* character already queued */
1169 /* FIXME: which error would Windows return? */
1170 ptr->commerror = CE_TXFULL;
1174 if (ptr->obuf_head == ptr->obuf_tail) {
1175 /* transmit queue empty, try to transmit directly */
1176 if (write(ptr->fd, &chTransmit, 1) == -1) {
1177 /* didn't work, queue it */
1178 ptr->xmit = chTransmit;
1181 /* data in queue, let this char be transmitted next */
1182 ptr->xmit = chTransmit;
1189 /*****************************************************************************
1190 * UngetCommChar (USER.212)
1192 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1194 struct DosDeviceStruct *ptr;
1196 TRACE("cid %d (char %d)\n", cid, chUnget);
1197 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1201 if (ptr->suspended) {
1202 ptr->commerror = IE_HARDWARE;
1206 if (ptr->unget>=0) {
1207 /* character already queued */
1208 /* FIXME: which error would Windows return? */
1209 ptr->commerror = CE_RXOVER;
1213 ptr->unget = chUnget;
1219 /*****************************************************************************
1220 * ReadComm (USER.204)
1222 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1225 struct DosDeviceStruct *ptr;
1226 LPSTR orgBuf = lpvBuf;
1228 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1229 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1233 if (ptr->suspended) {
1234 ptr->commerror = IE_HARDWARE;
1238 /* read unget character */
1239 if (ptr->unget>=0) {
1240 *lpvBuf++ = ptr->unget;
1247 /* read from receive buffer */
1248 while (length < cbRead) {
1249 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1250 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1252 if ((cbRead - length) < status)
1253 status = cbRead - length;
1255 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1256 ptr->ibuf_tail += status;
1257 if (ptr->ibuf_tail >= ptr->ibuf_size)
1263 TRACE("%.*s\n", length, orgBuf);
1268 /*****************************************************************************
1269 * WriteComm (USER.205)
1271 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1274 struct DosDeviceStruct *ptr;
1276 TRACE("cid %d, ptr %p, length %d\n",
1277 cid, lpvBuf, cbWrite);
1278 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1282 if (ptr->suspended) {
1283 ptr->commerror = IE_HARDWARE;
1287 TRACE("%.*s\n", cbWrite, lpvBuf );
1290 while (length < cbWrite) {
1291 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1292 /* no data queued, try to write directly */
1293 status = write(ptr->fd, lpvBuf, cbWrite - length);
1300 /* can't write directly, put into transmit buffer */
1301 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1302 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1304 if ((cbWrite - length) < status)
1305 status = cbWrite - length;
1306 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1307 ptr->obuf_head += status;
1308 if (ptr->obuf_head >= ptr->obuf_size)
1318 /***********************************************************************
1319 * EnableCommNotification (USER.246)
1321 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1322 INT16 cbWriteNotify, INT16 cbOutQueue )
1324 struct DosDeviceStruct *ptr;
1326 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1327 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1328 ptr->commerror = IE_BADID;
1332 ptr->n_read = cbWriteNotify;
1333 ptr->n_write = cbOutQueue;
1338 /**************************************************************************
1339 * BuildCommDCBA (KERNEL32.14)
1341 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1343 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1346 /**************************************************************************
1347 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1349 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1350 LPCOMMTIMEOUTS lptimeouts)
1355 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1357 if (!lstrncmpiA(device,"COM",3)) {
1360 ERR("BUG! COM0 can't exists!.\n");
1363 if (!ValidCOMPort(port))
1365 if (*(device+4)!=':')
1367 temp=(LPSTR)(device+5);
1371 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1373 lpdcb->DCBlength = sizeof(DCB);
1374 if (strchr(temp,',')) { /* old style */
1377 char last=temp[strlen(temp)-1];
1379 ret=BuildCommDCB16(device,&dcb16);
1382 lpdcb->BaudRate = dcb16.BaudRate;
1383 lpdcb->ByteSize = dcb16.ByteSize;
1384 lpdcb->fBinary = dcb16.fBinary;
1385 lpdcb->Parity = dcb16.Parity;
1386 lpdcb->fParity = dcb16.fParity;
1387 lpdcb->fNull = dcb16.fNull;
1388 lpdcb->StopBits = dcb16.StopBits;
1391 lpdcb->fOutX = TRUE;
1392 lpdcb->fOutxCtsFlow = FALSE;
1393 lpdcb->fOutxDsrFlow = FALSE;
1394 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1395 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1396 } else if (last=='p') {
1397 lpdcb->fInX = FALSE;
1398 lpdcb->fOutX = FALSE;
1399 lpdcb->fOutxCtsFlow = TRUE;
1400 lpdcb->fOutxDsrFlow = TRUE;
1401 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1402 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1404 lpdcb->fInX = FALSE;
1405 lpdcb->fOutX = FALSE;
1406 lpdcb->fOutxCtsFlow = FALSE;
1407 lpdcb->fOutxDsrFlow = FALSE;
1408 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1409 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1411 lpdcb->XonChar = dcb16.XonChar;
1412 lpdcb->XoffChar = dcb16.XoffChar;
1413 lpdcb->ErrorChar= dcb16.PeChar;
1414 lpdcb->fErrorChar= dcb16.fPeChar;
1415 lpdcb->EofChar = dcb16.EofChar;
1416 lpdcb->EvtChar = dcb16.EvtChar;
1417 lpdcb->XonLim = dcb16.XonLim;
1418 lpdcb->XoffLim = dcb16.XoffLim;
1421 ptr=strtok(temp," ");
1426 if (!strncmp("baud=",ptr,5)) {
1427 if (!sscanf(ptr+5,"%ld",&x))
1428 WARN("Couldn't parse %s\n",ptr);
1429 lpdcb->BaudRate = x;
1432 if (!strncmp("stop=",ptr,5)) {
1433 if (!sscanf(ptr+5,"%ld",&x))
1434 WARN("Couldn't parse %s\n",ptr);
1435 lpdcb->StopBits = x;
1438 if (!strncmp("data=",ptr,5)) {
1439 if (!sscanf(ptr+5,"%ld",&x))
1440 WARN("Couldn't parse %s\n",ptr);
1441 lpdcb->ByteSize = x;
1444 if (!strncmp("parity=",ptr,7)) {
1445 lpdcb->fParity = TRUE;
1448 lpdcb->fParity = FALSE;
1449 lpdcb->Parity = NOPARITY;
1452 lpdcb->Parity = EVENPARITY;
1455 lpdcb->Parity = ODDPARITY;
1458 lpdcb->Parity = MARKPARITY;
1464 ERR("Unhandled specifier '%s', please report.\n",ptr);
1465 ptr=strtok(NULL," ");
1467 if (lpdcb->BaudRate==110)
1468 lpdcb->StopBits = 2;
1472 /**************************************************************************
1473 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1475 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1476 LPCOMMTIMEOUTS lptimeouts )
1481 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1482 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1483 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1484 HeapFree( GetProcessHeap(), 0, devidA );
1488 /**************************************************************************
1489 * BuildCommDCBW (KERNEL32.17)
1491 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1493 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1496 /*****************************************************************************
1498 * Returns a file descriptor for reading.
1499 * Make sure to close the handle afterwards!
1501 static int COMM_GetReadFd( HANDLE handle)
1504 struct get_read_fd_request *req = get_req_buffer();
1505 req->handle = handle;
1506 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1510 /*****************************************************************************
1512 * Returns a file descriptor for writing.
1513 * Make sure to close the handle afterwards!
1515 static int COMM_GetWriteFd( HANDLE handle)
1518 struct get_write_fd_request *req = get_req_buffer();
1519 req->handle = handle;
1520 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1524 /* FIXME: having these global for win32 for now */
1525 int commerror=0,eventmask=0;
1527 /*****************************************************************************
1528 * SetCommBreak (KERNEL32.449)
1530 BOOL WINAPI SetCommBreak(HANDLE handle)
1532 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1535 fd = COMM_GetWriteFd(handle);
1537 TRACE("COMM_GetWriteFd failed\n");
1540 result = ioctl(fd,TIOCSBRK,0);
1544 TRACE("ioctl failed\n");
1545 SetLastError(ERROR_NOT_SUPPORTED);
1550 FIXME("ioctl not available\n");
1551 SetLastError(ERROR_NOT_SUPPORTED);
1556 /*****************************************************************************
1557 * ClearCommBreak (KERNEL32.20)
1559 BOOL WINAPI ClearCommBreak(HANDLE handle)
1561 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1564 fd = COMM_GetWriteFd(handle);
1566 TRACE("COMM_GetWriteFd failed\n");
1569 result = ioctl(fd,TIOCCBRK,0);
1573 TRACE("ioctl failed\n");
1574 SetLastError(ERROR_NOT_SUPPORTED);
1579 FIXME("ioctl not available\n");
1580 SetLastError(ERROR_NOT_SUPPORTED);
1585 /*****************************************************************************
1586 * EscapeCommFunction (KERNEL32.214)
1588 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1590 int fd,direct=FALSE,result=FALSE;
1591 struct termios port;
1593 TRACE("handle %d, function=%d\n", handle, nFunction);
1594 fd = COMM_GetWriteFd(handle);
1598 if (tcgetattr(fd,&port) == -1) {
1599 commerror=WinError();
1604 switch (nFunction) {
1613 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1621 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1629 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1637 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1643 port.c_iflag |= IXOFF;
1648 port.c_iflag |= IXON;
1651 TRACE("setbreak\n");
1654 result = ioctl(fd,TIOCSBRK,0);
1658 TRACE("clrbreak\n");
1661 result = ioctl(fd,TIOCCBRK,0);
1665 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1671 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1672 commerror = WinError();
1682 commerror=WinError();
1691 /********************************************************************
1692 * PurgeComm (KERNEL32.557)
1694 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1698 TRACE("handle %d, flags %lx\n", handle, flags);
1700 fd = COMM_GetWriteFd(handle);
1705 ** not exactly sure how these are different
1706 ** Perhaps if we had our own internal queues, one flushes them
1707 ** and the other flushes the kernel's buffers.
1709 if(flags&PURGE_TXABORT)
1711 tcflush(fd,TCOFLUSH);
1713 if(flags&PURGE_RXABORT)
1715 tcflush(fd,TCIFLUSH);
1717 if(flags&PURGE_TXCLEAR)
1719 tcflush(fd,TCOFLUSH);
1721 if(flags&PURGE_RXCLEAR)
1723 tcflush(fd,TCIFLUSH);
1730 /*****************************************************************************
1731 * ClearCommError (KERNEL32.21)
1733 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1737 fd=COMM_GetReadFd(handle);
1747 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1748 WARN("ioctl returned error\n");
1750 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1751 WARN("ioctl returned error\n");
1753 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1754 handle, lpStat->cbInQue, lpStat->cbOutQue);
1763 ** After an asynchronous write opperation, the
1764 ** app will call ClearCommError to see if the
1765 ** results are ready yet. It waits for ERROR_IO_PENDING
1767 commerror = ERROR_IO_PENDING;
1772 /*****************************************************************************
1773 * SetupComm (KERNEL32.676)
1775 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1779 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1780 fd=COMM_GetWriteFd(handle);
1789 /*****************************************************************************
1790 * GetCommMask (KERNEL32.156)
1792 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1796 TRACE("handle %d, mask %p\n", handle, evtmask);
1797 if(0>(fd=COMM_GetReadFd(handle)))
1802 *evtmask = eventmask;
1803 TRACE("%s%s%s%s%s%s%s%s%s\n",
1804 (eventmask&EV_BREAK)?"EV_BREAK":"",
1805 (eventmask&EV_CTS)?"EV_CTS":"",
1806 (eventmask&EV_DSR)?"EV_DSR":"",
1807 (eventmask&EV_ERR)?"EV_ERR":"",
1808 (eventmask&EV_RING)?"EV_RING":"",
1809 (eventmask&EV_RLSD)?"EV_RLSD":"",
1810 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1811 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1812 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1817 /*****************************************************************************
1818 * SetCommMask (KERNEL32.451)
1820 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1824 TRACE("handle %d, mask %lx\n", handle, evtmask);
1825 TRACE("%s%s%s%s%s%s%s%s%s\n",
1826 (evtmask&EV_BREAK)?"EV_BREAK":"",
1827 (evtmask&EV_CTS)?"EV_CTS":"",
1828 (evtmask&EV_DSR)?"EV_DSR":"",
1829 (evtmask&EV_ERR)?"EV_ERR":"",
1830 (evtmask&EV_RING)?"EV_RING":"",
1831 (evtmask&EV_RLSD)?"EV_RLSD":"",
1832 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1833 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1834 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1836 if(0>(fd=COMM_GetWriteFd(handle))) {
1840 eventmask = evtmask;
1844 /*****************************************************************************
1845 * SetCommState (KERNEL32.452)
1847 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1849 struct termios port;
1852 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1853 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1854 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1855 (lpdcb->StopBits == ONESTOPBIT)?1:
1856 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1857 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1858 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1860 if ((fd = COMM_GetWriteFd(handle)) < 0) return FALSE;
1862 if ((tcgetattr(fd,&port)) == -1) {
1863 int save_error = errno;
1864 commerror = WinError();
1866 #ifdef HAVE_STRERROR
1867 ERR("tcgetattr error '%s'\n", strerror(save_error));
1869 ERR("tcgetattr error %d\n", save_error);
1874 port.c_cc[VMIN] = 0;
1875 port.c_cc[VTIME] = 1;
1878 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1880 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1882 port.c_iflag |= (IGNBRK);
1884 port.c_oflag &= ~(OPOST);
1886 port.c_cflag &= ~(HUPCL);
1887 port.c_cflag |= CLOCAL | CREAD;
1889 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1890 port.c_lflag |= NOFLSH;
1893 ** MJM - removed default baudrate settings
1894 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1897 port.c_cflag &= ~CBAUD;
1898 switch (lpdcb->BaudRate) {
1901 port.c_cflag |= B110;
1905 port.c_cflag |= B300;
1909 port.c_cflag |= B600;
1913 port.c_cflag |= B1200;
1917 port.c_cflag |= B2400;
1921 port.c_cflag |= B4800;
1925 port.c_cflag |= B9600;
1929 port.c_cflag |= B19200;
1933 port.c_cflag |= B38400;
1937 port.c_cflag |= B57600;
1942 port.c_cflag |= B115200;
1947 port.c_cflag |= B230400;
1952 port.c_cflag |= B460800;
1956 commerror = IE_BAUDRATE;
1958 ERR("baudrate %ld\n",lpdcb->BaudRate);
1961 #elif !defined(__EMX__)
1962 switch (lpdcb->BaudRate) {
1965 port.c_ospeed = B110;
1969 port.c_ospeed = B300;
1973 port.c_ospeed = B600;
1977 port.c_ospeed = B1200;
1981 port.c_ospeed = B2400;
1985 port.c_ospeed = B4800;
1989 port.c_ospeed = B9600;
1993 port.c_ospeed = B19200;
1997 port.c_ospeed = B38400;
2000 commerror = IE_BAUDRATE;
2002 ERR("baudrate %d \n",lpdcb->BaudRate);
2005 port.c_ispeed = port.c_ospeed;
2007 port.c_cflag &= ~CSIZE;
2008 switch (lpdcb->ByteSize) {
2010 port.c_cflag |= CS5;
2013 port.c_cflag |= CS6;
2016 port.c_cflag |= CS7;
2019 port.c_cflag |= CS8;
2022 commerror = IE_BYTESIZE;
2028 port.c_cflag &= ~(PARENB | PARODD);
2030 port.c_iflag |= INPCK;
2032 port.c_iflag &= ~INPCK;
2033 switch (lpdcb->Parity) {
2037 port.c_cflag |= (PARENB | PARODD);
2040 port.c_cflag |= PARENB;
2043 commerror = IE_BYTESIZE;
2050 switch (lpdcb->StopBits) {
2052 port.c_cflag &= ~CSTOPB;
2055 port.c_cflag |= CSTOPB;
2058 commerror = IE_BYTESIZE;
2064 if ( lpdcb->fOutxCtsFlow ||
2065 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2066 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2069 port.c_cflag |= CRTSCTS;
2073 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2075 port.c_cflag &= ~CRTSCTS;
2076 TRACE("~CRTSCTS\n");
2081 port.c_iflag |= IXON;
2083 port.c_iflag &= ~IXON;
2085 port.c_iflag |= IXOFF;
2087 port.c_iflag &= ~IXOFF;
2089 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2090 int save_error=errno;
2091 commerror = WinError();
2093 #ifdef HAVE_STRERROR
2094 ERR("tcgetattr error '%s'\n", strerror(save_error));
2096 ERR("tcgetattr error %d\n", save_error);
2107 /*****************************************************************************
2108 * GetCommState (KERNEL32.159)
2110 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2112 struct termios port;
2115 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2117 if ((fd = COMM_GetReadFd(handle)) < 0)
2119 ERR("can't get COMM_GetReadFd\n");
2122 if (tcgetattr(fd, &port) == -1) {
2123 int save_error=errno;
2124 #ifdef HAVE_STRERROR
2125 ERR("tcgetattr error '%s'\n", strerror(save_error));
2127 ERR("tcgetattr error %d\n", save_error);
2129 commerror = WinError();
2136 speed= (port.c_cflag & CBAUD);
2138 speed= (cfgetospeed(&port));
2142 lpdcb->BaudRate = 110;
2145 lpdcb->BaudRate = 300;
2148 lpdcb->BaudRate = 600;
2151 lpdcb->BaudRate = 1200;
2154 lpdcb->BaudRate = 2400;
2157 lpdcb->BaudRate = 4800;
2160 lpdcb->BaudRate = 9600;
2163 lpdcb->BaudRate = 19200;
2166 lpdcb->BaudRate = 38400;
2170 lpdcb->BaudRate = 57600;
2175 lpdcb->BaudRate = 115200;
2180 lpdcb->BaudRate = 230400;
2185 lpdcb->BaudRate = 460800;
2189 ERR("unknown speed %x \n",speed);
2192 switch (port.c_cflag & CSIZE) {
2194 lpdcb->ByteSize = 5;
2197 lpdcb->ByteSize = 6;
2200 lpdcb->ByteSize = 7;
2203 lpdcb->ByteSize = 8;
2206 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2209 if(port.c_iflag & INPCK)
2210 lpdcb->fParity = TRUE;
2212 lpdcb->fParity = FALSE;
2213 switch (port.c_cflag & (PARENB | PARODD)) {
2215 lpdcb->Parity = NOPARITY;
2218 lpdcb->Parity = EVENPARITY;
2220 case (PARENB | PARODD):
2221 lpdcb->Parity = ODDPARITY;
2225 if (port.c_cflag & CSTOPB)
2226 lpdcb->StopBits = TWOSTOPBITS;
2228 lpdcb->StopBits = ONESTOPBIT;
2235 if (port.c_cflag & CRTSCTS) {
2236 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2237 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2238 lpdcb->fOutxCtsFlow = 1;
2239 lpdcb->fOutxDsrFlow = 1;
2243 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2244 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2246 if (port.c_iflag & IXON)
2251 if (port.c_iflag & IXOFF)
2260 lpdcb->XoffLim = 10;
2266 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2267 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2268 (lpdcb->StopBits == ONESTOPBIT)?1:
2269 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2270 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2271 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2273 if ( lpdcb->fOutxCtsFlow ||
2274 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2275 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2279 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2280 TRACE("~CRTSCTS\n");
2286 /*****************************************************************************
2287 * TransmitCommChar (KERNEL32.535)
2289 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2291 struct DosDeviceStruct *ptr;
2293 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2294 if ((ptr = GetDeviceStruct(cid)) == NULL) {
2298 if (ptr->suspended) {
2299 ptr->commerror = IE_HARDWARE;
2302 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2303 ptr->commerror = WinError();
2311 /*****************************************************************************
2312 * GetCommTimeouts (KERNEL32.160)
2314 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
2316 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2320 /*****************************************************************************
2321 * SetCommTimeouts (KERNEL32.453)
2323 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2324 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2325 TRACE("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2326 TRACE("ReadTotalTimeoutMultiplier %ld\n",
2327 lptimeouts->ReadTotalTimeoutMultiplier);
2328 TRACE("ReadTotalTimeoutConstant %ld\n",
2329 lptimeouts->ReadTotalTimeoutConstant);
2330 TRACE("WriteTotalTimeoutMultiplier %ld\n",
2331 lptimeouts->WriteTotalTimeoutMultiplier);
2332 TRACE("WriteTotalTimeoutConstant %ld\n",
2333 lptimeouts->WriteTotalTimeoutConstant);
2337 /***********************************************************************
2338 * GetCommModemStatus (KERNEL32.285)
2340 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2342 int fd,mstat, result=FALSE;
2346 fd = COMM_GetWriteFd(hFile);
2349 result = ioctl(fd, TIOCMGET, &mstat);
2353 TRACE("ioctl failed\n");
2356 if (mstat & TIOCM_CTS)
2357 *lpModemStat |= MS_CTS_ON;
2358 if (mstat & TIOCM_DSR)
2359 *lpModemStat |= MS_DSR_ON;
2360 if (mstat & TIOCM_RNG)
2361 *lpModemStat |= MS_RING_ON;
2362 /*FIXME: Not really sure about RLSD UB 990810*/
2363 if (mstat & TIOCM_CAR)
2364 *lpModemStat |= MS_RLSD_ON;
2366 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2367 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2368 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2369 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2375 /***********************************************************************
2376 * WaitCommEvent (KERNEL32.719)
2378 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2380 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2384 /***********************************************************************
2385 * GetCommProperties (KERNEL32.???)
2387 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2389 FIXME("(%d %p )\n",hFile,dcb);
2393 /***********************************************************************
2394 * SetCommProperties (KERNEL32.???)
2396 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2398 FIXME("(%d %p )\n",hFile,dcb);