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>
62 #ifdef HAVE_SYS_MODEM_H
63 # include <sys/modem.h>
65 #ifdef HAVE_SYS_STRTIO_H
66 # include <sys/strtio.h>
73 #define TIOCINQ FIONREAD
75 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
77 * [RER] These are globals are wrong. They should be in DosDeviceStruct
78 * on a per port basis.
80 int commerror
= 0, eventmask
= 0;
83 * [V] If above globals are wrong, the one below will be wrong as well. It
84 * should probably be in the DosDeviceStruct on per port basis too.
86 int iGlobalOutQueueFiller
;
88 #define SERIAL_XMIT_SIZE 4096
90 struct DosDeviceStruct COM
[MAX_PORTS
];
91 struct DosDeviceStruct LPT
[MAX_PORTS
];
92 /* pointers to unknown(==undocumented) comm structure */
93 LPCVOID
*unknown
[MAX_PORTS
];
94 /* save terminal states */
95 static struct termios m_stat
[MAX_PORTS
];
100 char option
[10], temp
[256], *btemp
;
103 for (x
=0; x
!=MAX_PORTS
; x
++) {
104 strcpy(option
,"COMx");
108 PROFILE_GetWineIniString( "serialports", option
, "*",
109 temp
, sizeof(temp
) );
110 if (!strcmp(temp
, "*") || *temp
== '\0')
111 COM
[x
].devicename
= NULL
;
113 btemp
= strchr(temp
,',');
116 COM
[x
].baudrate
= atoi(btemp
);
118 COM
[x
].baudrate
= -1;
121 if (!S_ISCHR(st
.st_mode
))
122 WARN(comm
,"Can't use `%s' as %s !\n", temp
, option
);
124 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
125 WARN(comm
,"Can't malloc for device info!\n");
128 strcpy(COM
[x
].devicename
, temp
);
130 TRACE(comm
, "%s = %s\n", option
, COM
[x
].devicename
);
133 strcpy(option
, "LPTx");
137 PROFILE_GetWineIniString( "parallelports", option
, "*",
138 temp
, sizeof(temp
) );
139 if (!strcmp(temp
, "*") || *temp
== '\0')
140 LPT
[x
].devicename
= NULL
;
143 if (!S_ISCHR(st
.st_mode
))
144 WARN(comm
,"Can't use `%s' as %s !\n", temp
, option
);
146 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
147 WARN(comm
,"Can't malloc for device info!\n");
150 strcpy(LPT
[x
].devicename
, temp
);
152 TRACE(comm
, "%s = %s\n", option
, LPT
[x
].devicename
);
159 struct DosDeviceStruct
*GetDeviceStruct(int fd
)
163 for (x
=0; x
!=MAX_PORTS
; x
++) {
173 int GetCommPort(int fd
)
177 for (x
=0; x
<MAX_PORTS
; x
++) {
185 int ValidCOMPort(int x
)
187 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
190 int ValidLPTPort(int x
)
192 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
197 TRACE(comm
, "errno = %d\n", errno
);
204 /**************************************************************************
205 * BuildCommDCB (USER.213)
207 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
209 /* "COM1:9600,n,8,1" */
212 char *ptr
, temp
[256];
214 TRACE(comm
, "(%s), ptr %p\n", device
, lpdcb
);
217 if (!lstrncmpi32A(device
,"COM",3)) {
218 port
= device
[3] - '0';
222 ERR(comm
, "BUG ! COM0 can't exists!.\n");
223 commerror
= IE_BADID
;
226 if (!ValidCOMPort(port
)) {
227 commerror
= IE_BADID
;
231 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
234 OpenComm(device
, 0, 0);
236 lpdcb
->Id
= COM
[port
].fd
;
241 if (*(device
+4) != ':')
244 strcpy(temp
,device
+5);
245 ptr
= strtok(temp
, ", ");
247 if (COM
[port
].baudrate
> 0)
248 lpdcb
->BaudRate
= COM
[port
].baudrate
;
250 lpdcb
->BaudRate
= atoi(ptr
);
251 TRACE(comm
,"baudrate (%d)\n", lpdcb
->BaudRate
);
253 ptr
= strtok(NULL
, ", ");
255 *ptr
= toupper(*ptr
);
257 TRACE(comm
,"parity (%c)\n", *ptr
);
258 lpdcb
->fParity
= TRUE
;
261 lpdcb
->Parity
= NOPARITY
;
262 lpdcb
->fParity
= FALSE
;
265 lpdcb
->Parity
= EVENPARITY
;
268 lpdcb
->Parity
= MARKPARITY
;
271 lpdcb
->Parity
= ODDPARITY
;
274 WARN(comm
,"Unknown parity `%c'!\n", *ptr
);
278 ptr
= strtok(NULL
, ", ");
279 TRACE(comm
, "charsize (%c)\n", *ptr
);
280 lpdcb
->ByteSize
= *ptr
- '0';
282 ptr
= strtok(NULL
, ", ");
283 TRACE(comm
, "stopbits (%c)\n", *ptr
);
286 lpdcb
->StopBits
= ONESTOPBIT
;
289 lpdcb
->StopBits
= TWOSTOPBITS
;
292 WARN(comm
,"Unknown # of stopbits `%c'!\n", *ptr
);
300 /**************************************************************************
301 * BuildCommDCBA (KERNEL32.14)
303 BOOL32 WINAPI
BuildCommDCB32A(LPCSTR device
,LPDCB32 lpdcb
)
305 return BuildCommDCBAndTimeouts32A(device
,lpdcb
,NULL
);
308 /**************************************************************************
309 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
311 BOOL32 WINAPI
BuildCommDCBAndTimeouts32A(LPCSTR device
, LPDCB32 lpdcb
,
312 LPCOMMTIMEOUTS lptimeouts
)
317 TRACE(comm
,"(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
320 if (!lstrncmpi32A(device
,"COM",3)) {
323 ERR(comm
,"BUG! COM0 can't exists!.\n");
326 if (!ValidCOMPort(port
))
328 if (*(device
+4)!=':')
330 temp
=(LPSTR
)(device
+5);
334 memset(lpdcb
, 0, sizeof(DCB32
)); /* initialize */
336 lpdcb
->DCBlength
= sizeof(DCB32
);
337 if (strchr(temp
,',')) { /* old style */
340 char last
=temp
[strlen(temp
)-1];
342 ret
=BuildCommDCB16(device
,&dcb16
);
345 lpdcb
->BaudRate
= dcb16
.BaudRate
;
346 lpdcb
->ByteSize
= dcb16
.ByteSize
;
347 lpdcb
->fBinary
= dcb16
.fBinary
;
348 lpdcb
->Parity
= dcb16
.Parity
;
349 lpdcb
->fParity
= dcb16
.fParity
;
350 lpdcb
->fNull
= dcb16
.fNull
;
351 lpdcb
->StopBits
= dcb16
.StopBits
;
355 lpdcb
->fOutxCtsFlow
= FALSE
;
356 lpdcb
->fOutxDsrFlow
= FALSE
;
357 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
358 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
359 } else if (last
=='p') {
361 lpdcb
->fOutX
= FALSE
;
362 lpdcb
->fOutxCtsFlow
= TRUE
;
363 lpdcb
->fOutxDsrFlow
= TRUE
;
364 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
365 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
368 lpdcb
->fOutX
= FALSE
;
369 lpdcb
->fOutxCtsFlow
= FALSE
;
370 lpdcb
->fOutxDsrFlow
= FALSE
;
371 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
372 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
374 lpdcb
->XonChar
= dcb16
.XonChar
;
375 lpdcb
->XoffChar
= dcb16
.XoffChar
;
376 lpdcb
->ErrorChar
= dcb16
.PeChar
;
377 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
378 lpdcb
->EofChar
= dcb16
.EofChar
;
379 lpdcb
->EvtChar
= dcb16
.EvtChar
;
380 lpdcb
->XonLim
= dcb16
.XonLim
;
381 lpdcb
->XoffLim
= dcb16
.XoffLim
;
384 ptr
=strtok(temp
," ");
389 if (!strncmp("baud=",ptr
,5)) {
390 if (!sscanf(ptr
+5,"%ld",&x
))
391 WARN(comm
,"Couldn't parse %s\n",ptr
);
395 if (!strncmp("stop=",ptr
,5)) {
396 if (!sscanf(ptr
+5,"%ld",&x
))
397 WARN(comm
,"Couldn't parse %s\n",ptr
);
401 if (!strncmp("data=",ptr
,5)) {
402 if (!sscanf(ptr
+5,"%ld",&x
))
403 WARN(comm
,"Couldn't parse %s\n",ptr
);
407 if (!strncmp("parity=",ptr
,7)) {
408 lpdcb
->fParity
= TRUE
;
411 lpdcb
->fParity
= FALSE
;
412 lpdcb
->Parity
= NOPARITY
;
415 lpdcb
->Parity
= EVENPARITY
;
418 lpdcb
->Parity
= ODDPARITY
;
421 lpdcb
->Parity
= MARKPARITY
;
427 ERR(comm
,"Unhandled specifier '%s', please report.\n",ptr
);
428 ptr
=strtok(NULL
," ");
430 if (lpdcb
->BaudRate
==110)
435 /**************************************************************************
436 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
438 BOOL32 WINAPI
BuildCommDCBAndTimeouts32W( LPCWSTR devid
, LPDCB32 lpdcb
,
439 LPCOMMTIMEOUTS lptimeouts
)
444 TRACE(comm
,"(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
445 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
446 ret
=BuildCommDCBAndTimeouts32A(devidA
,lpdcb
,lptimeouts
);
447 HeapFree( GetProcessHeap(), 0, devidA
);
451 /**************************************************************************
452 * BuildCommDCBW (KERNEL32.17)
454 BOOL32 WINAPI
BuildCommDCB32W(LPCWSTR devid
,LPDCB32 lpdcb
)
456 return BuildCommDCBAndTimeouts32W(devid
,lpdcb
,NULL
);
459 /*****************************************************************************
460 * OpenComm (USER.200)
462 INT16 WINAPI
OpenComm(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
466 TRACE(comm
, "%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
469 if (!lstrncmpi32A(device
,"COM",3)) {
470 port
= device
[3] - '0';
473 ERR(comm
, "BUG ! COM0 doesn't exist !\n");
474 commerror
= IE_BADID
;
477 /* to help GetCommError return left buffsize [V] */
478 iGlobalOutQueueFiller
= (cbOutQueue
- SERIAL_XMIT_SIZE
);
479 if (iGlobalOutQueueFiller
< 0) iGlobalOutQueueFiller
= 0;
481 TRACE(comm
, "%s = %s\n", device
, COM
[port
].devicename
);
483 if (!ValidCOMPort(port
)) {
484 commerror
= IE_BADID
;
491 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
493 commerror
= WinError();
496 unknown
[port
] = SEGPTR_ALLOC(40);
497 bzero(unknown
[port
],40);
499 /* save terminal state */
500 tcgetattr(fd
,&m_stat
[port
]);
505 if (!lstrncmpi32A(device
,"LPT",3)) {
506 port
= device
[3] - '0';
508 if (!ValidLPTPort(port
)) {
509 commerror
= IE_BADID
;
517 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
519 commerror
= WinError();
529 /*****************************************************************************
530 * CloseComm (USER.207)
532 INT16 WINAPI
CloseComm(INT16 fd
)
536 TRACE(comm
,"fd %d\n", fd
);
537 if ((port
= GetCommPort(fd
)) !=-1) { /* [LW] */
538 SEGPTR_FREE(unknown
[port
]);
539 COM
[port
].fd
= 0; /* my adaptation of RER's fix */
541 commerror
= IE_BADID
;
545 /* reset modem lines */
546 tcsetattr(fd
,TCSANOW
,&m_stat
[port
]);
548 if (close(fd
) == -1) {
549 commerror
= WinError();
557 /*****************************************************************************
558 * SetCommBreak (USER.210)
560 INT16 WINAPI
SetCommBreak16(INT16 fd
)
562 struct DosDeviceStruct
*ptr
;
564 TRACE(comm
,"fd=%d\n", fd
);
565 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
566 commerror
= IE_BADID
;
575 /*****************************************************************************
576 * SetCommBreak (KERNEL32.449)
578 BOOL32 WINAPI
SetCommBreak32(INT32 fd
)
581 struct DosDeviceStruct
*ptr
;
583 TRACE(comm
,"fd=%d\n", fd
);
584 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
585 commerror
= IE_BADID
;
594 /*****************************************************************************
595 * ClearCommBreak (USER.211)
597 INT16 WINAPI
ClearCommBreak16(INT16 fd
)
599 struct DosDeviceStruct
*ptr
;
601 TRACE(comm
,"fd=%d\n", fd
);
602 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
603 commerror
= IE_BADID
;
612 /*****************************************************************************
613 * ClearCommBreak (KERNEL32.20)
615 BOOL32 WINAPI
ClearCommBreak32(INT32 fd
)
617 struct DosDeviceStruct
*ptr
;
619 TRACE(comm
,"fd=%d\n", fd
);
620 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
621 commerror
= IE_BADID
;
630 /*****************************************************************************
631 * EscapeCommFunction (USER.214)
633 LONG WINAPI
EscapeCommFunction16(UINT16 fd
,UINT16 nFunction
)
638 TRACE(comm
,"fd=%d, function=%d\n", fd
, nFunction
);
639 if (tcgetattr(fd
,&port
) == -1) {
640 commerror
=WinError();
649 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
655 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
662 port
.c_cflag
&= TIOCM_DTR
;
668 port
.c_cflag
&= TIOCM_RTS
;
674 port
.c_cflag
|= CRTSCTS
;
678 port
.c_cflag
|= CRTSCTS
;
683 port
.c_iflag
|= IXOFF
;
687 port
.c_iflag
|= IXON
;
691 WARN(comm
,"(fd=%d,nFunction=%d): Unknown function\n",
696 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
697 commerror
= WinError();
705 /*****************************************************************************
706 * EscapeCommFunction (KERNEL32.214)
708 BOOL32 WINAPI
EscapeCommFunction32(INT32 fd
,UINT32 nFunction
)
711 struct DosDeviceStruct
*ptr
;
713 TRACE(comm
,"fd=%d, function=%d\n", fd
, nFunction
);
714 if (tcgetattr(fd
,&port
) == -1) {
715 commerror
=WinError();
718 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
719 commerror
= IE_BADID
;
729 port
.c_cflag
&= TIOCM_DTR
;
735 port
.c_cflag
&= TIOCM_RTS
;
741 port
.c_cflag
|= CRTSCTS
;
745 port
.c_cflag
|= CRTSCTS
;
750 port
.c_iflag
|= IXOFF
;
754 port
.c_iflag
|= IXON
;
763 WARN(comm
,"(fd=%d,nFunction=%d): Unknown function\n",
768 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
769 commerror
= WinError();
777 /*****************************************************************************
778 * FlushComm (USER.215)
780 INT16 WINAPI
FlushComm(INT16 fd
,INT16 fnQueue
)
784 TRACE(comm
,"fd=%d, queue=%d\n", fd
, fnQueue
);
786 case 0: queue
= TCOFLUSH
;
788 case 1: queue
= TCIFLUSH
;
790 default:WARN(comm
,"(fd=%d,fnQueue=%d):Unknown queue\n",
794 if (tcflush(fd
, queue
)) {
795 commerror
= WinError();
803 /********************************************************************
804 * PurgeComm (KERNEL32.557)
806 BOOL32 WINAPI
PurgeComm( HANDLE32 hFile
, DWORD flags
)
808 FIXME(comm
, "(%08x %08lx) unimplemented stub\n",
813 /********************************************************************
814 * GetCommError (USER.203)
816 INT16 WINAPI
GetCommError(INT16 fd
,LPCOMSTAT lpStat
)
825 if ((act
= GetCommPort(fd
)) == -1) {
826 WARN(comm
," fd %d not comm port\n",act
);
829 stol
= (unsigned char *)unknown
[act
] + COMM_MSR_OFFSET
;
830 ioctl(fd
,TIOCMGET
,&mstat
);
831 if( mstat
&TIOCM_CAR
)
839 rc
= ioctl(fd
, TIOCOUTQ
, &cnt
);
840 if (rc
) WARN(comm
, "Error !\n");
841 lpStat
->cbOutQue
= cnt
+ iGlobalOutQueueFiller
;
843 rc
= ioctl(fd
, TIOCINQ
, &cnt
);
844 if (rc
) WARN(comm
, "Error !\n");
845 lpStat
->cbInQue
= cnt
;
847 TRACE(comm
, "fd %d, error %d, lpStat %d %d %d stol %x\n",
848 fd
, commerror
, lpStat
->status
, lpStat
->cbInQue
,
849 lpStat
->cbOutQue
, *stol
);
852 TRACE(comm
, "fd %d, error %d, lpStat NULL stol %x\n",
853 fd
, commerror
, *stol
);
856 * [RER] I have no idea what the following is trying to accomplish.
857 * [RER] It is certainly not what the reference manual suggests.
859 temperror
= commerror
;
864 /*****************************************************************************
865 * ClearCommError (KERNEL32.21)
867 BOOL32 WINAPI
ClearCommError(INT32 fd
,LPDWORD errors
,LPCOMSTAT lpStat
)
871 TRACE(comm
, "fd %d (current error %d)\n",
873 temperror
= commerror
;
878 /*****************************************************************************
879 * SetCommEventMask (USER.208)
881 SEGPTR WINAPI
SetCommEventMask(INT16 fd
,UINT16 fuEvtMask
)
887 TRACE(comm
,"fd %d,mask %d\n",fd
,fuEvtMask
);
888 eventmask
|= fuEvtMask
;
889 if ((act
= GetCommPort(fd
)) == -1) {
890 WARN(comm
," fd %d not comm port\n",act
);
891 return SEGPTR_GET(NULL
);
893 stol
= (unsigned char *)unknown
[act
];
894 stol
+= COMM_MSR_OFFSET
;
895 repid
= ioctl(fd
,TIOCMGET
,&mstat
);
896 TRACE(comm
, " ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[act
]);
897 if ((mstat
&TIOCM_CAR
)) {*stol
|= 0x80;}
899 TRACE(comm
," modem dcd construct %x\n",*stol
);
900 return SEGPTR_GET(unknown
[act
]);
903 /*****************************************************************************
904 * GetCommEventMask (USER.209)
906 UINT16 WINAPI
GetCommEventMask(INT16 fd
,UINT16 fnEvtClear
)
910 TRACE(comm
, "fd %d, mask %d\n", fd
, fnEvtClear
);
913 * Determine if any characters are available
915 if (fnEvtClear
& EV_RXCHAR
)
920 rc
= ioctl(fd
, TIOCINQ
, &cnt
);
921 if (cnt
) events
|= EV_RXCHAR
;
923 TRACE(comm
, "rxchar %ld\n", cnt
);
927 * There are other events that need to be checked for
931 TRACE(comm
, "return events %d\n", events
);
935 * [RER] The following was gibberish
938 tempmask
= eventmask
;
939 eventmask
&= ~fnEvtClear
;
944 /*****************************************************************************
945 * SetupComm (KERNEL32.676)
947 BOOL32 WINAPI
SetupComm( HANDLE32 hFile
, DWORD insize
, DWORD outsize
)
949 FIXME(comm
, "insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
953 /*****************************************************************************
954 * GetCommMask (KERNEL32.156)
956 BOOL32 WINAPI
GetCommMask(HANDLE32 fd
,LPDWORD evtmask
)
958 TRACE(comm
, "fd %d, mask %p\n", fd
, evtmask
);
959 *evtmask
= eventmask
;
963 /*****************************************************************************
964 * SetCommMask (KERNEL32.451)
966 BOOL32 WINAPI
SetCommMask(INT32 fd
,DWORD evtmask
)
968 TRACE(comm
, "fd %d, mask %lx\n", fd
, evtmask
);
973 /*****************************************************************************
974 * SetCommState16 (USER.201)
976 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
979 struct DosDeviceStruct
*ptr
;
981 TRACE(comm
, "fd %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
982 if (tcgetattr(lpdcb
->Id
, &port
) == -1) {
983 commerror
= WinError();
988 port
.c_cc
[VTIME
] = 1;
991 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
993 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
995 port
.c_iflag
|= (IGNBRK
);
997 port
.c_oflag
&= ~(OPOST
);
999 port
.c_cflag
&= ~(HUPCL
);
1000 port
.c_cflag
|= CLOCAL
| CREAD
;
1002 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1003 port
.c_lflag
|= NOFLSH
;
1005 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
1006 commerror
= IE_BADID
;
1009 if (ptr
->baudrate
> 0)
1010 lpdcb
->BaudRate
= ptr
->baudrate
;
1011 TRACE(comm
,"baudrate %d\n",lpdcb
->BaudRate
);
1013 port
.c_cflag
&= ~CBAUD
;
1014 switch (lpdcb
->BaudRate
) {
1017 port
.c_cflag
|= B110
;
1021 port
.c_cflag
|= B300
;
1025 port
.c_cflag
|= B600
;
1029 port
.c_cflag
|= B1200
;
1033 port
.c_cflag
|= B2400
;
1037 port
.c_cflag
|= B4800
;
1041 port
.c_cflag
|= B9600
;
1045 port
.c_cflag
|= B19200
;
1049 port
.c_cflag
|= B38400
;
1052 port
.c_cflag
|= B57600
;
1055 port
.c_cflag
|= B115200
;
1058 commerror
= IE_BAUDRATE
;
1061 #elif !defined(__EMX__)
1062 switch (lpdcb
->BaudRate
) {
1065 port
.c_ospeed
= B110
;
1069 port
.c_ospeed
= B300
;
1073 port
.c_ospeed
= B600
;
1077 port
.c_ospeed
= B1200
;
1081 port
.c_ospeed
= B2400
;
1085 port
.c_ospeed
= B4800
;
1089 port
.c_ospeed
= B9600
;
1093 port
.c_ospeed
= B19200
;
1097 port
.c_ospeed
= B38400
;
1100 commerror
= IE_BAUDRATE
;
1103 port
.c_ispeed
= port
.c_ospeed
;
1105 TRACE(comm
,"bytesize %d\n",lpdcb
->ByteSize
);
1106 port
.c_cflag
&= ~CSIZE
;
1107 switch (lpdcb
->ByteSize
) {
1109 port
.c_cflag
|= CS5
;
1112 port
.c_cflag
|= CS6
;
1115 port
.c_cflag
|= CS7
;
1118 port
.c_cflag
|= CS8
;
1121 commerror
= IE_BYTESIZE
;
1125 TRACE(comm
,"parity %d\n",lpdcb
->Parity
);
1126 port
.c_cflag
&= ~(PARENB
| PARODD
);
1128 switch (lpdcb
->Parity
) {
1130 port
.c_iflag
&= ~INPCK
;
1133 port
.c_cflag
|= (PARENB
| PARODD
);
1134 port
.c_iflag
|= INPCK
;
1137 port
.c_cflag
|= PARENB
;
1138 port
.c_iflag
|= INPCK
;
1141 commerror
= IE_BYTESIZE
;
1146 TRACE(comm
,"stopbits %d\n",lpdcb
->StopBits
);
1148 switch (lpdcb
->StopBits
) {
1150 port
.c_cflag
&= ~CSTOPB
;
1153 port
.c_cflag
|= CSTOPB
;
1156 commerror
= IE_BYTESIZE
;
1161 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
1162 port
.c_cflag
|= CRTSCTS
;
1164 if (lpdcb
->fDtrDisable
)
1165 port
.c_cflag
&= ~CRTSCTS
;
1168 port
.c_iflag
|= IXON
;
1170 port
.c_iflag
&= ~IXON
;
1172 port
.c_iflag
|= IXOFF
;
1174 port
.c_iflag
&= ~IXOFF
;
1176 if (tcsetattr(lpdcb
->Id
, TCSADRAIN
, &port
) == -1) {
1177 commerror
= WinError();
1185 /*****************************************************************************
1186 * SetCommState32 (KERNEL32.452)
1188 BOOL32 WINAPI
SetCommState32(INT32 fd
,LPDCB32 lpdcb
)
1190 struct termios port
;
1191 struct DosDeviceStruct
*ptr
;
1193 TRACE(comm
,"fd %d, ptr %p\n",fd
,lpdcb
);
1194 if (tcgetattr(fd
,&port
) == -1) {
1195 commerror
= WinError();
1199 port
.c_cc
[VMIN
] = 0;
1200 port
.c_cc
[VTIME
] = 1;
1203 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1205 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1207 port
.c_iflag
|= (IGNBRK
);
1209 port
.c_oflag
&= ~(OPOST
);
1211 port
.c_cflag
&= ~(HUPCL
);
1212 port
.c_cflag
|= CLOCAL
| CREAD
;
1214 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1215 port
.c_lflag
|= NOFLSH
;
1217 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
1218 commerror
= IE_BADID
;
1221 if (ptr
->baudrate
> 0)
1222 lpdcb
->BaudRate
= ptr
->baudrate
;
1223 TRACE(comm
,"baudrate %ld\n",lpdcb
->BaudRate
);
1225 port
.c_cflag
&= ~CBAUD
;
1226 switch (lpdcb
->BaudRate
) {
1229 port
.c_cflag
|= B110
;
1233 port
.c_cflag
|= B300
;
1237 port
.c_cflag
|= B600
;
1241 port
.c_cflag
|= B1200
;
1245 port
.c_cflag
|= B2400
;
1249 port
.c_cflag
|= B4800
;
1253 port
.c_cflag
|= B9600
;
1257 port
.c_cflag
|= B19200
;
1261 port
.c_cflag
|= B38400
;
1264 commerror
= IE_BAUDRATE
;
1267 #elif !defined(__EMX__)
1268 switch (lpdcb
->BaudRate
) {
1271 port
.c_ospeed
= B110
;
1275 port
.c_ospeed
= B300
;
1279 port
.c_ospeed
= B600
;
1283 port
.c_ospeed
= B1200
;
1287 port
.c_ospeed
= B2400
;
1291 port
.c_ospeed
= B4800
;
1295 port
.c_ospeed
= B9600
;
1299 port
.c_ospeed
= B19200
;
1303 port
.c_ospeed
= B38400
;
1306 commerror
= IE_BAUDRATE
;
1309 port
.c_ispeed
= port
.c_ospeed
;
1311 TRACE(comm
,"bytesize %d\n",lpdcb
->ByteSize
);
1312 port
.c_cflag
&= ~CSIZE
;
1313 switch (lpdcb
->ByteSize
) {
1315 port
.c_cflag
|= CS5
;
1318 port
.c_cflag
|= CS6
;
1321 port
.c_cflag
|= CS7
;
1324 port
.c_cflag
|= CS8
;
1327 commerror
= IE_BYTESIZE
;
1331 TRACE(comm
,"parity %d\n",lpdcb
->Parity
);
1332 port
.c_cflag
&= ~(PARENB
| PARODD
);
1334 switch (lpdcb
->Parity
) {
1336 port
.c_iflag
&= ~INPCK
;
1339 port
.c_cflag
|= (PARENB
| PARODD
);
1340 port
.c_iflag
|= INPCK
;
1343 port
.c_cflag
|= PARENB
;
1344 port
.c_iflag
|= INPCK
;
1347 commerror
= IE_BYTESIZE
;
1352 TRACE(comm
,"stopbits %d\n",lpdcb
->StopBits
);
1353 switch (lpdcb
->StopBits
) {
1355 port
.c_cflag
&= ~CSTOPB
;
1358 port
.c_cflag
|= CSTOPB
;
1361 commerror
= IE_BYTESIZE
;
1365 if ( lpdcb
->fOutxCtsFlow
||
1366 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
1367 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
1369 port
.c_cflag
|= CRTSCTS
;
1370 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
1371 port
.c_cflag
&= ~CRTSCTS
;
1375 port
.c_iflag
|= IXON
;
1377 port
.c_iflag
&= ~IXON
;
1379 port
.c_iflag
|= IXOFF
;
1381 port
.c_iflag
&= ~IXOFF
;
1383 if (tcsetattr(fd
,TCSADRAIN
,&port
)==-1) {
1384 commerror
= WinError();
1393 /*****************************************************************************
1394 * GetCommState (USER.202)
1396 INT16 WINAPI
GetCommState16(INT16 fd
, LPDCB16 lpdcb
)
1398 struct termios port
;
1400 TRACE(comm
,"fd %d, ptr %p\n", fd
, lpdcb
);
1401 if (tcgetattr(fd
, &port
) == -1) {
1402 commerror
= WinError();
1408 switch (port
.c_cflag
& CBAUD
) {
1410 switch (port
.c_ospeed
) {
1413 lpdcb
->BaudRate
= 110;
1416 lpdcb
->BaudRate
= 300;
1419 lpdcb
->BaudRate
= 600;
1422 lpdcb
->BaudRate
= 1200;
1425 lpdcb
->BaudRate
= 2400;
1428 lpdcb
->BaudRate
= 4800;
1431 lpdcb
->BaudRate
= 9600;
1434 lpdcb
->BaudRate
= 19200;
1437 lpdcb
->BaudRate
= 38400;
1440 lpdcb
->BaudRate
= 57600;
1443 lpdcb
->BaudRate
= 57601;
1447 switch (port
.c_cflag
& CSIZE
) {
1449 lpdcb
->ByteSize
= 5;
1452 lpdcb
->ByteSize
= 6;
1455 lpdcb
->ByteSize
= 7;
1458 lpdcb
->ByteSize
= 8;
1462 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1464 lpdcb
->fParity
= FALSE
;
1465 lpdcb
->Parity
= NOPARITY
;
1468 lpdcb
->fParity
= TRUE
;
1469 lpdcb
->Parity
= EVENPARITY
;
1471 case (PARENB
| PARODD
):
1472 lpdcb
->fParity
= TRUE
;
1473 lpdcb
->Parity
= ODDPARITY
;
1477 if (port
.c_cflag
& CSTOPB
)
1478 lpdcb
->StopBits
= TWOSTOPBITS
;
1480 lpdcb
->StopBits
= ONESTOPBIT
;
1482 lpdcb
->RlsTimeout
= 50;
1483 lpdcb
->CtsTimeout
= 50;
1484 lpdcb
->DsrTimeout
= 50;
1488 lpdcb
->fDtrDisable
= 0;
1492 if (port
.c_cflag
& CRTSCTS
) {
1493 lpdcb
->fDtrflow
= 1;
1494 lpdcb
->fRtsflow
= 1;
1495 lpdcb
->fOutxCtsFlow
= 1;
1496 lpdcb
->fOutxDsrFlow
= 1;
1499 lpdcb
->fDtrDisable
= 1;
1501 if (port
.c_iflag
& IXON
)
1506 if (port
.c_iflag
& IXOFF
)
1515 lpdcb
->XoffLim
= 10;
1521 /*****************************************************************************
1522 * GetCommState (KERNEL32.159)
1524 BOOL32 WINAPI
GetCommState32(INT32 fd
, LPDCB32 lpdcb
)
1526 struct termios port
;
1528 TRACE(comm
,"fd %d, ptr %p\n", fd
, lpdcb
);
1529 if (GetDeviceStruct(fd
) == NULL
) return FALSE
;
1530 if (tcgetattr(fd
, &port
) == -1) {
1531 commerror
= WinError();
1536 switch (port
.c_cflag
& CBAUD
) {
1538 switch (port
.c_ospeed
) {
1541 lpdcb
->BaudRate
= 110;
1544 lpdcb
->BaudRate
= 300;
1547 lpdcb
->BaudRate
= 600;
1550 lpdcb
->BaudRate
= 1200;
1553 lpdcb
->BaudRate
= 2400;
1556 lpdcb
->BaudRate
= 4800;
1559 lpdcb
->BaudRate
= 9600;
1562 lpdcb
->BaudRate
= 19200;
1565 lpdcb
->BaudRate
= 38400;
1569 switch (port
.c_cflag
& CSIZE
) {
1571 lpdcb
->ByteSize
= 5;
1574 lpdcb
->ByteSize
= 6;
1577 lpdcb
->ByteSize
= 7;
1580 lpdcb
->ByteSize
= 8;
1584 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1586 lpdcb
->fParity
= FALSE
;
1587 lpdcb
->Parity
= NOPARITY
;
1590 lpdcb
->fParity
= TRUE
;
1591 lpdcb
->Parity
= EVENPARITY
;
1593 case (PARENB
| PARODD
):
1594 lpdcb
->fParity
= TRUE
;
1595 lpdcb
->Parity
= ODDPARITY
;
1599 if (port
.c_cflag
& CSTOPB
)
1600 lpdcb
->StopBits
= TWOSTOPBITS
;
1602 lpdcb
->StopBits
= ONESTOPBIT
;
1609 if (port
.c_cflag
& CRTSCTS
) {
1610 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1611 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1612 lpdcb
->fOutxCtsFlow
= 1;
1613 lpdcb
->fOutxDsrFlow
= 1;
1617 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
1618 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
1620 if (port
.c_iflag
& IXON
)
1625 if (port
.c_iflag
& IXOFF
)
1634 lpdcb
->XoffLim
= 10;
1640 /*****************************************************************************
1641 * TransmitCommChar (USER.206)
1643 INT16 WINAPI
TransmitCommChar16(INT16 fd
,CHAR chTransmit
)
1645 struct DosDeviceStruct
*ptr
;
1647 TRACE(comm
, "fd %d, data %d \n", fd
, chTransmit
);
1648 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
1649 commerror
= IE_BADID
;
1653 if (ptr
->suspended
) {
1654 commerror
= IE_HARDWARE
;
1658 if (write(fd
, (void *) &chTransmit
, 1) == -1) {
1659 commerror
= WinError();
1667 /*****************************************************************************
1668 * TransmitCommChar (KERNEL32.535)
1670 BOOL32 WINAPI
TransmitCommChar32(INT32 fd
,CHAR chTransmit
)
1672 struct DosDeviceStruct
*ptr
;
1674 TRACE(comm
,"(%d,'%c')\n",fd
,chTransmit
);
1675 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
1676 commerror
= IE_BADID
;
1680 if (ptr
->suspended
) {
1681 commerror
= IE_HARDWARE
;
1684 if (write(fd
, (void *) &chTransmit
, 1) == -1) {
1685 commerror
= WinError();
1693 /*****************************************************************************
1694 * UngetCommChar (USER.212)
1696 INT16 WINAPI
UngetCommChar(INT16 fd
,CHAR chUnget
)
1698 struct DosDeviceStruct
*ptr
;
1700 TRACE(comm
,"fd %d (char %d)\n", fd
, chUnget
);
1701 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
1702 commerror
= IE_BADID
;
1706 if (ptr
->suspended
) {
1707 commerror
= IE_HARDWARE
;
1712 ptr
->unget_byte
= chUnget
;
1717 /*****************************************************************************
1718 * ReadComm (USER.204)
1720 INT16 WINAPI
ReadComm(INT16 fd
,LPSTR lpvBuf
,INT16 cbRead
)
1723 struct DosDeviceStruct
*ptr
;
1725 TRACE(comm
, "fd %d, ptr %p, length %d\n", fd
, lpvBuf
, cbRead
);
1726 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
1727 commerror
= IE_BADID
;
1731 if (ptr
->suspended
) {
1732 commerror
= IE_HARDWARE
;
1737 *lpvBuf
= ptr
->unget_byte
;
1745 status
= read(fd
, (void *) lpvBuf
, cbRead
);
1748 if (errno
!= EAGAIN
) {
1749 commerror
= WinError();
1756 TRACE(comm
,"%.*s\n", length
+status
, lpvBuf
);
1758 return length
+ status
;
1762 /*****************************************************************************
1763 * WriteComm (USER.205)
1765 INT16 WINAPI
WriteComm(INT16 fd
, LPSTR lpvBuf
, INT16 cbWrite
)
1768 struct DosDeviceStruct
*ptr
;
1770 TRACE(comm
,"fd %d, ptr %p, length %d\n",
1771 fd
, lpvBuf
, cbWrite
);
1772 if ((ptr
= GetDeviceStruct(fd
)) == NULL
) {
1773 commerror
= IE_BADID
;
1777 if (ptr
->suspended
) {
1778 commerror
= IE_HARDWARE
;
1782 TRACE(comm
,"%.*s\n", cbWrite
, lpvBuf
);
1783 length
= write(fd
, (void *) lpvBuf
, cbWrite
);
1786 commerror
= WinError();
1795 /*****************************************************************************
1796 * GetCommTimeouts (KERNEL32.160)
1798 BOOL32 WINAPI
GetCommTimeouts(INT32 fd
,LPCOMMTIMEOUTS lptimeouts
)
1800 FIXME(comm
,"(%x,%p):stub.\n",fd
,lptimeouts
);
1804 /*****************************************************************************
1805 * SetCommTimeouts (KERNEL32.453)
1807 BOOL32 WINAPI
SetCommTimeouts(INT32 fd
,LPCOMMTIMEOUTS lptimeouts
) {
1808 FIXME(comm
,"(%x,%p):stub.\n",fd
,lptimeouts
);
1812 /***********************************************************************
1813 * EnableCommNotification (USER.246)
1815 BOOL16 WINAPI
EnableCommNotification( INT16 fd
, HWND16 hwnd
,
1816 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1818 FIXME(comm
, "(%d, %x, %d, %d):stub.\n", fd
, hwnd
, cbWriteNotify
, cbOutQueue
);
1822 /***********************************************************************
1823 * GetCommModemStatus (KERNEL32.285)
1825 BOOL32 WINAPI
GetCommModemStatus(HANDLE32 hFile
,LPDWORD lpModemStat
)
1827 FIXME(comm
, "(%d %p)\n",hFile
,lpModemStat
);
1830 /***********************************************************************
1831 * WaitCommEvent (KERNEL32.719)
1833 BOOL32 WINAPI
WaitCommEvent(HANDLE32 hFile
,LPDWORD eventmask
,LPOVERLAPPED overlapped
)
1835 FIXME(comm
, "(%d %p %p )\n",hFile
, eventmask
,overlapped
);