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
);