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
35 * Oktober 98, Rein Klazes [RHK]
36 * A program that wants to monitor the modem status line (RLSD/DCD) may
37 * poll the modem status register in the commMask structure. I update the bit
38 * in GetCommError, waiting for an implementation of communication events.
54 #ifdef HAVE_SYS_FILIO_H
55 # include <sys/filio.h>
57 #include <sys/ioctl.h>
60 #include "wine/winuser16.h"
62 #ifdef HAVE_SYS_MODEM_H
63 # include <sys/modem.h>
65 #ifdef HAVE_SYS_STRTIO_H
66 # include <sys/strtio.h>
72 #include "server/request.h"
78 #define TIOCINQ FIONREAD
80 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
82 * [RER] These are globals are wrong. They should be in DosDeviceStruct
83 * on a per port basis.
85 int commerror = 0, eventmask = 0;
88 * [V] If above globals are wrong, the one below will be wrong as well. It
89 * should probably be in the DosDeviceStruct on per port basis too.
91 int iGlobalOutQueueFiller;
93 #define SERIAL_XMIT_SIZE 4096
95 struct DosDeviceStruct COM[MAX_PORTS];
96 struct DosDeviceStruct LPT[MAX_PORTS];
97 /* pointers to unknown(==undocumented) comm structure */
98 LPCVOID *unknown[MAX_PORTS];
99 /* save terminal states */
100 static struct termios m_stat[MAX_PORTS];
105 char option[10], temp[256], *btemp;
108 for (x=0; x!=MAX_PORTS; x++) {
109 strcpy(option,"COMx");
113 PROFILE_GetWineIniString( "serialports", option, "*",
114 temp, sizeof(temp) );
115 if (!strcmp(temp, "*") || *temp == '\0')
116 COM[x].devicename = NULL;
118 btemp = strchr(temp,',');
121 COM[x].baudrate = atoi(btemp);
123 COM[x].baudrate = -1;
126 if (!S_ISCHR(st.st_mode))
127 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
129 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
130 WARN(comm,"Can't malloc for device info!\n");
133 strcpy(COM[x].devicename, temp);
135 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
138 strcpy(option, "LPTx");
142 PROFILE_GetWineIniString( "parallelports", option, "*",
143 temp, sizeof(temp) );
144 if (!strcmp(temp, "*") || *temp == '\0')
145 LPT[x].devicename = NULL;
148 if (!S_ISCHR(st.st_mode))
149 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
151 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
152 WARN(comm,"Can't malloc for device info!\n");
155 strcpy(LPT[x].devicename, temp);
157 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
164 struct DosDeviceStruct *GetDeviceStruct(int fd)
168 for (x=0; x!=MAX_PORTS; x++) {
178 int GetCommPort(int fd)
182 for (x=0; x<MAX_PORTS; x++) {
190 int ValidCOMPort(int x)
192 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
195 int ValidLPTPort(int x)
197 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
202 TRACE(comm, "errno = %d\n", errno);
209 /**************************************************************************
210 * BuildCommDCB (USER.213)
212 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
214 /* "COM1:9600,n,8,1" */
217 char *ptr, temp[256];
219 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
222 if (!lstrncmpiA(device,"COM",3)) {
223 port = device[3] - '0';
227 ERR(comm, "BUG ! COM0 can't exists!.\n");
228 commerror = IE_BADID;
231 if (!ValidCOMPort(port)) {
232 commerror = IE_BADID;
236 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
239 OpenComm16(device, 0, 0);
241 lpdcb->Id = COM[port].fd;
246 if (*(device+4) != ':')
249 strcpy(temp,device+5);
250 ptr = strtok(temp, ", ");
252 if (COM[port].baudrate > 0)
253 lpdcb->BaudRate = COM[port].baudrate;
255 lpdcb->BaudRate = atoi(ptr);
256 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
258 ptr = strtok(NULL, ", ");
260 *ptr = toupper(*ptr);
262 TRACE(comm,"parity (%c)\n", *ptr);
263 lpdcb->fParity = TRUE;
266 lpdcb->Parity = NOPARITY;
267 lpdcb->fParity = FALSE;
270 lpdcb->Parity = EVENPARITY;
273 lpdcb->Parity = MARKPARITY;
276 lpdcb->Parity = ODDPARITY;
279 WARN(comm,"Unknown parity `%c'!\n", *ptr);
283 ptr = strtok(NULL, ", ");
284 TRACE(comm, "charsize (%c)\n", *ptr);
285 lpdcb->ByteSize = *ptr - '0';
287 ptr = strtok(NULL, ", ");
288 TRACE(comm, "stopbits (%c)\n", *ptr);
291 lpdcb->StopBits = ONESTOPBIT;
294 lpdcb->StopBits = TWOSTOPBITS;
297 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
305 /**************************************************************************
306 * BuildCommDCBA (KERNEL32.14)
308 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
310 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
313 /**************************************************************************
314 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
316 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
317 LPCOMMTIMEOUTS lptimeouts)
322 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
325 if (!lstrncmpiA(device,"COM",3)) {
328 ERR(comm,"BUG! COM0 can't exists!.\n");
331 if (!ValidCOMPort(port))
333 if (*(device+4)!=':')
335 temp=(LPSTR)(device+5);
339 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
341 lpdcb->DCBlength = sizeof(DCB);
342 if (strchr(temp,',')) { /* old style */
345 char last=temp[strlen(temp)-1];
347 ret=BuildCommDCB16(device,&dcb16);
350 lpdcb->BaudRate = dcb16.BaudRate;
351 lpdcb->ByteSize = dcb16.ByteSize;
352 lpdcb->fBinary = dcb16.fBinary;
353 lpdcb->Parity = dcb16.Parity;
354 lpdcb->fParity = dcb16.fParity;
355 lpdcb->fNull = dcb16.fNull;
356 lpdcb->StopBits = dcb16.StopBits;
360 lpdcb->fOutxCtsFlow = FALSE;
361 lpdcb->fOutxDsrFlow = FALSE;
362 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
363 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
364 } else if (last=='p') {
366 lpdcb->fOutX = FALSE;
367 lpdcb->fOutxCtsFlow = TRUE;
368 lpdcb->fOutxDsrFlow = TRUE;
369 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
370 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
373 lpdcb->fOutX = FALSE;
374 lpdcb->fOutxCtsFlow = FALSE;
375 lpdcb->fOutxDsrFlow = FALSE;
376 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
377 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
379 lpdcb->XonChar = dcb16.XonChar;
380 lpdcb->XoffChar = dcb16.XoffChar;
381 lpdcb->ErrorChar= dcb16.PeChar;
382 lpdcb->fErrorChar= dcb16.fPeChar;
383 lpdcb->EofChar = dcb16.EofChar;
384 lpdcb->EvtChar = dcb16.EvtChar;
385 lpdcb->XonLim = dcb16.XonLim;
386 lpdcb->XoffLim = dcb16.XoffLim;
389 ptr=strtok(temp," ");
394 if (!strncmp("baud=",ptr,5)) {
395 if (!sscanf(ptr+5,"%ld",&x))
396 WARN(comm,"Couldn't parse %s\n",ptr);
400 if (!strncmp("stop=",ptr,5)) {
401 if (!sscanf(ptr+5,"%ld",&x))
402 WARN(comm,"Couldn't parse %s\n",ptr);
406 if (!strncmp("data=",ptr,5)) {
407 if (!sscanf(ptr+5,"%ld",&x))
408 WARN(comm,"Couldn't parse %s\n",ptr);
412 if (!strncmp("parity=",ptr,7)) {
413 lpdcb->fParity = TRUE;
416 lpdcb->fParity = FALSE;
417 lpdcb->Parity = NOPARITY;
420 lpdcb->Parity = EVENPARITY;
423 lpdcb->Parity = ODDPARITY;
426 lpdcb->Parity = MARKPARITY;
432 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
433 ptr=strtok(NULL," ");
435 if (lpdcb->BaudRate==110)
440 /**************************************************************************
441 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
443 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
444 LPCOMMTIMEOUTS lptimeouts )
449 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
450 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
451 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
452 HeapFree( GetProcessHeap(), 0, devidA );
456 /**************************************************************************
457 * BuildCommDCBW (KERNEL32.17)
459 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
461 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
464 /*****************************************************************************
465 * OpenComm (USER.200)
467 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
471 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
474 if (!lstrncmpiA(device,"COM",3)) {
475 port = device[3] - '0';
478 ERR(comm, "BUG ! COM0 doesn't exist !\n");
479 commerror = IE_BADID;
482 /* to help GetCommError return left buffsize [V] */
483 iGlobalOutQueueFiller = (cbOutQueue - SERIAL_XMIT_SIZE);
484 if (iGlobalOutQueueFiller < 0) iGlobalOutQueueFiller = 0;
486 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
488 if (!ValidCOMPort(port)) {
489 commerror = IE_BADID;
496 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
498 commerror = WinError();
501 unknown[port] = SEGPTR_ALLOC(40);
502 bzero(unknown[port],40);
504 /* save terminal state */
505 tcgetattr(fd,&m_stat[port]);
510 if (!lstrncmpiA(device,"LPT",3)) {
511 port = device[3] - '0';
513 if (!ValidLPTPort(port)) {
514 commerror = IE_BADID;
522 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
524 commerror = WinError();
534 /*****************************************************************************
535 * CloseComm (USER.207)
537 INT16 WINAPI CloseComm16(INT16 fd)
541 TRACE(comm,"fd %d\n", fd);
542 if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
543 SEGPTR_FREE(unknown[port]);
544 COM[port].fd = 0; /* my adaptation of RER's fix */
546 commerror = IE_BADID;
550 /* reset modem lines */
551 tcsetattr(fd,TCSANOW,&m_stat[port]);
553 if (close(fd) == -1) {
554 commerror = WinError();
562 /*****************************************************************************
563 * SetCommBreak (USER.210)
565 INT16 WINAPI SetCommBreak16(INT16 fd)
567 struct DosDeviceStruct *ptr;
569 TRACE(comm,"fd=%d\n", fd);
570 if ((ptr = GetDeviceStruct(fd)) == NULL) {
571 commerror = IE_BADID;
580 /*****************************************************************************
581 * SetCommBreak (KERNEL32.449)
583 BOOL WINAPI SetCommBreak(INT fd)
586 struct DosDeviceStruct *ptr;
588 TRACE(comm,"fd=%d\n", fd);
589 if ((ptr = GetDeviceStruct(fd)) == NULL) {
590 commerror = IE_BADID;
599 /*****************************************************************************
600 * ClearCommBreak (USER.211)
602 INT16 WINAPI ClearCommBreak16(INT16 fd)
604 struct DosDeviceStruct *ptr;
606 TRACE(comm,"fd=%d\n", fd);
607 if ((ptr = GetDeviceStruct(fd)) == NULL) {
608 commerror = IE_BADID;
617 /*****************************************************************************
618 * ClearCommBreak (KERNEL32.20)
620 BOOL WINAPI ClearCommBreak(INT fd)
622 struct DosDeviceStruct *ptr;
624 TRACE(comm,"fd=%d\n", fd);
625 if ((ptr = GetDeviceStruct(fd)) == NULL) {
626 commerror = IE_BADID;
635 /*****************************************************************************
636 * EscapeCommFunction (USER.214)
638 LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
643 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
644 if (tcgetattr(fd,&port) == -1) {
645 commerror=WinError();
654 for (max = MAX_PORTS;!COM[max].devicename;max--)
660 for (max = MAX_PORTS;!LPT[max].devicename;max--)
667 port.c_cflag &= TIOCM_DTR;
673 port.c_cflag &= TIOCM_RTS;
679 port.c_cflag |= CRTSCTS;
683 port.c_cflag |= CRTSCTS;
688 port.c_iflag |= IXOFF;
692 port.c_iflag |= IXON;
696 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
701 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
702 commerror = WinError();
710 /*****************************************************************************
711 * EscapeCommFunction (KERNEL32.214)
713 BOOL WINAPI EscapeCommFunction(INT fd,UINT nFunction)
716 struct DosDeviceStruct *ptr;
718 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
719 if (tcgetattr(fd,&port) == -1) {
720 commerror=WinError();
723 if ((ptr = GetDeviceStruct(fd)) == NULL) {
724 commerror = IE_BADID;
734 port.c_cflag &= TIOCM_DTR;
740 port.c_cflag &= TIOCM_RTS;
746 port.c_cflag |= CRTSCTS;
750 port.c_cflag |= CRTSCTS;
755 port.c_iflag |= IXOFF;
759 port.c_iflag |= IXON;
768 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
773 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
774 commerror = WinError();
782 /*****************************************************************************
783 * FlushComm (USER.215)
785 INT16 WINAPI FlushComm16(INT16 fd,INT16 fnQueue)
789 TRACE(comm,"fd=%d, queue=%d\n", fd, fnQueue);
791 case 0: queue = TCOFLUSH;
793 case 1: queue = TCIFLUSH;
795 default:WARN(comm,"(fd=%d,fnQueue=%d):Unknown queue\n",
799 if (tcflush(fd, queue)) {
800 commerror = WinError();
808 /********************************************************************
809 * PurgeComm (KERNEL32.557)
811 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
814 struct get_write_fd_request req;
816 TRACE(comm,"handle %d, flags %lx\n", handle, flags);
819 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
820 CLIENT_WaitReply( NULL, &fd, 0 );
826 ** not exactly sure how these are different
827 ** Perhaps if we had our own internal queues, one flushes them
828 ** and the other flushes the kernel's buffers.
830 if(flags&PURGE_TXABORT)
832 tcflush(fd,TCOFLUSH);
834 if(flags&PURGE_RXABORT)
836 tcflush(fd,TCIFLUSH);
838 if(flags&PURGE_TXCLEAR)
840 tcflush(fd,TCOFLUSH);
842 if(flags&PURGE_RXCLEAR)
844 tcflush(fd,TCIFLUSH);
850 /********************************************************************
851 * GetCommError (USER.203)
853 INT16 WINAPI GetCommError16(INT16 fd,LPCOMSTAT16 lpStat)
862 if ((act = GetCommPort(fd)) == -1) {
863 WARN(comm," fd %d not comm port\n",fd);
866 stol = (unsigned char *)unknown[act] + COMM_MSR_OFFSET;
867 ioctl(fd,TIOCMGET,&mstat);
868 if( mstat&TIOCM_CAR )
876 rc = ioctl(fd, TIOCOUTQ, &cnt);
877 if (rc) WARN(comm, "Error !\n");
878 lpStat->cbOutQue = cnt + iGlobalOutQueueFiller;
880 rc = ioctl(fd, TIOCINQ, &cnt);
881 if (rc) WARN(comm, "Error !\n");
882 lpStat->cbInQue = cnt;
884 TRACE(comm, "fd %d, error %d, lpStat %d %d %d stol %x\n",
885 fd, commerror, lpStat->status, lpStat->cbInQue,
886 lpStat->cbOutQue, *stol);
889 TRACE(comm, "fd %d, error %d, lpStat NULL stol %x\n",
890 fd, commerror, *stol);
893 * [RER] I have no idea what the following is trying to accomplish.
894 * [RER] It is certainly not what the reference manual suggests.
896 temperror = commerror;
901 /*****************************************************************************
903 * returns a file descriptor for reading from or writing to
904 * mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
905 * the handle afterwards!
907 int COMM_Handle2fd(HANDLE handle, int mode) {
908 struct get_read_fd_request r_req;
909 struct get_write_fd_request w_req;
912 w_req.handle = r_req.handle = handle;
916 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
919 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
922 ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
925 CLIENT_WaitReply( NULL, &fd, 0 );
930 /*****************************************************************************
931 * ClearCommError (KERNEL32.21)
933 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
937 fd=COMM_Handle2fd(handle,GENERIC_READ);
947 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
948 WARN(comm, "ioctl returned error\n");
950 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
951 WARN(comm, "ioctl returned error\n");
956 TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
965 ** After an asynchronous write opperation, the
966 ** app will call ClearCommError to see if the
967 ** results are ready yet. It waits for ERROR_IO_PENDING
969 commerror = ERROR_IO_PENDING;
974 /*****************************************************************************
975 * SetCommEventMask (USER.208)
977 SEGPTR WINAPI SetCommEventMask16(INT16 fd,UINT16 fuEvtMask)
983 TRACE(comm,"fd %d,mask %d\n",fd,fuEvtMask);
984 eventmask |= fuEvtMask;
985 if ((act = GetCommPort(fd)) == -1) {
986 WARN(comm," fd %d not comm port\n",act);
987 return SEGPTR_GET(NULL);
989 stol = (unsigned char *)unknown[act];
990 stol += COMM_MSR_OFFSET;
991 repid = ioctl(fd,TIOCMGET,&mstat);
992 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
993 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
995 TRACE(comm," modem dcd construct %x\n",*stol);
996 return SEGPTR_GET(unknown[act]);
999 /*****************************************************************************
1000 * GetCommEventMask (USER.209)
1002 UINT16 WINAPI GetCommEventMask16(INT16 fd,UINT16 fnEvtClear)
1006 TRACE(comm, "fd %d, mask %d\n", fd, fnEvtClear);
1009 * Determine if any characters are available
1011 if (fnEvtClear & EV_RXCHAR)
1016 rc = ioctl(fd, TIOCINQ, &cnt);
1017 if (cnt) events |= EV_RXCHAR;
1019 TRACE(comm, "rxchar %ld\n", cnt);
1023 * There are other events that need to be checked for
1027 TRACE(comm, "return events %d\n", events);
1031 * [RER] The following was gibberish
1034 tempmask = eventmask;
1035 eventmask &= ~fnEvtClear;
1040 /*****************************************************************************
1041 * SetupComm (KERNEL32.676)
1043 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1047 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1048 fd=COMM_Handle2fd(handle,GENERIC_WRITE);
1057 /*****************************************************************************
1058 * GetCommMask (KERNEL32.156)
1060 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1064 TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
1065 if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
1070 *evtmask = eventmask;
1074 /*****************************************************************************
1075 * SetCommMask (KERNEL32.451)
1077 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1081 TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
1082 if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
1086 eventmask = evtmask;
1090 /*****************************************************************************
1091 * SetCommState16 (USER.201)
1093 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
1095 struct termios port;
1096 struct DosDeviceStruct *ptr;
1098 TRACE(comm, "fd %d, ptr %p\n", lpdcb->Id, lpdcb);
1099 if (tcgetattr(lpdcb->Id, &port) == -1) {
1100 commerror = WinError();
1104 port.c_cc[VMIN] = 0;
1105 port.c_cc[VTIME] = 1;
1108 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1110 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1112 port.c_iflag |= (IGNBRK);
1114 port.c_oflag &= ~(OPOST);
1116 port.c_cflag &= ~(HUPCL);
1117 port.c_cflag |= CLOCAL | CREAD;
1119 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1120 port.c_lflag |= NOFLSH;
1122 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
1123 commerror = IE_BADID;
1126 if (ptr->baudrate > 0)
1127 lpdcb->BaudRate = ptr->baudrate;
1128 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
1130 port.c_cflag &= ~CBAUD;
1131 switch (lpdcb->BaudRate) {
1134 port.c_cflag |= B110;
1138 port.c_cflag |= B300;
1142 port.c_cflag |= B600;
1146 port.c_cflag |= B1200;
1150 port.c_cflag |= B2400;
1154 port.c_cflag |= B4800;
1158 port.c_cflag |= B9600;
1162 port.c_cflag |= B19200;
1166 port.c_cflag |= B38400;
1170 port.c_cflag |= B57600;
1175 port.c_cflag |= B115200;
1179 commerror = IE_BAUDRATE;
1182 #elif !defined(__EMX__)
1183 switch (lpdcb->BaudRate) {
1186 port.c_ospeed = B110;
1190 port.c_ospeed = B300;
1194 port.c_ospeed = B600;
1198 port.c_ospeed = B1200;
1202 port.c_ospeed = B2400;
1206 port.c_ospeed = B4800;
1210 port.c_ospeed = B9600;
1214 port.c_ospeed = B19200;
1218 port.c_ospeed = B38400;
1221 commerror = IE_BAUDRATE;
1224 port.c_ispeed = port.c_ospeed;
1226 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1227 port.c_cflag &= ~CSIZE;
1228 switch (lpdcb->ByteSize) {
1230 port.c_cflag |= CS5;
1233 port.c_cflag |= CS6;
1236 port.c_cflag |= CS7;
1239 port.c_cflag |= CS8;
1242 commerror = IE_BYTESIZE;
1246 TRACE(comm,"parity %d\n",lpdcb->Parity);
1247 port.c_cflag &= ~(PARENB | PARODD);
1249 switch (lpdcb->Parity) {
1251 port.c_iflag &= ~INPCK;
1254 port.c_cflag |= (PARENB | PARODD);
1255 port.c_iflag |= INPCK;
1258 port.c_cflag |= PARENB;
1259 port.c_iflag |= INPCK;
1262 commerror = IE_BYTESIZE;
1267 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1269 switch (lpdcb->StopBits) {
1271 port.c_cflag &= ~CSTOPB;
1274 port.c_cflag |= CSTOPB;
1277 commerror = IE_BYTESIZE;
1282 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1283 port.c_cflag |= CRTSCTS;
1285 if (lpdcb->fDtrDisable)
1286 port.c_cflag &= ~CRTSCTS;
1289 port.c_iflag |= IXON;
1291 port.c_iflag &= ~IXON;
1293 port.c_iflag |= IXOFF;
1295 port.c_iflag &= ~IXOFF;
1297 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
1298 commerror = WinError();
1306 /*****************************************************************************
1307 * SetCommState (KERNEL32.452)
1309 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1311 struct termios port;
1313 struct get_write_fd_request req;
1315 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1317 req.handle = handle;
1318 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
1319 CLIENT_WaitReply( NULL, &fd, 0 );
1324 if (tcgetattr(fd,&port) == -1) {
1325 commerror = WinError();
1329 port.c_cc[VMIN] = 0;
1330 port.c_cc[VTIME] = 1;
1333 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1335 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1337 port.c_iflag |= (IGNBRK);
1339 port.c_oflag &= ~(OPOST);
1341 port.c_cflag &= ~(HUPCL);
1342 port.c_cflag |= CLOCAL | CREAD;
1344 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1345 port.c_lflag |= NOFLSH;
1348 ** MJM - removed default baudrate settings
1349 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1352 port.c_cflag &= ~CBAUD;
1353 switch (lpdcb->BaudRate) {
1356 port.c_cflag |= B110;
1360 port.c_cflag |= B300;
1364 port.c_cflag |= B600;
1368 port.c_cflag |= B1200;
1372 port.c_cflag |= B2400;
1376 port.c_cflag |= B4800;
1380 port.c_cflag |= B9600;
1384 port.c_cflag |= B19200;
1388 port.c_cflag |= B38400;
1391 commerror = IE_BAUDRATE;
1394 #elif !defined(__EMX__)
1395 switch (lpdcb->BaudRate) {
1398 port.c_ospeed = B110;
1402 port.c_ospeed = B300;
1406 port.c_ospeed = B600;
1410 port.c_ospeed = B1200;
1414 port.c_ospeed = B2400;
1418 port.c_ospeed = B4800;
1422 port.c_ospeed = B9600;
1426 port.c_ospeed = B19200;
1430 port.c_ospeed = B38400;
1433 commerror = IE_BAUDRATE;
1436 port.c_ispeed = port.c_ospeed;
1438 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1439 port.c_cflag &= ~CSIZE;
1440 switch (lpdcb->ByteSize) {
1442 port.c_cflag |= CS5;
1445 port.c_cflag |= CS6;
1448 port.c_cflag |= CS7;
1451 port.c_cflag |= CS8;
1454 commerror = IE_BYTESIZE;
1458 TRACE(comm,"parity %d\n",lpdcb->Parity);
1459 port.c_cflag &= ~(PARENB | PARODD);
1461 switch (lpdcb->Parity) {
1463 port.c_iflag &= ~INPCK;
1466 port.c_cflag |= (PARENB | PARODD);
1467 port.c_iflag |= INPCK;
1470 port.c_cflag |= PARENB;
1471 port.c_iflag |= INPCK;
1474 commerror = IE_BYTESIZE;
1479 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1480 switch (lpdcb->StopBits) {
1482 port.c_cflag &= ~CSTOPB;
1485 port.c_cflag |= CSTOPB;
1488 commerror = IE_BYTESIZE;
1492 if ( lpdcb->fOutxCtsFlow ||
1493 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1494 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1496 port.c_cflag |= CRTSCTS;
1497 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1498 port.c_cflag &= ~CRTSCTS;
1502 port.c_iflag |= IXON;
1504 port.c_iflag &= ~IXON;
1506 port.c_iflag |= IXOFF;
1508 port.c_iflag &= ~IXOFF;
1510 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1511 commerror = WinError();
1520 /*****************************************************************************
1521 * GetCommState (USER.202)
1523 INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
1525 struct termios port;
1527 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1528 if (tcgetattr(fd, &port) == -1) {
1529 commerror = WinError();
1535 switch (port.c_cflag & CBAUD) {
1537 switch (port.c_ospeed) {
1540 lpdcb->BaudRate = 110;
1543 lpdcb->BaudRate = 300;
1546 lpdcb->BaudRate = 600;
1549 lpdcb->BaudRate = 1200;
1552 lpdcb->BaudRate = 2400;
1555 lpdcb->BaudRate = 4800;
1558 lpdcb->BaudRate = 9600;
1561 lpdcb->BaudRate = 19200;
1564 lpdcb->BaudRate = 38400;
1568 lpdcb->BaudRate = 57600;
1573 lpdcb->BaudRate = 57601;
1578 switch (port.c_cflag & CSIZE) {
1580 lpdcb->ByteSize = 5;
1583 lpdcb->ByteSize = 6;
1586 lpdcb->ByteSize = 7;
1589 lpdcb->ByteSize = 8;
1593 switch (port.c_cflag & (PARENB | PARODD)) {
1595 lpdcb->fParity = FALSE;
1596 lpdcb->Parity = NOPARITY;
1599 lpdcb->fParity = TRUE;
1600 lpdcb->Parity = EVENPARITY;
1602 case (PARENB | PARODD):
1603 lpdcb->fParity = TRUE;
1604 lpdcb->Parity = ODDPARITY;
1608 if (port.c_cflag & CSTOPB)
1609 lpdcb->StopBits = TWOSTOPBITS;
1611 lpdcb->StopBits = ONESTOPBIT;
1613 lpdcb->RlsTimeout = 50;
1614 lpdcb->CtsTimeout = 50;
1615 lpdcb->DsrTimeout = 50;
1619 lpdcb->fDtrDisable = 0;
1623 if (port.c_cflag & CRTSCTS) {
1624 lpdcb->fDtrflow = 1;
1625 lpdcb->fRtsflow = 1;
1626 lpdcb->fOutxCtsFlow = 1;
1627 lpdcb->fOutxDsrFlow = 1;
1630 lpdcb->fDtrDisable = 1;
1632 if (port.c_iflag & IXON)
1637 if (port.c_iflag & IXOFF)
1646 lpdcb->XoffLim = 10;
1652 /*****************************************************************************
1653 * GetCommState (KERNEL32.159)
1655 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
1657 struct termios port;
1659 struct get_read_fd_request req;
1661 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1662 req.handle = handle;
1663 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
1664 CLIENT_WaitReply( NULL, &fd, 0 );
1669 if (tcgetattr(fd, &port) == -1) {
1670 TRACE(comm,"tcgetattr(%d, ...) returned -1",fd);
1671 commerror = WinError();
1676 switch (port.c_cflag & CBAUD) {
1678 switch (port.c_ospeed) {
1681 lpdcb->BaudRate = 110;
1684 lpdcb->BaudRate = 300;
1687 lpdcb->BaudRate = 600;
1690 lpdcb->BaudRate = 1200;
1693 lpdcb->BaudRate = 2400;
1696 lpdcb->BaudRate = 4800;
1699 lpdcb->BaudRate = 9600;
1702 lpdcb->BaudRate = 19200;
1705 lpdcb->BaudRate = 38400;
1709 switch (port.c_cflag & CSIZE) {
1711 lpdcb->ByteSize = 5;
1714 lpdcb->ByteSize = 6;
1717 lpdcb->ByteSize = 7;
1720 lpdcb->ByteSize = 8;
1724 switch (port.c_cflag & (PARENB | PARODD)) {
1726 lpdcb->fParity = FALSE;
1727 lpdcb->Parity = NOPARITY;
1730 lpdcb->fParity = TRUE;
1731 lpdcb->Parity = EVENPARITY;
1733 case (PARENB | PARODD):
1734 lpdcb->fParity = TRUE;
1735 lpdcb->Parity = ODDPARITY;
1739 if (port.c_cflag & CSTOPB)
1740 lpdcb->StopBits = TWOSTOPBITS;
1742 lpdcb->StopBits = ONESTOPBIT;
1749 if (port.c_cflag & CRTSCTS) {
1750 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1751 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1752 lpdcb->fOutxCtsFlow = 1;
1753 lpdcb->fOutxDsrFlow = 1;
1757 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1758 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1760 if (port.c_iflag & IXON)
1765 if (port.c_iflag & IXOFF)
1774 lpdcb->XoffLim = 10;
1783 /*****************************************************************************
1784 * TransmitCommChar (USER.206)
1786 INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
1788 struct DosDeviceStruct *ptr;
1790 TRACE(comm, "fd %d, data %d \n", fd, chTransmit);
1791 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1792 commerror = IE_BADID;
1796 if (ptr->suspended) {
1797 commerror = IE_HARDWARE;
1801 if (write(fd, (void *) &chTransmit, 1) == -1) {
1802 commerror = WinError();
1810 /*****************************************************************************
1811 * TransmitCommChar (KERNEL32.535)
1813 BOOL WINAPI TransmitCommChar(INT fd,CHAR chTransmit)
1815 struct DosDeviceStruct *ptr;
1817 TRACE(comm,"(%d,'%c')\n",fd,chTransmit);
1818 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1819 commerror = IE_BADID;
1823 if (ptr->suspended) {
1824 commerror = IE_HARDWARE;
1827 if (write(fd, (void *) &chTransmit, 1) == -1) {
1828 commerror = WinError();
1836 /*****************************************************************************
1837 * UngetCommChar (USER.212)
1839 INT16 WINAPI UngetCommChar16(INT16 fd,CHAR chUnget)
1841 struct DosDeviceStruct *ptr;
1843 TRACE(comm,"fd %d (char %d)\n", fd, chUnget);
1844 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1845 commerror = IE_BADID;
1849 if (ptr->suspended) {
1850 commerror = IE_HARDWARE;
1855 ptr->unget_byte = chUnget;
1860 /*****************************************************************************
1861 * ReadComm (USER.204)
1863 INT16 WINAPI ReadComm16(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1866 struct DosDeviceStruct *ptr;
1868 TRACE(comm, "fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1869 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1870 commerror = IE_BADID;
1874 if (ptr->suspended) {
1875 commerror = IE_HARDWARE;
1880 *lpvBuf = ptr->unget_byte;
1888 status = read(fd, (void *) lpvBuf, cbRead);
1891 if (errno != EAGAIN) {
1892 commerror = WinError();
1899 TRACE(comm,"%.*s\n", length+status, lpvBuf);
1901 return length + status;
1905 /*****************************************************************************
1906 * WriteComm (USER.205)
1908 INT16 WINAPI WriteComm16(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1911 struct DosDeviceStruct *ptr;
1913 TRACE(comm,"fd %d, ptr %p, length %d\n",
1914 fd, lpvBuf, cbWrite);
1915 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1916 commerror = IE_BADID;
1920 if (ptr->suspended) {
1921 commerror = IE_HARDWARE;
1925 TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
1926 length = write(fd, (void *) lpvBuf, cbWrite);
1929 commerror = WinError();
1938 /*****************************************************************************
1939 * GetCommTimeouts (KERNEL32.160)
1941 BOOL WINAPI GetCommTimeouts(INT fd,LPCOMMTIMEOUTS lptimeouts)
1943 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1947 /*****************************************************************************
1948 * SetCommTimeouts (KERNEL32.453)
1950 BOOL WINAPI SetCommTimeouts(INT fd,LPCOMMTIMEOUTS lptimeouts) {
1951 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1955 /***********************************************************************
1956 * EnableCommNotification (USER.246)
1958 BOOL16 WINAPI EnableCommNotification16( INT16 fd, HWND16 hwnd,
1959 INT16 cbWriteNotify, INT16 cbOutQueue )
1961 FIXME(comm, "(%d, %x, %d, %d):stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
1965 /***********************************************************************
1966 * GetCommModemStatus (KERNEL32.285)
1968 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
1970 FIXME(comm, "(%d %p)\n",hFile,lpModemStat );
1973 /***********************************************************************
1974 * WaitCommEvent (KERNEL32.719)
1976 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
1978 FIXME(comm, "(%d %p %p )\n",hFile, eventmask,overlapped);
1982 /***********************************************************************
1983 * GetCommProperties (KERNEL32.???)
1985 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
1987 FIXME(comm, "(%d %p )\n",hFile,dcb);
1991 /***********************************************************************
1992 * SetCommProperties (KERNEL32.???)
1994 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
1996 FIXME(comm, "(%d %p )\n",hFile,dcb);