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.
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
51 #include <sys/ioctl.h>
56 #include "wine/winuser16.h"
58 #ifdef HAVE_SYS_MODEM_H
59 # include <sys/modem.h>
61 #ifdef HAVE_SYS_STRTIO_H
62 # include <sys/strtio.h>
74 #include "debugtools.h"
76 DEFAULT_DEBUG_CHANNEL(comm);
79 #define TIOCINQ FIONREAD
82 /* window's semi documented modem status register */
83 #define COMM_MSR_OFFSET 35
88 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
93 #define CMSPAR 0x40000000 /* stick parity */
96 struct DosDeviceStruct COM[MAX_PORTS];
97 struct DosDeviceStruct LPT[MAX_PORTS];
98 /* pointers to unknown(==undocumented) comm structure */
99 LPCVOID *unknown[MAX_PORTS];
100 /* save terminal states */
101 static struct termios m_stat[MAX_PORTS];
103 /* update window's semi documented modem status register */
104 /* see knowledge base Q101417 */
105 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
108 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
109 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
110 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
111 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
112 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
118 char option[10], temp[256], *btemp;
121 for (x=0; x!=MAX_PORTS; x++) {
122 strcpy(option,"COMx");
126 PROFILE_GetWineIniString( "serialports", option, "*",
127 temp, sizeof(temp) );
128 if (!strcmp(temp, "*") || *temp == '\0')
129 COM[x].devicename = NULL;
131 btemp = strchr(temp,',');
134 COM[x].baudrate = atoi(btemp);
136 COM[x].baudrate = -1;
139 if (!S_ISCHR(st.st_mode))
140 WARN("Can't use `%s' as %s !\n", temp, option);
142 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
143 WARN("Can't malloc for device info!\n");
146 strcpy(COM[x].devicename, temp);
148 TRACE("%s = %s\n", option, COM[x].devicename);
151 strcpy(option, "LPTx");
155 PROFILE_GetWineIniString( "parallelports", option, "*",
156 temp, sizeof(temp) );
157 if (!strcmp(temp, "*") || *temp == '\0')
158 LPT[x].devicename = NULL;
161 if (!S_ISCHR(st.st_mode))
162 WARN("Can't use `%s' as %s !\n", temp, option);
164 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
165 WARN("Can't malloc for device info!\n");
168 strcpy(LPT[x].devicename, temp);
170 TRACE("%s = %s\n", option, LPT[x].devicename);
177 static struct DosDeviceStruct *GetDeviceStruct(int fd)
179 if ((fd&0x7F)<=MAX_PORTS) {
180 if (!(fd&FLAG_LPT)) {
193 static int GetCommPort_fd(int fd)
197 for (x=0; x<MAX_PORTS; x++) {
205 static int ValidCOMPort(int x)
207 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
210 static int ValidLPTPort(int x)
212 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
215 static int WinError(void)
217 TRACE("errno = %d\n", errno);
224 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
226 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
227 + ptr->ibuf_head - ptr->ibuf_tail;
230 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
232 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
233 + ptr->obuf_head - ptr->obuf_tail;
236 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
238 unsigned int mstat, okay;
239 okay = ioctl(fd, TIOCMGET, &mstat);
240 if (okay) return okay;
241 if (andy) mstat &= andy;
243 return ioctl(fd, TIOCMSET, &mstat);
246 static void CALLBACK comm_notification( ULONG_PTR private )
248 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
249 int prev, bleft, len;
251 int cid = GetCommPort_fd(ptr->fd);
253 TRACE("async notification\n");
254 /* read data from comm port */
255 prev = comm_inbuf(ptr);
257 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
259 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
262 ptr->commerror = CE_RXOVER;
264 /* check for events */
265 if ((ptr->eventmask & EV_RXFLAG) &&
266 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
267 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
270 if (ptr->eventmask & EV_RXCHAR) {
271 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
274 /* advance buffer position */
275 ptr->ibuf_head += len;
276 if (ptr->ibuf_head >= ptr->ibuf_size)
281 /* check for notification */
282 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
283 (comm_inbuf(ptr)>=ptr->n_read)) {
284 /* passed the receive notification threshold */
288 /* write any TransmitCommChar character */
290 len = write(ptr->fd, &(ptr->xmit), 1);
291 if (len > 0) ptr->xmit = -1;
293 /* write from output queue */
294 prev = comm_outbuf(ptr);
296 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
298 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
300 ptr->obuf_tail += len;
301 if (ptr->obuf_tail >= ptr->obuf_size)
304 if (ptr->obuf_tail == ptr->obuf_head) {
306 SERVICE_Delete( ptr->s_write );
307 ptr->s_write = INVALID_HANDLE_VALUE;
309 if (ptr->eventmask & EV_TXEMPTY) {
310 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
316 /* check for notification */
317 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
318 (comm_outbuf(ptr)<ptr->n_write)) {
319 /* passed the transmit notification threshold */
323 /* send notifications, if any */
324 if (ptr->wnd && mask) {
325 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
326 Callout.PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
330 static void comm_waitread(struct DosDeviceStruct *ptr)
332 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
333 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
334 GENERIC_READ | SYNCHRONIZE ),
339 static void comm_waitwrite(struct DosDeviceStruct *ptr)
341 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
342 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
343 GENERIC_WRITE | SYNCHRONIZE ),
348 /**************************************************************************
349 * BuildCommDCB (USER.213)
351 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
353 /* "COM1:9600,n,8,1" */
356 char *ptr, temp[256];
358 TRACE("(%s), ptr %p\n", device, lpdcb);
360 if (!lstrncmpiA(device,"COM",3)) {
361 port = device[3] - '0';
365 ERR("BUG ! COM0 can't exist!.\n");
369 if (!ValidCOMPort(port)) {
370 FIXME("invalid COM port %d?\n",port);
374 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
381 if (*(device+4) != ':')
384 strcpy(temp,device+5);
385 ptr = strtok(temp, ", ");
387 if (COM[port].baudrate > 0)
388 lpdcb->BaudRate = COM[port].baudrate;
390 lpdcb->BaudRate = atoi(ptr);
391 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
393 ptr = strtok(NULL, ", ");
395 *ptr = toupper(*ptr);
397 TRACE("parity (%c)\n", *ptr);
398 lpdcb->fParity = TRUE;
401 lpdcb->Parity = NOPARITY;
402 lpdcb->fParity = FALSE;
405 lpdcb->Parity = EVENPARITY;
408 lpdcb->Parity = MARKPARITY;
411 lpdcb->Parity = ODDPARITY;
414 WARN("Unknown parity `%c'!\n", *ptr);
418 ptr = strtok(NULL, ", ");
419 TRACE("charsize (%c)\n", *ptr);
420 lpdcb->ByteSize = *ptr - '0';
422 ptr = strtok(NULL, ", ");
423 TRACE("stopbits (%c)\n", *ptr);
426 lpdcb->StopBits = ONESTOPBIT;
429 lpdcb->StopBits = TWOSTOPBITS;
432 WARN("Unknown # of stopbits `%c'!\n", *ptr);
440 /*****************************************************************************
441 * OpenComm (USER.200)
443 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
447 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
449 if (strlen(device) < 4)
452 port = device[3] - '0';
455 ERR("BUG ! COM0 or LPT0 don't exist !\n");
457 if (!lstrncmpiA(device,"COM",3)) {
459 TRACE("%s = %s\n", device, COM[port].devicename);
461 if (!ValidCOMPort(port))
467 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
469 ERR("error=%d\n", errno);
472 unknown[port] = SEGPTR_ALLOC(40);
473 bzero(unknown[port],40);
475 COM[port].commerror = 0;
476 COM[port].eventmask = 0;
477 COM[port].evtchar = 0; /* FIXME: default? */
478 /* save terminal state */
479 tcgetattr(fd,&m_stat[port]);
480 /* set default parameters */
481 if(COM[port].baudrate>-1){
483 GetCommState16(port, &dcb);
484 dcb.BaudRate=COM[port].baudrate;
486 * databits, parity, stopbits
488 SetCommState16( &dcb);
490 /* init priority characters */
491 COM[port].unget = -1;
493 /* allocate buffers */
494 COM[port].ibuf_size = cbInQueue;
495 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
496 COM[port].obuf_size = cbOutQueue;
497 COM[port].obuf_head = COM[port].obuf_tail = 0;
499 COM[port].inbuf = malloc(cbInQueue);
500 if (COM[port].inbuf) {
501 COM[port].outbuf = malloc(cbOutQueue);
502 if (!COM[port].outbuf)
503 free(COM[port].inbuf);
504 } else COM[port].outbuf = NULL;
505 if (!COM[port].outbuf) {
506 /* not enough memory */
507 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
509 ERR("out of memory");
513 COM[port].s_read = INVALID_HANDLE_VALUE;
514 COM[port].s_write = INVALID_HANDLE_VALUE;
515 comm_waitread( &COM[port] );
520 if (!lstrncmpiA(device,"LPT",3)) {
522 if (!ValidLPTPort(port))
528 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
533 LPT[port].commerror = 0;
534 LPT[port].eventmask = 0;
535 return port|FLAG_LPT;
541 /*****************************************************************************
542 * CloseComm (USER.207)
544 INT16 WINAPI CloseComm16(INT16 cid)
546 struct DosDeviceStruct *ptr;
548 TRACE("cid=%d\n", cid);
549 if ((ptr = GetDeviceStruct(cid)) == NULL) {
550 FIXME("no cid=%d found!\n", cid);
553 if (!(cid&FLAG_LPT)) {
555 SEGPTR_FREE(unknown[cid]); /* [LW] */
557 SERVICE_Delete( COM[cid].s_write );
558 SERVICE_Delete( COM[cid].s_read );
563 /* reset modem lines */
564 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
567 if (close(ptr->fd) == -1) {
568 ptr->commerror = WinError();
569 /* FIXME: should we clear ptr->fd here? */
578 /*****************************************************************************
579 * SetCommBreak (USER.210)
581 INT16 WINAPI SetCommBreak16(INT16 cid)
583 struct DosDeviceStruct *ptr;
585 TRACE("cid=%d\n", cid);
586 if ((ptr = GetDeviceStruct(cid)) == NULL) {
587 FIXME("no cid=%d found!\n", cid);
596 /*****************************************************************************
597 * ClearCommBreak (USER.211)
599 INT16 WINAPI ClearCommBreak16(INT16 cid)
601 struct DosDeviceStruct *ptr;
603 TRACE("cid=%d\n", cid);
604 if (!(ptr = GetDeviceStruct(cid))) {
605 FIXME("no cid=%d found!\n", cid);
613 /*****************************************************************************
614 * EscapeCommFunction (USER.214)
616 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
619 struct DosDeviceStruct *ptr;
622 TRACE("cid=%d, function=%d\n", cid, nFunction);
623 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
624 if ((ptr = GetDeviceStruct(cid)) == NULL) {
625 FIXME("no cid=%d found!\n", cid);
628 if (tcgetattr(ptr->fd,&port) == -1) {
629 TRACE("tcgetattr failed\n");
630 ptr->commerror=WinError();
641 TRACE("GETMAXCOM\n");
642 for (max = MAX_PORTS;!COM[max].devicename;max--)
648 TRACE("GETMAXLPT\n");
649 for (max = MAX_PORTS;!LPT[max].devicename;max--)
651 return FLAG_LPT + max;
655 TRACE("GETBASEIRQ\n");
656 /* FIXME: use tables */
657 /* just fake something for now */
658 if (cid & FLAG_LPT) {
659 /* LPT1: irq 7, LPT2: irq 5 */
660 return (cid & 0x7f) ? 5 : 7;
662 /* COM1: irq 4, COM2: irq 3,
663 COM3: irq 4, COM4: irq 3 */
664 return 4 - (cid & 1);
671 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
676 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
682 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
688 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
693 port.c_iflag |= IXOFF;
698 port.c_iflag |= IXON;
702 WARN("(cid=%d,nFunction=%d): Unknown function\n",
707 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
708 ptr->commerror = WinError();
716 /*****************************************************************************
717 * FlushComm (USER.215)
719 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
722 struct DosDeviceStruct *ptr;
724 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
725 if ((ptr = GetDeviceStruct(cid)) == NULL) {
726 FIXME("no cid=%d found!\n", cid);
732 ptr->obuf_tail = ptr->obuf_head;
736 ptr->ibuf_head = ptr->ibuf_tail;
739 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
743 if (tcflush(ptr->fd, queue)) {
744 ptr->commerror = WinError();
752 /********************************************************************
753 * GetCommError (USER.203)
755 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
758 struct DosDeviceStruct *ptr;
762 if ((ptr = GetDeviceStruct(cid)) == NULL) {
763 FIXME("no handle for cid = %0x!.\n",cid);
767 WARN(" cid %d not comm port\n",cid);
770 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
771 ioctl(ptr->fd,TIOCMGET,&mstat);
772 COMM_MSRUpdate( stol, mstat);
777 lpStat->cbOutQue = comm_outbuf(ptr);
778 lpStat->cbInQue = comm_inbuf(ptr);
780 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
781 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
782 lpStat->cbOutQue, *stol);
785 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
786 cid, ptr->commerror, *stol);
788 /* Return any errors and clear it */
789 temperror = ptr->commerror;
794 /*****************************************************************************
795 * SetCommEventMask (USER.208)
797 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
799 struct DosDeviceStruct *ptr;
804 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
805 if ((ptr = GetDeviceStruct(cid)) == NULL) {
806 FIXME("no handle for cid = %0x!.\n",cid);
810 ptr->eventmask = fuEvtMask;
812 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
813 WARN(" cid %d not comm port\n",cid);
816 /* it's a COM port ? -> modify flags */
817 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
818 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
819 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
820 COMM_MSRUpdate( stol, mstat);
822 TRACE(" modem dcd construct %x\n",*stol);
823 return SEGPTR_GET(unknown[cid]);
826 /*****************************************************************************
827 * GetCommEventMask (USER.209)
829 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
831 struct DosDeviceStruct *ptr;
834 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
835 if ((ptr = GetDeviceStruct(cid)) == NULL) {
836 FIXME("no handle for cid = %0x!.\n",cid);
840 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
841 WARN(" cid %d not comm port\n",cid);
845 events = *(WORD*)(unknown[cid]) & fnEvtClear;
846 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
850 /*****************************************************************************
851 * SetCommState16 (USER.201)
853 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
856 struct DosDeviceStruct *ptr;
857 int bytesize, stopbits;
860 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
861 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
862 FIXME("no handle for cid = %0x!.\n",lpdcb->Id);
865 if (tcgetattr(ptr->fd, &port) == -1) {
866 ptr->commerror = WinError();
871 port.c_cc[VTIME] = 1;
874 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
876 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
878 port.c_iflag |= (IGNBRK);
880 port.c_oflag &= ~(OPOST);
882 port.c_cflag &= ~(HUPCL);
883 port.c_cflag |= CLOCAL | CREAD;
885 port.c_lflag &= ~(ICANON|ECHO|ISIG);
886 port.c_lflag |= NOFLSH;
888 TRACE("baudrate %d\n",lpdcb->BaudRate);
890 port.c_cflag &= ~CBAUD;
891 switch (lpdcb->BaudRate) {
894 port.c_cflag |= B110;
898 port.c_cflag |= B300;
902 port.c_cflag |= B600;
906 port.c_cflag |= B1200;
910 port.c_cflag |= B2400;
914 port.c_cflag |= B4800;
918 port.c_cflag |= B9600;
922 port.c_cflag |= B19200;
926 port.c_cflag |= B38400;
930 port.c_cflag |= B57600;
935 port.c_cflag |= B115200;
939 ptr->commerror = IE_BAUDRATE;
942 #elif !defined(__EMX__)
943 switch (lpdcb->BaudRate) {
946 port.c_ospeed = B110;
950 port.c_ospeed = B300;
954 port.c_ospeed = B600;
958 port.c_ospeed = B1200;
962 port.c_ospeed = B2400;
966 port.c_ospeed = B4800;
970 port.c_ospeed = B9600;
974 port.c_ospeed = B19200;
978 port.c_ospeed = B38400;
981 ptr->commerror = IE_BAUDRATE;
984 port.c_ispeed = port.c_ospeed;
986 bytesize=lpdcb->ByteSize;
987 stopbits=lpdcb->StopBits;
989 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
991 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
993 port.c_cflag &= ~(PARENB | PARODD);
996 port.c_iflag |= INPCK;
998 port.c_iflag &= ~INPCK;
999 switch (lpdcb->Parity) {
1003 port.c_cflag |= (PARENB | PARODD);
1006 port.c_cflag |= PARENB;
1009 /* Linux defines mark/space (stick) parity */
1011 port.c_cflag |= (PARENB | CMSPAR);
1014 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1017 /* try the POSIX way */
1019 if( stopbits == ONESTOPBIT) {
1020 stopbits = TWOSTOPBITS;
1021 port.c_iflag &= ~INPCK;
1023 ptr->commerror = IE_BYTESIZE;
1030 port.c_iflag &= ~INPCK;
1032 ptr->commerror = IE_BYTESIZE;
1038 ptr->commerror = IE_BYTESIZE;
1042 TRACE("bytesize %d\n",bytesize);
1043 port.c_cflag &= ~CSIZE;
1046 port.c_cflag |= CS5;
1049 port.c_cflag |= CS6;
1052 port.c_cflag |= CS7;
1055 port.c_cflag |= CS8;
1058 ptr->commerror = IE_BYTESIZE;
1062 TRACE("stopbits %d\n",stopbits);
1066 port.c_cflag &= ~CSTOPB;
1068 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1070 port.c_cflag |= CSTOPB;
1073 ptr->commerror = IE_BYTESIZE;
1078 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1079 port.c_cflag |= CRTSCTS;
1081 if (lpdcb->fDtrDisable)
1082 port.c_cflag &= ~CRTSCTS;
1085 port.c_iflag |= IXON;
1087 port.c_iflag &= ~IXON;
1089 port.c_iflag |= IXOFF;
1091 port.c_iflag &= ~IXOFF;
1093 ptr->evtchar = lpdcb->EvtChar;
1098 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1099 ptr->commerror = WinError();
1107 /*****************************************************************************
1108 * GetCommState (USER.202)
1110 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1113 struct DosDeviceStruct *ptr;
1114 struct termios port;
1116 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1117 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1118 FIXME("no handle for cid = %0x!.\n",cid);
1121 if (tcgetattr(ptr->fd, &port) == -1) {
1122 ptr->commerror = WinError();
1128 speed = port.c_cflag & CBAUD;
1130 speed = port.c_ospeed;
1134 lpdcb->BaudRate = 110;
1137 lpdcb->BaudRate = 300;
1140 lpdcb->BaudRate = 600;
1143 lpdcb->BaudRate = 1200;
1146 lpdcb->BaudRate = 2400;
1149 lpdcb->BaudRate = 4800;
1152 lpdcb->BaudRate = 9600;
1155 lpdcb->BaudRate = 19200;
1158 lpdcb->BaudRate = 38400;
1162 lpdcb->BaudRate = 57600;
1167 lpdcb->BaudRate = 57601;
1172 switch (port.c_cflag & CSIZE) {
1174 lpdcb->ByteSize = 5;
1177 lpdcb->ByteSize = 6;
1180 lpdcb->ByteSize = 7;
1183 lpdcb->ByteSize = 8;
1187 if(port.c_iflag & INPCK)
1188 lpdcb->fParity = TRUE;
1190 lpdcb->fParity = FALSE;
1192 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1194 switch (port.c_cflag & (PARENB | PARODD))
1198 lpdcb->Parity = NOPARITY;
1201 lpdcb->Parity = EVENPARITY;
1203 case (PARENB | PARODD):
1204 lpdcb->Parity = ODDPARITY;
1207 case (PARENB | CMSPAR):
1208 lpdcb->Parity = MARKPARITY;
1210 case (PARENB | PARODD | CMSPAR):
1211 lpdcb->Parity = SPACEPARITY;
1216 if (port.c_cflag & CSTOPB)
1217 if(lpdcb->ByteSize == 5)
1218 lpdcb->StopBits = ONE5STOPBITS;
1220 lpdcb->StopBits = TWOSTOPBITS;
1222 lpdcb->StopBits = ONESTOPBIT;
1224 lpdcb->RlsTimeout = 50;
1225 lpdcb->CtsTimeout = 50;
1226 lpdcb->DsrTimeout = 50;
1230 lpdcb->fDtrDisable = 0;
1234 if (port.c_cflag & CRTSCTS) {
1235 lpdcb->fDtrflow = 1;
1236 lpdcb->fRtsflow = 1;
1237 lpdcb->fOutxCtsFlow = 1;
1238 lpdcb->fOutxDsrFlow = 1;
1241 lpdcb->fDtrDisable = 1;
1243 if (port.c_iflag & IXON)
1248 if (port.c_iflag & IXOFF)
1257 lpdcb->XoffLim = 10;
1259 lpdcb->EvtChar = ptr->evtchar;
1265 /*****************************************************************************
1266 * TransmitCommChar (USER.206)
1268 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1270 struct DosDeviceStruct *ptr;
1272 TRACE("cid %d, data %d \n", cid, chTransmit);
1273 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1274 FIXME("no handle for cid = %0x!.\n",cid);
1278 if (ptr->suspended) {
1279 ptr->commerror = IE_HARDWARE;
1283 if (ptr->xmit >= 0) {
1284 /* character already queued */
1285 /* FIXME: which error would Windows return? */
1286 ptr->commerror = CE_TXFULL;
1290 if (ptr->obuf_head == ptr->obuf_tail) {
1291 /* transmit queue empty, try to transmit directly */
1292 if (write(ptr->fd, &chTransmit, 1) == -1) {
1293 /* didn't work, queue it */
1294 ptr->xmit = chTransmit;
1295 comm_waitwrite(ptr);
1298 /* data in queue, let this char be transmitted next */
1299 ptr->xmit = chTransmit;
1300 comm_waitwrite(ptr);
1307 /*****************************************************************************
1308 * UngetCommChar (USER.212)
1310 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1312 struct DosDeviceStruct *ptr;
1314 TRACE("cid %d (char %d)\n", cid, chUnget);
1315 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1316 FIXME("no handle for cid = %0x!.\n",cid);
1320 if (ptr->suspended) {
1321 ptr->commerror = IE_HARDWARE;
1325 if (ptr->unget>=0) {
1326 /* character already queued */
1327 /* FIXME: which error would Windows return? */
1328 ptr->commerror = CE_RXOVER;
1332 ptr->unget = chUnget;
1338 /*****************************************************************************
1339 * ReadComm (USER.204)
1341 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1344 struct DosDeviceStruct *ptr;
1345 LPSTR orgBuf = lpvBuf;
1347 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1348 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1349 FIXME("no handle for cid = %0x!.\n",cid);
1353 if (ptr->suspended) {
1354 ptr->commerror = IE_HARDWARE;
1358 /* read unget character */
1359 if (ptr->unget>=0) {
1360 *lpvBuf++ = ptr->unget;
1367 /* read from receive buffer */
1368 while (length < cbRead) {
1369 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1370 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1372 if ((cbRead - length) < status)
1373 status = cbRead - length;
1375 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1376 ptr->ibuf_tail += status;
1377 if (ptr->ibuf_tail >= ptr->ibuf_size)
1383 TRACE("%.*s\n", length, orgBuf);
1388 /*****************************************************************************
1389 * WriteComm (USER.205)
1391 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1394 struct DosDeviceStruct *ptr;
1396 TRACE("cid %d, ptr %p, length %d\n",
1397 cid, lpvBuf, cbWrite);
1398 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1399 FIXME("no handle for cid = %0x!.\n",cid);
1403 if (ptr->suspended) {
1404 ptr->commerror = IE_HARDWARE;
1408 TRACE("%.*s\n", cbWrite, lpvBuf );
1411 while (length < cbWrite) {
1412 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1413 /* no data queued, try to write directly */
1414 status = write(ptr->fd, lpvBuf, cbWrite - length);
1421 /* can't write directly, put into transmit buffer */
1422 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1423 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1425 if ((cbWrite - length) < status)
1426 status = cbWrite - length;
1427 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1428 ptr->obuf_head += status;
1429 if (ptr->obuf_head >= ptr->obuf_size)
1433 comm_waitwrite(ptr);
1440 /***********************************************************************
1441 * EnableCommNotification (USER.246)
1443 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1444 INT16 cbWriteNotify, INT16 cbOutQueue )
1446 struct DosDeviceStruct *ptr;
1448 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1449 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1450 FIXME("no handle for cid = %0x!.\n",cid);
1454 ptr->n_read = cbWriteNotify;
1455 ptr->n_write = cbOutQueue;
1460 /**************************************************************************
1461 * BuildCommDCBA (KERNEL32.14)
1463 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1465 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1468 /**************************************************************************
1469 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1471 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1472 LPCOMMTIMEOUTS lptimeouts)
1477 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1479 if (!lstrncmpiA(device,"COM",3)) {
1482 ERR("BUG! COM0 can't exists!.\n");
1485 if (!ValidCOMPort(port))
1487 if (*(device+4)!=':')
1489 temp=(LPSTR)(device+5);
1493 lpdcb->DCBlength = sizeof(DCB);
1494 if (strchr(temp,',')) { /* old style */
1497 char last=temp[strlen(temp)-1];
1499 ret=BuildCommDCB16(device,&dcb16);
1502 lpdcb->BaudRate = dcb16.BaudRate;
1503 lpdcb->ByteSize = dcb16.ByteSize;
1504 lpdcb->fBinary = dcb16.fBinary;
1505 lpdcb->Parity = dcb16.Parity;
1506 lpdcb->fParity = dcb16.fParity;
1507 lpdcb->fNull = dcb16.fNull;
1508 lpdcb->StopBits = dcb16.StopBits;
1511 lpdcb->fOutX = TRUE;
1512 lpdcb->fOutxCtsFlow = FALSE;
1513 lpdcb->fOutxDsrFlow = FALSE;
1514 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1515 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1516 } else if (last=='p') {
1517 lpdcb->fInX = FALSE;
1518 lpdcb->fOutX = FALSE;
1519 lpdcb->fOutxCtsFlow = TRUE;
1520 lpdcb->fOutxDsrFlow = TRUE;
1521 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1522 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1524 lpdcb->fInX = FALSE;
1525 lpdcb->fOutX = FALSE;
1526 lpdcb->fOutxCtsFlow = FALSE;
1527 lpdcb->fOutxDsrFlow = FALSE;
1528 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1529 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1531 lpdcb->XonChar = dcb16.XonChar;
1532 lpdcb->XoffChar = dcb16.XoffChar;
1533 lpdcb->ErrorChar= dcb16.PeChar;
1534 lpdcb->fErrorChar= dcb16.fPeChar;
1535 lpdcb->EofChar = dcb16.EofChar;
1536 lpdcb->EvtChar = dcb16.EvtChar;
1537 lpdcb->XonLim = dcb16.XonLim;
1538 lpdcb->XoffLim = dcb16.XoffLim;
1541 ptr=strtok(temp," ");
1546 if (!strncmp("baud=",ptr,5)) {
1547 if (!sscanf(ptr+5,"%ld",&x))
1548 WARN("Couldn't parse %s\n",ptr);
1549 lpdcb->BaudRate = x;
1552 if (!strncmp("stop=",ptr,5)) {
1553 if (!sscanf(ptr+5,"%ld",&x))
1554 WARN("Couldn't parse %s\n",ptr);
1555 lpdcb->StopBits = x;
1558 if (!strncmp("data=",ptr,5)) {
1559 if (!sscanf(ptr+5,"%ld",&x))
1560 WARN("Couldn't parse %s\n",ptr);
1561 lpdcb->ByteSize = x;
1564 if (!strncmp("parity=",ptr,7)) {
1565 lpdcb->fParity = TRUE;
1568 lpdcb->fParity = FALSE;
1569 lpdcb->Parity = NOPARITY;
1572 lpdcb->Parity = EVENPARITY;
1575 lpdcb->Parity = ODDPARITY;
1578 lpdcb->Parity = MARKPARITY;
1584 ERR("Unhandled specifier '%s', please report.\n",ptr);
1585 ptr=strtok(NULL," ");
1587 if (lpdcb->BaudRate==110)
1588 lpdcb->StopBits = 2;
1592 /**************************************************************************
1593 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1595 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1596 LPCOMMTIMEOUTS lptimeouts )
1601 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1602 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1603 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1604 HeapFree( GetProcessHeap(), 0, devidA );
1608 /**************************************************************************
1609 * BuildCommDCBW (KERNEL32.17)
1611 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1613 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1616 /*****************************************************************************
1618 * Returns a file descriptor for reading.
1619 * Make sure to close the handle afterwards!
1621 static int COMM_GetReadFd( HANDLE handle)
1624 struct get_read_fd_request *req = get_req_buffer();
1625 req->handle = handle;
1626 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1630 /*****************************************************************************
1632 * Returns a file descriptor for writing.
1633 * Make sure to close the handle afterwards!
1635 static int COMM_GetWriteFd( HANDLE handle)
1638 struct get_write_fd_request *req = get_req_buffer();
1639 req->handle = handle;
1640 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1644 /* FIXME: having these global for win32 for now */
1645 int commerror=0,eventmask=0;
1647 /*****************************************************************************
1648 * SetCommBreak (KERNEL32.449)
1650 BOOL WINAPI SetCommBreak(HANDLE handle)
1652 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1655 fd = COMM_GetWriteFd(handle);
1657 TRACE("COMM_GetWriteFd failed\n");
1660 result = ioctl(fd,TIOCSBRK,0);
1664 TRACE("ioctl failed\n");
1665 SetLastError(ERROR_NOT_SUPPORTED);
1670 FIXME("ioctl not available\n");
1671 SetLastError(ERROR_NOT_SUPPORTED);
1676 /*****************************************************************************
1677 * ClearCommBreak (KERNEL32.20)
1679 BOOL WINAPI ClearCommBreak(HANDLE handle)
1681 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1684 fd = COMM_GetWriteFd(handle);
1686 TRACE("COMM_GetWriteFd failed\n");
1689 result = ioctl(fd,TIOCCBRK,0);
1693 TRACE("ioctl failed\n");
1694 SetLastError(ERROR_NOT_SUPPORTED);
1699 FIXME("ioctl not available\n");
1700 SetLastError(ERROR_NOT_SUPPORTED);
1705 /*****************************************************************************
1706 * EscapeCommFunction (KERNEL32.214)
1708 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1710 int fd,direct=FALSE,result=FALSE;
1711 struct termios port;
1713 TRACE("handle %d, function=%d\n", handle, nFunction);
1714 fd = COMM_GetWriteFd(handle);
1716 FIXME("handle %d not found.\n",handle);
1720 if (tcgetattr(fd,&port) == -1) {
1721 commerror=WinError();
1726 switch (nFunction) {
1735 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1743 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1751 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1759 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1765 port.c_iflag |= IXOFF;
1770 port.c_iflag |= IXON;
1773 TRACE("setbreak\n");
1776 result = ioctl(fd,TIOCSBRK,0);
1780 TRACE("clrbreak\n");
1783 result = ioctl(fd,TIOCCBRK,0);
1787 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1793 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1794 commerror = WinError();
1804 commerror=WinError();
1813 /********************************************************************
1814 * PurgeComm (KERNEL32.557)
1816 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1820 TRACE("handle %d, flags %lx\n", handle, flags);
1822 fd = COMM_GetWriteFd(handle);
1824 FIXME("no handle %d found\n",handle);
1829 ** not exactly sure how these are different
1830 ** Perhaps if we had our own internal queues, one flushes them
1831 ** and the other flushes the kernel's buffers.
1833 if(flags&PURGE_TXABORT)
1834 tcflush(fd,TCOFLUSH);
1835 if(flags&PURGE_RXABORT)
1836 tcflush(fd,TCIFLUSH);
1837 if(flags&PURGE_TXCLEAR)
1838 tcflush(fd,TCOFLUSH);
1839 if(flags&PURGE_RXCLEAR)
1840 tcflush(fd,TCIFLUSH);
1846 /*****************************************************************************
1847 * ClearCommError (KERNEL32.21)
1849 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1853 fd=COMM_GetReadFd(handle);
1856 FIXME("no handle %d found\n",handle);
1865 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1866 WARN("ioctl returned error\n");
1868 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1871 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1872 WARN("ioctl returned error\n");
1874 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1875 handle, lpStat->cbInQue, lpStat->cbOutQue);
1884 ** After an asynchronous write opperation, the
1885 ** app will call ClearCommError to see if the
1886 ** results are ready yet. It waits for ERROR_IO_PENDING
1888 commerror = ERROR_IO_PENDING;
1893 /*****************************************************************************
1894 * SetupComm (KERNEL32.676)
1896 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1900 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1901 fd=COMM_GetWriteFd(handle);
1903 FIXME("handle %d not found?\n",handle);
1910 /*****************************************************************************
1911 * GetCommMask (KERNEL32.156)
1913 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1917 TRACE("handle %d, mask %p\n", handle, evtmask);
1918 if(0>(fd=COMM_GetReadFd(handle)))
1920 FIXME("no handle %d found\n",handle);
1924 *evtmask = eventmask;
1925 TRACE("%s%s%s%s%s%s%s%s%s\n",
1926 (eventmask&EV_BREAK)?"EV_BREAK":"",
1927 (eventmask&EV_CTS)?"EV_CTS":"",
1928 (eventmask&EV_DSR)?"EV_DSR":"",
1929 (eventmask&EV_ERR)?"EV_ERR":"",
1930 (eventmask&EV_RING)?"EV_RING":"",
1931 (eventmask&EV_RLSD)?"EV_RLSD":"",
1932 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1933 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1934 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1939 /*****************************************************************************
1940 * SetCommMask (KERNEL32.451)
1942 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1946 TRACE("handle %d, mask %lx\n", handle, evtmask);
1947 TRACE("%s%s%s%s%s%s%s%s%s\n",
1948 (evtmask&EV_BREAK)?"EV_BREAK":"",
1949 (evtmask&EV_CTS)?"EV_CTS":"",
1950 (evtmask&EV_DSR)?"EV_DSR":"",
1951 (evtmask&EV_ERR)?"EV_ERR":"",
1952 (evtmask&EV_RING)?"EV_RING":"",
1953 (evtmask&EV_RLSD)?"EV_RLSD":"",
1954 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1955 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1956 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1958 if(0>(fd=COMM_GetWriteFd(handle))) {
1959 FIXME("no handle %d found\n",handle);
1963 eventmask = evtmask;
1967 /*****************************************************************************
1968 * SetCommState (KERNEL32.452)
1970 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1972 struct termios port;
1974 int bytesize, stopbits;
1976 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1977 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1978 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1979 (lpdcb->StopBits == ONESTOPBIT)?1:
1980 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1981 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1982 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1984 if ((fd = COMM_GetWriteFd(handle)) < 0) {
1985 FIXME("no handle %d found\n",handle);
1989 if ((tcgetattr(fd,&port)) == -1) {
1990 int save_error = errno;
1991 commerror = WinError();
1993 #ifdef HAVE_STRERROR
1994 ERR("tcgetattr error '%s'\n", strerror(save_error));
1996 ERR("tcgetattr error %d\n", save_error);
2001 port.c_cc[VMIN] = 0;
2002 port.c_cc[VTIME] = 1;
2005 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
2007 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
2009 port.c_iflag |= (IGNBRK);
2011 port.c_oflag &= ~(OPOST);
2013 port.c_cflag &= ~(HUPCL);
2014 port.c_cflag |= CLOCAL | CREAD;
2016 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2017 port.c_lflag |= NOFLSH;
2020 ** MJM - removed default baudrate settings
2021 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2024 port.c_cflag &= ~CBAUD;
2025 switch (lpdcb->BaudRate) {
2028 port.c_cflag |= B110;
2032 port.c_cflag |= B300;
2036 port.c_cflag |= B600;
2040 port.c_cflag |= B1200;
2044 port.c_cflag |= B2400;
2048 port.c_cflag |= B4800;
2052 port.c_cflag |= B9600;
2056 port.c_cflag |= B19200;
2060 port.c_cflag |= B38400;
2064 port.c_cflag |= B57600;
2069 port.c_cflag |= B115200;
2074 port.c_cflag |= B230400;
2079 port.c_cflag |= B460800;
2083 commerror = IE_BAUDRATE;
2085 ERR("baudrate %ld\n",lpdcb->BaudRate);
2088 #elif !defined(__EMX__)
2089 switch (lpdcb->BaudRate) {
2092 port.c_ospeed = B110;
2096 port.c_ospeed = B300;
2100 port.c_ospeed = B600;
2104 port.c_ospeed = B1200;
2108 port.c_ospeed = B2400;
2112 port.c_ospeed = B4800;
2116 port.c_ospeed = B9600;
2120 port.c_ospeed = B19200;
2124 port.c_ospeed = B38400;
2127 commerror = IE_BAUDRATE;
2129 ERR("baudrate %ld\n",lpdcb->BaudRate);
2132 port.c_ispeed = port.c_ospeed;
2134 bytesize=lpdcb->ByteSize;
2135 stopbits=lpdcb->StopBits;
2138 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2140 port.c_cflag &= ~(PARENB | PARODD);
2143 port.c_iflag |= INPCK;
2145 port.c_iflag &= ~INPCK;
2146 switch (lpdcb->Parity) {
2150 port.c_cflag |= (PARENB | PARODD);
2153 port.c_cflag |= PARENB;
2156 /* Linux defines mark/space (stick) parity */
2158 port.c_cflag |= (PARENB | CMSPAR);
2161 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2164 /* try the POSIX way */
2166 if( stopbits == ONESTOPBIT) {
2167 stopbits = TWOSTOPBITS;
2168 port.c_iflag &= ~INPCK;
2170 commerror = IE_BYTESIZE;
2172 ERR("Cannot set MARK Parity\n");
2179 port.c_iflag &= ~INPCK;
2181 commerror = IE_BYTESIZE;
2183 ERR("Cannot set SPACE Parity\n");
2189 commerror = IE_BYTESIZE;
2196 port.c_cflag &= ~CSIZE;
2199 port.c_cflag |= CS5;
2202 port.c_cflag |= CS6;
2205 port.c_cflag |= CS7;
2208 port.c_cflag |= CS8;
2211 commerror = IE_BYTESIZE;
2219 port.c_cflag &= ~CSTOPB;
2221 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2223 port.c_cflag |= CSTOPB;
2226 commerror = IE_BYTESIZE;
2232 if ( lpdcb->fOutxCtsFlow ||
2233 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2234 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2237 port.c_cflag |= CRTSCTS;
2241 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2243 port.c_cflag &= ~CRTSCTS;
2244 TRACE("~CRTSCTS\n");
2249 port.c_iflag |= IXON;
2251 port.c_iflag &= ~IXON;
2253 port.c_iflag |= IXOFF;
2255 port.c_iflag &= ~IXOFF;
2257 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2258 int save_error=errno;
2259 commerror = WinError();
2261 #ifdef HAVE_STRERROR
2262 ERR("tcgetattr error '%s'\n", strerror(save_error));
2264 ERR("tcgetattr error %d\n", save_error);
2275 /*****************************************************************************
2276 * GetCommState (KERNEL32.159)
2278 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2280 struct termios port;
2283 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2285 if ((fd = COMM_GetReadFd(handle)) < 0)
2287 ERR("can't get COMM_GetReadFd\n");
2290 if (tcgetattr(fd, &port) == -1) {
2291 int save_error=errno;
2292 #ifdef HAVE_STRERROR
2293 ERR("tcgetattr error '%s'\n", strerror(save_error));
2295 ERR("tcgetattr error %d\n", save_error);
2297 commerror = WinError();
2304 speed= (port.c_cflag & CBAUD);
2306 speed= (cfgetospeed(&port));
2310 lpdcb->BaudRate = 110;
2313 lpdcb->BaudRate = 300;
2316 lpdcb->BaudRate = 600;
2319 lpdcb->BaudRate = 1200;
2322 lpdcb->BaudRate = 2400;
2325 lpdcb->BaudRate = 4800;
2328 lpdcb->BaudRate = 9600;
2331 lpdcb->BaudRate = 19200;
2334 lpdcb->BaudRate = 38400;
2338 lpdcb->BaudRate = 57600;
2343 lpdcb->BaudRate = 115200;
2348 lpdcb->BaudRate = 230400;
2353 lpdcb->BaudRate = 460800;
2357 ERR("unknown speed %x \n",speed);
2360 switch (port.c_cflag & CSIZE) {
2362 lpdcb->ByteSize = 5;
2365 lpdcb->ByteSize = 6;
2368 lpdcb->ByteSize = 7;
2371 lpdcb->ByteSize = 8;
2374 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2377 if(port.c_iflag & INPCK)
2378 lpdcb->fParity = TRUE;
2380 lpdcb->fParity = FALSE;
2382 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
2384 switch (port.c_cflag & (PARENB | PARODD))
2388 lpdcb->Parity = NOPARITY;
2391 lpdcb->Parity = EVENPARITY;
2393 case (PARENB | PARODD):
2394 lpdcb->Parity = ODDPARITY;
2397 case (PARENB | CMSPAR):
2398 lpdcb->Parity = MARKPARITY;
2400 case (PARENB | PARODD | CMSPAR):
2401 lpdcb->Parity = SPACEPARITY;
2406 if (port.c_cflag & CSTOPB)
2407 if(lpdcb->ByteSize == 5)
2408 lpdcb->StopBits = ONE5STOPBITS;
2410 lpdcb->StopBits = TWOSTOPBITS;
2412 lpdcb->StopBits = ONESTOPBIT;
2419 if (port.c_cflag & CRTSCTS) {
2420 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2421 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2422 lpdcb->fOutxCtsFlow = 1;
2423 lpdcb->fOutxDsrFlow = 1;
2427 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2428 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2430 if (port.c_iflag & IXON)
2435 if (port.c_iflag & IXOFF)
2444 lpdcb->XoffLim = 10;
2450 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2451 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2452 (lpdcb->StopBits == ONESTOPBIT)?1:
2453 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2454 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2455 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2457 if ( lpdcb->fOutxCtsFlow ||
2458 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2459 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2463 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2464 TRACE("~CRTSCTS\n");
2470 /*****************************************************************************
2471 * TransmitCommChar (KERNEL32.535)
2473 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2475 struct DosDeviceStruct *ptr;
2477 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2478 if ((ptr = GetDeviceStruct(cid)) == NULL)
2479 FIXME("no handle for cid = %0x!.\n",cid);
2482 if (ptr->suspended) {
2483 ptr->commerror = IE_HARDWARE;
2486 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2487 ptr->commerror = WinError();
2495 /*****************************************************************************
2496 * GetCommTimeouts (KERNEL32.160)
2498 BOOL WINAPI GetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts)
2500 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2504 /*****************************************************************************
2505 * SetCommTimeouts (KERNEL32.453)
2507 BOOL WINAPI SetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts) {
2508 /* struct DosDeviceStruct *ptr; */
2509 struct termios tios;
2512 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2514 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2515 FIXME("no handle for cid = %0x!.\n",hcom);
2520 fd = COMM_GetWriteFd(hcom);
2522 FIXME("no fd for cid = %0x!.\n",hcom);
2527 FIXME("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2528 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts->ReadTotalTimeoutMultiplier);
2529 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts->ReadTotalTimeoutConstant);
2530 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts->WriteTotalTimeoutMultiplier);
2531 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts->WriteTotalTimeoutConstant);
2534 if (-1==tcgetattr(fd,&tios)) {
2535 FIXME("tcgetattr on fd %d failed!\n",fd);
2538 /* VTIME is in 1/10 seconds */
2539 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2540 if (-1==tcsetattr(fd,0,&tios)) {
2541 FIXME("tcsetattr on fd %d failed!\n",fd);
2547 /***********************************************************************
2548 * GetCommModemStatus (KERNEL32.285)
2550 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2552 int fd,mstat, result=FALSE;
2556 fd = COMM_GetWriteFd(hFile);
2559 result = ioctl(fd, TIOCMGET, &mstat);
2563 TRACE("ioctl failed\n");
2566 if (mstat & TIOCM_CTS)
2567 *lpModemStat |= MS_CTS_ON;
2568 if (mstat & TIOCM_DSR)
2569 *lpModemStat |= MS_DSR_ON;
2570 if (mstat & TIOCM_RNG)
2571 *lpModemStat |= MS_RING_ON;
2572 /*FIXME: Not really sure about RLSD UB 990810*/
2573 if (mstat & TIOCM_CAR)
2574 *lpModemStat |= MS_RLSD_ON;
2576 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2577 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2578 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2579 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2585 /***********************************************************************
2586 * WaitCommEvent (KERNEL32.719)
2588 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2590 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2594 /***********************************************************************
2595 * GetCommProperties (KERNEL32.???)
2597 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2599 FIXME("(%d %p )\n",hFile,dcb);
2603 /***********************************************************************
2604 * SetCommProperties (KERNEL32.???)
2606 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2608 FIXME("(%d %p )\n",hFile,dcb);