2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
51 #include <sys/ioctl.h>
56 #ifdef HAVE_SYS_MODEM_H
57 # include <sys/modem.h>
59 #ifdef HAVE_SYS_STRTIO_H
60 # include <sys/strtio.h>
64 #include "wine/port.h"
71 #include "debugtools.h"
73 DEFAULT_DEBUG_CHANNEL(comm
);
75 #if !defined(TIOCINQ) && defined(FIONREAD)
76 #define TIOCINQ FIONREAD
79 /* window's semi documented modem status register */
80 #define COMM_MSR_OFFSET 35
85 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
90 #define CMSPAR 0x40000000 /* stick parity */
95 struct DosDeviceStruct
{
96 char *devicename
; /* /dev/ttyS0 */
103 int commerror
, eventmask
;
106 unsigned ibuf_size
,ibuf_head
,ibuf_tail
;
107 unsigned obuf_size
,obuf_head
,obuf_tail
;
109 int wnd
, n_read
, n_write
;
110 HANDLE s_read
, s_write
;
114 static struct DosDeviceStruct COM
[MAX_PORTS
];
115 static struct DosDeviceStruct LPT
[MAX_PORTS
];
116 /* pointers to unknown(==undocumented) comm structure */
117 static LPCVOID
*unknown
[MAX_PORTS
];
118 /* save terminal states */
119 static struct termios m_stat
[MAX_PORTS
];
121 /* update window's semi documented modem status register */
122 /* see knowledge base Q101417 */
123 static void COMM_MSRUpdate( UCHAR
* pMsr
, unsigned int mstat
)
127 if(mstat
& TIOCM_CTS
) tmpmsr
|= MSR_CTS
;
130 if(mstat
& TIOCM_DSR
) tmpmsr
|= MSR_DSR
;
133 if(mstat
& TIOCM_RI
) tmpmsr
|= MSR_RI
;
136 if(mstat
& TIOCM_CAR
) tmpmsr
|= MSR_RLSD
;
138 *pMsr
= (*pMsr
& ~MSR_MASK
) | tmpmsr
;
144 char option
[10], temp
[256], *btemp
;
147 for (x
=0; x
!=MAX_PORTS
; x
++) {
148 strcpy(option
,"COMx");
152 PROFILE_GetWineIniString( "serialports", option
, "*",
153 temp
, sizeof(temp
) );
154 if (!strcmp(temp
, "*") || *temp
== '\0')
155 COM
[x
].devicename
= NULL
;
157 btemp
= strchr(temp
,',');
160 COM
[x
].baudrate
= atoi(btemp
);
162 COM
[x
].baudrate
= -1;
165 if (!S_ISCHR(st
.st_mode
))
166 WARN("Can't use `%s' as %s !\n", temp
, option
);
168 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
169 WARN("Can't malloc for device info!\n");
172 strcpy(COM
[x
].devicename
, temp
);
174 TRACE("%s = %s\n", option
, COM
[x
].devicename
);
177 strcpy(option
, "LPTx");
181 PROFILE_GetWineIniString( "parallelports", option
, "*",
182 temp
, sizeof(temp
) );
183 if (!strcmp(temp
, "*") || *temp
== '\0')
184 LPT
[x
].devicename
= NULL
;
187 if (!S_ISCHR(st
.st_mode
))
188 WARN("Can't use `%s' as %s !\n", temp
, option
);
190 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
191 WARN("Can't malloc for device info!\n");
194 strcpy(LPT
[x
].devicename
, temp
);
196 TRACE("%s = %s\n", option
, LPT
[x
].devicename
);
203 static struct DosDeviceStruct
*GetDeviceStruct(int fd
)
205 if ((fd
&0x7F)<=MAX_PORTS
) {
206 if (!(fd
&FLAG_LPT
)) {
219 static int GetCommPort_fd(int fd
)
223 for (x
=0; x
<MAX_PORTS
; x
++) {
231 static int ValidCOMPort(int x
)
233 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
236 static int ValidLPTPort(int x
)
238 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
241 static int WinError(void)
243 TRACE("errno = %d\n", errno
);
250 static unsigned comm_inbuf(struct DosDeviceStruct
*ptr
)
252 return ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? ptr
->ibuf_size
: 0)
253 + ptr
->ibuf_head
- ptr
->ibuf_tail
;
256 static unsigned comm_outbuf(struct DosDeviceStruct
*ptr
)
258 return ((ptr
->obuf_tail
> ptr
->obuf_head
) ? ptr
->obuf_size
: 0)
259 + ptr
->obuf_head
- ptr
->obuf_tail
;
262 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
264 unsigned int mstat
, okay
;
265 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
266 if (okay
) return okay
;
267 if (andy
) mstat
&= andy
;
269 return ioctl(fd
, TIOCMSET
, &mstat
);
272 static void CALLBACK
comm_notification( ULONG_PTR
private )
274 struct DosDeviceStruct
*ptr
= (struct DosDeviceStruct
*)private;
275 int prev
, bleft
, len
;
277 int cid
= GetCommPort_fd(ptr
->fd
);
279 TRACE("async notification\n");
280 /* read data from comm port */
281 prev
= comm_inbuf(ptr
);
283 bleft
= ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? (ptr
->ibuf_tail
-1) : ptr
->ibuf_size
)
285 len
= read(ptr
->fd
, ptr
->inbuf
+ ptr
->ibuf_head
, bleft
?bleft
:1);
288 ptr
->commerror
= CE_RXOVER
;
290 /* check for events */
291 if ((ptr
->eventmask
& EV_RXFLAG
) &&
292 memchr(ptr
->inbuf
+ ptr
->ibuf_head
, ptr
->evtchar
, len
)) {
293 *(WORD
*)(unknown
[cid
]) |= EV_RXFLAG
;
296 if (ptr
->eventmask
& EV_RXCHAR
) {
297 *(WORD
*)(unknown
[cid
]) |= EV_RXCHAR
;
300 /* advance buffer position */
301 ptr
->ibuf_head
+= len
;
302 if (ptr
->ibuf_head
>= ptr
->ibuf_size
)
307 /* check for notification */
308 if (ptr
->wnd
&& (ptr
->n_read
>0) && (prev
<ptr
->n_read
) &&
309 (comm_inbuf(ptr
)>=ptr
->n_read
)) {
310 /* passed the receive notification threshold */
314 /* write any TransmitCommChar character */
316 len
= write(ptr
->fd
, &(ptr
->xmit
), 1);
317 if (len
> 0) ptr
->xmit
= -1;
319 /* write from output queue */
320 prev
= comm_outbuf(ptr
);
322 bleft
= ((ptr
->obuf_tail
<= ptr
->obuf_head
) ? ptr
->obuf_head
: ptr
->obuf_size
)
324 len
= bleft
? write(ptr
->fd
, ptr
->outbuf
+ ptr
->obuf_tail
, bleft
) : 0;
326 ptr
->obuf_tail
+= len
;
327 if (ptr
->obuf_tail
>= ptr
->obuf_size
)
330 if (ptr
->obuf_tail
== ptr
->obuf_head
) {
332 SERVICE_Delete( ptr
->s_write
);
333 ptr
->s_write
= INVALID_HANDLE_VALUE
;
335 if (ptr
->eventmask
& EV_TXEMPTY
) {
336 *(WORD
*)(unknown
[cid
]) |= EV_TXEMPTY
;
342 /* check for notification */
343 if (ptr
->wnd
&& (ptr
->n_write
>0) && (prev
>=ptr
->n_write
) &&
344 (comm_outbuf(ptr
)<ptr
->n_write
)) {
345 /* passed the transmit notification threshold */
349 /* send notifications, if any */
350 if (ptr
->wnd
&& mask
) {
351 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr
->wnd
, cid
, mask
);
352 if (Callout
.PostMessageA
) Callout
.PostMessageA(ptr
->wnd
, WM_COMMNOTIFY
, cid
, mask
);
356 static void comm_waitread(struct DosDeviceStruct
*ptr
)
358 if (ptr
->s_read
!= INVALID_HANDLE_VALUE
) return;
359 ptr
->s_read
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
360 GENERIC_READ
| SYNCHRONIZE
),
365 static void comm_waitwrite(struct DosDeviceStruct
*ptr
)
367 if (ptr
->s_write
!= INVALID_HANDLE_VALUE
) return;
368 ptr
->s_write
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
369 GENERIC_WRITE
| SYNCHRONIZE
),
374 /**************************************************************************
375 * BuildCommDCB16 (USER.213)
377 * According to the ECMA-234 (368.3) the function will return FALSE on
378 * success, otherwise it will return -1.
379 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
382 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
384 /* "COM1:96,n,8,1" */
387 char *ptr
, temp
[256];
389 TRACE("(%s), ptr %p\n", device
, lpdcb
);
391 if (!strncasecmp(device
,"COM",3)) {
392 port
= device
[3] - '0';
396 ERR("BUG ! COM0 can't exist!\n");
400 if (!ValidCOMPort(port
)) {
401 FIXME("invalid COM port %d?\n",port
);
405 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
412 if (*(device
+4) != ':')
415 strcpy(temp
,device
+5);
416 ptr
= strtok(temp
, ", ");
418 if (COM
[port
].baudrate
> 0)
419 lpdcb
->BaudRate
= COM
[port
].baudrate
;
423 /* DOS/Windows only compares the first two numbers
424 * and assigns an appropriate baud rate.
425 * You can supply 961324245, it still returns 9600 ! */
428 WARN("Unknown baudrate string '%s' !\n", ptr
);
429 return -1; /* error: less than 2 chars */
450 WARN("Unknown baudrate indicator %d !\n", rate
);
454 lpdcb
->BaudRate
= rate
;
456 TRACE("baudrate (%d)\n", lpdcb
->BaudRate
);
458 ptr
= strtok(NULL
, ", ");
460 *ptr
= toupper(*ptr
);
462 TRACE("parity (%c)\n", *ptr
);
463 lpdcb
->fParity
= TRUE
;
466 lpdcb
->Parity
= NOPARITY
;
467 lpdcb
->fParity
= FALSE
;
470 lpdcb
->Parity
= EVENPARITY
;
473 lpdcb
->Parity
= MARKPARITY
;
476 lpdcb
->Parity
= ODDPARITY
;
479 WARN("Unknown parity `%c'!\n", *ptr
);
483 ptr
= strtok(NULL
, ", ");
484 TRACE("charsize (%c)\n", *ptr
);
485 lpdcb
->ByteSize
= *ptr
- '0';
487 ptr
= strtok(NULL
, ", ");
488 TRACE("stopbits (%c)\n", *ptr
);
491 lpdcb
->StopBits
= ONESTOPBIT
;
494 lpdcb
->StopBits
= TWOSTOPBITS
;
497 WARN("Unknown # of stopbits `%c'!\n", *ptr
);
505 /*****************************************************************************
506 * OpenComm16 (USER.200)
508 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
512 TRACE("%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
514 if (strlen(device
) < 4)
517 port
= device
[3] - '0';
520 ERR("BUG ! COM0 or LPT0 don't exist !\n");
522 if (!strncasecmp(device
,"COM",3)) {
524 TRACE("%s = %s\n", device
, COM
[port
].devicename
);
526 if (!ValidCOMPort(port
))
532 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
534 ERR("Couldn't open %s ! (%s)\n", COM
[port
].devicename
, strerror(errno
));
537 unknown
[port
] = SEGPTR_ALLOC(40);
538 bzero(unknown
[port
],40);
540 COM
[port
].commerror
= 0;
541 COM
[port
].eventmask
= 0;
542 COM
[port
].evtchar
= 0; /* FIXME: default? */
543 /* save terminal state */
544 tcgetattr(fd
,&m_stat
[port
]);
545 /* set default parameters */
546 if(COM
[port
].baudrate
>-1){
548 GetCommState16(port
, &dcb
);
549 dcb
.BaudRate
=COM
[port
].baudrate
;
551 * databits, parity, stopbits
553 SetCommState16( &dcb
);
555 /* init priority characters */
556 COM
[port
].unget
= -1;
558 /* allocate buffers */
559 COM
[port
].ibuf_size
= cbInQueue
;
560 COM
[port
].ibuf_head
= COM
[port
].ibuf_tail
= 0;
561 COM
[port
].obuf_size
= cbOutQueue
;
562 COM
[port
].obuf_head
= COM
[port
].obuf_tail
= 0;
564 COM
[port
].inbuf
= malloc(cbInQueue
);
565 if (COM
[port
].inbuf
) {
566 COM
[port
].outbuf
= malloc(cbOutQueue
);
567 if (!COM
[port
].outbuf
)
568 free(COM
[port
].inbuf
);
569 } else COM
[port
].outbuf
= NULL
;
570 if (!COM
[port
].outbuf
) {
571 /* not enough memory */
572 tcsetattr(COM
[port
].fd
,TCSANOW
,&m_stat
[port
]);
574 ERR("out of memory\n");
578 COM
[port
].s_read
= INVALID_HANDLE_VALUE
;
579 COM
[port
].s_write
= INVALID_HANDLE_VALUE
;
580 comm_waitread( &COM
[port
] );
585 if (!strncasecmp(device
,"LPT",3)) {
587 if (!ValidLPTPort(port
))
593 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
598 LPT
[port
].commerror
= 0;
599 LPT
[port
].eventmask
= 0;
600 return port
|FLAG_LPT
;
606 /*****************************************************************************
607 * CloseComm16 (USER.207)
609 INT16 WINAPI
CloseComm16(INT16 cid
)
611 struct DosDeviceStruct
*ptr
;
613 TRACE("cid=%d\n", cid
);
614 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
615 FIXME("no cid=%d found!\n", cid
);
618 if (!(cid
&FLAG_LPT
)) {
620 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
622 SERVICE_Delete( COM
[cid
].s_write
);
623 SERVICE_Delete( COM
[cid
].s_read
);
628 /* reset modem lines */
629 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
632 if (close(ptr
->fd
) == -1) {
633 ptr
->commerror
= WinError();
634 /* FIXME: should we clear ptr->fd here? */
643 /*****************************************************************************
644 * SetCommBreak16 (USER.210)
646 INT16 WINAPI
SetCommBreak16(INT16 cid
)
648 struct DosDeviceStruct
*ptr
;
650 TRACE("cid=%d\n", cid
);
651 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
652 FIXME("no cid=%d found!\n", cid
);
661 /*****************************************************************************
662 * ClearCommBreak16 (USER.211)
664 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
666 struct DosDeviceStruct
*ptr
;
668 TRACE("cid=%d\n", cid
);
669 if (!(ptr
= GetDeviceStruct(cid
))) {
670 FIXME("no cid=%d found!\n", cid
);
678 /*****************************************************************************
679 * EscapeCommFunction16 (USER.214)
681 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
684 struct DosDeviceStruct
*ptr
;
687 TRACE("cid=%d, function=%d\n", cid
, nFunction
);
688 if ((nFunction
!= GETMAXCOM
) && (nFunction
!= GETMAXLPT
)) {
689 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
690 FIXME("no cid=%d found!\n", cid
);
693 if (tcgetattr(ptr
->fd
,&port
) == -1) {
694 TRACE("tcgetattr failed\n");
695 ptr
->commerror
=WinError();
706 TRACE("GETMAXCOM\n");
707 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
713 TRACE("GETMAXLPT\n");
714 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
716 return FLAG_LPT
+ max
;
720 TRACE("GETBASEIRQ\n");
721 /* FIXME: use tables */
722 /* just fake something for now */
723 if (cid
& FLAG_LPT
) {
724 /* LPT1: irq 7, LPT2: irq 5 */
725 return (cid
& 0x7f) ? 5 : 7;
727 /* COM1: irq 4, COM2: irq 3,
728 COM3: irq 4, COM4: irq 3 */
729 return 4 - (cid
& 1);
736 return COMM_WhackModem(ptr
->fd
, ~TIOCM_DTR
, 0);
741 return COMM_WhackModem(ptr
->fd
, ~TIOCM_RTS
, 0);
747 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_DTR
);
753 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_RTS
);
758 port
.c_iflag
|= IXOFF
;
763 port
.c_iflag
|= IXON
;
767 WARN("(cid=%d,nFunction=%d): Unknown function\n",
772 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
773 ptr
->commerror
= WinError();
781 /*****************************************************************************
782 * FlushComm16 (USER.215)
784 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
787 struct DosDeviceStruct
*ptr
;
789 TRACE("cid=%d, queue=%d\n", cid
, fnQueue
);
790 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
791 FIXME("no cid=%d found!\n", cid
);
797 ptr
->obuf_tail
= ptr
->obuf_head
;
801 ptr
->ibuf_head
= ptr
->ibuf_tail
;
804 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
808 if (tcflush(ptr
->fd
, queue
)) {
809 ptr
->commerror
= WinError();
817 /********************************************************************
818 * GetCommError16 (USER.203)
820 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
823 struct DosDeviceStruct
*ptr
;
827 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
828 FIXME("no handle for cid = %0x!\n",cid
);
832 WARN(" cid %d not comm port\n",cid
);
835 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
836 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
837 COMM_MSRUpdate( stol
, mstat
);
842 lpStat
->cbOutQue
= comm_outbuf(ptr
);
843 lpStat
->cbInQue
= comm_inbuf(ptr
);
845 TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
846 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
847 lpStat
->cbOutQue
, *stol
);
850 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
851 cid
, ptr
->commerror
, *stol
);
853 /* Return any errors and clear it */
854 temperror
= ptr
->commerror
;
859 /*****************************************************************************
860 * SetCommEventMask16 (USER.208)
862 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
864 struct DosDeviceStruct
*ptr
;
869 TRACE("cid %d,mask %d\n",cid
,fuEvtMask
);
870 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
871 FIXME("no handle for cid = %0x!\n",cid
);
875 ptr
->eventmask
= fuEvtMask
;
877 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
878 WARN(" cid %d not comm port\n",cid
);
881 /* it's a COM port ? -> modify flags */
882 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
883 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
884 TRACE(" ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
885 COMM_MSRUpdate( stol
, mstat
);
887 TRACE(" modem dcd construct %x\n",*stol
);
888 return SEGPTR_GET(unknown
[cid
]);
891 /*****************************************************************************
892 * GetCommEventMask16 (USER.209)
894 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
896 struct DosDeviceStruct
*ptr
;
899 TRACE("cid %d, mask %d\n", cid
, fnEvtClear
);
900 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
901 FIXME("no handle for cid = %0x!\n",cid
);
905 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
906 WARN(" cid %d not comm port\n",cid
);
910 events
= *(WORD
*)(unknown
[cid
]) & fnEvtClear
;
911 *(WORD
*)(unknown
[cid
]) &= ~fnEvtClear
;
915 /*****************************************************************************
916 * SetCommState16 (USER.201)
918 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
921 struct DosDeviceStruct
*ptr
;
922 int bytesize
, stopbits
;
925 TRACE("cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
926 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
927 FIXME("no handle for cid = %0x!\n",lpdcb
->Id
);
930 if (tcgetattr(ptr
->fd
, &port
) == -1) {
931 ptr
->commerror
= WinError();
936 port
.c_cc
[VTIME
] = 1;
939 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
941 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
943 port
.c_iflag
|= (IGNBRK
);
945 port
.c_oflag
&= ~(OPOST
);
947 port
.c_cflag
&= ~(HUPCL
);
948 port
.c_cflag
|= CLOCAL
| CREAD
;
950 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
951 port
.c_lflag
|= NOFLSH
;
953 TRACE("baudrate %d\n",lpdcb
->BaudRate
);
955 port
.c_cflag
&= ~CBAUD
;
956 switch (lpdcb
->BaudRate
) {
959 port
.c_cflag
|= B110
;
963 port
.c_cflag
|= B300
;
967 port
.c_cflag
|= B600
;
971 port
.c_cflag
|= B1200
;
975 port
.c_cflag
|= B2400
;
979 port
.c_cflag
|= B4800
;
983 port
.c_cflag
|= B9600
;
987 port
.c_cflag
|= B19200
;
991 port
.c_cflag
|= B38400
;
995 port
.c_cflag
|= B57600
;
1000 port
.c_cflag
|= B115200
;
1004 ptr
->commerror
= IE_BAUDRATE
;
1007 #elif !defined(__EMX__)
1008 switch (lpdcb
->BaudRate
) {
1011 port
.c_ospeed
= B110
;
1015 port
.c_ospeed
= B300
;
1019 port
.c_ospeed
= B600
;
1023 port
.c_ospeed
= B1200
;
1027 port
.c_ospeed
= B2400
;
1031 port
.c_ospeed
= B4800
;
1035 port
.c_ospeed
= B9600
;
1039 port
.c_ospeed
= B19200
;
1043 port
.c_ospeed
= B38400
;
1046 ptr
->commerror
= IE_BAUDRATE
;
1049 port
.c_ispeed
= port
.c_ospeed
;
1051 bytesize
=lpdcb
->ByteSize
;
1052 stopbits
=lpdcb
->StopBits
;
1054 TRACE("fParity %d Parity %d\n",lpdcb
->fParity
, lpdcb
->Parity
);
1056 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1058 port
.c_cflag
&= ~(PARENB
| PARODD
);
1061 port
.c_iflag
|= INPCK
;
1063 port
.c_iflag
&= ~INPCK
;
1064 switch (lpdcb
->Parity
) {
1068 port
.c_cflag
|= (PARENB
| PARODD
);
1071 port
.c_cflag
|= PARENB
;
1074 /* Linux defines mark/space (stick) parity */
1076 port
.c_cflag
|= (PARENB
| CMSPAR
);
1079 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1082 /* try the POSIX way */
1084 if( stopbits
== ONESTOPBIT
) {
1085 stopbits
= TWOSTOPBITS
;
1086 port
.c_iflag
&= ~INPCK
;
1088 ptr
->commerror
= IE_BYTESIZE
;
1095 port
.c_iflag
&= ~INPCK
;
1097 ptr
->commerror
= IE_BYTESIZE
;
1103 ptr
->commerror
= IE_BYTESIZE
;
1107 TRACE("bytesize %d\n",bytesize
);
1108 port
.c_cflag
&= ~CSIZE
;
1111 port
.c_cflag
|= CS5
;
1114 port
.c_cflag
|= CS6
;
1117 port
.c_cflag
|= CS7
;
1120 port
.c_cflag
|= CS8
;
1123 ptr
->commerror
= IE_BYTESIZE
;
1127 TRACE("stopbits %d\n",stopbits
);
1131 port
.c_cflag
&= ~CSTOPB
;
1133 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
1135 port
.c_cflag
|= CSTOPB
;
1138 ptr
->commerror
= IE_BYTESIZE
;
1143 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
1144 port
.c_cflag
|= CRTSCTS
;
1146 if (lpdcb
->fDtrDisable
)
1147 port
.c_cflag
&= ~CRTSCTS
;
1150 port
.c_iflag
|= IXON
;
1152 port
.c_iflag
&= ~IXON
;
1154 port
.c_iflag
|= IXOFF
;
1156 port
.c_iflag
&= ~IXOFF
;
1158 ptr
->evtchar
= lpdcb
->EvtChar
;
1163 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
1164 ptr
->commerror
= WinError();
1172 /*****************************************************************************
1173 * GetCommState16 (USER.202)
1175 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
1178 struct DosDeviceStruct
*ptr
;
1179 struct termios port
;
1181 TRACE("cid %d, ptr %p\n", cid
, lpdcb
);
1182 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1183 FIXME("no handle for cid = %0x!\n",cid
);
1186 if (tcgetattr(ptr
->fd
, &port
) == -1) {
1187 ptr
->commerror
= WinError();
1193 speed
= port
.c_cflag
& CBAUD
;
1195 speed
= port
.c_ospeed
;
1199 lpdcb
->BaudRate
= 110;
1202 lpdcb
->BaudRate
= 300;
1205 lpdcb
->BaudRate
= 600;
1208 lpdcb
->BaudRate
= 1200;
1211 lpdcb
->BaudRate
= 2400;
1214 lpdcb
->BaudRate
= 4800;
1217 lpdcb
->BaudRate
= 9600;
1220 lpdcb
->BaudRate
= 19200;
1223 lpdcb
->BaudRate
= 38400;
1227 lpdcb
->BaudRate
= 57600;
1232 lpdcb
->BaudRate
= 57601;
1237 switch (port
.c_cflag
& CSIZE
) {
1239 lpdcb
->ByteSize
= 5;
1242 lpdcb
->ByteSize
= 6;
1245 lpdcb
->ByteSize
= 7;
1248 lpdcb
->ByteSize
= 8;
1252 if(port
.c_iflag
& INPCK
)
1253 lpdcb
->fParity
= TRUE
;
1255 lpdcb
->fParity
= FALSE
;
1257 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1259 switch (port
.c_cflag
& (PARENB
| PARODD
))
1263 lpdcb
->Parity
= NOPARITY
;
1266 lpdcb
->Parity
= EVENPARITY
;
1268 case (PARENB
| PARODD
):
1269 lpdcb
->Parity
= ODDPARITY
;
1272 case (PARENB
| CMSPAR
):
1273 lpdcb
->Parity
= MARKPARITY
;
1275 case (PARENB
| PARODD
| CMSPAR
):
1276 lpdcb
->Parity
= SPACEPARITY
;
1281 if (port
.c_cflag
& CSTOPB
)
1282 if(lpdcb
->ByteSize
== 5)
1283 lpdcb
->StopBits
= ONE5STOPBITS
;
1285 lpdcb
->StopBits
= TWOSTOPBITS
;
1287 lpdcb
->StopBits
= ONESTOPBIT
;
1289 lpdcb
->RlsTimeout
= 50;
1290 lpdcb
->CtsTimeout
= 50;
1291 lpdcb
->DsrTimeout
= 50;
1295 lpdcb
->fDtrDisable
= 0;
1299 if (port
.c_cflag
& CRTSCTS
) {
1300 lpdcb
->fDtrflow
= 1;
1301 lpdcb
->fRtsflow
= 1;
1302 lpdcb
->fOutxCtsFlow
= 1;
1303 lpdcb
->fOutxDsrFlow
= 1;
1306 lpdcb
->fDtrDisable
= 1;
1308 if (port
.c_iflag
& IXON
)
1313 if (port
.c_iflag
& IXOFF
)
1322 lpdcb
->XoffLim
= 10;
1324 lpdcb
->EvtChar
= ptr
->evtchar
;
1330 /*****************************************************************************
1331 * TransmitCommChar16 (USER.206)
1333 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1335 struct DosDeviceStruct
*ptr
;
1337 TRACE("cid %d, data %d \n", cid
, chTransmit
);
1338 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1339 FIXME("no handle for cid = %0x!\n",cid
);
1343 if (ptr
->suspended
) {
1344 ptr
->commerror
= IE_HARDWARE
;
1348 if (ptr
->xmit
>= 0) {
1349 /* character already queued */
1350 /* FIXME: which error would Windows return? */
1351 ptr
->commerror
= CE_TXFULL
;
1355 if (ptr
->obuf_head
== ptr
->obuf_tail
) {
1356 /* transmit queue empty, try to transmit directly */
1357 if (write(ptr
->fd
, &chTransmit
, 1) == -1) {
1358 /* didn't work, queue it */
1359 ptr
->xmit
= chTransmit
;
1360 comm_waitwrite(ptr
);
1363 /* data in queue, let this char be transmitted next */
1364 ptr
->xmit
= chTransmit
;
1365 comm_waitwrite(ptr
);
1372 /*****************************************************************************
1373 * UngetCommChar16 (USER.212)
1375 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1377 struct DosDeviceStruct
*ptr
;
1379 TRACE("cid %d (char %d)\n", cid
, chUnget
);
1380 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1381 FIXME("no handle for cid = %0x!\n",cid
);
1385 if (ptr
->suspended
) {
1386 ptr
->commerror
= IE_HARDWARE
;
1390 if (ptr
->unget
>=0) {
1391 /* character already queued */
1392 /* FIXME: which error would Windows return? */
1393 ptr
->commerror
= CE_RXOVER
;
1397 ptr
->unget
= chUnget
;
1403 /*****************************************************************************
1404 * ReadComm16 (USER.204)
1406 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1409 struct DosDeviceStruct
*ptr
;
1410 LPSTR orgBuf
= lpvBuf
;
1412 TRACE("cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1413 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1414 FIXME("no handle for cid = %0x!\n",cid
);
1418 if (ptr
->suspended
) {
1419 ptr
->commerror
= IE_HARDWARE
;
1423 /* read unget character */
1424 if (ptr
->unget
>=0) {
1425 *lpvBuf
++ = ptr
->unget
;
1432 /* read from receive buffer */
1433 while (length
< cbRead
) {
1434 status
= ((ptr
->ibuf_head
< ptr
->ibuf_tail
) ?
1435 ptr
->ibuf_size
: ptr
->ibuf_head
) - ptr
->ibuf_tail
;
1437 if ((cbRead
- length
) < status
)
1438 status
= cbRead
- length
;
1440 memcpy(lpvBuf
, ptr
->inbuf
+ ptr
->ibuf_tail
, status
);
1441 ptr
->ibuf_tail
+= status
;
1442 if (ptr
->ibuf_tail
>= ptr
->ibuf_size
)
1448 TRACE("%.*s\n", length
, orgBuf
);
1453 /*****************************************************************************
1454 * WriteComm16 (USER.205)
1456 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1459 struct DosDeviceStruct
*ptr
;
1461 TRACE("cid %d, ptr %p, length %d\n",
1462 cid
, lpvBuf
, cbWrite
);
1463 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1464 FIXME("no handle for cid = %0x!\n",cid
);
1468 if (ptr
->suspended
) {
1469 ptr
->commerror
= IE_HARDWARE
;
1473 TRACE("%.*s\n", cbWrite
, lpvBuf
);
1476 while (length
< cbWrite
) {
1477 if ((ptr
->obuf_head
== ptr
->obuf_tail
) && (ptr
->xmit
< 0)) {
1478 /* no data queued, try to write directly */
1479 status
= write(ptr
->fd
, lpvBuf
, cbWrite
- length
);
1486 /* can't write directly, put into transmit buffer */
1487 status
= ((ptr
->obuf_tail
> ptr
->obuf_head
) ?
1488 (ptr
->obuf_tail
-1) : ptr
->obuf_size
) - ptr
->obuf_head
;
1490 if ((cbWrite
- length
) < status
)
1491 status
= cbWrite
- length
;
1492 memcpy(lpvBuf
, ptr
->outbuf
+ ptr
->obuf_head
, status
);
1493 ptr
->obuf_head
+= status
;
1494 if (ptr
->obuf_head
>= ptr
->obuf_size
)
1498 comm_waitwrite(ptr
);
1505 /***********************************************************************
1506 * EnableCommNotification (USER.245)
1508 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1509 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1511 struct DosDeviceStruct
*ptr
;
1513 TRACE("(%d, %x, %d, %d)\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1514 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1515 FIXME("no handle for cid = %0x!\n",cid
);
1519 ptr
->n_read
= cbWriteNotify
;
1520 ptr
->n_write
= cbOutQueue
;
1525 /**************************************************************************
1526 * BuildCommDCBA (KERNEL32.113)
1528 * Updates a device control block data structure with values from an
1529 * ascii device control string. The device control string has two forms
1530 * normal and extended, it must be exclusively in one or the other form.
1534 * True on success, false on an malformed control string.
1536 BOOL WINAPI
BuildCommDCBA(
1537 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
1538 LPDCB lpdcb
) /* [out] The device control block to be updated. */
1540 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1543 /**************************************************************************
1544 * BuildCommDCBAndTimeoutsA (KERNEL32.114)
1546 * Updates a device control block data structure with values from an
1547 * ascii device control string. Taking time out values from a time outs
1548 * struct if desired by the control string.
1552 * True on success, false bad handles etc
1554 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
1555 LPCSTR device
, /* [in] The ascii device control string. */
1556 LPDCB lpdcb
, /* [out] The device control block to be updated. */
1557 LPCOMMTIMEOUTS lptimeouts
) /* [in] The time outs to use if asked to set them by the control string. */
1562 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1564 if (!strncasecmp(device
,"COM",3)) {
1567 ERR("BUG! COM0 can't exist!\n");
1570 if (!ValidCOMPort(port
))
1572 if (*(device
+4)!=':')
1574 temp
=(LPSTR
)(device
+5);
1578 lpdcb
->DCBlength
= sizeof(DCB
);
1579 if (strchr(temp
,',')) { /* old style */
1582 char last
=temp
[strlen(temp
)-1];
1584 ret
=BuildCommDCB16(device
,&dcb16
);
1587 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1588 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1589 lpdcb
->fBinary
= dcb16
.fBinary
;
1590 lpdcb
->Parity
= dcb16
.Parity
;
1591 lpdcb
->fParity
= dcb16
.fParity
;
1592 lpdcb
->fNull
= dcb16
.fNull
;
1593 lpdcb
->StopBits
= dcb16
.StopBits
;
1596 lpdcb
->fOutX
= TRUE
;
1597 lpdcb
->fOutxCtsFlow
= FALSE
;
1598 lpdcb
->fOutxDsrFlow
= FALSE
;
1599 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1600 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1601 } else if (last
=='p') {
1602 lpdcb
->fInX
= FALSE
;
1603 lpdcb
->fOutX
= FALSE
;
1604 lpdcb
->fOutxCtsFlow
= TRUE
;
1605 lpdcb
->fOutxDsrFlow
= TRUE
;
1606 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1607 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1609 lpdcb
->fInX
= FALSE
;
1610 lpdcb
->fOutX
= FALSE
;
1611 lpdcb
->fOutxCtsFlow
= FALSE
;
1612 lpdcb
->fOutxDsrFlow
= FALSE
;
1613 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1614 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1616 lpdcb
->XonChar
= dcb16
.XonChar
;
1617 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1618 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1619 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1620 lpdcb
->EofChar
= dcb16
.EofChar
;
1621 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1622 lpdcb
->XonLim
= dcb16
.XonLim
;
1623 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1626 ptr
=strtok(temp
," ");
1631 if (!strncmp("baud=",ptr
,5)) {
1632 if (!sscanf(ptr
+5,"%ld",&x
))
1633 WARN("Couldn't parse %s\n",ptr
);
1634 lpdcb
->BaudRate
= x
;
1637 if (!strncmp("stop=",ptr
,5)) {
1638 if (!sscanf(ptr
+5,"%ld",&x
))
1639 WARN("Couldn't parse %s\n",ptr
);
1640 lpdcb
->StopBits
= x
;
1643 if (!strncmp("data=",ptr
,5)) {
1644 if (!sscanf(ptr
+5,"%ld",&x
))
1645 WARN("Couldn't parse %s\n",ptr
);
1646 lpdcb
->ByteSize
= x
;
1649 if (!strncmp("parity=",ptr
,7)) {
1650 lpdcb
->fParity
= TRUE
;
1653 lpdcb
->fParity
= FALSE
;
1654 lpdcb
->Parity
= NOPARITY
;
1657 lpdcb
->Parity
= EVENPARITY
;
1660 lpdcb
->Parity
= ODDPARITY
;
1663 lpdcb
->Parity
= MARKPARITY
;
1669 ERR("Unhandled specifier '%s', please report.\n",ptr
);
1670 ptr
=strtok(NULL
," ");
1672 if (lpdcb
->BaudRate
==110)
1673 lpdcb
->StopBits
= 2;
1677 /**************************************************************************
1678 * BuildCommDCBAndTimeoutsW (KERNEL32.115)
1680 * Updates a device control block data structure with values from an
1681 * unicode device control string. Taking time out values from a time outs
1682 * struct if desired by the control string.
1686 * True on success, false bad handles etc.
1688 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
1689 LPCWSTR devid
, /* [in] The unicode device control string. */
1690 LPDCB lpdcb
, /* [out] The device control block to be updated. */
1691 LPCOMMTIMEOUTS lptimeouts
) /* [in] The time outs to use if asked to set them by the control string. */
1696 TRACE("(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1697 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1700 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1701 HeapFree( GetProcessHeap(), 0, devidA
);
1706 /**************************************************************************
1707 * BuildCommDCBW (KERNEL32.116)
1709 * Updates a device control block structure with values from an
1710 * unicode device control string. The device control string has two forms
1711 * normal and extended, it must be exclusively in one or the other form.
1715 * True on success, false on an malformed control string.
1717 BOOL WINAPI
BuildCommDCBW(
1718 LPCWSTR devid
, /* [in] The unicode device control string. */
1719 LPDCB lpdcb
) /* [out] The device control block to be updated. */
1721 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1724 /* FIXME: having these global for win32 for now */
1727 /*****************************************************************************
1728 * SetCommBreak (KERNEL32.616)
1730 * Halts the transmission of characters to a communications device.
1734 * True on success, and false if the communications device could not be found,
1735 * the control is not supported.
1739 * Only TIOCSBRK and TIOCCBRK are supported.
1741 BOOL WINAPI
SetCommBreak(
1742 HANDLE handle
) /* [in] The communictions device to suspend. */
1744 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1747 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
1749 TRACE("FILE_GetUnixHandle failed\n");
1752 result
= ioctl(fd
,TIOCSBRK
,0);
1756 TRACE("ioctl failed\n");
1757 SetLastError(ERROR_NOT_SUPPORTED
);
1762 FIXME("ioctl not available\n");
1763 SetLastError(ERROR_NOT_SUPPORTED
);
1768 /*****************************************************************************
1769 * ClearCommBreak (KERNEL32.135)
1771 * Resumes character transmission from a communication device.
1775 * True on success and false if the communications device could not be found.
1779 * Only TIOCSBRK and TIOCCBRK are supported.
1781 BOOL WINAPI
ClearCommBreak(
1782 HANDLE handle
) /* [in] The halted communication device whose character transmission is to be resumed. */
1784 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1787 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
1789 TRACE("FILE_GetUnixHandle failed\n");
1792 result
= ioctl(fd
,TIOCCBRK
,0);
1796 TRACE("ioctl failed\n");
1797 SetLastError(ERROR_NOT_SUPPORTED
);
1802 FIXME("ioctl not available\n");
1803 SetLastError(ERROR_NOT_SUPPORTED
);
1808 /*****************************************************************************
1809 * EscapeCommFunction (KERNEL32.213)
1811 * Directs a communication device to perform an extended function.
1815 * True or requested data on successful completion of the command,
1816 * false if the device is not present cannot execute the command
1817 * or the command failed.
1819 BOOL WINAPI
EscapeCommFunction(
1820 HANDLE handle
, /* [in] The communication device to perform the extended function. */
1821 UINT nFunction
) /* [in] The extended function to be performed. */
1823 int fd
,direct
=FALSE
,result
=FALSE
;
1824 struct termios port
;
1826 TRACE("handle %d, function=%d\n", handle
, nFunction
);
1827 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
1829 FIXME("handle %d not found.\n",handle
);
1833 if (tcgetattr(fd
,&port
) == -1) {
1834 commerror
=WinError();
1839 switch (nFunction
) {
1848 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1856 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1864 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1872 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1878 port
.c_iflag
|= IXOFF
;
1883 port
.c_iflag
|= IXON
;
1886 TRACE("setbreak\n");
1889 result
= ioctl(fd
,TIOCSBRK
,0);
1893 TRACE("clrbreak\n");
1896 result
= ioctl(fd
,TIOCCBRK
,0);
1900 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1906 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1907 commerror
= WinError();
1917 commerror
=WinError();
1926 /********************************************************************
1927 * PurgeComm (KERNEL32.558)
1929 * Terminates pending operations and/or discards buffers on a
1930 * communication resource.
1934 * True on success and false if the communications handle is bad.
1936 BOOL WINAPI
PurgeComm(
1937 HANDLE handle
, /* [in] The communication resource to be purged. */
1938 DWORD flags
) /* [in] Flags for clear pending/buffer on input/output. */
1942 TRACE("handle %d, flags %lx\n", handle
, flags
);
1944 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
1946 FIXME("no handle %d found\n",handle
);
1951 ** not exactly sure how these are different
1952 ** Perhaps if we had our own internal queues, one flushes them
1953 ** and the other flushes the kernel's buffers.
1955 if(flags
&PURGE_TXABORT
)
1956 tcflush(fd
,TCOFLUSH
);
1957 if(flags
&PURGE_RXABORT
)
1958 tcflush(fd
,TCIFLUSH
);
1959 if(flags
&PURGE_TXCLEAR
)
1960 tcflush(fd
,TCOFLUSH
);
1961 if(flags
&PURGE_RXCLEAR
)
1962 tcflush(fd
,TCIFLUSH
);
1968 /*****************************************************************************
1969 * ClearCommError (KERNEL32.136)
1971 * Enables further I/O operations on a communications resource after
1972 * supplying error and current status information.
1976 * True on success, false if the communication resource handle is bad.
1978 BOOL WINAPI
ClearCommError(
1979 HANDLE handle
, /* [in] The communication resource with the error. */
1980 LPDWORD errors
, /* [out] Flags indicating error the resource experienced. */
1981 LPCOMSTAT lpStat
) /* [out] The status of the communication resource. */
1985 fd
=FILE_GetUnixHandle( handle
, GENERIC_READ
);
1988 FIXME("no handle %d found\n",handle
);
1997 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1998 WARN("ioctl returned error\n");
2000 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
2004 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
2005 WARN("ioctl returned error\n");
2008 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
2009 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
2018 ** After an asynchronous write opperation, the
2019 ** app will call ClearCommError to see if the
2020 ** results are ready yet. It waits for ERROR_IO_PENDING
2022 commerror
= ERROR_IO_PENDING
;
2027 /*****************************************************************************
2028 * SetupComm (KERNEL32.677)
2030 * Called after CreateFile to hint to the communication resource to use
2031 * specified sizes for input and output buffers rather than the default values.
2035 * True if successful, false if the communications resource handle is bad.
2041 BOOL WINAPI
SetupComm(
2042 HANDLE handle
, /* [in] The just created communication resource handle. */
2043 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
2044 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
2048 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
2049 fd
=FILE_GetUnixHandle( handle
, GENERIC_READ
);
2051 FIXME("handle %d not found?\n",handle
);
2058 /*****************************************************************************
2059 * GetCommMask (KERNEL32.284)
2061 * Obtain the events associated with a communication device that will cause a call
2062 * WaitCommEvent to return.
2066 * True on success, fail on bad device handle etc.
2068 BOOL WINAPI
GetCommMask(
2069 HANDLE handle
, /* [in] The communications device. */
2070 LPDWORD evtmask
) /* [out] The events which cause WaitCommEvent to return. */
2074 TRACE("handle %d, mask %p\n", handle
, evtmask
);
2076 SERVER_START_REQ( get_serial_info
)
2078 req
->handle
= handle
;
2079 if ((ret
= !SERVER_CALL_ERR()))
2081 if (evtmask
) *evtmask
= req
->eventmask
;
2088 /*****************************************************************************
2089 * SetCommMask (KERNEL32.618)
2091 * There be some things we need to hear about yon there communications device.
2092 * (Set which events associated with a communication device should cause
2093 * a call WaitCommEvent to return.)
2097 * True on success, false on bad handle etc.
2099 BOOL WINAPI
SetCommMask(
2100 HANDLE handle
, /* [in] The communications device. */
2101 DWORD evtmask
) /* [in] The events that to be monitored. */
2105 TRACE("handle %d, mask %lx\n", handle
, evtmask
);
2107 SERVER_START_REQ( set_serial_info
)
2109 req
->handle
= handle
;
2110 req
->flags
= SERIALINFO_SET_MASK
;
2111 req
->eventmask
= evtmask
;
2112 ret
= !SERVER_CALL_ERR();
2118 /*****************************************************************************
2119 * SetCommState (KERNEL32.619)
2121 * Re-initializes all hardware and control settings of a communications device,
2122 * with values from a device control block without effecting the input and output
2127 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
2129 BOOL WINAPI
SetCommState(
2130 HANDLE handle
, /* [in] The communications device. */
2131 LPDCB lpdcb
) /* [out] The device control block. */
2133 struct termios port
;
2134 int fd
, bytesize
, stopbits
;
2136 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2137 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2138 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2139 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2140 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2141 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2142 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2144 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
2146 FIXME("no handle %d found\n",handle
);
2150 if ((tcgetattr(fd
,&port
)) == -1) {
2151 int save_error
= errno
;
2152 commerror
= WinError();
2154 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2158 port
.c_cc
[VMIN
] = 0;
2159 port
.c_cc
[VTIME
] = 1;
2162 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
2164 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
2166 port
.c_iflag
|= (IGNBRK
);
2168 port
.c_oflag
&= ~(OPOST
);
2170 port
.c_cflag
&= ~(HUPCL
);
2171 port
.c_cflag
|= CLOCAL
| CREAD
;
2173 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
2174 port
.c_lflag
|= NOFLSH
;
2177 ** MJM - removed default baudrate settings
2178 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2181 port
.c_cflag
&= ~CBAUD
;
2182 switch (lpdcb
->BaudRate
) {
2185 port
.c_cflag
|= B110
;
2189 port
.c_cflag
|= B300
;
2193 port
.c_cflag
|= B600
;
2197 port
.c_cflag
|= B1200
;
2201 port
.c_cflag
|= B2400
;
2205 port
.c_cflag
|= B4800
;
2209 port
.c_cflag
|= B9600
;
2213 port
.c_cflag
|= B19200
;
2217 port
.c_cflag
|= B38400
;
2221 port
.c_cflag
|= B57600
;
2226 port
.c_cflag
|= B115200
;
2231 port
.c_cflag
|= B230400
;
2236 port
.c_cflag
|= B460800
;
2240 commerror
= IE_BAUDRATE
;
2242 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2245 #elif !defined(__EMX__)
2246 switch (lpdcb
->BaudRate
) {
2249 port
.c_ospeed
= B110
;
2253 port
.c_ospeed
= B300
;
2257 port
.c_ospeed
= B600
;
2261 port
.c_ospeed
= B1200
;
2265 port
.c_ospeed
= B2400
;
2269 port
.c_ospeed
= B4800
;
2273 port
.c_ospeed
= B9600
;
2277 port
.c_ospeed
= B19200
;
2281 port
.c_ospeed
= B38400
;
2284 commerror
= IE_BAUDRATE
;
2286 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2289 port
.c_ispeed
= port
.c_ospeed
;
2291 bytesize
=lpdcb
->ByteSize
;
2292 stopbits
=lpdcb
->StopBits
;
2295 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
2297 port
.c_cflag
&= ~(PARENB
| PARODD
);
2300 port
.c_iflag
|= INPCK
;
2302 port
.c_iflag
&= ~INPCK
;
2303 switch (lpdcb
->Parity
) {
2307 port
.c_cflag
|= (PARENB
| PARODD
);
2310 port
.c_cflag
|= PARENB
;
2313 /* Linux defines mark/space (stick) parity */
2315 port
.c_cflag
|= (PARENB
| CMSPAR
);
2318 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
2321 /* try the POSIX way */
2323 if( stopbits
== ONESTOPBIT
) {
2324 stopbits
= TWOSTOPBITS
;
2325 port
.c_iflag
&= ~INPCK
;
2327 commerror
= IE_BYTESIZE
;
2329 ERR("Cannot set MARK Parity\n");
2336 port
.c_iflag
&= ~INPCK
;
2338 commerror
= IE_BYTESIZE
;
2340 ERR("Cannot set SPACE Parity\n");
2346 commerror
= IE_BYTESIZE
;
2353 port
.c_cflag
&= ~CSIZE
;
2356 port
.c_cflag
|= CS5
;
2359 port
.c_cflag
|= CS6
;
2362 port
.c_cflag
|= CS7
;
2365 port
.c_cflag
|= CS8
;
2368 commerror
= IE_BYTESIZE
;
2376 port
.c_cflag
&= ~CSTOPB
;
2378 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
2380 port
.c_cflag
|= CSTOPB
;
2383 commerror
= IE_BYTESIZE
;
2389 if ( lpdcb
->fOutxCtsFlow
||
2390 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2393 port
.c_cflag
|= CRTSCTS
;
2397 if (lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
)
2399 port
.c_cflag
&= ~CRTSCTS
;
2400 TRACE("~CRTSCTS\n");
2405 port
.c_iflag
|= IXON
;
2407 port
.c_iflag
&= ~IXON
;
2409 port
.c_iflag
|= IXOFF
;
2411 port
.c_iflag
&= ~IXOFF
;
2413 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
2414 int save_error
=errno
;
2415 commerror
= WinError();
2417 ERR("tcsetattr error '%s'\n", strerror(save_error
));
2427 /*****************************************************************************
2428 * GetCommState (KERNEL32.287)
2430 * Fills in a device control block with information from a communications device.
2434 * True on success, false if the communication device handle is bad etc
2438 * XonChar and XoffChar are not set.
2440 BOOL WINAPI
GetCommState(
2441 HANDLE handle
, /* [in] The communications device. */
2442 LPDCB lpdcb
) /* [out] The device control block. */
2444 struct termios port
;
2447 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2449 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
2452 ERR("FILE_GetUnixHandle failed\n");
2455 if (tcgetattr(fd
, &port
) == -1) {
2456 int save_error
=errno
;
2457 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2458 commerror
= WinError();
2465 speed
= (port
.c_cflag
& CBAUD
);
2467 speed
= (cfgetospeed(&port
));
2471 lpdcb
->BaudRate
= 110;
2474 lpdcb
->BaudRate
= 300;
2477 lpdcb
->BaudRate
= 600;
2480 lpdcb
->BaudRate
= 1200;
2483 lpdcb
->BaudRate
= 2400;
2486 lpdcb
->BaudRate
= 4800;
2489 lpdcb
->BaudRate
= 9600;
2492 lpdcb
->BaudRate
= 19200;
2495 lpdcb
->BaudRate
= 38400;
2499 lpdcb
->BaudRate
= 57600;
2504 lpdcb
->BaudRate
= 115200;
2509 lpdcb
->BaudRate
= 230400;
2514 lpdcb
->BaudRate
= 460800;
2518 ERR("unknown speed %x \n",speed
);
2521 switch (port
.c_cflag
& CSIZE
) {
2523 lpdcb
->ByteSize
= 5;
2526 lpdcb
->ByteSize
= 6;
2529 lpdcb
->ByteSize
= 7;
2532 lpdcb
->ByteSize
= 8;
2535 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
2538 if(port
.c_iflag
& INPCK
)
2539 lpdcb
->fParity
= TRUE
;
2541 lpdcb
->fParity
= FALSE
;
2543 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
2545 switch (port
.c_cflag
& (PARENB
| PARODD
))
2549 lpdcb
->Parity
= NOPARITY
;
2552 lpdcb
->Parity
= EVENPARITY
;
2554 case (PARENB
| PARODD
):
2555 lpdcb
->Parity
= ODDPARITY
;
2558 case (PARENB
| CMSPAR
):
2559 lpdcb
->Parity
= MARKPARITY
;
2561 case (PARENB
| PARODD
| CMSPAR
):
2562 lpdcb
->Parity
= SPACEPARITY
;
2567 if (port
.c_cflag
& CSTOPB
)
2568 if(lpdcb
->ByteSize
== 5)
2569 lpdcb
->StopBits
= ONE5STOPBITS
;
2571 lpdcb
->StopBits
= TWOSTOPBITS
;
2573 lpdcb
->StopBits
= ONESTOPBIT
;
2580 if (port
.c_cflag
& CRTSCTS
) {
2581 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
2582 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
2583 lpdcb
->fOutxCtsFlow
= 1;
2584 lpdcb
->fOutxDsrFlow
= 1;
2588 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
2589 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
2591 if (port
.c_iflag
& IXON
)
2596 if (port
.c_iflag
& IXOFF
)
2605 lpdcb
->XoffLim
= 10;
2611 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2612 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2613 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2614 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2615 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2616 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2618 if ( lpdcb
->fOutxCtsFlow
||
2619 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2620 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2624 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2625 TRACE("~CRTSCTS\n");
2631 /*****************************************************************************
2632 * TransmitCommChar (KERNEL32.697)
2634 * Transmits a single character in front of any pending characters in the
2635 * output buffer. Usually used to send an interrupt character to a host.
2639 * True if the call succeeded, false if the previous command character to the
2640 * same device has not been sent yet the handle is bad etc.
2646 BOOL WINAPI
TransmitCommChar(
2647 HANDLE hComm
, /* [in] The communication device in need of a command character. */
2648 CHAR chTransmit
) /* [in] The character to transmit. */
2650 FIXME("(%x,'%c'), use win32 handle!\n",hComm
,chTransmit
);
2654 /*****************************************************************************
2655 * GetCommTimeouts (KERNEL32.288)
2657 * Obtains the request time out values for the communications device.
2661 * True on success, false if communications device handle is bad
2662 * or the target structure is null.
2664 BOOL WINAPI
GetCommTimeouts(
2665 HANDLE hComm
, /* [in] The communications device. */
2666 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request time outs. */
2670 TRACE("(%x,%p)\n",hComm
,lptimeouts
);
2674 SetLastError(ERROR_INVALID_PARAMETER
);
2678 SERVER_START_REQ( get_serial_info
)
2680 req
->handle
= hComm
;
2681 if ((ret
= !SERVER_CALL_ERR()))
2683 lptimeouts
->ReadIntervalTimeout
= req
->readinterval
;
2684 lptimeouts
->ReadTotalTimeoutMultiplier
= req
->readmult
;
2685 lptimeouts
->ReadTotalTimeoutConstant
= req
->readconst
;
2686 lptimeouts
->WriteTotalTimeoutMultiplier
= req
->writemult
;
2687 lptimeouts
->WriteTotalTimeoutConstant
= req
->writeconst
;
2694 /*****************************************************************************
2695 * SetCommTimeouts (KERNEL32.620)
2697 * Sets the timeouts used when reading and writing data to/from COMM ports.
2699 * ReadIntervalTimeout
2700 * - converted and passes to linux kernel as c_cc[VTIME]
2701 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
2702 * - used in ReadFile to calculate GetOverlappedResult's timeout
2703 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
2704 * - used in WriteFile to calculate GetOverlappedResult's timeout
2708 * True if the time outs were set, false otherwise.
2710 BOOL WINAPI
SetCommTimeouts(
2711 HANDLE hComm
, /* [in] handle of COMM device */
2712 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
2716 struct termios tios
;
2718 TRACE("(%x,%p)\n",hComm
,lptimeouts
);
2722 SetLastError(ERROR_INVALID_PARAMETER
);
2726 SERVER_START_REQ( set_serial_info
)
2728 req
->handle
= hComm
;
2729 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
2730 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
2731 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
2732 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
2733 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
2734 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
2735 ret
= !SERVER_CALL_ERR();
2738 if (!ret
) return FALSE
;
2740 /* FIXME: move this stuff to the server */
2741 fd
= FILE_GetUnixHandle( hComm
, GENERIC_READ
);
2743 FIXME("no fd for handle = %0x!.\n",hComm
);
2747 if (-1==tcgetattr(fd
,&tios
)) {
2748 FIXME("tcgetattr on fd %d failed!\n",fd
);
2752 /* VTIME is in 1/10 seconds */
2754 unsigned int ux_timeout
;
2756 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
2762 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
2765 ux_timeout
= 1; /* must be at least some timeout */
2768 tios
.c_cc
[VTIME
] = ux_timeout
;
2771 if (-1==tcsetattr(fd
,0,&tios
)) {
2772 FIXME("tcsetattr on fd %d failed!\n",fd
);
2779 /***********************************************************************
2780 * GetCommModemStatus (KERNEL32.285)
2782 * Obtains the four control register bits if supported by the hardware.
2786 * True if the communications handle was good and for hardware that
2787 * control register access, false otherwise.
2789 BOOL WINAPI
GetCommModemStatus(
2790 HANDLE hFile
, /* [in] The communications device. */
2791 LPDWORD lpModemStat
) /* [out] The control register bits. */
2793 int fd
,mstat
, result
=FALSE
;
2797 fd
= FILE_GetUnixHandle( hFile
, GENERIC_READ
);
2800 result
= ioctl(fd
, TIOCMGET
, &mstat
);
2804 WARN("ioctl failed\n");
2808 if (mstat
& TIOCM_CTS
)
2809 *lpModemStat
|= MS_CTS_ON
;
2812 if (mstat
& TIOCM_DSR
)
2813 *lpModemStat
|= MS_DSR_ON
;
2816 if (mstat
& TIOCM_RNG
)
2817 *lpModemStat
|= MS_RING_ON
;
2820 /*FIXME: Not really sure about RLSD UB 990810*/
2821 if (mstat
& TIOCM_CAR
)
2822 *lpModemStat
|= MS_RLSD_ON
;
2824 TRACE("%04x -> %s%s%s%s\n", mstat
,
2825 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
2826 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
2827 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
2828 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
2835 /***********************************************************************
2836 * COMM_WaitCommEventService (INTERNAL)
2838 * This function is called while the client is waiting on the
2839 * server, so we can't make any server calls here.
2841 static void COMM_WaitCommEventService(async_private
*ovp
, int events
)
2843 LPOVERLAPPED lpOverlapped
= ovp
->lpOverlapped
;
2845 TRACE("overlapped %p wait complete %p <- %x\n",lpOverlapped
,ovp
->buffer
,events
);
2848 lpOverlapped
->Internal
= STATUS_HANDLES_CLOSED
;
2854 *ovp
->buffer
= EV_RXCHAR
;
2857 lpOverlapped
->Internal
= STATUS_SUCCESS
;
2862 /***********************************************************************
2863 * COMM_WaitCommEvent (INTERNAL)
2865 * This function must have an lpOverlapped.
2867 static BOOL
COMM_WaitCommEvent(
2868 HANDLE hFile
, /* [in] handle of comm port to wait for */
2869 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2870 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2877 SetLastError(ERROR_INVALID_PARAMETER
);
2881 if(NtResetEvent(lpOverlapped
->hEvent
,NULL
))
2884 lpOverlapped
->Internal
= STATUS_PENDING
;
2885 lpOverlapped
->InternalHigh
= 0;
2886 lpOverlapped
->Offset
= 0;
2887 lpOverlapped
->OffsetHigh
= 0;
2889 /* start an ASYNCHRONOUS WaitCommEvent */
2890 SERVER_START_REQ( create_async
)
2892 req
->file_handle
= hFile
;
2894 req
->type
= ASYNC_TYPE_WAIT
;
2896 ret
=SERVER_CALL_ERR();
2903 fd
= FILE_GetUnixHandle( hFile
, GENERIC_WRITE
);
2907 ovp
= (async_private
*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private
));
2913 ovp
->lpOverlapped
= lpOverlapped
;
2916 ovp
->tv
.tv_usec
= 0;
2917 ovp
->event
= POLLIN
;
2918 ovp
->func
= COMM_WaitCommEventService
;
2919 ovp
->buffer
= (char *)lpdwEvents
;
2922 ovp
->next
= NtCurrentTeb()->pending_list
;
2925 ovp
->next
->prev
=ovp
;
2926 NtCurrentTeb()->pending_list
= ovp
;
2928 SetLastError(ERROR_IO_PENDING
);
2933 /***********************************************************************
2934 * WaitCommEvent (KERNEL32.719)
2936 * Wait until something interesting happens on a COMM port.
2937 * Interesting things (events) are set by calling SetCommMask before
2938 * this function is called.
2941 * TRUE if successful
2944 * The set of detected events will be written to *lpdwEventMask
2945 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2948 * Only supports EV_RXCHAR and EV_TXEMPTY
2950 BOOL WINAPI
WaitCommEvent(
2951 HANDLE hFile
, /* [in] handle of comm port to wait for */
2952 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2953 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2958 TRACE("(%x %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
2961 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
2963 /* if there is no overlapped structure, create our own */
2964 ov
.hEvent
= CreateEventA(NULL
,FALSE
,FALSE
,NULL
);
2966 COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
2968 if(GetLastError()!=STATUS_PENDING
)
2970 CloseHandle(ov
.hEvent
);
2974 /* wait for the overlapped to complete */
2975 ret
= GetOverlappedResult(hFile
, &ov
, NULL
, TRUE
);
2976 CloseHandle(ov
.hEvent
);
2981 /***********************************************************************
2982 * GetCommProperties (KERNEL32.286)
2984 * This function fills in a structure with the capabilities of the
2985 * communications port driver.
2989 * TRUE on success, FALSE on failure
2990 * If successful, the lpCommProp structure be filled in with
2991 * properties of the comm port.
2993 BOOL WINAPI
GetCommProperties(
2994 HANDLE hFile
, /* [in] handle of the comm port */
2995 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
2997 FIXME("(%d %p )\n",hFile
,lpCommProp
);
3002 * These values should be valid for LINUX's serial driver
3003 * FIXME: Perhaps they deserve an #ifdef LINUX
3005 memset(lpCommProp
,0,sizeof(COMMPROP
));
3006 lpCommProp
->wPacketLength
= 1;
3007 lpCommProp
->wPacketVersion
= 1;
3008 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
3009 lpCommProp
->dwReserved1
= 0;
3010 lpCommProp
->dwMaxTxQueue
= 4096;
3011 lpCommProp
->dwMaxRxQueue
= 4096;
3012 lpCommProp
->dwMaxBaud
= BAUD_115200
;
3013 lpCommProp
->dwProvSubType
= PST_RS232
;
3014 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
;
3015 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
3016 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
3017 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
3018 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
3019 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
3020 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
3021 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
3022 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
3023 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
3024 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
3029 /***********************************************************************
3031 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
3032 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
3033 * This is dependent on the type of COMM port, but since it is doubtful
3034 * anybody will get around to implementing support for fancy serial
3035 * ports in WINE, this is hardcoded for the time being. The name of
3036 * this DLL should be stored in and read from the system registry in
3037 * the hive HKEY_LOCAL_MACHINE, key
3038 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
3039 * where ???? is the port number... that is determined by PNP
3040 * The DLL should be loaded when the COMM port is opened, and closed
3041 * when the COMM port is closed. - MJM 20 June 2000
3042 ***********************************************************************/
3043 static CHAR lpszSerialUI
[] = "serialui.dll";
3046 /***********************************************************************
3047 * CommConfigDialogA (KERNEL32.140)
3049 * Raises a dialog that allows the user to configure a comm port.
3050 * Fills the COMMCONFIG struct with information specified by the user.
3051 * This function should call a similar routine in the COMM driver...
3055 * TRUE on success, FALSE on failure
3056 * If successful, the lpCommConfig structure will contain a new
3057 * configuration for the comm port, as specified by the user.
3060 * The library with the CommConfigDialog code is never unloaded.
3061 * Perhaps this should be done when the comm port is closed?
3063 BOOL WINAPI
CommConfigDialogA(
3064 LPCSTR lpszDevice
, /* [in] name of communications device */
3065 HANDLE hWnd
, /* [in] parent window for the dialog */
3066 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
3068 FARPROC lpfnCommDialog
;
3069 HMODULE hConfigModule
;
3072 TRACE("(%p %x %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
3074 hConfigModule
= LoadLibraryA(lpszSerialUI
);
3078 lpfnCommDialog
= GetProcAddress(hConfigModule
, (LPCSTR
)3L);
3083 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
3085 /* UnloadLibrary(hConfigModule); */
3090 /***********************************************************************
3091 * CommConfigDialogW (KERNEL32.141)
3093 * see CommConfigDialogA for more info
3095 BOOL WINAPI
CommConfigDialogW(
3096 LPCWSTR lpszDevice
, /* [in] name of communications device */
3097 HANDLE hWnd
, /* [in] parent window for the dialog */
3098 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
3103 lpDeviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice
);
3106 r
= CommConfigDialogA(lpDeviceA
,hWnd
,lpCommConfig
);
3107 HeapFree( GetProcessHeap(), 0, lpDeviceA
);
3111 /***********************************************************************
3112 * GetCommConfig (KERNEL32.283)
3114 * Fill in the COMMCONFIG structure for the comm port hFile
3118 * TRUE on success, FALSE on failure
3119 * If successful, lpCommConfig contains the comm port configuration.
3123 * The signature is missing a the parameter for the size of the COMMCONFIG
3124 * structure/buffer it should be
3125 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
3127 BOOL WINAPI
GetCommConfig(
3128 HANDLE hFile
, /* [in] The communications device. */
3129 LPCOMMCONFIG lpCommConfig
) /* [out] The communications configuration of the device (if it fits). */
3130 #if 0 /* FIXME: Why is this "commented" out? */
3131 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
3132 afterwards the number of bytes copied to the buffer or
3133 the needed size of the buffer. */
3138 TRACE("(%x %p)\n",hFile
,lpCommConfig
);
3140 if(lpCommConfig
== NULL
)
3143 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
3144 lpCommConfig
->wVersion
= 1;
3145 lpCommConfig
->wReserved
= 0;
3146 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
3147 lpCommConfig
->dwProviderSubType
= PST_RS232
;
3148 lpCommConfig
->dwProviderOffset
= 0;
3149 lpCommConfig
->dwProviderSize
= 0;
3154 /***********************************************************************
3155 * SetCommConfig (KERNEL32.617)
3157 * Sets the configuration of the commications device.
3161 * True on success, false if the handle was bad is not a communications device.
3163 BOOL WINAPI
SetCommConfig(
3164 HANDLE hFile
, /* [in] The communications device. */
3165 LPCOMMCONFIG lpCommConfig
) /* [in] The desired configuration. */
3167 TRACE("(%x %p)\n",hFile
,lpCommConfig
);
3168 return SetCommState(hFile
,&lpCommConfig
->dcb
);
3171 /***********************************************************************
3172 * SetDefaultCommConfigA (KERNEL32.638)
3174 * Initializes the default configuration for the specified communication
3179 * True if the device was found and the defaults set, false otherwise
3181 BOOL WINAPI
SetDefaultCommConfigA(
3182 LPCSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
3183 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
3184 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
3186 FARPROC lpfnSetDefaultCommConfig
;
3187 HMODULE hConfigModule
;
3190 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
3192 hConfigModule
= LoadLibraryA(lpszSerialUI
);
3196 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, (LPCSTR
)4L);
3198 if(! lpfnSetDefaultCommConfig
)
3201 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
3203 /* UnloadLibrary(hConfigModule); */
3209 /***********************************************************************
3210 * SetDefaultCommConfigW (KERNEL32.639)
3212 * Initializes the default configuration for the specified
3213 * communication device. (unicode)
3218 BOOL WINAPI
SetDefaultCommConfigW(
3219 LPCWSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
3220 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
3221 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
3226 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice
),lpCommConfig
,dwSize
);
3228 lpDeviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice
);
3231 r
= SetDefaultCommConfigA(lpDeviceA
,lpCommConfig
,dwSize
);
3232 HeapFree( GetProcessHeap(), 0, lpDeviceA
);
3237 /***********************************************************************
3238 * GetDefaultCommConfigA (KERNEL32.313)
3240 * Acquires the default configuration of the specified communication device. (unicode)
3244 * True on successful reading of the default configuration,
3245 * if the device is not found or the buffer is too small.
3247 BOOL WINAPI
GetDefaultCommConfigA(
3248 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
3249 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
3250 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
3251 afterwards the number of bytes copied to the buffer or
3252 the needed size of the buffer. */
3254 LPDCB lpdcb
= &(lpCC
->dcb
);
3257 if (strncasecmp(lpszName
,"COM",3)) {
3258 ERR("not implemented for <%s>\n", lpszName
);
3262 if (!ValidCOMPort(lpszName
[3]-'1'))
3265 TRACE("(%s %p %ld)\n", lpszName
, lpCC
, *lpdwSize
);
3266 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
3267 *lpdwSize
= sizeof(COMMCONFIG
);
3271 *lpdwSize
= sizeof(COMMCONFIG
);
3273 lpCC
->dwSize
= sizeof(COMMCONFIG
);
3275 lpCC
->dwProviderSubType
= PST_RS232
;
3276 lpCC
->dwProviderOffset
= 0L;
3277 lpCC
->dwProviderSize
= 0L;
3279 (void) sprintf( temp
, "COM%c:38400,n,8,1", lpszName
[3]);
3280 FIXME("setting %s as default\n", temp
);
3282 return BuildCommDCBA( temp
, lpdcb
);
3285 /**************************************************************************
3286 * GetDefaultCommConfigW (KERNEL32.314)
3288 * Acquires the default configuration of the specified communication device. (unicode)
3292 * True on successful reading of the default configuration,
3293 * if the device is not found or the buffer is too small.
3295 BOOL WINAPI
GetDefaultCommConfigW(
3296 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
3297 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
3298 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
3299 afterwards the number of bytes copied to the buffer or
3300 the needed size of the buffer. */
3305 TRACE("(%p,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
3306 lpszNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName
);
3309 ret
=GetDefaultCommConfigA(lpszNameA
,lpCC
,lpdwSize
);
3310 HeapFree( GetProcessHeap(), 0, lpszNameA
);