2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
5 * FIXME: use HFILEs instead of unixfds
6 * the win32 functions here get HFILEs already.
8 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
9 * - ptr->fd wasn't getting cleared on close.
10 * - GetCommEventMask() and GetCommError() didn't do much of anything.
11 * IMHO, they are still wrong, but they at least implement the RXCHAR
12 * event and return I/O queue sizes, which makes the app I'm interested
13 * in (analog devices EZKIT DSP development system) work.
15 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
16 * <lawson_whitney@juno.com>
17 * July 6, 1998. Fixes and comments by Valentijn Sessink
18 * <vsessink@ic.uva.nl> [V]
19 * I only quick-fixed an error for the output buffers. The thing is this: if a
20 * WinApp starts using serial ports, it calls OpenComm, asking it to open two
21 * buffers, cbInQueue and cbOutQueue size, to hold data to/from the serial
22 * ports. Wine OpenComm only returns "OK". Now the kernel buffer size for
23 * serial communication is only 4096 bytes large. Error: (App asks for
24 * a 104,000 bytes size buffer, Wine returns "OK", App asks "How many char's
25 * are in the buffer", Wine returns "4000" and App thinks "OK, another
26 * 100,000 chars left, good!")
27 * The solution below is a bad but working quickfix for the transmit buffer:
28 * the cbInQueue is saved in a variable; when the program asks how many chars
29 * there are in the buffer, GetCommError returns # in buffer PLUS
30 * the additional (cbOutQeueu - 4096), which leaves the application thinking
32 * Sorry for the rather chatty explanation - but I think comm.c needs to be
33 * redefined with real working buffers make it work; maybe these comments are
49 #ifdef HAVE_SYS_FILIO_H
50 # include <sys/filio.h>
52 #include <sys/ioctl.h>
57 #ifdef HAVE_SYS_MODEM_H
58 # include <sys/modem.h>
60 #ifdef HAVE_SYS_STRTIO_H
61 # include <sys/strtio.h>
68 #define TIOCINQ FIONREAD
70 #define msr 35 /* offset in unknown structure commMask */
72 * [RER] These are globals are wrong. They should be in DosDeviceStruct
73 * on a per port basis.
75 int commerror = 0, eventmask = 0;
78 * [V] If above globals are wrong, the one below will be wrong as well. It
79 * should probably be in the DosDeviceStruct on per port basis too.
81 int iGlobalOutQueueFiller;
83 #define SERIAL_XMIT_SIZE 4096
85 struct DosDeviceStruct COM[MAX_PORTS];
86 struct DosDeviceStruct LPT[MAX_PORTS];
87 LPCVOID *unknown[MAX_PORTS];
92 char option[10], temp[256], *btemp;
95 for (x=0; x!=MAX_PORTS; x++) {
96 strcpy(option,"COMx");
100 PROFILE_GetWineIniString( "serialports", option, "*",
101 temp, sizeof(temp) );
102 if (!strcmp(temp, "*") || *temp == '\0')
103 COM[x].devicename = NULL;
105 btemp = strchr(temp,',');
108 COM[x].baudrate = atoi(btemp);
110 COM[x].baudrate = -1;
113 if (!S_ISCHR(st.st_mode))
114 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
116 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
117 WARN(comm,"Can't malloc for device info!\n");
120 strcpy(COM[x].devicename, temp);
122 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
125 strcpy(option, "LPTx");
129 PROFILE_GetWineIniString( "parallelports", option, "*",
130 temp, sizeof(temp) );
131 if (!strcmp(temp, "*") || *temp == '\0')
132 LPT[x].devicename = NULL;
135 if (!S_ISCHR(st.st_mode))
136 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
138 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
139 WARN(comm,"Can't malloc for device info!\n");
142 strcpy(LPT[x].devicename, temp);
144 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
151 struct DosDeviceStruct *GetDeviceStruct(int fd)
155 for (x=0; x!=MAX_PORTS; x++) {
165 int GetCommPort(int fd)
169 for (x=0; x<MAX_PORTS; x++) {
177 int ValidCOMPort(int x)
179 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
182 int ValidLPTPort(int x)
184 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
189 TRACE(comm, "errno = %d\n", errno);
196 /**************************************************************************
197 * BuildCommDCB (USER.213)
199 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
201 /* "COM1:9600,n,8,1" */
204 char *ptr, temp[256];
206 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
209 if (!lstrncmpi32A(device,"COM",3)) {
210 port = device[3] - '0';
214 ERR(comm, "BUG ! COM0 can't exists!.\n");
215 commerror = IE_BADID;
218 if (!ValidCOMPort(port)) {
219 commerror = IE_BADID;
223 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
226 OpenComm(device, 0, 0);
228 lpdcb->Id = COM[port].fd;
233 if (*(device+4) != ':')
236 strcpy(temp,device+5);
237 ptr = strtok(temp, ", ");
239 if (COM[port].baudrate > 0)
240 lpdcb->BaudRate = COM[port].baudrate;
242 lpdcb->BaudRate = atoi(ptr);
243 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
245 ptr = strtok(NULL, ", ");
247 *ptr = toupper(*ptr);
249 TRACE(comm,"parity (%c)\n", *ptr);
253 lpdcb->Parity = NOPARITY;
257 lpdcb->Parity = EVENPARITY;
260 lpdcb->Parity = MARKPARITY;
263 lpdcb->Parity = ODDPARITY;
266 WARN(comm,"Unknown parity `%c'!\n", *ptr);
270 ptr = strtok(NULL, ", ");
271 TRACE(comm, "charsize (%c)\n", *ptr);
272 lpdcb->ByteSize = *ptr - '0';
274 ptr = strtok(NULL, ", ");
275 TRACE(comm, "stopbits (%c)\n", *ptr);
278 lpdcb->StopBits = ONESTOPBIT;
281 lpdcb->StopBits = TWOSTOPBITS;
284 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
292 /**************************************************************************
293 * BuildCommDCBA (KERNEL32.14)
295 BOOL32 WINAPI BuildCommDCB32A(LPCSTR device,LPDCB32 lpdcb)
297 return BuildCommDCBAndTimeouts32A(device,lpdcb,NULL);
300 /**************************************************************************
301 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
303 BOOL32 WINAPI BuildCommDCBAndTimeouts32A(LPCSTR device, LPDCB32 lpdcb,
304 LPCOMMTIMEOUTS lptimeouts)
309 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
312 if (!lstrncmpi32A(device,"COM",3)) {
315 ERR(comm,"BUG! COM0 can't exists!.\n");
318 if (!ValidCOMPort(port))
320 if (*(device+4)!=':')
322 temp=(LPSTR)(device+5);
326 memset(lpdcb, 0, sizeof(DCB32)); /* initialize */
328 lpdcb->DCBlength = sizeof(DCB32);
329 if (strchr(temp,',')) { /* old style */
332 char last=temp[strlen(temp)-1];
334 ret=BuildCommDCB16(device,&dcb16);
337 lpdcb->BaudRate = dcb16.BaudRate;
338 lpdcb->ByteSize = dcb16.ByteSize;
339 lpdcb->fBinary = dcb16.fBinary;
340 lpdcb->Parity = dcb16.Parity;
341 lpdcb->fParity = dcb16.fParity;
342 lpdcb->fNull = dcb16.fNull;
343 lpdcb->StopBits = dcb16.StopBits;
347 lpdcb->fOutxCtsFlow = FALSE;
348 lpdcb->fOutxDsrFlow = FALSE;
349 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
350 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
351 } else if (last=='p') {
353 lpdcb->fOutX = FALSE;
354 lpdcb->fOutxCtsFlow = TRUE;
355 lpdcb->fOutxDsrFlow = TRUE;
356 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
357 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
360 lpdcb->fOutX = FALSE;
361 lpdcb->fOutxCtsFlow = FALSE;
362 lpdcb->fOutxDsrFlow = FALSE;
363 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
364 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
366 lpdcb->XonChar = dcb16.XonChar;
367 lpdcb->XoffChar = dcb16.XoffChar;
368 lpdcb->ErrorChar= dcb16.PeChar;
369 lpdcb->fErrorChar= dcb16.fPeChar;
370 lpdcb->EofChar = dcb16.EofChar;
371 lpdcb->EvtChar = dcb16.EvtChar;
372 lpdcb->XonLim = dcb16.XonLim;
373 lpdcb->XoffLim = dcb16.XoffLim;
376 ptr=strtok(temp," ");
381 if (!strncmp("baud=",ptr,5)) {
382 if (!sscanf(ptr+5,"%ld",&x))
383 WARN(comm,"Couldn't parse %s\n",ptr);
387 if (!strncmp("stop=",ptr,5)) {
388 if (!sscanf(ptr+5,"%ld",&x))
389 WARN(comm,"Couldn't parse %s\n",ptr);
393 if (!strncmp("data=",ptr,5)) {
394 if (!sscanf(ptr+5,"%ld",&x))
395 WARN(comm,"Couldn't parse %s\n",ptr);
399 if (!strncmp("parity=",ptr,7)) {
400 lpdcb->fParity = TRUE;
403 lpdcb->fParity = FALSE;
404 lpdcb->Parity = NOPARITY;
407 lpdcb->Parity = EVENPARITY;
410 lpdcb->Parity = ODDPARITY;
413 lpdcb->Parity = MARKPARITY;
419 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
420 ptr=strtok(NULL," ");
422 if (lpdcb->BaudRate==110)
427 /**************************************************************************
428 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
430 BOOL32 WINAPI BuildCommDCBAndTimeouts32W( LPCWSTR devid, LPDCB32 lpdcb,
431 LPCOMMTIMEOUTS lptimeouts )
436 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
437 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
438 ret=BuildCommDCBAndTimeouts32A(devidA,lpdcb,lptimeouts);
439 HeapFree( GetProcessHeap(), 0, devidA );
443 /**************************************************************************
444 * BuildCommDCBW (KERNEL32.17)
446 BOOL32 WINAPI BuildCommDCB32W(LPCWSTR devid,LPDCB32 lpdcb)
448 return BuildCommDCBAndTimeouts32W(devid,lpdcb,NULL);
451 /*****************************************************************************
452 * OpenComm (USER.200)
454 INT16 WINAPI OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
458 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
461 if (!lstrncmpi32A(device,"COM",3)) {
462 port = device[3] - '0';
465 ERR(comm, "BUG ! COM0 doesn't exist !\n");
466 commerror = IE_BADID;
469 /* to help GetCommError return left buffsize [V] */
470 iGlobalOutQueueFiller = (cbOutQueue - SERIAL_XMIT_SIZE);
471 if (iGlobalOutQueueFiller < 0) iGlobalOutQueueFiller = 0;
473 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
475 if (!ValidCOMPort(port)) {
476 commerror = IE_BADID;
483 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
485 commerror = WinError();
488 unknown[port] = SEGPTR_ALLOC(40);
489 bzero(unknown[port],40);
495 if (!lstrncmpi32A(device,"LPT",3)) {
496 port = device[3] - '0';
498 if (!ValidLPTPort(port)) {
499 commerror = IE_BADID;
507 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
509 commerror = WinError();
519 /*****************************************************************************
520 * CloseComm (USER.207)
522 INT16 WINAPI CloseComm(INT16 fd)
525 TRACE(comm,"fd %d\n", fd);
526 if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
527 SEGPTR_FREE(unknown[port]);
528 COM[port].fd = 0; /* my adaptation of RER's fix */
530 commerror = IE_BADID;
534 if (close(fd) == -1) {
535 commerror = WinError();
543 /*****************************************************************************
544 * SetCommBreak (USER.210)
546 INT16 WINAPI SetCommBreak16(INT16 fd)
548 struct DosDeviceStruct *ptr;
550 TRACE(comm,"fd=%d\n", fd);
551 if ((ptr = GetDeviceStruct(fd)) == NULL) {
552 commerror = IE_BADID;
561 /*****************************************************************************
562 * SetCommBreak (KERNEL32.449)
564 BOOL32 WINAPI SetCommBreak32(INT32 fd)
567 struct DosDeviceStruct *ptr;
569 TRACE(comm,"fd=%d\n", fd);
570 if ((ptr = GetDeviceStruct(fd)) == NULL) {
571 commerror = IE_BADID;
580 /*****************************************************************************
581 * ClearCommBreak (USER.211)
583 INT16 WINAPI ClearCommBreak16(INT16 fd)
585 struct DosDeviceStruct *ptr;
587 TRACE(comm,"fd=%d\n", fd);
588 if ((ptr = GetDeviceStruct(fd)) == NULL) {
589 commerror = IE_BADID;
598 /*****************************************************************************
599 * ClearCommBreak (KERNEL32.20)
601 BOOL32 WINAPI ClearCommBreak32(INT32 fd)
603 struct DosDeviceStruct *ptr;
605 TRACE(comm,"fd=%d\n", fd);
606 if ((ptr = GetDeviceStruct(fd)) == NULL) {
607 commerror = IE_BADID;
616 /*****************************************************************************
617 * EscapeCommFunction (USER.214)
619 LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
624 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
625 if (tcgetattr(fd,&port) == -1) {
626 commerror=WinError();
635 for (max = MAX_PORTS;!COM[max].devicename;max--)
641 for (max = MAX_PORTS;!LPT[max].devicename;max--)
648 port.c_cflag &= TIOCM_DTR;
654 port.c_cflag &= TIOCM_RTS;
660 port.c_cflag |= CRTSCTS;
664 port.c_cflag |= CRTSCTS;
669 port.c_iflag |= IXOFF;
673 port.c_iflag |= IXON;
677 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
682 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
683 commerror = WinError();
691 /*****************************************************************************
692 * EscapeCommFunction (KERNEL32.214)
694 BOOL32 WINAPI EscapeCommFunction32(INT32 fd,UINT32 nFunction)
697 struct DosDeviceStruct *ptr;
699 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
700 if (tcgetattr(fd,&port) == -1) {
701 commerror=WinError();
704 if ((ptr = GetDeviceStruct(fd)) == NULL) {
705 commerror = IE_BADID;
715 port.c_cflag &= TIOCM_DTR;
721 port.c_cflag &= TIOCM_RTS;
727 port.c_cflag |= CRTSCTS;
731 port.c_cflag |= CRTSCTS;
736 port.c_iflag |= IXOFF;
740 port.c_iflag |= IXON;
749 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
754 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
755 commerror = WinError();
763 /*****************************************************************************
764 * FlushComm (USER.215)
766 INT16 WINAPI FlushComm(INT16 fd,INT16 fnQueue)
770 TRACE(comm,"fd=%d, queue=%d\n", fd, fnQueue);
772 case 0: queue = TCOFLUSH;
774 case 1: queue = TCIFLUSH;
776 default:WARN(comm,"(fd=%d,fnQueue=%d):Unknown queue\n",
780 if (tcflush(fd, queue)) {
781 commerror = WinError();
789 /********************************************************************
790 * PurgeComm (KERNEL32.557)
792 BOOL32 WINAPI PurgeComm( HANDLE32 hFile, DWORD flags)
794 FIXME(comm, "(%08x %08lx) unimplemented stub\n",
799 /********************************************************************
800 * GetCommError (USER.203)
802 INT16 WINAPI GetCommError(INT16 fd,LPCOMSTAT lpStat)
811 rc = ioctl(fd, TIOCOUTQ, &cnt);
812 if (rc) WARN(comm, "Error !\n");
813 lpStat->cbOutQue = cnt + iGlobalOutQueueFiller;
815 rc = ioctl(fd, TIOCINQ, &cnt);
816 if (rc) WARN(comm, "Error !\n");
817 lpStat->cbInQue = cnt;
819 TRACE(comm, "fd %d, error %d, lpStat %d %d %d\n",
820 fd, commerror, lpStat->status, lpStat->cbInQue,
824 TRACE(comm, "fd %d, error %d, lpStat NULL\n",
828 * [RER] I have no idea what the following is trying to accomplish.
829 * [RER] It is certainly not what the reference manual suggests.
831 temperror = commerror;
836 /*****************************************************************************
837 * ClearCommError (KERNEL32.21)
839 BOOL32 WINAPI ClearCommError(INT32 fd,LPDWORD errors,LPCOMSTAT lpStat)
843 TRACE(comm, "fd %d (current error %d)\n",
845 temperror = commerror;
850 /*****************************************************************************
851 * SetCommEventMask (USER.208)
853 SEGPTR WINAPI SetCommEventMask(INT16 fd,UINT16 fuEvtMask)
859 TRACE(comm,"fd %d,mask %d\n",fd,fuEvtMask);
860 eventmask |= fuEvtMask;
861 if ((act = GetCommPort(fd)) == -1) {
862 WARN(comm," fd %d not comm port\n",act);
864 stol = (unsigned char *)unknown[act];
866 repid = ioctl(fd,TIOCMGET,&mstat);
867 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
868 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
870 TRACE(comm," modem dcd construct %x\n",*stol);
871 return SEGPTR_GET(unknown[act]);
874 /*****************************************************************************
875 * GetCommEventMask (USER.209)
877 UINT16 WINAPI GetCommEventMask(INT16 fd,UINT16 fnEvtClear)
881 TRACE(comm, "fd %d, mask %d\n", fd, fnEvtClear);
884 * Determine if any characters are available
886 if (fnEvtClear & EV_RXCHAR)
891 rc = ioctl(fd, TIOCINQ, &cnt);
892 if (cnt) events |= EV_RXCHAR;
894 TRACE(comm, "rxchar %ld\n", cnt);
898 * There are other events that need to be checked for
902 TRACE(comm, "return events %d\n", events);
906 * [RER] The following was gibberish
909 tempmask = eventmask;
910 eventmask &= ~fnEvtClear;
915 /*****************************************************************************
916 * SetupComm (KERNEL32.676)
918 BOOL32 WINAPI SetupComm( HANDLE32 hFile, DWORD insize, DWORD outsize)
920 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
924 /*****************************************************************************
925 * GetCommMask (KERNEL32.156)
927 BOOL32 WINAPI GetCommMask(INT32 fd,LPDWORD evtmask)
929 TRACE(comm, "fd %d, mask %p\n", fd, evtmask);
930 *evtmask = eventmask;
934 /*****************************************************************************
935 * SetCommMask (KERNEL32.451)
937 BOOL32 WINAPI SetCommMask(INT32 fd,DWORD evtmask)
939 TRACE(comm, "fd %d, mask %lx\n", fd, evtmask);
944 /*****************************************************************************
945 * SetCommState16 (USER.201)
947 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
950 struct DosDeviceStruct *ptr;
952 TRACE(comm, "fd %d, ptr %p\n", lpdcb->Id, lpdcb);
953 if (tcgetattr(lpdcb->Id, &port) == -1) {
954 commerror = WinError();
959 port.c_cc[VTIME] = 1;
962 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
964 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
966 port.c_iflag |= (IGNBRK);
968 port.c_oflag &= ~(OPOST);
970 port.c_cflag &= ~(HUPCL);
971 port.c_cflag |= CLOCAL | CREAD;
973 port.c_lflag &= ~(ICANON|ECHO|ISIG);
974 port.c_lflag |= NOFLSH;
976 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
977 commerror = IE_BADID;
980 if (ptr->baudrate > 0)
981 lpdcb->BaudRate = ptr->baudrate;
982 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
984 port.c_cflag &= ~CBAUD;
985 switch (lpdcb->BaudRate) {
988 port.c_cflag |= B110;
992 port.c_cflag |= B300;
996 port.c_cflag |= B600;
1000 port.c_cflag |= B1200;
1004 port.c_cflag |= B2400;
1008 port.c_cflag |= B4800;
1012 port.c_cflag |= B9600;
1016 port.c_cflag |= B19200;
1020 port.c_cflag |= B38400;
1023 port.c_cflag |= B57600;
1026 port.c_cflag |= B115200;
1029 commerror = IE_BAUDRATE;
1032 #elif !defined(__EMX__)
1033 switch (lpdcb->BaudRate) {
1036 port.c_ospeed = B110;
1040 port.c_ospeed = B300;
1044 port.c_ospeed = B600;
1048 port.c_ospeed = B1200;
1052 port.c_ospeed = B2400;
1056 port.c_ospeed = B4800;
1060 port.c_ospeed = B9600;
1064 port.c_ospeed = B19200;
1068 port.c_ospeed = B38400;
1071 commerror = IE_BAUDRATE;
1074 port.c_ispeed = port.c_ospeed;
1076 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1077 port.c_cflag &= ~CSIZE;
1078 switch (lpdcb->ByteSize) {
1080 port.c_cflag |= CS5;
1083 port.c_cflag |= CS6;
1086 port.c_cflag |= CS7;
1089 port.c_cflag |= CS8;
1092 commerror = IE_BYTESIZE;
1096 TRACE(comm,"parity %d\n",lpdcb->Parity);
1097 port.c_cflag &= ~(PARENB | PARODD);
1099 switch (lpdcb->Parity) {
1101 port.c_iflag &= ~INPCK;
1104 port.c_cflag |= (PARENB | PARODD);
1105 port.c_iflag |= INPCK;
1108 port.c_cflag |= PARENB;
1109 port.c_iflag |= INPCK;
1112 commerror = IE_BYTESIZE;
1117 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1119 switch (lpdcb->StopBits) {
1121 port.c_cflag &= ~CSTOPB;
1124 port.c_cflag |= CSTOPB;
1127 commerror = IE_BYTESIZE;
1132 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1133 port.c_cflag |= CRTSCTS;
1135 if (lpdcb->fDtrDisable)
1136 port.c_cflag &= ~CRTSCTS;
1139 port.c_iflag |= IXON;
1141 port.c_iflag &= ~IXON;
1143 port.c_iflag |= IXOFF;
1145 port.c_iflag &= ~IXOFF;
1147 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
1148 commerror = WinError();
1156 /*****************************************************************************
1157 * SetCommState32 (KERNEL32.452)
1159 BOOL32 WINAPI SetCommState32(INT32 fd,LPDCB32 lpdcb)
1161 struct termios port;
1162 struct DosDeviceStruct *ptr;
1164 TRACE(comm,"fd %d, ptr %p\n",fd,lpdcb);
1165 if (tcgetattr(fd,&port) == -1) {
1166 commerror = WinError();
1170 port.c_cc[VMIN] = 0;
1171 port.c_cc[VTIME] = 1;
1174 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1176 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1178 port.c_iflag |= (IGNBRK);
1180 port.c_oflag &= ~(OPOST);
1182 port.c_cflag &= ~(HUPCL);
1183 port.c_cflag |= CLOCAL | CREAD;
1185 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1186 port.c_lflag |= NOFLSH;
1188 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1189 commerror = IE_BADID;
1192 if (ptr->baudrate > 0)
1193 lpdcb->BaudRate = ptr->baudrate;
1194 TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1196 port.c_cflag &= ~CBAUD;
1197 switch (lpdcb->BaudRate) {
1200 port.c_cflag |= B110;
1204 port.c_cflag |= B300;
1208 port.c_cflag |= B600;
1212 port.c_cflag |= B1200;
1216 port.c_cflag |= B2400;
1220 port.c_cflag |= B4800;
1224 port.c_cflag |= B9600;
1228 port.c_cflag |= B19200;
1232 port.c_cflag |= B38400;
1235 commerror = IE_BAUDRATE;
1238 #elif !defined(__EMX__)
1239 switch (lpdcb->BaudRate) {
1242 port.c_ospeed = B110;
1246 port.c_ospeed = B300;
1250 port.c_ospeed = B600;
1254 port.c_ospeed = B1200;
1258 port.c_ospeed = B2400;
1262 port.c_ospeed = B4800;
1266 port.c_ospeed = B9600;
1270 port.c_ospeed = B19200;
1274 port.c_ospeed = B38400;
1277 commerror = IE_BAUDRATE;
1280 port.c_ispeed = port.c_ospeed;
1282 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1283 port.c_cflag &= ~CSIZE;
1284 switch (lpdcb->ByteSize) {
1286 port.c_cflag |= CS5;
1289 port.c_cflag |= CS6;
1292 port.c_cflag |= CS7;
1295 port.c_cflag |= CS8;
1298 commerror = IE_BYTESIZE;
1302 TRACE(comm,"parity %d\n",lpdcb->Parity);
1303 port.c_cflag &= ~(PARENB | PARODD);
1305 switch (lpdcb->Parity) {
1307 port.c_iflag &= ~INPCK;
1310 port.c_cflag |= (PARENB | PARODD);
1311 port.c_iflag |= INPCK;
1314 port.c_cflag |= PARENB;
1315 port.c_iflag |= INPCK;
1318 commerror = IE_BYTESIZE;
1323 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1324 switch (lpdcb->StopBits) {
1326 port.c_cflag &= ~CSTOPB;
1329 port.c_cflag |= CSTOPB;
1332 commerror = IE_BYTESIZE;
1336 if ( lpdcb->fOutxCtsFlow ||
1337 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1338 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1340 port.c_cflag |= CRTSCTS;
1341 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1342 port.c_cflag &= ~CRTSCTS;
1346 port.c_iflag |= IXON;
1348 port.c_iflag &= ~IXON;
1350 port.c_iflag |= IXOFF;
1352 port.c_iflag &= ~IXOFF;
1354 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1355 commerror = WinError();
1364 /*****************************************************************************
1365 * GetCommState (USER.202)
1367 INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
1369 struct termios port;
1371 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1372 if (tcgetattr(fd, &port) == -1) {
1373 commerror = WinError();
1379 switch (port.c_cflag & CBAUD) {
1381 switch (port.c_ospeed) {
1384 lpdcb->BaudRate = 110;
1387 lpdcb->BaudRate = 300;
1390 lpdcb->BaudRate = 600;
1393 lpdcb->BaudRate = 1200;
1396 lpdcb->BaudRate = 2400;
1399 lpdcb->BaudRate = 4800;
1402 lpdcb->BaudRate = 9600;
1405 lpdcb->BaudRate = 19200;
1408 lpdcb->BaudRate = 38400;
1411 lpdcb->BaudRate = 57600;
1414 lpdcb->BaudRate = 57601;
1418 switch (port.c_cflag & CSIZE) {
1420 lpdcb->ByteSize = 5;
1423 lpdcb->ByteSize = 6;
1426 lpdcb->ByteSize = 7;
1429 lpdcb->ByteSize = 8;
1433 switch (port.c_cflag & ~(PARENB | PARODD)) {
1435 lpdcb->fParity = NOPARITY;
1438 lpdcb->fParity = EVENPARITY;
1440 case (PARENB | PARODD):
1441 lpdcb->fParity = ODDPARITY;
1445 if (port.c_cflag & CSTOPB)
1446 lpdcb->StopBits = TWOSTOPBITS;
1448 lpdcb->StopBits = ONESTOPBIT;
1450 lpdcb->RlsTimeout = 50;
1451 lpdcb->CtsTimeout = 50;
1452 lpdcb->DsrTimeout = 50;
1456 lpdcb->fDtrDisable = 0;
1460 if (port.c_cflag & CRTSCTS) {
1461 lpdcb->fDtrflow = 1;
1462 lpdcb->fRtsflow = 1;
1463 lpdcb->fOutxCtsFlow = 1;
1464 lpdcb->fOutxDsrFlow = 1;
1467 lpdcb->fDtrDisable = 1;
1469 if (port.c_iflag & IXON)
1474 if (port.c_iflag & IXOFF)
1483 lpdcb->XoffLim = 10;
1489 /*****************************************************************************
1490 * GetCommState (KERNEL32.159)
1492 BOOL32 WINAPI GetCommState32(INT32 fd, LPDCB32 lpdcb)
1494 struct termios port;
1496 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1497 if (GetDeviceStruct(fd) == NULL) return FALSE;
1498 if (tcgetattr(fd, &port) == -1) {
1499 commerror = WinError();
1504 switch (port.c_cflag & CBAUD) {
1506 switch (port.c_ospeed) {
1509 lpdcb->BaudRate = 110;
1512 lpdcb->BaudRate = 300;
1515 lpdcb->BaudRate = 600;
1518 lpdcb->BaudRate = 1200;
1521 lpdcb->BaudRate = 2400;
1524 lpdcb->BaudRate = 4800;
1527 lpdcb->BaudRate = 9600;
1530 lpdcb->BaudRate = 19200;
1533 lpdcb->BaudRate = 38400;
1537 switch (port.c_cflag & CSIZE) {
1539 lpdcb->ByteSize = 5;
1542 lpdcb->ByteSize = 6;
1545 lpdcb->ByteSize = 7;
1548 lpdcb->ByteSize = 8;
1552 switch (port.c_cflag & ~(PARENB | PARODD)) {
1554 lpdcb->fParity = NOPARITY;
1557 lpdcb->fParity = EVENPARITY;
1559 case (PARENB | PARODD):
1560 lpdcb->fParity = ODDPARITY;
1564 if (port.c_cflag & CSTOPB)
1565 lpdcb->StopBits = TWOSTOPBITS;
1567 lpdcb->StopBits = ONESTOPBIT;
1574 if (port.c_cflag & CRTSCTS) {
1575 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1576 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1577 lpdcb->fOutxCtsFlow = 1;
1578 lpdcb->fOutxDsrFlow = 1;
1582 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1583 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1585 if (port.c_iflag & IXON)
1590 if (port.c_iflag & IXOFF)
1599 lpdcb->XoffLim = 10;
1605 /*****************************************************************************
1606 * TransmitCommChar (USER.206)
1608 INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
1610 struct DosDeviceStruct *ptr;
1612 TRACE(comm, "fd %d, data %d \n", fd, chTransmit);
1613 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1614 commerror = IE_BADID;
1618 if (ptr->suspended) {
1619 commerror = IE_HARDWARE;
1623 if (write(fd, (void *) &chTransmit, 1) == -1) {
1624 commerror = WinError();
1632 /*****************************************************************************
1633 * TransmitCommChar (KERNEL32.535)
1635 BOOL32 WINAPI TransmitCommChar32(INT32 fd,CHAR chTransmit)
1637 struct DosDeviceStruct *ptr;
1639 TRACE(comm,"(%d,'%c')\n",fd,chTransmit);
1640 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1641 commerror = IE_BADID;
1645 if (ptr->suspended) {
1646 commerror = IE_HARDWARE;
1649 if (write(fd, (void *) &chTransmit, 1) == -1) {
1650 commerror = WinError();
1658 /*****************************************************************************
1659 * UngetCommChar (USER.212)
1661 INT16 WINAPI UngetCommChar(INT16 fd,CHAR chUnget)
1663 struct DosDeviceStruct *ptr;
1665 TRACE(comm,"fd %d (char %d)\n", fd, chUnget);
1666 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1667 commerror = IE_BADID;
1671 if (ptr->suspended) {
1672 commerror = IE_HARDWARE;
1677 ptr->unget_byte = chUnget;
1682 /*****************************************************************************
1683 * ReadComm (USER.204)
1685 INT16 WINAPI ReadComm(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1688 struct DosDeviceStruct *ptr;
1690 TRACE(comm, "fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1691 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1692 commerror = IE_BADID;
1696 if (ptr->suspended) {
1697 commerror = IE_HARDWARE;
1702 *lpvBuf = ptr->unget_byte;
1710 status = read(fd, (void *) lpvBuf, cbRead);
1713 if (errno != EAGAIN) {
1714 commerror = WinError();
1721 TRACE(comm,"%*s\n", length+status, lpvBuf);
1723 return length + status;
1727 /*****************************************************************************
1728 * WriteComm (USER.205)
1730 INT16 WINAPI WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1733 struct DosDeviceStruct *ptr;
1735 TRACE(comm,"fd %d, ptr %p, length %d\n",
1736 fd, lpvBuf, cbWrite);
1737 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1738 commerror = IE_BADID;
1742 if (ptr->suspended) {
1743 commerror = IE_HARDWARE;
1747 TRACE(comm,"%*s\n", cbWrite, lpvBuf );
1748 length = write(fd, (void *) lpvBuf, cbWrite);
1751 commerror = WinError();
1760 /*****************************************************************************
1761 * GetCommTimeouts (KERNEL32.160)
1763 BOOL32 WINAPI GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts)
1765 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1769 /*****************************************************************************
1770 * SetCommTimeouts (KERNEL32.453)
1772 BOOL32 WINAPI SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
1773 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1777 /***********************************************************************
1778 * EnableCommNotification (USER.246)
1780 BOOL16 WINAPI EnableCommNotification( INT16 fd, HWND16 hwnd,
1781 INT16 cbWriteNotify, INT16 cbOutQueue )
1783 FIXME(comm, "(%d, %x, %d, %d):stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);