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>
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
63 #include "wine/port.h"
70 #include "debugtools.h"
72 DEFAULT_DEBUG_CHANNEL(comm
);
74 #if !defined(TIOCINQ) && defined(FIONREAD)
75 #define TIOCINQ FIONREAD
78 /* window's semi documented modem status register */
79 #define COMM_MSR_OFFSET 35
84 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
89 #define CMSPAR 0x40000000 /* stick parity */
94 struct DosDeviceStruct
{
95 char *devicename
; /* /dev/ttyS0 */
102 int commerror
, eventmask
;
105 unsigned ibuf_size
,ibuf_head
,ibuf_tail
;
106 unsigned obuf_size
,obuf_head
,obuf_tail
;
108 int wnd
, n_read
, n_write
;
109 HANDLE s_read
, s_write
;
113 static struct DosDeviceStruct COM
[MAX_PORTS
];
114 static struct DosDeviceStruct LPT
[MAX_PORTS
];
115 /* pointers to unknown(==undocumented) comm structure */
116 static LPCVOID
*unknown
[MAX_PORTS
];
117 /* save terminal states */
118 static struct termios m_stat
[MAX_PORTS
];
120 /* update window's semi documented modem status register */
121 /* see knowledge base Q101417 */
122 static void COMM_MSRUpdate( UCHAR
* pMsr
, unsigned int mstat
)
126 if(mstat
& TIOCM_CTS
) tmpmsr
|= MSR_CTS
;
129 if(mstat
& TIOCM_DSR
) tmpmsr
|= MSR_DSR
;
132 if(mstat
& TIOCM_RI
) tmpmsr
|= MSR_RI
;
135 if(mstat
& TIOCM_CAR
) tmpmsr
|= MSR_RLSD
;
137 *pMsr
= (*pMsr
& ~MSR_MASK
) | tmpmsr
;
143 char option
[10], temp
[256], *btemp
;
146 for (x
=0; x
!=MAX_PORTS
; x
++) {
147 strcpy(option
,"COMx");
151 PROFILE_GetWineIniString( "serialports", option
, "*",
152 temp
, sizeof(temp
) );
153 if (!strcmp(temp
, "*") || *temp
== '\0')
154 COM
[x
].devicename
= NULL
;
156 btemp
= strchr(temp
,',');
159 COM
[x
].baudrate
= atoi(btemp
);
161 COM
[x
].baudrate
= -1;
164 if (!S_ISCHR(st
.st_mode
))
165 WARN("Can't use `%s' as %s !\n", temp
, option
);
167 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
168 WARN("Can't malloc for device info!\n");
171 strcpy(COM
[x
].devicename
, temp
);
173 TRACE("%s = %s\n", option
, COM
[x
].devicename
);
176 strcpy(option
, "LPTx");
180 PROFILE_GetWineIniString( "parallelports", option
, "*",
181 temp
, sizeof(temp
) );
182 if (!strcmp(temp
, "*") || *temp
== '\0')
183 LPT
[x
].devicename
= NULL
;
186 if (!S_ISCHR(st
.st_mode
))
187 WARN("Can't use `%s' as %s !\n", temp
, option
);
189 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
190 WARN("Can't malloc for device info!\n");
193 strcpy(LPT
[x
].devicename
, temp
);
195 TRACE("%s = %s\n", option
, LPT
[x
].devicename
);
202 static struct DosDeviceStruct
*GetDeviceStruct(int fd
)
204 if ((fd
&0x7F)<=MAX_PORTS
) {
205 if (!(fd
&FLAG_LPT
)) {
218 static int GetCommPort_fd(int fd
)
222 for (x
=0; x
<MAX_PORTS
; x
++) {
230 static int ValidCOMPort(int x
)
232 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
235 static int ValidLPTPort(int x
)
237 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
240 static int WinError(void)
242 TRACE("errno = %d\n", errno
);
249 static unsigned comm_inbuf(struct DosDeviceStruct
*ptr
)
251 return ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? ptr
->ibuf_size
: 0)
252 + ptr
->ibuf_head
- ptr
->ibuf_tail
;
255 static unsigned comm_outbuf(struct DosDeviceStruct
*ptr
)
257 return ((ptr
->obuf_tail
> ptr
->obuf_head
) ? ptr
->obuf_size
: 0)
258 + ptr
->obuf_head
- ptr
->obuf_tail
;
261 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
263 unsigned int mstat
, okay
;
264 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
265 if (okay
) return okay
;
266 if (andy
) mstat
&= andy
;
268 return ioctl(fd
, TIOCMSET
, &mstat
);
271 static void CALLBACK
comm_notification( ULONG_PTR
private )
273 struct DosDeviceStruct
*ptr
= (struct DosDeviceStruct
*)private;
274 int prev
, bleft
, len
;
276 int cid
= GetCommPort_fd(ptr
->fd
);
278 TRACE("async notification\n");
279 /* read data from comm port */
280 prev
= comm_inbuf(ptr
);
282 bleft
= ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? (ptr
->ibuf_tail
-1) : ptr
->ibuf_size
)
284 len
= read(ptr
->fd
, ptr
->inbuf
+ ptr
->ibuf_head
, bleft
?bleft
:1);
287 ptr
->commerror
= CE_RXOVER
;
289 /* check for events */
290 if ((ptr
->eventmask
& EV_RXFLAG
) &&
291 memchr(ptr
->inbuf
+ ptr
->ibuf_head
, ptr
->evtchar
, len
)) {
292 *(WORD
*)(unknown
[cid
]) |= EV_RXFLAG
;
295 if (ptr
->eventmask
& EV_RXCHAR
) {
296 *(WORD
*)(unknown
[cid
]) |= EV_RXCHAR
;
299 /* advance buffer position */
300 ptr
->ibuf_head
+= len
;
301 if (ptr
->ibuf_head
>= ptr
->ibuf_size
)
306 /* check for notification */
307 if (ptr
->wnd
&& (ptr
->n_read
>0) && (prev
<ptr
->n_read
) &&
308 (comm_inbuf(ptr
)>=ptr
->n_read
)) {
309 /* passed the receive notification threshold */
313 /* write any TransmitCommChar character */
315 len
= write(ptr
->fd
, &(ptr
->xmit
), 1);
316 if (len
> 0) ptr
->xmit
= -1;
318 /* write from output queue */
319 prev
= comm_outbuf(ptr
);
321 bleft
= ((ptr
->obuf_tail
<= ptr
->obuf_head
) ? ptr
->obuf_head
: ptr
->obuf_size
)
323 len
= bleft
? write(ptr
->fd
, ptr
->outbuf
+ ptr
->obuf_tail
, bleft
) : 0;
325 ptr
->obuf_tail
+= len
;
326 if (ptr
->obuf_tail
>= ptr
->obuf_size
)
329 if (ptr
->obuf_tail
== ptr
->obuf_head
) {
331 SERVICE_Delete( ptr
->s_write
);
332 ptr
->s_write
= INVALID_HANDLE_VALUE
;
334 if (ptr
->eventmask
& EV_TXEMPTY
) {
335 *(WORD
*)(unknown
[cid
]) |= EV_TXEMPTY
;
341 /* check for notification */
342 if (ptr
->wnd
&& (ptr
->n_write
>0) && (prev
>=ptr
->n_write
) &&
343 (comm_outbuf(ptr
)<ptr
->n_write
)) {
344 /* passed the transmit notification threshold */
348 /* send notifications, if any */
349 if (ptr
->wnd
&& mask
) {
350 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr
->wnd
, cid
, mask
);
351 if (Callout
.PostMessageA
) Callout
.PostMessageA(ptr
->wnd
, WM_COMMNOTIFY
, cid
, mask
);
355 static void comm_waitread(struct DosDeviceStruct
*ptr
)
357 if (ptr
->s_read
!= INVALID_HANDLE_VALUE
) return;
358 ptr
->s_read
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
359 GENERIC_READ
| SYNCHRONIZE
),
364 static void comm_waitwrite(struct DosDeviceStruct
*ptr
)
366 if (ptr
->s_write
!= INVALID_HANDLE_VALUE
) return;
367 ptr
->s_write
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
368 GENERIC_WRITE
| SYNCHRONIZE
),
373 /**************************************************************************
374 * BuildCommDCB16 (USER.213)
376 * According to the ECMA-234 (368.3) the function will return FALSE on
377 * success, otherwise it will return -1.
378 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
381 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
383 /* "COM1:9600,n,8,1" */
386 char *ptr
, temp
[256];
388 TRACE("(%s), ptr %p\n", device
, lpdcb
);
390 if (!strncasecmp(device
,"COM",3)) {
391 port
= device
[3] - '0';
395 ERR("BUG ! COM0 can't exist!\n");
399 if (!ValidCOMPort(port
)) {
400 FIXME("invalid COM port %d?\n",port
);
404 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
411 if (*(device
+4) != ':')
414 strcpy(temp
,device
+5);
415 ptr
= strtok(temp
, ", ");
417 if (COM
[port
].baudrate
> 0)
418 lpdcb
->BaudRate
= COM
[port
].baudrate
;
420 lpdcb
->BaudRate
= atoi(ptr
);
421 TRACE("baudrate (%d)\n", lpdcb
->BaudRate
);
423 ptr
= strtok(NULL
, ", ");
425 *ptr
= toupper(*ptr
);
427 TRACE("parity (%c)\n", *ptr
);
428 lpdcb
->fParity
= TRUE
;
431 lpdcb
->Parity
= NOPARITY
;
432 lpdcb
->fParity
= FALSE
;
435 lpdcb
->Parity
= EVENPARITY
;
438 lpdcb
->Parity
= MARKPARITY
;
441 lpdcb
->Parity
= ODDPARITY
;
444 WARN("Unknown parity `%c'!\n", *ptr
);
448 ptr
= strtok(NULL
, ", ");
449 TRACE("charsize (%c)\n", *ptr
);
450 lpdcb
->ByteSize
= *ptr
- '0';
452 ptr
= strtok(NULL
, ", ");
453 TRACE("stopbits (%c)\n", *ptr
);
456 lpdcb
->StopBits
= ONESTOPBIT
;
459 lpdcb
->StopBits
= TWOSTOPBITS
;
462 WARN("Unknown # of stopbits `%c'!\n", *ptr
);
470 /*****************************************************************************
471 * OpenComm16 (USER.200)
473 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
477 TRACE("%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
479 if (strlen(device
) < 4)
482 port
= device
[3] - '0';
485 ERR("BUG ! COM0 or LPT0 don't exist !\n");
487 if (!strncasecmp(device
,"COM",3)) {
489 TRACE("%s = %s\n", device
, COM
[port
].devicename
);
491 if (!ValidCOMPort(port
))
497 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
499 ERR("Couldn't open %s ! (%s)\n", COM
[port
].devicename
, strerror(errno
));
502 unknown
[port
] = SEGPTR_ALLOC(40);
503 bzero(unknown
[port
],40);
505 COM
[port
].commerror
= 0;
506 COM
[port
].eventmask
= 0;
507 COM
[port
].evtchar
= 0; /* FIXME: default? */
508 /* save terminal state */
509 tcgetattr(fd
,&m_stat
[port
]);
510 /* set default parameters */
511 if(COM
[port
].baudrate
>-1){
513 GetCommState16(port
, &dcb
);
514 dcb
.BaudRate
=COM
[port
].baudrate
;
516 * databits, parity, stopbits
518 SetCommState16( &dcb
);
520 /* init priority characters */
521 COM
[port
].unget
= -1;
523 /* allocate buffers */
524 COM
[port
].ibuf_size
= cbInQueue
;
525 COM
[port
].ibuf_head
= COM
[port
].ibuf_tail
= 0;
526 COM
[port
].obuf_size
= cbOutQueue
;
527 COM
[port
].obuf_head
= COM
[port
].obuf_tail
= 0;
529 COM
[port
].inbuf
= malloc(cbInQueue
);
530 if (COM
[port
].inbuf
) {
531 COM
[port
].outbuf
= malloc(cbOutQueue
);
532 if (!COM
[port
].outbuf
)
533 free(COM
[port
].inbuf
);
534 } else COM
[port
].outbuf
= NULL
;
535 if (!COM
[port
].outbuf
) {
536 /* not enough memory */
537 tcsetattr(COM
[port
].fd
,TCSANOW
,&m_stat
[port
]);
539 ERR("out of memory\n");
543 COM
[port
].s_read
= INVALID_HANDLE_VALUE
;
544 COM
[port
].s_write
= INVALID_HANDLE_VALUE
;
545 comm_waitread( &COM
[port
] );
550 if (!strncasecmp(device
,"LPT",3)) {
552 if (!ValidLPTPort(port
))
558 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
563 LPT
[port
].commerror
= 0;
564 LPT
[port
].eventmask
= 0;
565 return port
|FLAG_LPT
;
571 /*****************************************************************************
572 * CloseComm16 (USER.207)
574 INT16 WINAPI
CloseComm16(INT16 cid
)
576 struct DosDeviceStruct
*ptr
;
578 TRACE("cid=%d\n", cid
);
579 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
580 FIXME("no cid=%d found!\n", cid
);
583 if (!(cid
&FLAG_LPT
)) {
585 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
587 SERVICE_Delete( COM
[cid
].s_write
);
588 SERVICE_Delete( COM
[cid
].s_read
);
593 /* reset modem lines */
594 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
597 if (close(ptr
->fd
) == -1) {
598 ptr
->commerror
= WinError();
599 /* FIXME: should we clear ptr->fd here? */
608 /*****************************************************************************
609 * SetCommBreak16 (USER.210)
611 INT16 WINAPI
SetCommBreak16(INT16 cid
)
613 struct DosDeviceStruct
*ptr
;
615 TRACE("cid=%d\n", cid
);
616 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
617 FIXME("no cid=%d found!\n", cid
);
626 /*****************************************************************************
627 * ClearCommBreak16 (USER.211)
629 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
631 struct DosDeviceStruct
*ptr
;
633 TRACE("cid=%d\n", cid
);
634 if (!(ptr
= GetDeviceStruct(cid
))) {
635 FIXME("no cid=%d found!\n", cid
);
643 /*****************************************************************************
644 * EscapeCommFunction16 (USER.214)
646 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
649 struct DosDeviceStruct
*ptr
;
652 TRACE("cid=%d, function=%d\n", cid
, nFunction
);
653 if ((nFunction
!= GETMAXCOM
) && (nFunction
!= GETMAXLPT
)) {
654 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
655 FIXME("no cid=%d found!\n", cid
);
658 if (tcgetattr(ptr
->fd
,&port
) == -1) {
659 TRACE("tcgetattr failed\n");
660 ptr
->commerror
=WinError();
671 TRACE("GETMAXCOM\n");
672 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
678 TRACE("GETMAXLPT\n");
679 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
681 return FLAG_LPT
+ max
;
685 TRACE("GETBASEIRQ\n");
686 /* FIXME: use tables */
687 /* just fake something for now */
688 if (cid
& FLAG_LPT
) {
689 /* LPT1: irq 7, LPT2: irq 5 */
690 return (cid
& 0x7f) ? 5 : 7;
692 /* COM1: irq 4, COM2: irq 3,
693 COM3: irq 4, COM4: irq 3 */
694 return 4 - (cid
& 1);
701 return COMM_WhackModem(ptr
->fd
, ~TIOCM_DTR
, 0);
706 return COMM_WhackModem(ptr
->fd
, ~TIOCM_RTS
, 0);
712 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_DTR
);
718 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_RTS
);
723 port
.c_iflag
|= IXOFF
;
728 port
.c_iflag
|= IXON
;
732 WARN("(cid=%d,nFunction=%d): Unknown function\n",
737 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
738 ptr
->commerror
= WinError();
746 /*****************************************************************************
747 * FlushComm16 (USER.215)
749 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
752 struct DosDeviceStruct
*ptr
;
754 TRACE("cid=%d, queue=%d\n", cid
, fnQueue
);
755 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
756 FIXME("no cid=%d found!\n", cid
);
762 ptr
->obuf_tail
= ptr
->obuf_head
;
766 ptr
->ibuf_head
= ptr
->ibuf_tail
;
769 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
773 if (tcflush(ptr
->fd
, queue
)) {
774 ptr
->commerror
= WinError();
782 /********************************************************************
783 * GetCommError16 (USER.203)
785 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
788 struct DosDeviceStruct
*ptr
;
792 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
793 FIXME("no handle for cid = %0x!\n",cid
);
797 WARN(" cid %d not comm port\n",cid
);
800 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
801 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
802 COMM_MSRUpdate( stol
, mstat
);
807 lpStat
->cbOutQue
= comm_outbuf(ptr
);
808 lpStat
->cbInQue
= comm_inbuf(ptr
);
810 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
811 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
812 lpStat
->cbOutQue
, *stol
);
815 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
816 cid
, ptr
->commerror
, *stol
);
818 /* Return any errors and clear it */
819 temperror
= ptr
->commerror
;
824 /*****************************************************************************
825 * SetCommEventMask16 (USER.208)
827 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
829 struct DosDeviceStruct
*ptr
;
834 TRACE("cid %d,mask %d\n",cid
,fuEvtMask
);
835 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
836 FIXME("no handle for cid = %0x!\n",cid
);
840 ptr
->eventmask
= fuEvtMask
;
842 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
843 WARN(" cid %d not comm port\n",cid
);
846 /* it's a COM port ? -> modify flags */
847 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
848 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
849 TRACE(" ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
850 COMM_MSRUpdate( stol
, mstat
);
852 TRACE(" modem dcd construct %x\n",*stol
);
853 return SEGPTR_GET(unknown
[cid
]);
856 /*****************************************************************************
857 * GetCommEventMask16 (USER.209)
859 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
861 struct DosDeviceStruct
*ptr
;
864 TRACE("cid %d, mask %d\n", cid
, fnEvtClear
);
865 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
866 FIXME("no handle for cid = %0x!\n",cid
);
870 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
871 WARN(" cid %d not comm port\n",cid
);
875 events
= *(WORD
*)(unknown
[cid
]) & fnEvtClear
;
876 *(WORD
*)(unknown
[cid
]) &= ~fnEvtClear
;
880 /*****************************************************************************
881 * SetCommState16 (USER.201)
883 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
886 struct DosDeviceStruct
*ptr
;
887 int bytesize
, stopbits
;
890 TRACE("cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
891 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
892 FIXME("no handle for cid = %0x!\n",lpdcb
->Id
);
895 if (tcgetattr(ptr
->fd
, &port
) == -1) {
896 ptr
->commerror
= WinError();
901 port
.c_cc
[VTIME
] = 1;
904 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
906 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
908 port
.c_iflag
|= (IGNBRK
);
910 port
.c_oflag
&= ~(OPOST
);
912 port
.c_cflag
&= ~(HUPCL
);
913 port
.c_cflag
|= CLOCAL
| CREAD
;
915 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
916 port
.c_lflag
|= NOFLSH
;
918 TRACE("baudrate %d\n",lpdcb
->BaudRate
);
920 port
.c_cflag
&= ~CBAUD
;
921 switch (lpdcb
->BaudRate
) {
924 port
.c_cflag
|= B110
;
928 port
.c_cflag
|= B300
;
932 port
.c_cflag
|= B600
;
936 port
.c_cflag
|= B1200
;
940 port
.c_cflag
|= B2400
;
944 port
.c_cflag
|= B4800
;
948 port
.c_cflag
|= B9600
;
952 port
.c_cflag
|= B19200
;
956 port
.c_cflag
|= B38400
;
960 port
.c_cflag
|= B57600
;
965 port
.c_cflag
|= B115200
;
969 ptr
->commerror
= IE_BAUDRATE
;
972 #elif !defined(__EMX__)
973 switch (lpdcb
->BaudRate
) {
976 port
.c_ospeed
= B110
;
980 port
.c_ospeed
= B300
;
984 port
.c_ospeed
= B600
;
988 port
.c_ospeed
= B1200
;
992 port
.c_ospeed
= B2400
;
996 port
.c_ospeed
= B4800
;
1000 port
.c_ospeed
= B9600
;
1004 port
.c_ospeed
= B19200
;
1008 port
.c_ospeed
= B38400
;
1011 ptr
->commerror
= IE_BAUDRATE
;
1014 port
.c_ispeed
= port
.c_ospeed
;
1016 bytesize
=lpdcb
->ByteSize
;
1017 stopbits
=lpdcb
->StopBits
;
1019 TRACE("fParity %d Parity %d\n",lpdcb
->fParity
, lpdcb
->Parity
);
1021 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1023 port
.c_cflag
&= ~(PARENB
| PARODD
);
1026 port
.c_iflag
|= INPCK
;
1028 port
.c_iflag
&= ~INPCK
;
1029 switch (lpdcb
->Parity
) {
1033 port
.c_cflag
|= (PARENB
| PARODD
);
1036 port
.c_cflag
|= PARENB
;
1039 /* Linux defines mark/space (stick) parity */
1041 port
.c_cflag
|= (PARENB
| CMSPAR
);
1044 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1047 /* try the POSIX way */
1049 if( stopbits
== ONESTOPBIT
) {
1050 stopbits
= TWOSTOPBITS
;
1051 port
.c_iflag
&= ~INPCK
;
1053 ptr
->commerror
= IE_BYTESIZE
;
1060 port
.c_iflag
&= ~INPCK
;
1062 ptr
->commerror
= IE_BYTESIZE
;
1068 ptr
->commerror
= IE_BYTESIZE
;
1072 TRACE("bytesize %d\n",bytesize
);
1073 port
.c_cflag
&= ~CSIZE
;
1076 port
.c_cflag
|= CS5
;
1079 port
.c_cflag
|= CS6
;
1082 port
.c_cflag
|= CS7
;
1085 port
.c_cflag
|= CS8
;
1088 ptr
->commerror
= IE_BYTESIZE
;
1092 TRACE("stopbits %d\n",stopbits
);
1096 port
.c_cflag
&= ~CSTOPB
;
1098 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
1100 port
.c_cflag
|= CSTOPB
;
1103 ptr
->commerror
= IE_BYTESIZE
;
1108 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
1109 port
.c_cflag
|= CRTSCTS
;
1111 if (lpdcb
->fDtrDisable
)
1112 port
.c_cflag
&= ~CRTSCTS
;
1115 port
.c_iflag
|= IXON
;
1117 port
.c_iflag
&= ~IXON
;
1119 port
.c_iflag
|= IXOFF
;
1121 port
.c_iflag
&= ~IXOFF
;
1123 ptr
->evtchar
= lpdcb
->EvtChar
;
1128 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
1129 ptr
->commerror
= WinError();
1137 /*****************************************************************************
1138 * GetCommState16 (USER.202)
1140 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
1143 struct DosDeviceStruct
*ptr
;
1144 struct termios port
;
1146 TRACE("cid %d, ptr %p\n", cid
, lpdcb
);
1147 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1148 FIXME("no handle for cid = %0x!\n",cid
);
1151 if (tcgetattr(ptr
->fd
, &port
) == -1) {
1152 ptr
->commerror
= WinError();
1158 speed
= port
.c_cflag
& CBAUD
;
1160 speed
= port
.c_ospeed
;
1164 lpdcb
->BaudRate
= 110;
1167 lpdcb
->BaudRate
= 300;
1170 lpdcb
->BaudRate
= 600;
1173 lpdcb
->BaudRate
= 1200;
1176 lpdcb
->BaudRate
= 2400;
1179 lpdcb
->BaudRate
= 4800;
1182 lpdcb
->BaudRate
= 9600;
1185 lpdcb
->BaudRate
= 19200;
1188 lpdcb
->BaudRate
= 38400;
1192 lpdcb
->BaudRate
= 57600;
1197 lpdcb
->BaudRate
= 57601;
1202 switch (port
.c_cflag
& CSIZE
) {
1204 lpdcb
->ByteSize
= 5;
1207 lpdcb
->ByteSize
= 6;
1210 lpdcb
->ByteSize
= 7;
1213 lpdcb
->ByteSize
= 8;
1217 if(port
.c_iflag
& INPCK
)
1218 lpdcb
->fParity
= TRUE
;
1220 lpdcb
->fParity
= FALSE
;
1222 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1224 switch (port
.c_cflag
& (PARENB
| PARODD
))
1228 lpdcb
->Parity
= NOPARITY
;
1231 lpdcb
->Parity
= EVENPARITY
;
1233 case (PARENB
| PARODD
):
1234 lpdcb
->Parity
= ODDPARITY
;
1237 case (PARENB
| CMSPAR
):
1238 lpdcb
->Parity
= MARKPARITY
;
1240 case (PARENB
| PARODD
| CMSPAR
):
1241 lpdcb
->Parity
= SPACEPARITY
;
1246 if (port
.c_cflag
& CSTOPB
)
1247 if(lpdcb
->ByteSize
== 5)
1248 lpdcb
->StopBits
= ONE5STOPBITS
;
1250 lpdcb
->StopBits
= TWOSTOPBITS
;
1252 lpdcb
->StopBits
= ONESTOPBIT
;
1254 lpdcb
->RlsTimeout
= 50;
1255 lpdcb
->CtsTimeout
= 50;
1256 lpdcb
->DsrTimeout
= 50;
1260 lpdcb
->fDtrDisable
= 0;
1264 if (port
.c_cflag
& CRTSCTS
) {
1265 lpdcb
->fDtrflow
= 1;
1266 lpdcb
->fRtsflow
= 1;
1267 lpdcb
->fOutxCtsFlow
= 1;
1268 lpdcb
->fOutxDsrFlow
= 1;
1271 lpdcb
->fDtrDisable
= 1;
1273 if (port
.c_iflag
& IXON
)
1278 if (port
.c_iflag
& IXOFF
)
1287 lpdcb
->XoffLim
= 10;
1289 lpdcb
->EvtChar
= ptr
->evtchar
;
1295 /*****************************************************************************
1296 * TransmitCommChar16 (USER.206)
1298 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1300 struct DosDeviceStruct
*ptr
;
1302 TRACE("cid %d, data %d \n", cid
, chTransmit
);
1303 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1304 FIXME("no handle for cid = %0x!\n",cid
);
1308 if (ptr
->suspended
) {
1309 ptr
->commerror
= IE_HARDWARE
;
1313 if (ptr
->xmit
>= 0) {
1314 /* character already queued */
1315 /* FIXME: which error would Windows return? */
1316 ptr
->commerror
= CE_TXFULL
;
1320 if (ptr
->obuf_head
== ptr
->obuf_tail
) {
1321 /* transmit queue empty, try to transmit directly */
1322 if (write(ptr
->fd
, &chTransmit
, 1) == -1) {
1323 /* didn't work, queue it */
1324 ptr
->xmit
= chTransmit
;
1325 comm_waitwrite(ptr
);
1328 /* data in queue, let this char be transmitted next */
1329 ptr
->xmit
= chTransmit
;
1330 comm_waitwrite(ptr
);
1337 /*****************************************************************************
1338 * UngetCommChar16 (USER.212)
1340 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1342 struct DosDeviceStruct
*ptr
;
1344 TRACE("cid %d (char %d)\n", cid
, chUnget
);
1345 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1346 FIXME("no handle for cid = %0x!\n",cid
);
1350 if (ptr
->suspended
) {
1351 ptr
->commerror
= IE_HARDWARE
;
1355 if (ptr
->unget
>=0) {
1356 /* character already queued */
1357 /* FIXME: which error would Windows return? */
1358 ptr
->commerror
= CE_RXOVER
;
1362 ptr
->unget
= chUnget
;
1368 /*****************************************************************************
1369 * ReadComm16 (USER.204)
1371 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1374 struct DosDeviceStruct
*ptr
;
1375 LPSTR orgBuf
= lpvBuf
;
1377 TRACE("cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1378 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1379 FIXME("no handle for cid = %0x!\n",cid
);
1383 if (ptr
->suspended
) {
1384 ptr
->commerror
= IE_HARDWARE
;
1388 /* read unget character */
1389 if (ptr
->unget
>=0) {
1390 *lpvBuf
++ = ptr
->unget
;
1397 /* read from receive buffer */
1398 while (length
< cbRead
) {
1399 status
= ((ptr
->ibuf_head
< ptr
->ibuf_tail
) ?
1400 ptr
->ibuf_size
: ptr
->ibuf_head
) - ptr
->ibuf_tail
;
1402 if ((cbRead
- length
) < status
)
1403 status
= cbRead
- length
;
1405 memcpy(lpvBuf
, ptr
->inbuf
+ ptr
->ibuf_tail
, status
);
1406 ptr
->ibuf_tail
+= status
;
1407 if (ptr
->ibuf_tail
>= ptr
->ibuf_size
)
1413 TRACE("%.*s\n", length
, orgBuf
);
1418 /*****************************************************************************
1419 * WriteComm16 (USER.205)
1421 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1424 struct DosDeviceStruct
*ptr
;
1426 TRACE("cid %d, ptr %p, length %d\n",
1427 cid
, lpvBuf
, cbWrite
);
1428 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1429 FIXME("no handle for cid = %0x!\n",cid
);
1433 if (ptr
->suspended
) {
1434 ptr
->commerror
= IE_HARDWARE
;
1438 TRACE("%.*s\n", cbWrite
, lpvBuf
);
1441 while (length
< cbWrite
) {
1442 if ((ptr
->obuf_head
== ptr
->obuf_tail
) && (ptr
->xmit
< 0)) {
1443 /* no data queued, try to write directly */
1444 status
= write(ptr
->fd
, lpvBuf
, cbWrite
- length
);
1451 /* can't write directly, put into transmit buffer */
1452 status
= ((ptr
->obuf_tail
> ptr
->obuf_head
) ?
1453 (ptr
->obuf_tail
-1) : ptr
->obuf_size
) - ptr
->obuf_head
;
1455 if ((cbWrite
- length
) < status
)
1456 status
= cbWrite
- length
;
1457 memcpy(lpvBuf
, ptr
->outbuf
+ ptr
->obuf_head
, status
);
1458 ptr
->obuf_head
+= status
;
1459 if (ptr
->obuf_head
>= ptr
->obuf_size
)
1463 comm_waitwrite(ptr
);
1470 /***********************************************************************
1471 * EnableCommNotification16 (USER.246)
1473 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1474 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1476 struct DosDeviceStruct
*ptr
;
1478 TRACE("(%d, %x, %d, %d)\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1479 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1480 FIXME("no handle for cid = %0x!\n",cid
);
1484 ptr
->n_read
= cbWriteNotify
;
1485 ptr
->n_write
= cbOutQueue
;
1490 /**************************************************************************
1491 * BuildCommDCBA (KERNEL32.14)
1493 * Updates a device control block data structure with values from an
1494 * ascii device control string. The device control string has two forms
1495 * normal and extended, it must be exclusively in one or the other form.
1499 * True on success, false on an malformed control string.
1501 BOOL WINAPI
BuildCommDCBA(
1502 LPCSTR device
, /* The ascii device control string used to update the DCB. */
1503 LPDCB lpdcb
/* The device control block to be updated. */)
1505 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1508 /**************************************************************************
1509 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1511 * Updates a device control block data structure with values from an
1512 * ascii device control string. Taking time out values from a time outs
1513 * struct if desired by the control string.
1517 * True on success, false bad handles etc
1519 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
1520 LPCSTR device
, /* The ascii device control string. */
1521 LPDCB lpdcb
, /* The device control block to be updated. */
1522 LPCOMMTIMEOUTS lptimeouts
/* The time outs to use if asked to set them by the control string. */)
1527 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1529 if (!strncasecmp(device
,"COM",3)) {
1532 ERR("BUG! COM0 can't exist!\n");
1535 if (!ValidCOMPort(port
))
1537 if (*(device
+4)!=':')
1539 temp
=(LPSTR
)(device
+5);
1543 lpdcb
->DCBlength
= sizeof(DCB
);
1544 if (strchr(temp
,',')) { /* old style */
1547 char last
=temp
[strlen(temp
)-1];
1549 ret
=BuildCommDCB16(device
,&dcb16
);
1552 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1553 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1554 lpdcb
->fBinary
= dcb16
.fBinary
;
1555 lpdcb
->Parity
= dcb16
.Parity
;
1556 lpdcb
->fParity
= dcb16
.fParity
;
1557 lpdcb
->fNull
= dcb16
.fNull
;
1558 lpdcb
->StopBits
= dcb16
.StopBits
;
1561 lpdcb
->fOutX
= TRUE
;
1562 lpdcb
->fOutxCtsFlow
= FALSE
;
1563 lpdcb
->fOutxDsrFlow
= FALSE
;
1564 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1565 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1566 } else if (last
=='p') {
1567 lpdcb
->fInX
= FALSE
;
1568 lpdcb
->fOutX
= FALSE
;
1569 lpdcb
->fOutxCtsFlow
= TRUE
;
1570 lpdcb
->fOutxDsrFlow
= TRUE
;
1571 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1572 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1574 lpdcb
->fInX
= FALSE
;
1575 lpdcb
->fOutX
= FALSE
;
1576 lpdcb
->fOutxCtsFlow
= FALSE
;
1577 lpdcb
->fOutxDsrFlow
= FALSE
;
1578 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1579 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1581 lpdcb
->XonChar
= dcb16
.XonChar
;
1582 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1583 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1584 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1585 lpdcb
->EofChar
= dcb16
.EofChar
;
1586 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1587 lpdcb
->XonLim
= dcb16
.XonLim
;
1588 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1591 ptr
=strtok(temp
," ");
1596 if (!strncmp("baud=",ptr
,5)) {
1597 if (!sscanf(ptr
+5,"%ld",&x
))
1598 WARN("Couldn't parse %s\n",ptr
);
1599 lpdcb
->BaudRate
= x
;
1602 if (!strncmp("stop=",ptr
,5)) {
1603 if (!sscanf(ptr
+5,"%ld",&x
))
1604 WARN("Couldn't parse %s\n",ptr
);
1605 lpdcb
->StopBits
= x
;
1608 if (!strncmp("data=",ptr
,5)) {
1609 if (!sscanf(ptr
+5,"%ld",&x
))
1610 WARN("Couldn't parse %s\n",ptr
);
1611 lpdcb
->ByteSize
= x
;
1614 if (!strncmp("parity=",ptr
,7)) {
1615 lpdcb
->fParity
= TRUE
;
1618 lpdcb
->fParity
= FALSE
;
1619 lpdcb
->Parity
= NOPARITY
;
1622 lpdcb
->Parity
= EVENPARITY
;
1625 lpdcb
->Parity
= ODDPARITY
;
1628 lpdcb
->Parity
= MARKPARITY
;
1634 ERR("Unhandled specifier '%s', please report.\n",ptr
);
1635 ptr
=strtok(NULL
," ");
1637 if (lpdcb
->BaudRate
==110)
1638 lpdcb
->StopBits
= 2;
1642 /**************************************************************************
1643 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1645 * Updates a device control block data structure with values from an
1646 * unicode device control string. Taking time out values from a time outs
1647 * struct if desired by the control string.
1651 * True on success, false bad handles etc.
1653 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
1654 LPCWSTR devid
, /* The unicode device control string. */
1655 LPDCB lpdcb
, /* The device control block to be updated. */
1656 LPCOMMTIMEOUTS lptimeouts
/* The time outs to use if asked to set them by the control string. */)
1661 TRACE("(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1662 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1665 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1666 HeapFree( GetProcessHeap(), 0, devidA
);
1671 /**************************************************************************
1672 * BuildCommDCBW (KERNEL32.17)
1674 * Updates a device control block structure with values from an
1675 * unicode device control string. The device control string has two forms
1676 * normal and extended, it must be exclusively in one or the other form.
1680 * True on success, false on an malformed control string.
1682 BOOL WINAPI
BuildCommDCBW(
1683 LPCWSTR devid
, /* The unicode device control string. */
1684 LPDCB lpdcb
/* The device control block to be updated. */)
1686 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1689 /* FIXME: having these global for win32 for now */
1692 /*****************************************************************************
1693 * SetCommBreak (KERNEL32.449)
1695 * Halts the transmission of characters to a communications device.
1699 * True on success, and false if the communications device could not be found,
1700 * the control is not supported.
1704 * Only TIOCSBRK and TIOCCBRK are supported.
1706 BOOL WINAPI
SetCommBreak(
1707 HANDLE handle
/* The communictions device to suspend. */)
1709 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1712 fd
= FILE_GetUnixHandle( handle
, GENERIC_WRITE
);
1714 TRACE("FILE_GetUnixHandle failed\n");
1717 result
= ioctl(fd
,TIOCSBRK
,0);
1721 TRACE("ioctl failed\n");
1722 SetLastError(ERROR_NOT_SUPPORTED
);
1727 FIXME("ioctl not available\n");
1728 SetLastError(ERROR_NOT_SUPPORTED
);
1733 /*****************************************************************************
1734 * ClearCommBreak (KERNEL32.20)
1736 * Resumes character transmission from a communication device.
1740 * True on success and false if the communications device could not be found.
1744 * Only TIOCSBRK and TIOCCBRK are supported.
1746 BOOL WINAPI
ClearCommBreak(
1747 HANDLE handle
/* The halted communication device whose character transmission is to be resumed. */)
1749 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1752 fd
= FILE_GetUnixHandle( handle
, GENERIC_WRITE
);
1754 TRACE("FILE_GetUnixHandle failed\n");
1757 result
= ioctl(fd
,TIOCCBRK
,0);
1761 TRACE("ioctl failed\n");
1762 SetLastError(ERROR_NOT_SUPPORTED
);
1767 FIXME("ioctl not available\n");
1768 SetLastError(ERROR_NOT_SUPPORTED
);
1773 /*****************************************************************************
1774 * EscapeCommFunction (KERNEL32.214)
1776 * Directs a communication device to perform an extended function.
1780 * True or requested data on successful completion of the command,
1781 * false if the device is not present cannot execute the command
1782 * or the command failed.
1784 BOOL WINAPI
EscapeCommFunction(
1785 HANDLE handle
, /* The communication device to perform the extended function. */
1786 UINT nFunction
/* The extended function to be performed. */)
1788 int fd
,direct
=FALSE
,result
=FALSE
;
1789 struct termios port
;
1791 TRACE("handle %d, function=%d\n", handle
, nFunction
);
1792 fd
= FILE_GetUnixHandle( handle
, GENERIC_WRITE
);
1794 FIXME("handle %d not found.\n",handle
);
1798 if (tcgetattr(fd
,&port
) == -1) {
1799 commerror
=WinError();
1804 switch (nFunction
) {
1813 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1821 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1829 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1837 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1843 port
.c_iflag
|= IXOFF
;
1848 port
.c_iflag
|= IXON
;
1851 TRACE("setbreak\n");
1854 result
= ioctl(fd
,TIOCSBRK
,0);
1858 TRACE("clrbreak\n");
1861 result
= ioctl(fd
,TIOCCBRK
,0);
1865 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1871 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1872 commerror
= WinError();
1882 commerror
=WinError();
1891 /********************************************************************
1892 * PurgeComm (KERNEL32.557)
1894 * Terminates pending operations and/or discards buffers on a
1895 * communication resource.
1899 * True on success and false if the communications handle is bad.
1901 BOOL WINAPI
PurgeComm(
1902 HANDLE handle
, /* The communication resource to be purged. */
1903 DWORD flags
/* Flags for clear pending/buffer on input/output. */)
1907 TRACE("handle %d, flags %lx\n", handle
, flags
);
1909 fd
= FILE_GetUnixHandle( handle
, GENERIC_WRITE
);
1911 FIXME("no handle %d found\n",handle
);
1916 ** not exactly sure how these are different
1917 ** Perhaps if we had our own internal queues, one flushes them
1918 ** and the other flushes the kernel's buffers.
1920 if(flags
&PURGE_TXABORT
)
1921 tcflush(fd
,TCOFLUSH
);
1922 if(flags
&PURGE_RXABORT
)
1923 tcflush(fd
,TCIFLUSH
);
1924 if(flags
&PURGE_TXCLEAR
)
1925 tcflush(fd
,TCOFLUSH
);
1926 if(flags
&PURGE_RXCLEAR
)
1927 tcflush(fd
,TCIFLUSH
);
1933 /*****************************************************************************
1934 * ClearCommError (KERNEL32.21)
1936 * Enables further I/O operations on a communications resource after
1937 * supplying error and current status information.
1941 * True on success, false if the communication resource handle is bad.
1943 BOOL WINAPI
ClearCommError(
1944 HANDLE handle
, /* The communication resource with the error. */
1945 LPDWORD errors
, /* Flags indicating error the resource experienced. */
1946 LPCOMSTAT lpStat
/* The status of the communication resource. */)
1950 fd
=FILE_GetUnixHandle( handle
, GENERIC_READ
);
1953 FIXME("no handle %d found\n",handle
);
1962 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1963 WARN("ioctl returned error\n");
1965 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
1969 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
1970 WARN("ioctl returned error\n");
1973 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1974 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
1983 ** After an asynchronous write opperation, the
1984 ** app will call ClearCommError to see if the
1985 ** results are ready yet. It waits for ERROR_IO_PENDING
1987 commerror
= ERROR_IO_PENDING
;
1992 /*****************************************************************************
1993 * SetupComm (KERNEL32.676)
1995 * Called after CreateFile to hint to the communication resource to use
1996 * specified sizes for input and output buffers rather than the default values.
2000 * True if successful, false if the communications resource handle is bad.
2006 BOOL WINAPI
SetupComm(
2007 HANDLE handle
, /* The just created communication resource handle. */
2008 DWORD insize
, /* The suggested size of the communication resources input buffer in bytes. */
2009 DWORD outsize
/* The suggested size of the communication resources output buffer in bytes. */)
2013 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
2014 fd
=FILE_GetUnixHandle( handle
, GENERIC_WRITE
);
2016 FIXME("handle %d not found?\n",handle
);
2023 /*****************************************************************************
2024 * GetCommMask (KERNEL32.156)
2026 * Obtain the events associated with a communication device that will cause a call
2027 * WaitCommEvent to return.
2031 * True on success, fail on bad device handle etc.
2033 BOOL WINAPI
GetCommMask(
2034 HANDLE handle
, /* The communications device. */
2035 LPDWORD evtmask
/* The events which cause WaitCommEvent to return. */)
2039 TRACE("handle %d, mask %p\n", handle
, evtmask
);
2043 struct get_serial_info_request
*req
= server_alloc_req( sizeof(*req
), 0 );
2044 req
->handle
= handle
;
2045 if ((ret
= !server_call( REQ_GET_SERIAL_INFO
)))
2047 if (evtmask
) *evtmask
= req
->eventmask
;
2054 /*****************************************************************************
2055 * SetCommMask (KERNEL32.451)
2057 * There be some things we need to hear about yon there communications device.
2058 * (Set which events associated with a communication device should cause
2059 * a call WaitCommEvent to return.)
2063 * True on success, false on bad handle etc.
2065 BOOL WINAPI
SetCommMask(
2066 HANDLE handle
, /* The communications device. */
2067 DWORD evtmask
/* The events that to be monitored. */)
2071 TRACE("handle %d, mask %lx\n", handle
, evtmask
);
2075 struct set_serial_info_request
*req
= server_alloc_req( sizeof(*req
), 0 );
2076 req
->handle
= handle
;
2077 req
->flags
= SERIALINFO_SET_MASK
;
2078 req
->eventmask
= evtmask
;
2079 ret
= !server_call( REQ_SET_SERIAL_INFO
);
2085 /*****************************************************************************
2086 * SetCommState (KERNEL32.452)
2088 * Re-initializes all hardware and control settings of a communications device,
2089 * with values from a device control block without effecting the input and output
2094 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
2096 BOOL WINAPI
SetCommState(
2097 HANDLE handle
, /* The communications device. */
2098 LPDCB lpdcb
/* The device control block. */)
2100 struct termios port
;
2101 int fd
, bytesize
, stopbits
;
2103 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2104 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2105 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2106 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2107 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2108 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2109 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2111 fd
= FILE_GetUnixHandle( handle
, GENERIC_WRITE
);
2113 FIXME("no handle %d found\n",handle
);
2117 if ((tcgetattr(fd
,&port
)) == -1) {
2118 int save_error
= errno
;
2119 commerror
= WinError();
2121 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2125 port
.c_cc
[VMIN
] = 0;
2126 port
.c_cc
[VTIME
] = 1;
2129 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
2131 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
2133 port
.c_iflag
|= (IGNBRK
);
2135 port
.c_oflag
&= ~(OPOST
);
2137 port
.c_cflag
&= ~(HUPCL
);
2138 port
.c_cflag
|= CLOCAL
| CREAD
;
2140 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
2141 port
.c_lflag
|= NOFLSH
;
2144 ** MJM - removed default baudrate settings
2145 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2148 port
.c_cflag
&= ~CBAUD
;
2149 switch (lpdcb
->BaudRate
) {
2152 port
.c_cflag
|= B110
;
2156 port
.c_cflag
|= B300
;
2160 port
.c_cflag
|= B600
;
2164 port
.c_cflag
|= B1200
;
2168 port
.c_cflag
|= B2400
;
2172 port
.c_cflag
|= B4800
;
2176 port
.c_cflag
|= B9600
;
2180 port
.c_cflag
|= B19200
;
2184 port
.c_cflag
|= B38400
;
2188 port
.c_cflag
|= B57600
;
2193 port
.c_cflag
|= B115200
;
2198 port
.c_cflag
|= B230400
;
2203 port
.c_cflag
|= B460800
;
2207 commerror
= IE_BAUDRATE
;
2209 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2212 #elif !defined(__EMX__)
2213 switch (lpdcb
->BaudRate
) {
2216 port
.c_ospeed
= B110
;
2220 port
.c_ospeed
= B300
;
2224 port
.c_ospeed
= B600
;
2228 port
.c_ospeed
= B1200
;
2232 port
.c_ospeed
= B2400
;
2236 port
.c_ospeed
= B4800
;
2240 port
.c_ospeed
= B9600
;
2244 port
.c_ospeed
= B19200
;
2248 port
.c_ospeed
= B38400
;
2251 commerror
= IE_BAUDRATE
;
2253 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2256 port
.c_ispeed
= port
.c_ospeed
;
2258 bytesize
=lpdcb
->ByteSize
;
2259 stopbits
=lpdcb
->StopBits
;
2262 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
2264 port
.c_cflag
&= ~(PARENB
| PARODD
);
2267 port
.c_iflag
|= INPCK
;
2269 port
.c_iflag
&= ~INPCK
;
2270 switch (lpdcb
->Parity
) {
2274 port
.c_cflag
|= (PARENB
| PARODD
);
2277 port
.c_cflag
|= PARENB
;
2280 /* Linux defines mark/space (stick) parity */
2282 port
.c_cflag
|= (PARENB
| CMSPAR
);
2285 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
2288 /* try the POSIX way */
2290 if( stopbits
== ONESTOPBIT
) {
2291 stopbits
= TWOSTOPBITS
;
2292 port
.c_iflag
&= ~INPCK
;
2294 commerror
= IE_BYTESIZE
;
2296 ERR("Cannot set MARK Parity\n");
2303 port
.c_iflag
&= ~INPCK
;
2305 commerror
= IE_BYTESIZE
;
2307 ERR("Cannot set SPACE Parity\n");
2313 commerror
= IE_BYTESIZE
;
2320 port
.c_cflag
&= ~CSIZE
;
2323 port
.c_cflag
|= CS5
;
2326 port
.c_cflag
|= CS6
;
2329 port
.c_cflag
|= CS7
;
2332 port
.c_cflag
|= CS8
;
2335 commerror
= IE_BYTESIZE
;
2343 port
.c_cflag
&= ~CSTOPB
;
2345 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
2347 port
.c_cflag
|= CSTOPB
;
2350 commerror
= IE_BYTESIZE
;
2356 if ( lpdcb
->fOutxCtsFlow
||
2357 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2358 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2361 port
.c_cflag
|= CRTSCTS
;
2365 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2367 port
.c_cflag
&= ~CRTSCTS
;
2368 TRACE("~CRTSCTS\n");
2373 port
.c_iflag
|= IXON
;
2375 port
.c_iflag
&= ~IXON
;
2377 port
.c_iflag
|= IXOFF
;
2379 port
.c_iflag
&= ~IXOFF
;
2381 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
2382 int save_error
=errno
;
2383 commerror
= WinError();
2385 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2395 /*****************************************************************************
2396 * GetCommState (KERNEL32.159)
2398 * Fills in a device control block with information from a communications device.
2402 * True on success, false if the communication device handle is bad etc
2406 * XonChar and XoffChar are not set.
2408 BOOL WINAPI
GetCommState(
2409 HANDLE handle
, /* The communications device. */
2410 LPDCB lpdcb
/* The device control block. */)
2412 struct termios port
;
2415 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2417 fd
= FILE_GetUnixHandle( handle
, GENERIC_READ
);
2420 ERR("FILE_GetUnixHandle failed\n");
2423 if (tcgetattr(fd
, &port
) == -1) {
2424 int save_error
=errno
;
2425 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2426 commerror
= WinError();
2433 speed
= (port
.c_cflag
& CBAUD
);
2435 speed
= (cfgetospeed(&port
));
2439 lpdcb
->BaudRate
= 110;
2442 lpdcb
->BaudRate
= 300;
2445 lpdcb
->BaudRate
= 600;
2448 lpdcb
->BaudRate
= 1200;
2451 lpdcb
->BaudRate
= 2400;
2454 lpdcb
->BaudRate
= 4800;
2457 lpdcb
->BaudRate
= 9600;
2460 lpdcb
->BaudRate
= 19200;
2463 lpdcb
->BaudRate
= 38400;
2467 lpdcb
->BaudRate
= 57600;
2472 lpdcb
->BaudRate
= 115200;
2477 lpdcb
->BaudRate
= 230400;
2482 lpdcb
->BaudRate
= 460800;
2486 ERR("unknown speed %x \n",speed
);
2489 switch (port
.c_cflag
& CSIZE
) {
2491 lpdcb
->ByteSize
= 5;
2494 lpdcb
->ByteSize
= 6;
2497 lpdcb
->ByteSize
= 7;
2500 lpdcb
->ByteSize
= 8;
2503 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
2506 if(port
.c_iflag
& INPCK
)
2507 lpdcb
->fParity
= TRUE
;
2509 lpdcb
->fParity
= FALSE
;
2511 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
2513 switch (port
.c_cflag
& (PARENB
| PARODD
))
2517 lpdcb
->Parity
= NOPARITY
;
2520 lpdcb
->Parity
= EVENPARITY
;
2522 case (PARENB
| PARODD
):
2523 lpdcb
->Parity
= ODDPARITY
;
2526 case (PARENB
| CMSPAR
):
2527 lpdcb
->Parity
= MARKPARITY
;
2529 case (PARENB
| PARODD
| CMSPAR
):
2530 lpdcb
->Parity
= SPACEPARITY
;
2535 if (port
.c_cflag
& CSTOPB
)
2536 if(lpdcb
->ByteSize
== 5)
2537 lpdcb
->StopBits
= ONE5STOPBITS
;
2539 lpdcb
->StopBits
= TWOSTOPBITS
;
2541 lpdcb
->StopBits
= ONESTOPBIT
;
2548 if (port
.c_cflag
& CRTSCTS
) {
2549 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
2550 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
2551 lpdcb
->fOutxCtsFlow
= 1;
2552 lpdcb
->fOutxDsrFlow
= 1;
2556 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
2557 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
2559 if (port
.c_iflag
& IXON
)
2564 if (port
.c_iflag
& IXOFF
)
2573 lpdcb
->XoffLim
= 10;
2579 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2580 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2581 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2582 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2583 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2584 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2586 if ( lpdcb
->fOutxCtsFlow
||
2587 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2588 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2592 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2593 TRACE("~CRTSCTS\n");
2599 /*****************************************************************************
2600 * TransmitCommChar (KERNEL32.535)
2602 * Transmits a single character in front of any pending characters in the
2603 * output buffer. Usually used to send an interrupt character to a host.
2607 * True if the call succeeded, false if the previous command character to the
2608 * same device has not been sent yet the handle is bad etc.
2614 BOOL WINAPI
TransmitCommChar(
2615 HANDLE hComm
, /* The communication device in need of a command character. */
2616 CHAR chTransmit
/* The character to transmit. */)
2618 FIXME("(%x,'%c'), use win32 handle!\n",hComm
,chTransmit
);
2622 /*****************************************************************************
2623 * GetCommTimeouts (KERNEL32.160)
2625 * Obtains the request time out values for the communications device.
2629 * True on success, false if communications device handle is bad
2630 * or the target structure is null.
2632 BOOL WINAPI
GetCommTimeouts(
2633 HANDLE hComm
, /* The communications device. */
2634 LPCOMMTIMEOUTS lptimeouts
/* The struct of request time outs. */)
2638 TRACE("(%x,%p)\n",hComm
,lptimeouts
);
2642 SetLastError(ERROR_INVALID_PARAMETER
);
2648 struct get_serial_info_request
*req
= server_alloc_req( sizeof(*req
), 0 );
2649 req
->handle
= hComm
;
2650 if ((ret
= !server_call( REQ_GET_SERIAL_INFO
)))
2652 lptimeouts
->ReadIntervalTimeout
= req
->readinterval
;
2653 lptimeouts
->ReadTotalTimeoutMultiplier
= req
->readmult
;
2654 lptimeouts
->ReadTotalTimeoutConstant
= req
->readconst
;
2655 lptimeouts
->WriteTotalTimeoutMultiplier
= req
->writemult
;
2656 lptimeouts
->WriteTotalTimeoutConstant
= req
->writeconst
;
2663 /*****************************************************************************
2664 * SetCommTimeouts (KERNEL32.453)
2666 * Sets the timeouts used when reading and writing data to/from COMM ports.
2668 * ReadIntervalTimeout
2669 * - converted and passes to linux kernel as c_cc[VTIME]
2670 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
2671 * - used in ReadFile to calculate GetOverlappedResult's timeout
2672 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
2673 * - used in WriteFile to calculate GetOverlappedResult's timeout
2677 * True if the time outs were set, false otherwise.
2679 BOOL WINAPI
SetCommTimeouts(
2680 HANDLE hComm
, /* [in] handle of COMM device */
2681 LPCOMMTIMEOUTS lptimeouts
/* [in] pointer to COMMTIMEOUTS structure */
2685 struct termios tios
;
2687 TRACE("(%x,%p)\n",hComm
,lptimeouts
);
2691 SetLastError(ERROR_INVALID_PARAMETER
);
2697 struct set_serial_info_request
*req
= server_alloc_req( sizeof(*req
), 0 );
2698 req
->handle
= hComm
;
2699 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
2700 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
2701 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
2702 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
2703 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
2704 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
2705 ret
= !server_call( REQ_SET_SERIAL_INFO
);
2708 if (!ret
) return FALSE
;
2710 /* FIXME: move this stuff to the server */
2711 fd
= FILE_GetUnixHandle( hComm
, GENERIC_WRITE
);
2713 FIXME("no fd for handle = %0x!.\n",hComm
);
2717 if (-1==tcgetattr(fd
,&tios
)) {
2718 FIXME("tcgetattr on fd %d failed!\n",fd
);
2721 /* VTIME is in 1/10 seconds */
2722 tios
.c_cc
[VTIME
]= (lptimeouts
->ReadIntervalTimeout
+99)/100;
2723 if (-1==tcsetattr(fd
,0,&tios
)) {
2724 FIXME("tcsetattr on fd %d failed!\n",fd
);
2731 /***********************************************************************
2732 * GetCommModemStatus (KERNEL32.285)
2734 * Obtains the four control register bits if supported by the hardware.
2738 * True if the communications handle was good and for hardware that
2739 * control register access, false otherwise.
2741 BOOL WINAPI
GetCommModemStatus(
2742 HANDLE hFile
, /* The communications device. */
2743 LPDWORD lpModemStat
/* The control register bits. */)
2745 int fd
,mstat
, result
=FALSE
;
2749 fd
= FILE_GetUnixHandle( hFile
, GENERIC_WRITE
);
2752 result
= ioctl(fd
, TIOCMGET
, &mstat
);
2756 TRACE("ioctl failed\n");
2760 if (mstat
& TIOCM_CTS
)
2761 *lpModemStat
|= MS_CTS_ON
;
2764 if (mstat
& TIOCM_DSR
)
2765 *lpModemStat
|= MS_DSR_ON
;
2768 if (mstat
& TIOCM_RNG
)
2769 *lpModemStat
|= MS_RING_ON
;
2772 /*FIXME: Not really sure about RLSD UB 990810*/
2773 if (mstat
& TIOCM_CAR
)
2774 *lpModemStat
|= MS_RLSD_ON
;
2777 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
2778 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
2779 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
2780 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
2787 VOID
COMM_WaitCommEventService(void **args
)
2789 LPOVERLAPPED lpOverlapped
= (LPOVERLAPPED
)args
[0];
2790 LPDWORD buffer
= (LPDWORD
)args
[1];
2791 DWORD events
= (DWORD
)args
[2];
2793 TRACE("overlapped %p wait complete %p <- %lx\n",lpOverlapped
,buffer
,events
);
2797 lpOverlapped
->Internal
= STATUS_SUCCESS
;
2798 SetEvent( lpOverlapped
->hEvent
);
2799 CloseHandle(lpOverlapped
->InternalHigh
);
2802 /***********************************************************************
2803 * WaitCommEvent (KERNEL32.719)
2805 * Wait until something interesting happens on a COMM port.
2806 * Interesting things (events) are set by calling SetCommMask before
2807 * this function is called.
2810 * TRUE if successful
2813 * The set of detected events will be written to *lpdwEventMask
2814 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2817 * Only supports EV_RXCHAR and EV_TXEMPTY
2819 BOOL WINAPI
WaitCommEvent(
2820 HANDLE hFile
, /* [in] handle of comm port to wait for */
2821 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2822 LPOVERLAPPED lpOverlapped
/* [in/out] for Asynchronous waiting */
2828 TRACE("(%x %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
2830 /* if there is no overlapped structure, create our own */
2833 ov
.hEvent
= CreateEventA(NULL
,FALSE
,FALSE
,NULL
);
2837 lpov
= lpOverlapped
;
2839 /* check that the overlapped structure has a valid event flag */
2840 if ( (lpov
->hEvent
==0) || (lpov
->hEvent
== INVALID_HANDLE_VALUE
) )
2842 ERR("Couldn't create Event flag for Overlapped structure\n");
2843 SetLastError(ERROR_INVALID_PARAMETER
);
2847 ResetEvent(lpov
->hEvent
);
2849 lpov
->Internal
= STATUS_PENDING
;
2850 lpov
->InternalHigh
= 0;
2852 lpov
->OffsetHigh
= 0;
2854 /* start an ASYNCHRONOUS WaitCommEvent */
2857 struct create_async_request
*req
= server_alloc_req( sizeof(*req
), 0 );
2859 req
->file_handle
= hFile
;
2860 req
->overlapped
= lpov
;
2861 req
->buffer
= lpdwEvents
;
2863 req
->func
= COMM_WaitCommEventService
;
2864 req
->type
= ASYNC_TYPE_WAIT
;
2866 ret
=server_call( REQ_CREATE_ASYNC
);
2868 lpov
->InternalHigh
= req
->ov_handle
;
2875 CloseHandle(lpov
->hEvent
);
2876 TRACE("server call failed.\n");
2880 /* activate the overlapped operation */
2881 lpov
->Internal
= STATUS_PENDING
;
2883 /* wait ourselves if the caller didn't give us an overlapped struct */
2886 GetOverlappedResult(hFile
, lpov
, NULL
, TRUE
);
2887 CloseHandle(lpov
->hEvent
);
2892 /* caller wants overlapped I/O using GetOverlapped result */
2893 SetLastError(ERROR_IO_PENDING
);
2900 /***********************************************************************
2901 * GetCommProperties (KERNEL32.286)
2903 * This function fills in a structure with the capabilities of the
2904 * communications port driver.
2908 * TRUE on success, FALSE on failure
2909 * If successful, the lpCommProp structure be filled in with
2910 * properties of the comm port.
2912 BOOL WINAPI
GetCommProperties(
2913 HANDLE hFile
, /* [in] handle of the comm port */
2914 LPCOMMPROP lpCommProp
/* [out] pointer to struct to be filled */
2916 FIXME("(%d %p )\n",hFile
,lpCommProp
);
2921 * These values should be valid for LINUX's serial driver
2922 * FIXME: Perhaps they deserve an #ifdef LINUX
2924 memset(lpCommProp
,0,sizeof(COMMPROP
));
2925 lpCommProp
->wPacketLength
= 1;
2926 lpCommProp
->wPacketVersion
= 1;
2927 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
2928 lpCommProp
->dwReserved1
= 0;
2929 lpCommProp
->dwMaxTxQueue
= 4096;
2930 lpCommProp
->dwMaxRxQueue
= 4096;
2931 lpCommProp
->dwMaxBaud
= BAUD_115200
;
2932 lpCommProp
->dwProvSubType
= PST_RS232
;
2933 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
;
2934 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
2935 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
2936 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
2937 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
2938 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
2939 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
2940 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
2941 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
2942 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
2943 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
2948 /***********************************************************************
2950 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2951 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2952 * This is dependent on the type of COMM port, but since it is doubtful
2953 * anybody will get around to implementing support for fancy serial
2954 * ports in WINE, this is hardcoded for the time being. The name of
2955 * this DLL should be stored in and read from the system registry in
2956 * the hive HKEY_LOCAL_MACHINE, key
2957 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2958 * where ???? is the port number... that is determined by PNP
2959 * The DLL should be loaded when the COMM port is opened, and closed
2960 * when the COMM port is closed. - MJM 20 June 2000
2961 ***********************************************************************/
2962 static CHAR lpszSerialUI
[] = "serialui.dll";
2965 /***********************************************************************
2966 * CommConfigDialogA (KERNEL32.140)
2968 * Raises a dialog that allows the user to configure a comm port.
2969 * Fills the COMMCONFIG struct with information specified by the user.
2970 * This function should call a similar routine in the COMM driver...
2974 * TRUE on success, FALSE on failure
2975 * If successful, the lpCommConfig structure will contain a new
2976 * configuration for the comm port, as specified by the user.
2979 * The library with the CommConfigDialog code is never unloaded.
2980 * Perhaps this should be done when the comm port is closed?
2982 BOOL WINAPI
CommConfigDialogA(
2983 LPCSTR lpszDevice
, /* [in] name of communications device */
2984 HANDLE hWnd
, /* [in] parent window for the dialog */
2985 LPCOMMCONFIG lpCommConfig
/* [out] pointer to struct to fill */
2987 FARPROC lpfnCommDialog
;
2988 HMODULE hConfigModule
;
2991 TRACE("(%p %x %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2993 hConfigModule
= LoadLibraryA(lpszSerialUI
);
2997 lpfnCommDialog
= GetProcAddress(hConfigModule
, (LPCSTR
)3L);
3002 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
3004 /* UnloadLibrary(hConfigModule); */
3009 /***********************************************************************
3010 * CommConfigDialogW (KERNEL32.141)
3012 * see CommConfigDialogA for more info
3014 BOOL WINAPI
CommConfigDialogW(
3015 LPCWSTR lpszDevice
, /* [in] name of communications device */
3016 HANDLE hWnd
, /* [in] parent window for the dialog */
3017 LPCOMMCONFIG lpCommConfig
/* [out] pointer to struct to fill */
3022 lpDeviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice
);
3025 r
= CommConfigDialogA(lpDeviceA
,hWnd
,lpCommConfig
);
3026 HeapFree( GetProcessHeap(), 0, lpDeviceA
);
3030 /***********************************************************************
3031 * GetCommConfig (KERNEL32.283)
3033 * Fill in the COMMCONFIG structure for the comm port hFile
3037 * TRUE on success, FALSE on failure
3038 * If successful, lpCommConfig contains the comm port configuration.
3042 * The signature is missing a the parameter for the size of the COMMCONFIG
3043 * structure/buffer it should be
3044 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
3046 BOOL WINAPI
GetCommConfig(
3047 HANDLE hFile
, /* The communications device. */
3048 LPCOMMCONFIG lpCommConfig
/* The communications configuration of the device (if it fits). */
3049 /* LPDWORD lpdwSize Initially the size of the configuration buffer/structure,
3050 afterwards the number of bytes copied to the buffer or the needed size of the buffer. */
3054 TRACE("(%x %p)\n",hFile
,lpCommConfig
);
3056 if(lpCommConfig
== NULL
)
3059 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
3060 lpCommConfig
->wVersion
= 1;
3061 lpCommConfig
->wReserved
= 0;
3062 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
3063 lpCommConfig
->dwProviderSubType
= PST_RS232
;
3064 lpCommConfig
->dwProviderOffset
= 0;
3065 lpCommConfig
->dwProviderSize
= 0;
3070 /***********************************************************************
3071 * SetCommConfig (KERNEL32.617)
3073 * Sets the configuration of the commications device.
3077 * True on success, false if the handle was bad is not a communications device.
3079 BOOL WINAPI
SetCommConfig(
3080 HANDLE hFile
, /* The communications device. */
3081 LPCOMMCONFIG lpCommConfig
/* The desired configuration. */
3083 TRACE("(%x %p)\n",hFile
,lpCommConfig
);
3084 return SetCommState(hFile
,&lpCommConfig
->dcb
);
3087 /***********************************************************************
3088 * SetDefaultCommConfigA (KERNEL32.638)
3090 * Initializes the default configuration for the specified communication
3095 * True if the device was found and the defaults set, false otherwise
3097 BOOL WINAPI
SetDefaultCommConfigA(
3098 LPCSTR lpszDevice
, /* The ascii name of the device targeted for configuration. */
3099 LPCOMMCONFIG lpCommConfig
, /* The default configuration for the device. */
3100 DWORD dwSize
/* The number of bytes in the configuration structure. */
3102 FARPROC lpfnSetDefaultCommConfig
;
3103 HMODULE hConfigModule
;
3106 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
3108 hConfigModule
= LoadLibraryA(lpszSerialUI
);
3112 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, (LPCSTR
)4L);
3114 if(! lpfnSetDefaultCommConfig
)
3117 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
3119 /* UnloadLibrary(hConfigModule); */
3125 /***********************************************************************
3126 * SetDefaultCommConfigW (KERNEL32.639)
3128 * Initializes the default configuration for the specified
3129 * communication device. (unicode)
3134 BOOL WINAPI
SetDefaultCommConfigW(
3135 LPCWSTR lpszDevice
, /* The unicode name of the device targeted for configuration. */
3136 LPCOMMCONFIG lpCommConfig
, /* The default configuration for the device. */
3137 DWORD dwSize
/* The number of bytes in the configuration structure. */
3142 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice
),lpCommConfig
,dwSize
);
3144 lpDeviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice
);
3147 r
= SetDefaultCommConfigA(lpDeviceA
,lpCommConfig
,dwSize
);
3148 HeapFree( GetProcessHeap(), 0, lpDeviceA
);
3153 /***********************************************************************
3154 * GetDefaultCommConfigA (KERNEL32.313)
3156 * Acquires the default configuration of the specified communication device. (unicode)
3160 * True on successful reading of the default configuration,
3161 * if the device is not found or the buffer is too small.
3163 BOOL WINAPI
GetDefaultCommConfigA(
3164 LPCSTR lpszName
, /* The ascii name of the device targeted for configuration. */
3165 LPCOMMCONFIG lpCC
, /* The default configuration for the device. */
3166 LPDWORD lpdwSize
) /* Initially the size of the default configuration buffer,
3167 afterwards the number of bytes copied to the buffer or the needed size of the buffer. */
3169 LPDCB lpdcb
= &(lpCC
->dcb
);
3172 if (strncasecmp(lpszName
,"COM",3)) {
3173 ERR("not implemented for <%s>\n", lpszName
);
3177 if (!ValidCOMPort(lpszName
[3]-'1'))
3180 TRACE("(%s %p %ld)\n", lpszName
, lpCC
, *lpdwSize
);
3181 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
3182 *lpdwSize
= sizeof(COMMCONFIG
);
3186 *lpdwSize
= sizeof(COMMCONFIG
);
3188 lpCC
->dwSize
= sizeof(COMMCONFIG
);
3190 lpCC
->dwProviderSubType
= PST_RS232
;
3191 lpCC
->dwProviderOffset
= 0L;
3192 lpCC
->dwProviderSize
= 0L;
3194 (void) sprintf( temp
, "COM%c:38400,n,8,1", lpszName
[3]);
3195 FIXME("setting %s as default\n", temp
);
3197 return BuildCommDCBA( temp
, lpdcb
);
3200 /**************************************************************************
3201 * GetDefaultCommConfigW (KERNEL32.314)
3203 * Acquires the default configuration of the specified communication device. (unicode)
3207 * True on successful reading of the default configuration,
3208 * if the device is not found or the buffer is too small.
3210 BOOL WINAPI
GetDefaultCommConfigW(
3211 LPCWSTR lpszName
, /* The unicode name of the device targeted for configuration. */
3212 LPCOMMCONFIG lpCC
, /* The default configuration for the device. */
3213 LPDWORD lpdwSize
/* Initially the size of the default configuration buffer,
3214 afterwards the number of bytes copied to the buffer or the needed size of the buffer. */
3219 TRACE("(%p,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
3220 lpszNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName
);
3223 ret
=GetDefaultCommConfigA(lpszNameA
,lpCC
,lpdwSize
);
3224 HeapFree( GetProcessHeap(), 0, lpszNameA
);