2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Use port indices instead of unixfds for win16
8 * - Moved things around (separated win16 and win32 routines)
9 * - Added some hints on how to implement buffers and EnableCommNotification.
11 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
12 * - ptr->fd wasn't getting cleared on close.
13 * - GetCommEventMask() and GetCommError() didn't do much of anything.
14 * IMHO, they are still wrong, but they at least implement the RXCHAR
15 * event and return I/O queue sizes, which makes the app I'm interested
16 * in (analog devices EZKIT DSP development system) work.
18 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
19 * <lawson_whitney@juno.com>
20 * July 6, 1998. Fixes and comments by Valentijn Sessink
21 * <vsessink@ic.uva.nl> [V]
22 * I only quick-fixed an error for the output buffers. The thing is this: if a
23 * WinApp starts using serial ports, it calls OpenComm, asking it to open two
24 * buffers, cbInQueue and cbOutQueue size, to hold data to/from the serial
25 * ports. Wine OpenComm only returns "OK". Now the kernel buffer size for
26 * serial communication is only 4096 bytes large. Error: (App asks for
27 * a 104,000 bytes size buffer, Wine returns "OK", App asks "How many char's
28 * are in the buffer", Wine returns "4000" and App thinks "OK, another
29 * 100,000 chars left, good!")
30 * The solution below is a bad but working quickfix for the transmit buffer:
31 * the cbInQueue is saved in a variable; when the program asks how many chars
32 * there are in the buffer, GetCommError returns # in buffer PLUS
33 * the additional (cbOutQeueu - 4096), which leaves the application thinking
35 * Sorry for the rather chatty explanation - but I think comm.c needs to be
36 * redefined with real working buffers make it work; maybe these comments are
38 * Oktober 98, Rein Klazes [RHK]
39 * A program that wants to monitor the modem status line (RLSD/DCD) may
40 * poll the modem status register in the commMask structure. I update the bit
41 * in GetCommError, waiting for an implementation of communication events.
57 #ifdef HAVE_SYS_FILIO_H
58 # include <sys/filio.h>
60 #include <sys/ioctl.h>
63 #include "wine/winuser16.h"
65 #ifdef HAVE_SYS_MODEM_H
66 # include <sys/modem.h>
68 #ifdef HAVE_SYS_STRTIO_H
69 # include <sys/strtio.h>
74 #include "server/request.h"
83 #define TIOCINQ FIONREAD
85 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
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_fd(int fd
)
168 for (x
=0; x
!=MAX_PORTS
; x
++) {
178 struct DosDeviceStruct
*GetDeviceStruct(int fd
)
180 if ((fd
&0x7F)<=MAX_PORTS
) {
193 int GetCommPort_fd(int fd
)
197 for (x
=0; x
<MAX_PORTS
; x
++) {
205 int ValidCOMPort(int x
)
207 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
210 int ValidLPTPort(int x
)
212 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
217 TRACE(comm
, "errno = %d\n", errno
);
224 static void WINE_UNUSED
comm_notification(int fd
,void*private)
226 /* in here, we need to:
227 1. read any data from the comm port
228 2. save it into our own internal buffers
229 (we need our own buffers to implement notifications properly!)
230 3. write data from our own internal buffers to the comm port
231 4. if wnd is set, send WM_COMMNOTIFY (using PostMessage) when
232 thresholds set by EnableCommNotification are passed */
236 /**************************************************************************
237 * BuildCommDCB (USER.213)
239 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
241 /* "COM1:9600,n,8,1" */
244 char *ptr
, temp
[256];
246 TRACE(comm
, "(%s), ptr %p\n", device
, lpdcb
);
248 if (!lstrncmpiA(device
,"COM",3)) {
249 port
= device
[3] - '0';
253 ERR(comm
, "BUG ! COM0 can't exist!.\n");
257 if (!ValidCOMPort(port
)) {
261 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
268 if (*(device
+4) != ':')
271 strcpy(temp
,device
+5);
272 ptr
= strtok(temp
, ", ");
274 if (COM
[port
].baudrate
> 0)
275 lpdcb
->BaudRate
= COM
[port
].baudrate
;
277 lpdcb
->BaudRate
= atoi(ptr
);
278 TRACE(comm
,"baudrate (%d)\n", lpdcb
->BaudRate
);
280 ptr
= strtok(NULL
, ", ");
282 *ptr
= toupper(*ptr
);
284 TRACE(comm
,"parity (%c)\n", *ptr
);
285 lpdcb
->fParity
= TRUE
;
288 lpdcb
->Parity
= NOPARITY
;
289 lpdcb
->fParity
= FALSE
;
292 lpdcb
->Parity
= EVENPARITY
;
295 lpdcb
->Parity
= MARKPARITY
;
298 lpdcb
->Parity
= ODDPARITY
;
301 WARN(comm
,"Unknown parity `%c'!\n", *ptr
);
305 ptr
= strtok(NULL
, ", ");
306 TRACE(comm
, "charsize (%c)\n", *ptr
);
307 lpdcb
->ByteSize
= *ptr
- '0';
309 ptr
= strtok(NULL
, ", ");
310 TRACE(comm
, "stopbits (%c)\n", *ptr
);
313 lpdcb
->StopBits
= ONESTOPBIT
;
316 lpdcb
->StopBits
= TWOSTOPBITS
;
319 WARN(comm
,"Unknown # of stopbits `%c'!\n", *ptr
);
327 /*****************************************************************************
328 * OpenComm (USER.200)
330 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
334 TRACE(comm
, "%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
336 if (!lstrncmpiA(device
,"COM",3)) {
337 port
= device
[3] - '0';
340 ERR(comm
, "BUG ! COM0 doesn't exist !\n");
343 /* to help GetCommError return left buffsize [V] */
344 iGlobalOutQueueFiller
= (cbOutQueue
- SERIAL_XMIT_SIZE
);
345 if (iGlobalOutQueueFiller
< 0) iGlobalOutQueueFiller
= 0;
347 TRACE(comm
, "%s = %s\n", device
, COM
[port
].devicename
);
349 if (!ValidCOMPort(port
)) {
356 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
360 unknown
[port
] = SEGPTR_ALLOC(40);
361 bzero(unknown
[port
],40);
363 COM
[port
].commerror
= 0;
364 COM
[port
].eventmask
= 0;
365 /* save terminal state */
366 tcgetattr(fd
,&m_stat
[port
]);
368 /* allocate buffers */
370 /* enable async notifications */
371 ASYNC_RegisterFD(COM
[port
].fd
,comm_notification
,&COM
[port
]);
377 if (!lstrncmpiA(device
,"LPT",3)) {
378 port
= device
[3] - '0';
381 ERR(comm
, "BUG ! LPT0 doesn't exist !\n");
384 if (!ValidLPTPort(port
)) {
391 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
396 LPT
[port
].commerror
= 0;
397 LPT
[port
].eventmask
= 0;
404 /*****************************************************************************
405 * CloseComm (USER.207)
407 INT16 WINAPI
CloseComm16(INT16 cid
)
409 struct DosDeviceStruct
*ptr
;
411 TRACE(comm
,"cid=%d\n", cid
);
412 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
417 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
419 /* disable async notifications */
420 ASYNC_UnregisterFD(COM
[cid
].fd
,comm_notification
);
424 /* reset modem lines */
425 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
428 if (close(ptr
->fd
) == -1) {
429 ptr
->commerror
= WinError();
430 /* FIXME: should we clear ptr->fd here? */
439 /*****************************************************************************
440 * SetCommBreak (USER.210)
442 INT16 WINAPI
SetCommBreak16(INT16 cid
)
444 struct DosDeviceStruct
*ptr
;
446 TRACE(comm
,"cid=%d\n", cid
);
447 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
456 /*****************************************************************************
457 * ClearCommBreak (USER.211)
459 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
461 struct DosDeviceStruct
*ptr
;
463 TRACE(comm
,"cid=%d\n", cid
);
464 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
473 /*****************************************************************************
474 * EscapeCommFunction (USER.214)
476 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
479 struct DosDeviceStruct
*ptr
;
482 TRACE(comm
,"cid=%d, function=%d\n", cid
, nFunction
);
483 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
486 if (tcgetattr(ptr
->fd
,&port
) == -1) {
487 ptr
->commerror
=WinError();
496 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
502 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
509 port
.c_cflag
&= TIOCM_DTR
;
515 port
.c_cflag
&= TIOCM_RTS
;
521 port
.c_cflag
|= CRTSCTS
;
525 port
.c_cflag
|= CRTSCTS
;
530 port
.c_iflag
|= IXOFF
;
534 port
.c_iflag
|= IXON
;
538 WARN(comm
,"(cid=%d,nFunction=%d): Unknown function\n",
543 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
544 ptr
->commerror
= WinError();
552 /*****************************************************************************
553 * FlushComm (USER.215)
555 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
558 struct DosDeviceStruct
*ptr
;
560 TRACE(comm
,"cid=%d, queue=%d\n", cid
, fnQueue
);
561 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
565 case 0: queue
= TCOFLUSH
;
567 case 1: queue
= TCIFLUSH
;
569 default:WARN(comm
,"(cid=%d,fnQueue=%d):Unknown queue\n",
573 if (tcflush(ptr
->fd
, queue
)) {
574 ptr
->commerror
= WinError();
582 /********************************************************************
583 * GetCommError (USER.203)
585 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
590 struct DosDeviceStruct
*ptr
;
594 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
598 WARN(comm
," cid %d not comm port\n",cid
);
601 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
602 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
603 if( mstat
&TIOCM_CAR
)
611 rc
= ioctl(ptr
->fd
, TIOCOUTQ
, &cnt
);
612 if (rc
) WARN(comm
, "Error !\n");
613 lpStat
->cbOutQue
= cnt
+ iGlobalOutQueueFiller
;
615 rc
= ioctl(ptr
->fd
, TIOCINQ
, &cnt
);
616 if (rc
) WARN(comm
, "Error !\n");
617 lpStat
->cbInQue
= cnt
;
619 TRACE(comm
, "cid %d, error %d, lpStat %d %d %d stol %x\n",
620 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
621 lpStat
->cbOutQue
, *stol
);
624 TRACE(comm
, "cid %d, error %d, lpStat NULL stol %x\n",
625 cid
, ptr
->commerror
, *stol
);
627 /* Return any errors and clear it */
628 temperror
= ptr
->commerror
;
633 /*****************************************************************************
634 * SetCommEventMask (USER.208)
636 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
638 struct DosDeviceStruct
*ptr
;
643 TRACE(comm
,"cid %d,mask %d\n",cid
,fuEvtMask
);
644 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
647 ptr
->eventmask
|= fuEvtMask
;
649 WARN(comm
," cid %d not comm port\n",cid
);
650 return SEGPTR_GET(NULL
);
652 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
653 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
654 TRACE(comm
, " ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
655 if ((mstat
&TIOCM_CAR
)) {*stol
|= 0x80;}
657 TRACE(comm
," modem dcd construct %x\n",*stol
);
658 return SEGPTR_GET(unknown
[cid
]);
661 /*****************************************************************************
662 * GetCommEventMask (USER.209)
664 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
667 struct DosDeviceStruct
*ptr
;
669 TRACE(comm
, "cid %d, mask %d\n", cid
, fnEvtClear
);
670 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
675 * Determine if any characters are available
677 if (fnEvtClear
& EV_RXCHAR
)
682 rc
= ioctl(ptr
->fd
, TIOCINQ
, &cnt
);
683 if (cnt
) events
|= EV_RXCHAR
;
685 TRACE(comm
, "rxchar %ld\n", cnt
);
689 * There are other events that need to be checked for
693 TRACE(comm
, "return events %d\n", events
);
697 * [RER] The following was gibberish
700 tempmask
= ptr
->eventmask
;
701 ptr
->eventmask
&= ~fnEvtClear
;
702 return ptr
->eventmask
;
706 /*****************************************************************************
707 * SetCommState16 (USER.201)
709 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
712 struct DosDeviceStruct
*ptr
;
714 TRACE(comm
, "cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
715 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
718 if (tcgetattr(ptr
->fd
, &port
) == -1) {
719 ptr
->commerror
= WinError();
724 port
.c_cc
[VTIME
] = 1;
727 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
729 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
731 port
.c_iflag
|= (IGNBRK
);
733 port
.c_oflag
&= ~(OPOST
);
735 port
.c_cflag
&= ~(HUPCL
);
736 port
.c_cflag
|= CLOCAL
| CREAD
;
738 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
739 port
.c_lflag
|= NOFLSH
;
741 if (ptr
->baudrate
> 0)
742 lpdcb
->BaudRate
= ptr
->baudrate
;
743 TRACE(comm
,"baudrate %d\n",lpdcb
->BaudRate
);
745 port
.c_cflag
&= ~CBAUD
;
746 switch (lpdcb
->BaudRate
) {
749 port
.c_cflag
|= B110
;
753 port
.c_cflag
|= B300
;
757 port
.c_cflag
|= B600
;
761 port
.c_cflag
|= B1200
;
765 port
.c_cflag
|= B2400
;
769 port
.c_cflag
|= B4800
;
773 port
.c_cflag
|= B9600
;
777 port
.c_cflag
|= B19200
;
781 port
.c_cflag
|= B38400
;
785 port
.c_cflag
|= B57600
;
790 port
.c_cflag
|= B115200
;
794 ptr
->commerror
= IE_BAUDRATE
;
797 #elif !defined(__EMX__)
798 switch (lpdcb
->BaudRate
) {
801 port
.c_ospeed
= B110
;
805 port
.c_ospeed
= B300
;
809 port
.c_ospeed
= B600
;
813 port
.c_ospeed
= B1200
;
817 port
.c_ospeed
= B2400
;
821 port
.c_ospeed
= B4800
;
825 port
.c_ospeed
= B9600
;
829 port
.c_ospeed
= B19200
;
833 port
.c_ospeed
= B38400
;
836 ptr
->commerror
= IE_BAUDRATE
;
839 port
.c_ispeed
= port
.c_ospeed
;
841 TRACE(comm
,"bytesize %d\n",lpdcb
->ByteSize
);
842 port
.c_cflag
&= ~CSIZE
;
843 switch (lpdcb
->ByteSize
) {
857 ptr
->commerror
= IE_BYTESIZE
;
861 TRACE(comm
,"parity %d\n",lpdcb
->Parity
);
862 port
.c_cflag
&= ~(PARENB
| PARODD
);
864 switch (lpdcb
->Parity
) {
866 port
.c_iflag
&= ~INPCK
;
869 port
.c_cflag
|= (PARENB
| PARODD
);
870 port
.c_iflag
|= INPCK
;
873 port
.c_cflag
|= PARENB
;
874 port
.c_iflag
|= INPCK
;
877 ptr
->commerror
= IE_BYTESIZE
;
882 TRACE(comm
,"stopbits %d\n",lpdcb
->StopBits
);
884 switch (lpdcb
->StopBits
) {
886 port
.c_cflag
&= ~CSTOPB
;
889 port
.c_cflag
|= CSTOPB
;
892 ptr
->commerror
= IE_BYTESIZE
;
897 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
898 port
.c_cflag
|= CRTSCTS
;
900 if (lpdcb
->fDtrDisable
)
901 port
.c_cflag
&= ~CRTSCTS
;
904 port
.c_iflag
|= IXON
;
906 port
.c_iflag
&= ~IXON
;
908 port
.c_iflag
|= IXOFF
;
910 port
.c_iflag
&= ~IXOFF
;
912 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
913 ptr
->commerror
= WinError();
921 /*****************************************************************************
922 * GetCommState (USER.202)
924 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
926 struct DosDeviceStruct
*ptr
;
929 TRACE(comm
,"cid %d, ptr %p\n", cid
, lpdcb
);
930 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
933 if (tcgetattr(ptr
->fd
, &port
) == -1) {
934 ptr
->commerror
= WinError();
940 switch (port
.c_cflag
& CBAUD
) {
942 switch (port
.c_ospeed
) {
945 lpdcb
->BaudRate
= 110;
948 lpdcb
->BaudRate
= 300;
951 lpdcb
->BaudRate
= 600;
954 lpdcb
->BaudRate
= 1200;
957 lpdcb
->BaudRate
= 2400;
960 lpdcb
->BaudRate
= 4800;
963 lpdcb
->BaudRate
= 9600;
966 lpdcb
->BaudRate
= 19200;
969 lpdcb
->BaudRate
= 38400;
973 lpdcb
->BaudRate
= 57600;
978 lpdcb
->BaudRate
= 57601;
983 switch (port
.c_cflag
& CSIZE
) {
998 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1000 lpdcb
->fParity
= FALSE
;
1001 lpdcb
->Parity
= NOPARITY
;
1004 lpdcb
->fParity
= TRUE
;
1005 lpdcb
->Parity
= EVENPARITY
;
1007 case (PARENB
| PARODD
):
1008 lpdcb
->fParity
= TRUE
;
1009 lpdcb
->Parity
= ODDPARITY
;
1013 if (port
.c_cflag
& CSTOPB
)
1014 lpdcb
->StopBits
= TWOSTOPBITS
;
1016 lpdcb
->StopBits
= ONESTOPBIT
;
1018 lpdcb
->RlsTimeout
= 50;
1019 lpdcb
->CtsTimeout
= 50;
1020 lpdcb
->DsrTimeout
= 50;
1024 lpdcb
->fDtrDisable
= 0;
1028 if (port
.c_cflag
& CRTSCTS
) {
1029 lpdcb
->fDtrflow
= 1;
1030 lpdcb
->fRtsflow
= 1;
1031 lpdcb
->fOutxCtsFlow
= 1;
1032 lpdcb
->fOutxDsrFlow
= 1;
1035 lpdcb
->fDtrDisable
= 1;
1037 if (port
.c_iflag
& IXON
)
1042 if (port
.c_iflag
& IXOFF
)
1051 lpdcb
->XoffLim
= 10;
1057 /*****************************************************************************
1058 * TransmitCommChar (USER.206)
1060 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1062 struct DosDeviceStruct
*ptr
;
1064 TRACE(comm
, "cid %d, data %d \n", cid
, chTransmit
);
1065 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1069 if (ptr
->suspended
) {
1070 ptr
->commerror
= IE_HARDWARE
;
1074 if (write(ptr
->fd
, (void *) &chTransmit
, 1) == -1) {
1075 ptr
->commerror
= WinError();
1083 /*****************************************************************************
1084 * UngetCommChar (USER.212)
1086 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1088 struct DosDeviceStruct
*ptr
;
1090 TRACE(comm
,"cid %d (char %d)\n", cid
, chUnget
);
1091 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1095 if (ptr
->suspended
) {
1096 ptr
->commerror
= IE_HARDWARE
;
1101 ptr
->unget_byte
= chUnget
;
1106 /*****************************************************************************
1107 * ReadComm (USER.204)
1109 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1112 struct DosDeviceStruct
*ptr
;
1114 TRACE(comm
, "cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1115 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1119 if (ptr
->suspended
) {
1120 ptr
->commerror
= IE_HARDWARE
;
1125 *lpvBuf
= ptr
->unget_byte
;
1133 status
= read(ptr
->fd
, (void *) lpvBuf
, cbRead
);
1136 if (errno
!= EAGAIN
) {
1137 ptr
->commerror
= WinError();
1144 TRACE(comm
,"%.*s\n", length
+status
, lpvBuf
);
1146 return length
+ status
;
1150 /*****************************************************************************
1151 * WriteComm (USER.205)
1153 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1156 struct DosDeviceStruct
*ptr
;
1158 TRACE(comm
,"cid %d, ptr %p, length %d\n",
1159 cid
, lpvBuf
, cbWrite
);
1160 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1164 if (ptr
->suspended
) {
1165 ptr
->commerror
= IE_HARDWARE
;
1169 TRACE(comm
,"%.*s\n", cbWrite
, lpvBuf
);
1170 length
= write(ptr
->fd
, (void *) lpvBuf
, cbWrite
);
1173 ptr
->commerror
= WinError();
1181 /***********************************************************************
1182 * EnableCommNotification (USER.246)
1184 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1185 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1187 struct DosDeviceStruct
*ptr
;
1189 FIXME(comm
, "(%d, %x, %d, %d):stub.\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1190 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1191 ptr
->commerror
= IE_BADID
;
1195 ptr
->n_read
= cbWriteNotify
;
1196 ptr
->n_write
= cbOutQueue
;
1201 /**************************************************************************
1202 * BuildCommDCBA (KERNEL32.14)
1204 BOOL WINAPI
BuildCommDCBA(LPCSTR device
,LPDCB lpdcb
)
1206 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1209 /**************************************************************************
1210 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1212 BOOL WINAPI
BuildCommDCBAndTimeoutsA(LPCSTR device
, LPDCB lpdcb
,
1213 LPCOMMTIMEOUTS lptimeouts
)
1218 TRACE(comm
,"(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1220 if (!lstrncmpiA(device
,"COM",3)) {
1223 ERR(comm
,"BUG! COM0 can't exists!.\n");
1226 if (!ValidCOMPort(port
))
1228 if (*(device
+4)!=':')
1230 temp
=(LPSTR
)(device
+5);
1234 memset(lpdcb
, 0, sizeof(DCB
)); /* initialize */
1236 lpdcb
->DCBlength
= sizeof(DCB
);
1237 if (strchr(temp
,',')) { /* old style */
1240 char last
=temp
[strlen(temp
)-1];
1242 ret
=BuildCommDCB16(device
,&dcb16
);
1245 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1246 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1247 lpdcb
->fBinary
= dcb16
.fBinary
;
1248 lpdcb
->Parity
= dcb16
.Parity
;
1249 lpdcb
->fParity
= dcb16
.fParity
;
1250 lpdcb
->fNull
= dcb16
.fNull
;
1251 lpdcb
->StopBits
= dcb16
.StopBits
;
1254 lpdcb
->fOutX
= TRUE
;
1255 lpdcb
->fOutxCtsFlow
= FALSE
;
1256 lpdcb
->fOutxDsrFlow
= FALSE
;
1257 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1258 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1259 } else if (last
=='p') {
1260 lpdcb
->fInX
= FALSE
;
1261 lpdcb
->fOutX
= FALSE
;
1262 lpdcb
->fOutxCtsFlow
= TRUE
;
1263 lpdcb
->fOutxDsrFlow
= TRUE
;
1264 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1265 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1267 lpdcb
->fInX
= FALSE
;
1268 lpdcb
->fOutX
= FALSE
;
1269 lpdcb
->fOutxCtsFlow
= FALSE
;
1270 lpdcb
->fOutxDsrFlow
= FALSE
;
1271 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1272 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1274 lpdcb
->XonChar
= dcb16
.XonChar
;
1275 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1276 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1277 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1278 lpdcb
->EofChar
= dcb16
.EofChar
;
1279 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1280 lpdcb
->XonLim
= dcb16
.XonLim
;
1281 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1284 ptr
=strtok(temp
," ");
1289 if (!strncmp("baud=",ptr
,5)) {
1290 if (!sscanf(ptr
+5,"%ld",&x
))
1291 WARN(comm
,"Couldn't parse %s\n",ptr
);
1292 lpdcb
->BaudRate
= x
;
1295 if (!strncmp("stop=",ptr
,5)) {
1296 if (!sscanf(ptr
+5,"%ld",&x
))
1297 WARN(comm
,"Couldn't parse %s\n",ptr
);
1298 lpdcb
->StopBits
= x
;
1301 if (!strncmp("data=",ptr
,5)) {
1302 if (!sscanf(ptr
+5,"%ld",&x
))
1303 WARN(comm
,"Couldn't parse %s\n",ptr
);
1304 lpdcb
->ByteSize
= x
;
1307 if (!strncmp("parity=",ptr
,7)) {
1308 lpdcb
->fParity
= TRUE
;
1311 lpdcb
->fParity
= FALSE
;
1312 lpdcb
->Parity
= NOPARITY
;
1315 lpdcb
->Parity
= EVENPARITY
;
1318 lpdcb
->Parity
= ODDPARITY
;
1321 lpdcb
->Parity
= MARKPARITY
;
1327 ERR(comm
,"Unhandled specifier '%s', please report.\n",ptr
);
1328 ptr
=strtok(NULL
," ");
1330 if (lpdcb
->BaudRate
==110)
1331 lpdcb
->StopBits
= 2;
1335 /**************************************************************************
1336 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1338 BOOL WINAPI
BuildCommDCBAndTimeoutsW( LPCWSTR devid
, LPDCB lpdcb
,
1339 LPCOMMTIMEOUTS lptimeouts
)
1344 TRACE(comm
,"(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1345 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1346 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1347 HeapFree( GetProcessHeap(), 0, devidA
);
1351 /**************************************************************************
1352 * BuildCommDCBW (KERNEL32.17)
1354 BOOL WINAPI
BuildCommDCBW(LPCWSTR devid
,LPDCB lpdcb
)
1356 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1359 /*****************************************************************************
1361 * returns a file descriptor for reading from or writing to
1362 * mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
1363 * the handle afterwards!
1365 int COMM_Handle2fd(HANDLE handle
, int mode
) {
1366 struct get_read_fd_request r_req
;
1367 struct get_write_fd_request w_req
;
1370 w_req
.handle
= r_req
.handle
= handle
;
1374 CLIENT_SendRequest( REQ_GET_WRITE_FD
, -1, 1, &w_req
, sizeof(w_req
) );
1377 CLIENT_SendRequest( REQ_GET_READ_FD
, -1, 1, &r_req
, sizeof(r_req
) );
1380 ERR(comm
,"COMM_Handle2fd: Don't know what type of fd is required.\n");
1383 CLIENT_WaitReply( NULL
, &fd
, 0 );
1388 /* FIXME: having these global for win32 for now */
1389 int commerror
=0,eventmask
=0;
1391 /*****************************************************************************
1392 * SetCommBreak (KERNEL32.449)
1394 BOOL WINAPI
SetCommBreak(HANDLE handle
)
1396 FIXME(comm
,"handle %d, stub!\n", handle
);
1400 /*****************************************************************************
1401 * ClearCommBreak (KERNEL32.20)
1403 BOOL WINAPI
ClearCommBreak(HANDLE handle
)
1405 FIXME(comm
,"handle %d, stub!\n", handle
);
1409 /*****************************************************************************
1410 * EscapeCommFunction (KERNEL32.214)
1412 BOOL WINAPI
EscapeCommFunction(HANDLE handle
,UINT nFunction
)
1415 struct termios port
;
1417 TRACE(comm
,"handle %d, function=%d\n", handle
, nFunction
);
1418 fd
= COMM_Handle2fd(handle
, GENERIC_WRITE
);
1422 if (tcgetattr(fd
,&port
) == -1) {
1423 commerror
=WinError();
1428 switch (nFunction
) {
1434 port
.c_cflag
&= TIOCM_DTR
;
1440 port
.c_cflag
&= TIOCM_RTS
;
1446 port
.c_cflag
|= CRTSCTS
;
1450 port
.c_cflag
|= CRTSCTS
;
1455 port
.c_iflag
|= IXOFF
;
1459 port
.c_iflag
|= IXON
;
1462 FIXME(comm
,"setbreak, stub\n");
1463 /* ptr->suspended = 1; */
1466 FIXME(comm
,"clrbreak, stub\n");
1467 /* ptr->suspended = 0; */
1470 WARN(comm
,"(handle=%d,nFunction=%d): Unknown function\n",
1475 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1476 commerror
= WinError();
1486 /********************************************************************
1487 * PurgeComm (KERNEL32.557)
1489 BOOL WINAPI
PurgeComm( HANDLE handle
, DWORD flags
)
1493 TRACE(comm
,"handle %d, flags %lx\n", handle
, flags
);
1495 fd
= COMM_Handle2fd(handle
, GENERIC_WRITE
);
1500 ** not exactly sure how these are different
1501 ** Perhaps if we had our own internal queues, one flushes them
1502 ** and the other flushes the kernel's buffers.
1504 if(flags
&PURGE_TXABORT
)
1506 tcflush(fd
,TCOFLUSH
);
1508 if(flags
&PURGE_RXABORT
)
1510 tcflush(fd
,TCIFLUSH
);
1512 if(flags
&PURGE_TXCLEAR
)
1514 tcflush(fd
,TCOFLUSH
);
1516 if(flags
&PURGE_RXCLEAR
)
1518 tcflush(fd
,TCIFLUSH
);
1525 /*****************************************************************************
1526 * ClearCommError (KERNEL32.21)
1528 BOOL WINAPI
ClearCommError(INT handle
,LPDWORD errors
,LPCOMSTAT lpStat
)
1532 fd
=COMM_Handle2fd(handle
,GENERIC_READ
);
1542 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1543 WARN(comm
, "ioctl returned error\n");
1545 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
1546 WARN(comm
, "ioctl returned error\n");
1551 TRACE(comm
,"handle %d cbInQue = %ld cbOutQue = %ld\n",
1560 ** After an asynchronous write opperation, the
1561 ** app will call ClearCommError to see if the
1562 ** results are ready yet. It waits for ERROR_IO_PENDING
1564 commerror
= ERROR_IO_PENDING
;
1569 /*****************************************************************************
1570 * SetupComm (KERNEL32.676)
1572 BOOL WINAPI
SetupComm( HANDLE handle
, DWORD insize
, DWORD outsize
)
1576 FIXME(comm
, "insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1577 fd
=COMM_Handle2fd(handle
,GENERIC_WRITE
);
1586 /*****************************************************************************
1587 * GetCommMask (KERNEL32.156)
1589 BOOL WINAPI
GetCommMask(HANDLE handle
,LPDWORD evtmask
)
1593 TRACE(comm
, "handle %d, mask %p\n", handle
, evtmask
);
1594 if(0>(fd
=COMM_Handle2fd(handle
,GENERIC_READ
)))
1599 *evtmask
= eventmask
;
1603 /*****************************************************************************
1604 * SetCommMask (KERNEL32.451)
1606 BOOL WINAPI
SetCommMask(INT handle
,DWORD evtmask
)
1610 TRACE(comm
, "handle %d, mask %lx\n", handle
, evtmask
);
1611 if(0>(fd
=COMM_Handle2fd(handle
,GENERIC_WRITE
))) {
1615 eventmask
= evtmask
;
1619 /*****************************************************************************
1620 * SetCommState (KERNEL32.452)
1622 BOOL WINAPI
SetCommState(INT handle
,LPDCB lpdcb
)
1624 struct termios port
;
1626 struct get_write_fd_request req
;
1628 TRACE(comm
,"handle %d, ptr %p\n", handle
, lpdcb
);
1630 req
.handle
= handle
;
1631 CLIENT_SendRequest( REQ_GET_WRITE_FD
, -1, 1, &req
, sizeof(req
) );
1632 CLIENT_WaitReply( NULL
, &fd
, 0 );
1637 if (tcgetattr(fd
,&port
) == -1) {
1638 commerror
= WinError();
1642 port
.c_cc
[VMIN
] = 0;
1643 port
.c_cc
[VTIME
] = 1;
1646 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1648 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1650 port
.c_iflag
|= (IGNBRK
);
1652 port
.c_oflag
&= ~(OPOST
);
1654 port
.c_cflag
&= ~(HUPCL
);
1655 port
.c_cflag
|= CLOCAL
| CREAD
;
1657 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1658 port
.c_lflag
|= NOFLSH
;
1661 ** MJM - removed default baudrate settings
1662 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1665 port
.c_cflag
&= ~CBAUD
;
1666 switch (lpdcb
->BaudRate
) {
1669 port
.c_cflag
|= B110
;
1673 port
.c_cflag
|= B300
;
1677 port
.c_cflag
|= B600
;
1681 port
.c_cflag
|= B1200
;
1685 port
.c_cflag
|= B2400
;
1689 port
.c_cflag
|= B4800
;
1693 port
.c_cflag
|= B9600
;
1697 port
.c_cflag
|= B19200
;
1701 port
.c_cflag
|= B38400
;
1704 commerror
= IE_BAUDRATE
;
1707 #elif !defined(__EMX__)
1708 switch (lpdcb
->BaudRate
) {
1711 port
.c_ospeed
= B110
;
1715 port
.c_ospeed
= B300
;
1719 port
.c_ospeed
= B600
;
1723 port
.c_ospeed
= B1200
;
1727 port
.c_ospeed
= B2400
;
1731 port
.c_ospeed
= B4800
;
1735 port
.c_ospeed
= B9600
;
1739 port
.c_ospeed
= B19200
;
1743 port
.c_ospeed
= B38400
;
1746 commerror
= IE_BAUDRATE
;
1749 port
.c_ispeed
= port
.c_ospeed
;
1751 TRACE(comm
,"bytesize %d\n",lpdcb
->ByteSize
);
1752 port
.c_cflag
&= ~CSIZE
;
1753 switch (lpdcb
->ByteSize
) {
1755 port
.c_cflag
|= CS5
;
1758 port
.c_cflag
|= CS6
;
1761 port
.c_cflag
|= CS7
;
1764 port
.c_cflag
|= CS8
;
1767 commerror
= IE_BYTESIZE
;
1771 TRACE(comm
,"parity %d\n",lpdcb
->Parity
);
1772 port
.c_cflag
&= ~(PARENB
| PARODD
);
1774 switch (lpdcb
->Parity
) {
1776 port
.c_iflag
&= ~INPCK
;
1779 port
.c_cflag
|= (PARENB
| PARODD
);
1780 port
.c_iflag
|= INPCK
;
1783 port
.c_cflag
|= PARENB
;
1784 port
.c_iflag
|= INPCK
;
1787 commerror
= IE_BYTESIZE
;
1792 TRACE(comm
,"stopbits %d\n",lpdcb
->StopBits
);
1793 switch (lpdcb
->StopBits
) {
1795 port
.c_cflag
&= ~CSTOPB
;
1798 port
.c_cflag
|= CSTOPB
;
1801 commerror
= IE_BYTESIZE
;
1805 if ( lpdcb
->fOutxCtsFlow
||
1806 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
1807 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
1809 port
.c_cflag
|= CRTSCTS
;
1810 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
1811 port
.c_cflag
&= ~CRTSCTS
;
1815 port
.c_iflag
|= IXON
;
1817 port
.c_iflag
&= ~IXON
;
1819 port
.c_iflag
|= IXOFF
;
1821 port
.c_iflag
&= ~IXOFF
;
1823 if (tcsetattr(fd
,TCSADRAIN
,&port
)==-1) {
1824 commerror
= WinError();
1833 /*****************************************************************************
1834 * GetCommState (KERNEL32.159)
1836 BOOL WINAPI
GetCommState(INT handle
, LPDCB lpdcb
)
1838 struct termios port
;
1840 struct get_read_fd_request req
;
1842 TRACE(comm
,"handle %d, ptr %p\n", handle
, lpdcb
);
1843 req
.handle
= handle
;
1844 CLIENT_SendRequest( REQ_GET_READ_FD
, -1, 1, &req
, sizeof(req
) );
1845 CLIENT_WaitReply( NULL
, &fd
, 0 );
1850 if (tcgetattr(fd
, &port
) == -1) {
1851 TRACE(comm
,"tcgetattr(%d, ...) returned -1",fd
);
1852 commerror
= WinError();
1857 switch (port
.c_cflag
& CBAUD
) {
1859 switch (port
.c_ospeed
) {
1862 lpdcb
->BaudRate
= 110;
1865 lpdcb
->BaudRate
= 300;
1868 lpdcb
->BaudRate
= 600;
1871 lpdcb
->BaudRate
= 1200;
1874 lpdcb
->BaudRate
= 2400;
1877 lpdcb
->BaudRate
= 4800;
1880 lpdcb
->BaudRate
= 9600;
1883 lpdcb
->BaudRate
= 19200;
1886 lpdcb
->BaudRate
= 38400;
1890 switch (port
.c_cflag
& CSIZE
) {
1892 lpdcb
->ByteSize
= 5;
1895 lpdcb
->ByteSize
= 6;
1898 lpdcb
->ByteSize
= 7;
1901 lpdcb
->ByteSize
= 8;
1905 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1907 lpdcb
->fParity
= FALSE
;
1908 lpdcb
->Parity
= NOPARITY
;
1911 lpdcb
->fParity
= TRUE
;
1912 lpdcb
->Parity
= EVENPARITY
;
1914 case (PARENB
| PARODD
):
1915 lpdcb
->fParity
= TRUE
;
1916 lpdcb
->Parity
= ODDPARITY
;
1920 if (port
.c_cflag
& CSTOPB
)
1921 lpdcb
->StopBits
= TWOSTOPBITS
;
1923 lpdcb
->StopBits
= ONESTOPBIT
;
1930 if (port
.c_cflag
& CRTSCTS
) {
1931 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1932 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1933 lpdcb
->fOutxCtsFlow
= 1;
1934 lpdcb
->fOutxDsrFlow
= 1;
1938 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
1939 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
1941 if (port
.c_iflag
& IXON
)
1946 if (port
.c_iflag
& IXOFF
)
1955 lpdcb
->XoffLim
= 10;
1964 /*****************************************************************************
1965 * TransmitCommChar (KERNEL32.535)
1967 BOOL WINAPI
TransmitCommChar(INT cid
,CHAR chTransmit
)
1969 struct DosDeviceStruct
*ptr
;
1971 FIXME(comm
,"(%d,'%c'), use win32 handle!\n",cid
,chTransmit
);
1972 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1976 if (ptr
->suspended
) {
1977 ptr
->commerror
= IE_HARDWARE
;
1980 if (write(ptr
->fd
, (void *) &chTransmit
, 1) == -1) {
1981 ptr
->commerror
= WinError();
1989 /*****************************************************************************
1990 * GetCommTimeouts (KERNEL32.160)
1992 BOOL WINAPI
GetCommTimeouts(INT cid
,LPCOMMTIMEOUTS lptimeouts
)
1994 FIXME(comm
,"(%x,%p):stub.\n",cid
,lptimeouts
);
1998 /*****************************************************************************
1999 * SetCommTimeouts (KERNEL32.453)
2001 BOOL WINAPI
SetCommTimeouts(INT cid
,LPCOMMTIMEOUTS lptimeouts
) {
2002 FIXME(comm
,"(%x,%p):stub.\n",cid
,lptimeouts
);
2006 /***********************************************************************
2007 * GetCommModemStatus (KERNEL32.285)
2009 BOOL WINAPI
GetCommModemStatus(HANDLE hFile
,LPDWORD lpModemStat
)
2011 FIXME(comm
, "(%d %p)\n",hFile
,lpModemStat
);
2014 /***********************************************************************
2015 * WaitCommEvent (KERNEL32.719)
2017 BOOL WINAPI
WaitCommEvent(HANDLE hFile
,LPDWORD eventmask
,LPOVERLAPPED overlapped
)
2019 FIXME(comm
, "(%d %p %p )\n",hFile
, eventmask
,overlapped
);
2023 /***********************************************************************
2024 * GetCommProperties (KERNEL32.???)
2026 BOOL WINAPI
GetCommProperties(HANDLE hFile
, LPDCB
*dcb
)
2028 FIXME(comm
, "(%d %p )\n",hFile
,dcb
);
2032 /***********************************************************************
2033 * SetCommProperties (KERNEL32.???)
2035 BOOL WINAPI
SetCommProperties(HANDLE hFile
, LPDCB dcb
)
2037 FIXME(comm
, "(%d %p )\n",hFile
,dcb
);