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