2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
23 * - Fixed the modem control part of EscapeCommFunction16.
25 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
26 * - Implemented buffers and EnableCommNotification.
28 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
29 * - Use port indices instead of unixfds for win16
30 * - Moved things around (separated win16 and win32 routines)
31 * - Added some hints on how to implement buffers and EnableCommNotification.
33 * Oktober 98, Rein Klazes [RHK]
34 * A program that wants to monitor the modem status line (RLSD/DCD) may
35 * poll the modem status register in the commMask structure. I update the bit
36 * in GetCommError, waiting for an implementation of communication events.
38 * July 6, 1998. Fixes and comments by Valentijn Sessink
39 * <vsessink@ic.uva.nl> [V]
41 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
42 * <lawson_whitney@juno.com>
44 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
45 * - ptr->fd wasn't getting cleared on close.
46 * - GetCommEventMask() and GetCommError() didn't do much of anything.
47 * IMHO, they are still wrong, but they at least implement the RXCHAR
48 * event and return I/O queue sizes, which makes the app I'm interested
49 * in (analog devices EZKIT DSP development system) work.
53 #include "wine/port.h"
69 #ifdef HAVE_SYS_FILIO_H
70 # include <sys/filio.h>
72 #ifdef HAVE_SYS_IOCTL_H
73 #include <sys/ioctl.h>
78 #ifdef HAVE_SYS_POLL_H
79 # include <sys/poll.h>
81 #ifdef HAVE_SYS_MODEM_H
82 # include <sys/modem.h>
84 #ifdef HAVE_SYS_STRTIO_H
85 # include <sys/strtio.h>
88 #define NONAMELESSUNION
89 #define NONAMELESSSTRUCT
95 #include "wine/server.h"
98 #include "wine/unicode.h"
100 #include "wine/debug.h"
102 #ifdef HAVE_LINUX_SERIAL_H
103 #include <linux/serial.h>
106 WINE_DEFAULT_DEBUG_CHANNEL(comm
);
108 /* retrieve the Unix handle corresponding to a comm handle */
109 static int get_comm_fd( HANDLE handle
, DWORD access
)
113 ret
= wine_server_handle_to_fd( handle
, access
, &fd
, NULL
, NULL
);
114 if (ret
) SetLastError( RtlNtStatusToDosError(ret
) );
118 /* release the Unix handle returned by get_comm_fd */
119 static inline void release_comm_fd( HANDLE handle
, int fd
)
121 wine_server_release_fd( handle
, fd
);
125 /***********************************************************************
126 * Asynchronous I/O for asynchronous wait requests *
129 static DWORD
commio_get_async_count (const async_private
*ovp
);
130 static void commio_async_cleanup (async_private
*ovp
);
132 static async_ops commio_async_ops
=
134 commio_get_async_count
, /* get_count */
135 NULL
, /* call_completion */
136 commio_async_cleanup
/* cleanup */
139 typedef struct async_commio
141 struct async_private async
;
145 static DWORD
commio_get_async_count (const struct async_private
*ovp
)
150 static void commio_async_cleanup (async_private
*ovp
)
152 HeapFree(GetProcessHeap(), 0, ovp
);
155 /***********************************************************************/
157 #if !defined(TIOCINQ) && defined(FIONREAD)
158 #define TIOCINQ FIONREAD
161 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
164 unsigned int mstat
, okay
;
165 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
166 if (okay
) return okay
;
167 if (andy
) mstat
&= andy
;
169 return ioctl(fd
, TIOCMSET
, &mstat
);
175 /***********************************************************************
176 * COMM_Parse* (Internal)
178 * The following COMM_Parse* functions are used by the BuildCommDCB
179 * functions to help parse the various parts of the device control string.
181 static LPCWSTR
COMM_ParseStart(LPCWSTR ptr
)
183 const WCHAR comW
[] = {'C','O','M',0};
185 /* The device control string may optionally start with "COMx" followed
186 by an optional ':' and spaces. */
187 if(!strncmpiW(ptr
, comW
, 3))
191 /* Allow any com port above 0 as Win 9x does (NT only allows
192 values for com ports which are actually present) */
193 if(*ptr
< '1' || *ptr
> '9')
196 /* Advance pointer past port number */
197 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
199 /* The com port number must be followed by a ':' or ' ' */
200 if(*ptr
!= ':' && *ptr
!= ' ')
203 /* Advance pointer to beginning of next parameter */
204 while(*ptr
== ' ') ptr
++;
208 while(*ptr
== ' ') ptr
++;
211 /* The device control string must not start with a space. */
218 static LPCWSTR
COMM_ParseNumber(LPCWSTR ptr
, LPDWORD lpnumber
)
220 if(*ptr
< '0' || *ptr
> '9') return NULL
;
221 *lpnumber
= strtoulW(ptr
, NULL
, 10);
222 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
226 static LPCWSTR
COMM_ParseParity(LPCWSTR ptr
, LPBYTE lpparity
)
228 /* Contrary to what you might expect, Windows only sets the Parity
229 member of DCB and not fParity even when parity is specified in the
230 device control string */
232 switch(toupperW(*ptr
++))
235 *lpparity
= EVENPARITY
;
238 *lpparity
= MARKPARITY
;
241 *lpparity
= NOPARITY
;
244 *lpparity
= ODDPARITY
;
247 *lpparity
= SPACEPARITY
;
256 static LPCWSTR
COMM_ParseByteSize(LPCWSTR ptr
, LPBYTE lpbytesize
)
260 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
263 if(temp
>= 5 && temp
<= 8)
272 static LPCWSTR
COMM_ParseStopBits(LPCWSTR ptr
, LPBYTE lpstopbits
)
275 const WCHAR stopbits15W
[] = {'1','.','5',0};
277 if(!strncmpW(stopbits15W
, ptr
, 3))
280 *lpstopbits
= ONE5STOPBITS
;
284 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
288 *lpstopbits
= ONESTOPBIT
;
290 *lpstopbits
= TWOSTOPBITS
;
298 static LPCWSTR
COMM_ParseOnOff(LPCWSTR ptr
, LPDWORD lponoff
)
300 const WCHAR onW
[] = {'o','n',0};
301 const WCHAR offW
[] = {'o','f','f',0};
303 if(!strncmpiW(onW
, ptr
, 2))
308 else if(!strncmpiW(offW
, ptr
, 3))
319 /***********************************************************************
320 * COMM_BuildOldCommDCB (Internal)
322 * Build a DCB using the old style settings string eg: "96,n,8,1"
324 static BOOL
COMM_BuildOldCommDCB(LPCWSTR device
, LPDCB lpdcb
)
328 if(!(device
= COMM_ParseNumber(device
, &lpdcb
->BaudRate
)))
331 switch(lpdcb
->BaudRate
)
336 lpdcb
->BaudRate
*= 10;
342 lpdcb
->BaudRate
*= 100;
345 lpdcb
->BaudRate
= 19200;
349 while(*device
== ' ') device
++;
350 if(*device
++ != ',') return FALSE
;
351 while(*device
== ' ') device
++;
353 if(!(device
= COMM_ParseParity(device
, &lpdcb
->Parity
)))
356 while(*device
== ' ') device
++;
357 if(*device
++ != ',') return FALSE
;
358 while(*device
== ' ') device
++;
360 if(!(device
= COMM_ParseByteSize(device
, &lpdcb
->ByteSize
)))
363 while(*device
== ' ') device
++;
364 if(*device
++ != ',') return FALSE
;
365 while(*device
== ' ') device
++;
367 if(!(device
= COMM_ParseStopBits(device
, &lpdcb
->StopBits
)))
370 /* The last parameter for flow control is optional. */
371 while(*device
== ' ') device
++;
375 while(*device
== ' ') device
++;
376 if(*device
) last
= toupperW(*device
++);
377 while(*device
== ' ') device
++;
380 /* Win NT sets the flow control members based on (or lack of) the last
381 parameter. Win 9x does not set these members. */
386 lpdcb
->fOutX
= FALSE
;
387 lpdcb
->fOutxCtsFlow
= FALSE
;
388 lpdcb
->fOutxDsrFlow
= FALSE
;
389 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
390 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
395 lpdcb
->fOutxCtsFlow
= FALSE
;
396 lpdcb
->fOutxDsrFlow
= FALSE
;
397 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
398 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
402 lpdcb
->fOutX
= FALSE
;
403 lpdcb
->fOutxCtsFlow
= TRUE
;
404 lpdcb
->fOutxDsrFlow
= TRUE
;
405 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
406 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
412 /* This should be the end of the string. */
413 if(*device
) return FALSE
;
418 /***********************************************************************
419 * COMM_BuildNewCommDCB (Internal)
421 * Build a DCB using the new style settings string.
422 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
424 static BOOL
COMM_BuildNewCommDCB(LPCWSTR device
, LPDCB lpdcb
, LPCOMMTIMEOUTS lptimeouts
)
427 BOOL baud
= FALSE
, stop
= FALSE
;
428 const WCHAR baudW
[] = {'b','a','u','d','=',0};
429 const WCHAR parityW
[] = {'p','a','r','i','t','y','=',0};
430 const WCHAR dataW
[] = {'d','a','t','a','=',0};
431 const WCHAR stopW
[] = {'s','t','o','p','=',0};
432 const WCHAR toW
[] = {'t','o','=',0};
433 const WCHAR xonW
[] = {'x','o','n','=',0};
434 const WCHAR odsrW
[] = {'o','d','s','r','=',0};
435 const WCHAR octsW
[] = {'o','c','t','s','=',0};
436 const WCHAR dtrW
[] = {'d','t','r','=',0};
437 const WCHAR rtsW
[] = {'r','t','s','=',0};
438 const WCHAR idsrW
[] = {'i','d','s','r','=',0};
442 while(*device
== ' ') device
++;
444 if(!strncmpiW(baudW
, device
, 5))
448 if(!(device
= COMM_ParseNumber(device
+ 5, &lpdcb
->BaudRate
)))
451 else if(!strncmpiW(parityW
, device
, 7))
453 if(!(device
= COMM_ParseParity(device
+ 7, &lpdcb
->Parity
)))
456 else if(!strncmpiW(dataW
, device
, 5))
458 if(!(device
= COMM_ParseByteSize(device
+ 5, &lpdcb
->ByteSize
)))
461 else if(!strncmpiW(stopW
, device
, 5))
465 if(!(device
= COMM_ParseStopBits(device
+ 5, &lpdcb
->StopBits
)))
468 else if(!strncmpiW(toW
, device
, 3))
470 if(!(device
= COMM_ParseOnOff(device
+ 3, &temp
)))
473 lptimeouts
->ReadIntervalTimeout
= 0;
474 lptimeouts
->ReadTotalTimeoutMultiplier
= 0;
475 lptimeouts
->ReadTotalTimeoutConstant
= 0;
476 lptimeouts
->WriteTotalTimeoutMultiplier
= 0;
477 lptimeouts
->WriteTotalTimeoutConstant
= temp
? 60000 : 0;
479 else if(!strncmpiW(xonW
, device
, 4))
481 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
487 else if(!strncmpiW(odsrW
, device
, 5))
489 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
492 lpdcb
->fOutxDsrFlow
= temp
;
494 else if(!strncmpiW(octsW
, device
, 5))
496 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
499 lpdcb
->fOutxCtsFlow
= temp
;
501 else if(!strncmpiW(dtrW
, device
, 4))
503 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
506 lpdcb
->fDtrControl
= temp
;
508 else if(!strncmpiW(rtsW
, device
, 4))
510 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
513 lpdcb
->fRtsControl
= temp
;
515 else if(!strncmpiW(idsrW
, device
, 5))
517 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
520 /* Win NT sets the fDsrSensitivity member based on the
521 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
522 lpdcb
->fDsrSensitivity
= temp
;
527 /* After the above parsing, the next character (if not the end of
528 the string) should be a space */
529 if(*device
&& *device
!= ' ')
533 /* If stop bits were not specified, a default is always supplied. */
536 if(baud
&& lpdcb
->BaudRate
== 110)
537 lpdcb
->StopBits
= TWOSTOPBITS
;
539 lpdcb
->StopBits
= ONESTOPBIT
;
545 /**************************************************************************
546 * BuildCommDCBA (KERNEL32.@)
548 * Updates a device control block data structure with values from an
549 * ascii device control string. The device control string has two forms
550 * normal and extended, it must be exclusively in one or the other form.
554 * True on success, false on a malformed control string.
556 BOOL WINAPI
BuildCommDCBA(
557 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
558 LPDCB lpdcb
) /* [out] The device control block to be updated. */
560 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
563 /**************************************************************************
564 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
566 * Updates a device control block data structure with values from an
567 * ascii device control string. Taking timeout values from a timeouts
568 * struct if desired by the control string.
572 * True on success, false bad handles etc.
574 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
575 LPCSTR device
, /* [in] The ascii device control string. */
576 LPDCB lpdcb
, /* [out] The device control block to be updated. */
577 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
580 UNICODE_STRING deviceW
;
582 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
583 if(device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
,device
);
584 else deviceW
.Buffer
= NULL
;
586 if(deviceW
.Buffer
) ret
= BuildCommDCBAndTimeoutsW(deviceW
.Buffer
,lpdcb
,lptimeouts
);
588 RtlFreeUnicodeString(&deviceW
);
592 /**************************************************************************
593 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
595 * Updates a device control block data structure with values from a
596 * unicode device control string. Taking timeout values from a timeouts
597 * struct if desired by the control string.
601 * True on success, false bad handles etc
603 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
604 LPCWSTR devid
, /* [in] The unicode device control string. */
605 LPDCB lpdcb
, /* [out] The device control block to be updated. */
606 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
609 COMMTIMEOUTS timeouts
;
613 TRACE("(%s,%p,%p)\n",debugstr_w(devid
),lpdcb
,lptimeouts
);
615 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
616 lpdcb
->DCBlength
= sizeof(DCB
);
618 /* Make a copy of the original data structures to work with since if
619 if there is an error in the device control string the originals
620 should not be modified (except possibly DCBlength) */
621 memcpy(&dcb
, lpdcb
, sizeof(DCB
));
622 if(lptimeouts
) memcpy(&timeouts
, lptimeouts
, sizeof(COMMTIMEOUTS
));
624 ptr
= COMM_ParseStart(ptr
);
628 else if(strchrW(ptr
, ','))
629 result
= COMM_BuildOldCommDCB(ptr
, &dcb
);
631 result
= COMM_BuildNewCommDCB(ptr
, &dcb
, &timeouts
);
635 memcpy(lpdcb
, &dcb
, sizeof(DCB
));
636 if(lptimeouts
) memcpy(lptimeouts
, &timeouts
, sizeof(COMMTIMEOUTS
));
641 WARN("Invalid device control string: %s\n", debugstr_w(devid
));
642 SetLastError(ERROR_INVALID_PARAMETER
);
647 /**************************************************************************
648 * BuildCommDCBW (KERNEL32.@)
650 * Updates a device control block structure with values from an
651 * unicode device control string. The device control string has two forms
652 * normal and extended, it must be exclusively in one or the other form.
656 * True on success, false on an malformed control string.
658 BOOL WINAPI
BuildCommDCBW(
659 LPCWSTR devid
, /* [in] The unicode device control string. */
660 LPDCB lpdcb
) /* [out] The device control block to be updated. */
662 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
665 static BOOL
COMM_SetCommError(HANDLE handle
, DWORD error
)
669 SERVER_START_REQ( set_serial_info
)
671 req
->handle
= handle
;
672 req
->flags
= SERIALINFO_SET_ERROR
;
673 req
->commerror
= error
;
674 ret
= !wine_server_call_err( req
);
680 static BOOL
COMM_GetCommError(HANDLE handle
, LPDWORD lperror
)
687 SERVER_START_REQ( get_serial_info
)
689 req
->handle
= handle
;
690 ret
= !wine_server_call_err( req
);
691 *lperror
= reply
->commerror
;
698 /*****************************************************************************
699 * SetCommBreak (KERNEL32.@)
701 * Halts the transmission of characters to a communications device.
705 * True on success, and false if the communications device could not be found,
706 * the control is not supported.
710 * Only TIOCSBRK and TIOCCBRK are supported.
712 BOOL WINAPI
SetCommBreak(
713 HANDLE handle
) /* [in] The communictions device to suspend. */
715 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
718 fd
= get_comm_fd( handle
, GENERIC_READ
);
719 if(fd
<0) return FALSE
;
720 result
= ioctl(fd
,TIOCSBRK
,0);
721 release_comm_fd( handle
, fd
);
724 TRACE("ioctl failed\n");
725 SetLastError(ERROR_NOT_SUPPORTED
);
730 FIXME("ioctl not available\n");
731 SetLastError(ERROR_NOT_SUPPORTED
);
736 /*****************************************************************************
737 * ClearCommBreak (KERNEL32.@)
739 * Resumes character transmission from a communication device.
743 * True on success and false if the communications device could not be found.
747 * Only TIOCSBRK and TIOCCBRK are supported.
749 BOOL WINAPI
ClearCommBreak(
750 HANDLE handle
) /* [in] The halted communication device whose character transmission is to be resumed. */
752 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
755 fd
= get_comm_fd( handle
, GENERIC_READ
);
756 if(fd
<0) return FALSE
;
757 result
= ioctl(fd
,TIOCCBRK
,0);
758 release_comm_fd( handle
, fd
);
761 TRACE("ioctl failed\n");
762 SetLastError(ERROR_NOT_SUPPORTED
);
767 FIXME("ioctl not available\n");
768 SetLastError(ERROR_NOT_SUPPORTED
);
773 /*****************************************************************************
774 * EscapeCommFunction (KERNEL32.@)
776 * Directs a communication device to perform an extended function.
780 * True or requested data on successful completion of the command,
781 * false if the device is not present cannot execute the command
782 * or the command failed.
784 BOOL WINAPI
EscapeCommFunction(
785 HANDLE handle
, /* [in] The communication device to perform the extended function. */
786 UINT nFunction
) /* [in] The extended function to be performed. */
788 int fd
,direct
=FALSE
,result
=FALSE
;
791 TRACE("handle %p, function=%d\n", handle
, nFunction
);
792 fd
= get_comm_fd( handle
, GENERIC_READ
);
793 if(fd
<0) return FALSE
;
795 if (tcgetattr(fd
,&port
) == -1) {
796 COMM_SetCommError(handle
,CE_IOE
);
797 release_comm_fd( handle
, fd
);
810 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
818 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
826 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
834 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
840 port
.c_iflag
|= IXOFF
;
845 port
.c_iflag
|= IXON
;
851 result
= ioctl(fd
,TIOCSBRK
,0);
858 result
= ioctl(fd
,TIOCCBRK
,0);
862 WARN("(handle=%p,nFunction=%d): Unknown function\n",
868 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
869 release_comm_fd( handle
, fd
);
870 COMM_SetCommError(handle
,CE_IOE
);
879 COMM_SetCommError(handle
,CE_IOE
);
884 release_comm_fd( handle
, fd
);
888 /********************************************************************
889 * PurgeComm (KERNEL32.@)
891 * Terminates pending operations and/or discards buffers on a
892 * communication resource.
896 * True on success and false if the communications handle is bad.
898 BOOL WINAPI
PurgeComm(
899 HANDLE handle
, /* [in] The communication resource to be purged. */
900 DWORD flags
) /* [in] Flags for clear pending/buffer on input/output. */
904 TRACE("handle %p, flags %lx\n", handle
, flags
);
906 fd
= get_comm_fd( handle
, GENERIC_READ
);
907 if(fd
<0) return FALSE
;
910 ** not exactly sure how these are different
911 ** Perhaps if we had our own internal queues, one flushes them
912 ** and the other flushes the kernel's buffers.
914 if(flags
&PURGE_TXABORT
)
915 tcflush(fd
,TCOFLUSH
);
916 if(flags
&PURGE_RXABORT
)
917 tcflush(fd
,TCIFLUSH
);
918 if(flags
&PURGE_TXCLEAR
)
919 tcflush(fd
,TCOFLUSH
);
920 if(flags
&PURGE_RXCLEAR
)
921 tcflush(fd
,TCIFLUSH
);
922 release_comm_fd( handle
, fd
);
927 /*****************************************************************************
928 * ClearCommError (KERNEL32.@)
930 * Enables further I/O operations on a communications resource after
931 * supplying error and current status information.
935 * True on success, false if the communication resource handle is bad.
937 BOOL WINAPI
ClearCommError(
938 HANDLE handle
, /* [in] The communication resource with the error. */
939 LPDWORD errors
, /* [out] Flags indicating error the resource experienced. */
940 LPCOMSTAT lpStat
) /* [out] The status of the communication resource. */
944 fd
=get_comm_fd( handle
, GENERIC_READ
);
945 if(0>fd
) return FALSE
;
949 lpStat
->fCtsHold
= 0;
950 lpStat
->fDsrHold
= 0;
951 lpStat
->fRlsdHold
= 0;
952 lpStat
->fXoffHold
= 0;
953 lpStat
->fXoffSent
= 0;
956 lpStat
->fReserved
= 0;
959 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
960 WARN("ioctl returned error\n");
962 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
966 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
967 WARN("ioctl returned error\n");
970 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
971 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
974 release_comm_fd( handle
, fd
);
976 COMM_GetCommError(handle
, errors
);
977 COMM_SetCommError(handle
, 0);
982 /*****************************************************************************
983 * SetupComm (KERNEL32.@)
985 * Called after CreateFile to hint to the communication resource to use
986 * specified sizes for input and output buffers rather than the default values.
990 * True if successful, false if the communications resource handle is bad.
996 BOOL WINAPI
SetupComm(
997 HANDLE handle
, /* [in] The just created communication resource handle. */
998 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
999 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
1003 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1004 fd
=get_comm_fd( handle
, GENERIC_READ
);
1005 if(0>fd
) return FALSE
;
1006 release_comm_fd( handle
, fd
);
1010 /*****************************************************************************
1011 * GetCommMask (KERNEL32.@)
1013 * Obtain the events associated with a communication device that will cause
1014 * a call WaitCommEvent to return.
1018 * True on success, fail on bad device handle etc.
1020 BOOL WINAPI
GetCommMask(
1021 HANDLE handle
, /* [in] The communications device. */
1022 LPDWORD evtmask
) /* [out] The events which cause WaitCommEvent to return. */
1026 TRACE("handle %p, mask %p\n", handle
, evtmask
);
1028 SERVER_START_REQ( get_serial_info
)
1030 req
->handle
= handle
;
1031 if ((ret
= !wine_server_call_err( req
)))
1033 if (evtmask
) *evtmask
= reply
->eventmask
;
1040 /*****************************************************************************
1041 * SetCommMask (KERNEL32.@)
1043 * There be some things we need to hear about yon there communications device.
1044 * (Set which events associated with a communication device should cause
1045 * a call WaitCommEvent to return.)
1049 * True on success, false on bad handle etc.
1051 BOOL WINAPI
SetCommMask(
1052 HANDLE handle
, /* [in] The communications device. */
1053 DWORD evtmask
) /* [in] The events that are to be monitored. */
1057 TRACE("handle %p, mask %lx\n", handle
, evtmask
);
1059 SERVER_START_REQ( set_serial_info
)
1061 req
->handle
= handle
;
1062 req
->flags
= SERIALINFO_SET_MASK
;
1063 req
->eventmask
= evtmask
;
1064 ret
= !wine_server_call_err( req
);
1070 /*****************************************************************************
1071 * SetCommState (KERNEL32.@)
1073 * Re-initializes all hardware and control settings of a communications device,
1074 * with values from a device control block without effecting the input and output
1079 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1081 BOOL WINAPI
SetCommState(
1082 HANDLE handle
, /* [in] The communications device. */
1083 LPDCB lpdcb
) /* [out] The device control block. */
1085 struct termios port
;
1086 int fd
, bytesize
, stopbits
;
1088 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1089 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1090 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1091 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1092 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1093 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1094 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1096 fd
= get_comm_fd( handle
, GENERIC_READ
);
1097 if (fd
< 0) return FALSE
;
1099 if ((tcgetattr(fd
,&port
)) == -1) {
1100 int save_error
= errno
;
1101 COMM_SetCommError(handle
,CE_IOE
);
1102 release_comm_fd( handle
, fd
);
1103 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1107 port
.c_cc
[VMIN
] = 0;
1108 port
.c_cc
[VTIME
] = 1;
1111 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1113 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1115 port
.c_iflag
|= (IGNBRK
);
1117 port
.c_oflag
&= ~(OPOST
);
1119 port
.c_cflag
&= ~(HUPCL
);
1120 port
.c_cflag
|= CLOCAL
| CREAD
;
1122 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1123 port
.c_lflag
|= NOFLSH
;
1126 port
.c_cflag
&= ~CBAUD
;
1127 switch (lpdcb
->BaudRate
) {
1130 port
.c_cflag
|= B110
;
1134 port
.c_cflag
|= B300
;
1138 port
.c_cflag
|= B600
;
1142 port
.c_cflag
|= B1200
;
1146 port
.c_cflag
|= B2400
;
1150 port
.c_cflag
|= B4800
;
1154 port
.c_cflag
|= B9600
;
1158 port
.c_cflag
|= B19200
;
1162 port
.c_cflag
|= B38400
;
1166 port
.c_cflag
|= B57600
;
1171 port
.c_cflag
|= B115200
;
1176 port
.c_cflag
|= B230400
;
1181 port
.c_cflag
|= B460800
;
1185 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1186 { struct serial_struct nuts
;
1188 ioctl(fd
, TIOCGSERIAL
, &nuts
);
1189 nuts
.custom_divisor
= nuts
.baud_base
/ lpdcb
->BaudRate
;
1190 if (!(nuts
.custom_divisor
)) nuts
.custom_divisor
= 1;
1191 arby
= nuts
.baud_base
/ nuts
.custom_divisor
;
1192 nuts
.flags
&= ~ASYNC_SPD_MASK
;
1193 nuts
.flags
|= ASYNC_SPD_CUST
;
1194 WARN("You (or a program acting at your behest) have specified\n"
1195 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1196 "which is as close as we can get by our present understanding of your\n"
1197 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1198 "has caused to your linux system can be undone with setserial \n"
1199 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1200 "reset it and it will probably recover.\n", lpdcb
->BaudRate
, arby
);
1201 ioctl(fd
, TIOCSSERIAL
, &nuts
);
1202 port
.c_cflag
|= B38400
;
1205 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1208 COMM_SetCommError(handle
,IE_BAUDRATE
);
1209 release_comm_fd( handle
, fd
);
1210 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1213 #elif !defined(__EMX__)
1214 switch (lpdcb
->BaudRate
) {
1217 port
.c_ospeed
= B110
;
1221 port
.c_ospeed
= B300
;
1225 port
.c_ospeed
= B600
;
1229 port
.c_ospeed
= B1200
;
1233 port
.c_ospeed
= B2400
;
1237 port
.c_ospeed
= B4800
;
1241 port
.c_ospeed
= B9600
;
1245 port
.c_ospeed
= B19200
;
1249 port
.c_ospeed
= B38400
;
1254 port
.c_cflag
|= B57600
;
1260 port
.c_cflag
|= B115200
;
1265 port
.c_cflag
|= B230400
;
1270 port
.c_cflag
|= B460800
;
1274 COMM_SetCommError(handle
,IE_BAUDRATE
);
1275 release_comm_fd( handle
, fd
);
1276 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1279 port
.c_ispeed
= port
.c_ospeed
;
1281 bytesize
=lpdcb
->ByteSize
;
1282 stopbits
=lpdcb
->StopBits
;
1285 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1287 port
.c_cflag
&= ~(PARENB
| PARODD
);
1290 port
.c_iflag
|= INPCK
;
1292 port
.c_iflag
&= ~INPCK
;
1293 switch (lpdcb
->Parity
) {
1297 port
.c_cflag
|= (PARENB
| PARODD
);
1300 port
.c_cflag
|= PARENB
;
1303 /* Linux defines mark/space (stick) parity */
1305 port
.c_cflag
|= (PARENB
| CMSPAR
);
1308 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1311 /* try the POSIX way */
1313 if( stopbits
== ONESTOPBIT
) {
1314 stopbits
= TWOSTOPBITS
;
1315 port
.c_iflag
&= ~INPCK
;
1317 COMM_SetCommError(handle
,IE_BYTESIZE
);
1318 release_comm_fd( handle
, fd
);
1319 ERR("Cannot set MARK Parity\n");
1326 port
.c_iflag
&= ~INPCK
;
1328 COMM_SetCommError(handle
,IE_BYTESIZE
);
1329 release_comm_fd( handle
, fd
);
1330 ERR("Cannot set SPACE Parity\n");
1336 COMM_SetCommError(handle
,IE_BYTESIZE
);
1337 release_comm_fd( handle
, fd
);
1343 port
.c_cflag
&= ~CSIZE
;
1346 port
.c_cflag
|= CS5
;
1349 port
.c_cflag
|= CS6
;
1352 port
.c_cflag
|= CS7
;
1355 port
.c_cflag
|= CS8
;
1358 COMM_SetCommError(handle
,IE_BYTESIZE
);
1359 release_comm_fd( handle
, fd
);
1366 port
.c_cflag
&= ~CSTOPB
;
1368 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
1370 port
.c_cflag
|= CSTOPB
;
1373 COMM_SetCommError(handle
,IE_BYTESIZE
);
1374 release_comm_fd( handle
, fd
);
1379 if ( lpdcb
->fOutxCtsFlow
||
1380 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1383 port
.c_cflag
|= CRTSCTS
;
1388 if (lpdcb
->fDtrControl
== DTR_CONTROL_HANDSHAKE
)
1390 WARN("DSR/DTR flow control not supported\n");
1394 port
.c_iflag
|= IXON
;
1396 port
.c_iflag
&= ~IXON
;
1398 port
.c_iflag
|= IXOFF
;
1400 port
.c_iflag
&= ~IXOFF
;
1402 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
1403 int save_error
=errno
;
1404 COMM_SetCommError(handle
,CE_IOE
);
1405 release_comm_fd( handle
, fd
);
1406 ERR("tcsetattr error '%s'\n", strerror(save_error
));
1409 COMM_SetCommError(handle
,0);
1410 release_comm_fd( handle
, fd
);
1416 /*****************************************************************************
1417 * GetCommState (KERNEL32.@)
1419 * Fills in a device control block with information from a communications device.
1423 * True on success, false if the communication device handle is bad etc
1427 * XonChar and XoffChar are not set.
1429 BOOL WINAPI
GetCommState(
1430 HANDLE handle
, /* [in] The communications device. */
1431 LPDCB lpdcb
) /* [out] The device control block. */
1433 struct termios port
;
1436 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1438 fd
= get_comm_fd( handle
, GENERIC_READ
);
1439 if (fd
< 0) return FALSE
;
1440 if (tcgetattr(fd
, &port
) == -1) {
1441 int save_error
=errno
;
1442 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1443 COMM_SetCommError(handle
,CE_IOE
);
1444 release_comm_fd( handle
, fd
);
1447 release_comm_fd( handle
, fd
);
1450 speed
= (port
.c_cflag
& CBAUD
);
1452 speed
= (cfgetospeed(&port
));
1456 lpdcb
->BaudRate
= 110;
1459 lpdcb
->BaudRate
= 300;
1462 lpdcb
->BaudRate
= 600;
1465 lpdcb
->BaudRate
= 1200;
1468 lpdcb
->BaudRate
= 2400;
1471 lpdcb
->BaudRate
= 4800;
1474 lpdcb
->BaudRate
= 9600;
1477 lpdcb
->BaudRate
= 19200;
1480 lpdcb
->BaudRate
= 38400;
1484 lpdcb
->BaudRate
= 57600;
1489 lpdcb
->BaudRate
= 115200;
1494 lpdcb
->BaudRate
= 230400;
1499 lpdcb
->BaudRate
= 460800;
1503 ERR("unknown speed %x \n",speed
);
1506 switch (port
.c_cflag
& CSIZE
) {
1508 lpdcb
->ByteSize
= 5;
1511 lpdcb
->ByteSize
= 6;
1514 lpdcb
->ByteSize
= 7;
1517 lpdcb
->ByteSize
= 8;
1520 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
1523 if(port
.c_iflag
& INPCK
)
1524 lpdcb
->fParity
= TRUE
;
1526 lpdcb
->fParity
= FALSE
;
1528 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1530 switch (port
.c_cflag
& (PARENB
| PARODD
))
1534 lpdcb
->Parity
= NOPARITY
;
1537 lpdcb
->Parity
= EVENPARITY
;
1539 case (PARENB
| PARODD
):
1540 lpdcb
->Parity
= ODDPARITY
;
1543 case (PARENB
| CMSPAR
):
1544 lpdcb
->Parity
= MARKPARITY
;
1546 case (PARENB
| PARODD
| CMSPAR
):
1547 lpdcb
->Parity
= SPACEPARITY
;
1552 if (port
.c_cflag
& CSTOPB
)
1553 if(lpdcb
->ByteSize
== 5)
1554 lpdcb
->StopBits
= ONE5STOPBITS
;
1556 lpdcb
->StopBits
= TWOSTOPBITS
;
1558 lpdcb
->StopBits
= ONESTOPBIT
;
1563 /* termios does not support DTR/DSR flow control */
1564 lpdcb
->fOutxDsrFlow
= 0;
1565 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1569 if (port
.c_cflag
& CRTSCTS
) {
1570 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1571 lpdcb
->fOutxCtsFlow
= 1;
1575 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1576 lpdcb
->fOutxCtsFlow
= 0;
1578 if (port
.c_iflag
& IXON
)
1583 if (port
.c_iflag
& IXOFF
)
1592 lpdcb
->XoffLim
= 10;
1594 COMM_SetCommError(handle
,0);
1598 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1599 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1600 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1601 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1602 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1603 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1605 if ( lpdcb
->fOutxCtsFlow
||
1606 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1611 TRACE("~CRTSCTS\n");
1617 /*****************************************************************************
1618 * TransmitCommChar (KERNEL32.@)
1620 * Transmits a single character in front of any pending characters in the
1621 * output buffer. Usually used to send an interrupt character to a host.
1625 * True if the call succeeded, false if the previous command character to the
1626 * same device has not been sent yet the handle is bad etc.
1632 BOOL WINAPI
TransmitCommChar(
1633 HANDLE hComm
, /* [in] The communication device in need of a command character. */
1634 CHAR chTransmit
) /* [in] The character to transmit. */
1636 WARN("(%p,'%c') not perfect!\n",hComm
,chTransmit
);
1638 return WriteFile( hComm
, &chTransmit
, 1, NULL
, NULL
);
1642 /*****************************************************************************
1643 * GetCommTimeouts (KERNEL32.@)
1645 * Obtains the request timeout values for the communications device.
1649 * True on success, false if communications device handle is bad
1650 * or the target structure is null.
1652 BOOL WINAPI
GetCommTimeouts(
1653 HANDLE hComm
, /* [in] The communications device. */
1654 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request timeouts. */
1658 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1662 SetLastError(ERROR_INVALID_PARAMETER
);
1666 SERVER_START_REQ( get_serial_info
)
1668 req
->handle
= hComm
;
1669 if ((ret
= !wine_server_call_err( req
)))
1671 lptimeouts
->ReadIntervalTimeout
= reply
->readinterval
;
1672 lptimeouts
->ReadTotalTimeoutMultiplier
= reply
->readmult
;
1673 lptimeouts
->ReadTotalTimeoutConstant
= reply
->readconst
;
1674 lptimeouts
->WriteTotalTimeoutMultiplier
= reply
->writemult
;
1675 lptimeouts
->WriteTotalTimeoutConstant
= reply
->writeconst
;
1682 /*****************************************************************************
1683 * SetCommTimeouts (KERNEL32.@)
1685 * Sets the timeouts used when reading and writing data to/from COMM ports.
1687 * ReadIntervalTimeout
1688 * - converted and passes to linux kernel as c_cc[VTIME]
1689 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1690 * - used in ReadFile to calculate GetOverlappedResult's timeout
1691 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1692 * - used in WriteFile to calculate GetOverlappedResult's timeout
1696 * True if the timeouts were set, false otherwise.
1698 BOOL WINAPI
SetCommTimeouts(
1699 HANDLE hComm
, /* [in] handle of COMM device */
1700 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
1704 struct termios tios
;
1706 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1710 SetLastError(ERROR_INVALID_PARAMETER
);
1714 SERVER_START_REQ( set_serial_info
)
1716 req
->handle
= hComm
;
1717 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
1718 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
1719 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
1720 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
1721 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
1722 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
1723 ret
= !wine_server_call_err( req
);
1726 if (!ret
) return FALSE
;
1728 /* FIXME: move this stuff to the server */
1729 fd
= get_comm_fd( hComm
, GENERIC_READ
);
1730 if (fd
< 0) return FALSE
;
1732 if (-1==tcgetattr(fd
,&tios
)) {
1733 FIXME("tcgetattr on fd %d failed!\n",fd
);
1734 release_comm_fd( hComm
, fd
);
1738 /* VTIME is in 1/10 seconds */
1740 unsigned int ux_timeout
;
1742 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
1748 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
1751 ux_timeout
= 1; /* must be at least some timeout */
1754 tios
.c_cc
[VTIME
] = ux_timeout
;
1757 if (-1==tcsetattr(fd
,0,&tios
)) {
1758 FIXME("tcsetattr on fd %d failed!\n",fd
);
1759 release_comm_fd( hComm
, fd
);
1762 release_comm_fd( hComm
, fd
);
1766 /***********************************************************************
1767 * GetCommModemStatus (KERNEL32.@)
1769 * Obtains the four control register bits if supported by the hardware.
1773 * True if the communications handle was good and for hardware that
1774 * control register access, false otherwise.
1776 BOOL WINAPI
GetCommModemStatus(
1777 HANDLE hFile
, /* [in] The communications device. */
1778 LPDWORD lpModemStat
) /* [out] The control register bits. */
1780 int fd
,mstat
, result
=FALSE
;
1784 fd
= get_comm_fd( hFile
, GENERIC_READ
);
1787 result
= ioctl(fd
, TIOCMGET
, &mstat
);
1788 release_comm_fd( hFile
, fd
);
1791 WARN("ioctl failed\n");
1795 if (mstat
& TIOCM_CTS
)
1796 *lpModemStat
|= MS_CTS_ON
;
1799 if (mstat
& TIOCM_DSR
)
1800 *lpModemStat
|= MS_DSR_ON
;
1803 if (mstat
& TIOCM_RNG
)
1804 *lpModemStat
|= MS_RING_ON
;
1807 /*FIXME: Not really sure about RLSD UB 990810*/
1808 if (mstat
& TIOCM_CAR
)
1809 *lpModemStat
|= MS_RLSD_ON
;
1811 TRACE("%04x -> %s%s%s%s\n", mstat
,
1812 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
1813 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
1814 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
1815 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
1822 /***********************************************************************
1823 * COMM_WaitCommEventService (INTERNAL)
1825 * This function is called while the client is waiting on the
1826 * server, so we can't make any server calls here.
1828 static void COMM_WaitCommEventService(async_private
*ovp
)
1830 async_commio
*commio
= (async_commio
*) ovp
;
1831 IO_STATUS_BLOCK
* iosb
= commio
->async
.iosb
;
1833 TRACE("iosb %p\n",iosb
);
1835 /* FIXME: detect other events */
1836 *commio
->buffer
= EV_RXCHAR
;
1838 iosb
->u
.Status
= STATUS_SUCCESS
;
1842 /***********************************************************************
1843 * COMM_WaitCommEvent (INTERNAL)
1845 * This function must have an lpOverlapped.
1847 static BOOL
COMM_WaitCommEvent(
1848 HANDLE hFile
, /* [in] handle of comm port to wait for */
1849 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1850 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1857 SetLastError(ERROR_INVALID_PARAMETER
);
1861 if(NtResetEvent(lpOverlapped
->hEvent
,NULL
))
1864 fd
= get_comm_fd( hFile
, GENERIC_WRITE
);
1868 ovp
= (async_commio
*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio
));
1871 release_comm_fd( hFile
, fd
);
1875 ovp
->async
.ops
= &commio_async_ops
;
1876 ovp
->async
.handle
= hFile
;
1877 ovp
->async
.fd
= fd
; /* FIXME */
1878 ovp
->async
.type
= ASYNC_TYPE_WAIT
;
1879 ovp
->async
.func
= COMM_WaitCommEventService
;
1880 ovp
->async
.event
= lpOverlapped
->hEvent
;
1881 ovp
->async
.iosb
= (IO_STATUS_BLOCK
*)lpOverlapped
;
1882 ovp
->buffer
= (char *)lpdwEvents
;
1884 lpOverlapped
->InternalHigh
= 0;
1885 lpOverlapped
->Offset
= 0;
1886 lpOverlapped
->OffsetHigh
= 0;
1888 if ( !register_new_async (&ovp
->async
) )
1889 SetLastError( ERROR_IO_PENDING
);
1894 /***********************************************************************
1895 * WaitCommEvent (KERNEL32.@)
1897 * Wait until something interesting happens on a COMM port.
1898 * Interesting things (events) are set by calling SetCommMask before
1899 * this function is called.
1902 * TRUE if successful
1905 * The set of detected events will be written to *lpdwEventMask
1906 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1909 * Only supports EV_RXCHAR and EV_TXEMPTY
1911 BOOL WINAPI
WaitCommEvent(
1912 HANDLE hFile
, /* [in] handle of comm port to wait for */
1913 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1914 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1919 TRACE("(%p %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
1922 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
1924 /* if there is no overlapped structure, create our own */
1925 ov
.hEvent
= CreateEventA(NULL
,FALSE
,FALSE
,NULL
);
1927 COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
1929 /* wait for the overlapped to complete */
1930 ret
= GetOverlappedResult(hFile
, &ov
, NULL
, TRUE
);
1931 CloseHandle(ov
.hEvent
);
1936 /***********************************************************************
1937 * GetCommProperties (KERNEL32.@)
1939 * This function fills in a structure with the capabilities of the
1940 * communications port driver.
1944 * TRUE on success, FALSE on failure
1945 * If successful, the lpCommProp structure be filled in with
1946 * properties of the comm port.
1948 BOOL WINAPI
GetCommProperties(
1949 HANDLE hFile
, /* [in] handle of the comm port */
1950 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
1952 FIXME("(%p %p )\n",hFile
,lpCommProp
);
1957 * These values should be valid for LINUX's serial driver
1958 * FIXME: Perhaps they deserve an #ifdef LINUX
1960 memset(lpCommProp
,0,sizeof(COMMPROP
));
1961 lpCommProp
->wPacketLength
= 1;
1962 lpCommProp
->wPacketVersion
= 1;
1963 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
1964 lpCommProp
->dwReserved1
= 0;
1965 lpCommProp
->dwMaxTxQueue
= 4096;
1966 lpCommProp
->dwMaxRxQueue
= 4096;
1967 lpCommProp
->dwMaxBaud
= BAUD_115200
;
1968 lpCommProp
->dwProvSubType
= PST_RS232
;
1969 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
| PCF_TOTALTIMEOUTS
;
1970 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
1971 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
1972 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
1973 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
1974 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
1975 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
1976 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
1977 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
1978 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
1979 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
1984 /***********************************************************************
1986 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1987 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1988 * This is dependent on the type of COMM port, but since it is doubtful
1989 * anybody will get around to implementing support for fancy serial
1990 * ports in WINE, this is hardcoded for the time being. The name of
1991 * this DLL should be stored in and read from the system registry in
1992 * the hive HKEY_LOCAL_MACHINE, key
1993 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1994 * where ???? is the port number... that is determined by PNP
1995 * The DLL should be loaded when the COMM port is opened, and closed
1996 * when the COMM port is closed. - MJM 20 June 2000
1997 ***********************************************************************/
1998 static CHAR lpszSerialUI
[] = "serialui.dll";
2001 /***********************************************************************
2002 * CommConfigDialogA (KERNEL32.@)
2004 * Raises a dialog that allows the user to configure a comm port.
2005 * Fills the COMMCONFIG struct with information specified by the user.
2006 * This function should call a similar routine in the COMM driver...
2010 * TRUE on success, FALSE on failure
2011 * If successful, the lpCommConfig structure will contain a new
2012 * configuration for the comm port, as specified by the user.
2015 * The library with the CommConfigDialog code is never unloaded.
2016 * Perhaps this should be done when the comm port is closed?
2018 BOOL WINAPI
CommConfigDialogA(
2019 LPCSTR lpszDevice
, /* [in] name of communications device */
2020 HANDLE hWnd
, /* [in] parent window for the dialog */
2021 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2023 FARPROC lpfnCommDialog
;
2024 HMODULE hConfigModule
;
2027 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2029 hConfigModule
= LoadLibraryA(lpszSerialUI
);
2033 lpfnCommDialog
= GetProcAddress(hConfigModule
, (LPCSTR
)3L);
2038 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2040 /* UnloadLibrary(hConfigModule); */
2045 /***********************************************************************
2046 * CommConfigDialogW (KERNEL32.@)
2048 * see CommConfigDialogA for more info
2050 BOOL WINAPI
CommConfigDialogW(
2051 LPCWSTR lpszDevice
, /* [in] name of communications device */
2052 HANDLE hWnd
, /* [in] parent window for the dialog */
2053 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2058 lpDeviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice
);
2061 r
= CommConfigDialogA(lpDeviceA
,hWnd
,lpCommConfig
);
2062 HeapFree( GetProcessHeap(), 0, lpDeviceA
);
2066 /***********************************************************************
2067 * GetCommConfig (KERNEL32.@)
2069 * Fill in the COMMCONFIG structure for the comm port hFile
2073 * TRUE on success, FALSE on failure
2074 * If successful, lpCommConfig contains the comm port configuration.
2079 BOOL WINAPI
GetCommConfig(
2080 HANDLE hFile
, /* [in] The communications device. */
2081 LPCOMMCONFIG lpCommConfig
, /* [out] The communications configuration of the device (if it fits). */
2082 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
2083 afterwards the number of bytes copied to the buffer or
2084 the needed size of the buffer. */
2088 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2090 if(lpCommConfig
== NULL
)
2092 r
= *lpdwSize
< sizeof(COMMCONFIG
); /* TRUE if not enough space */
2093 *lpdwSize
= sizeof(COMMCONFIG
);
2097 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
2098 lpCommConfig
->wVersion
= 1;
2099 lpCommConfig
->wReserved
= 0;
2100 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
2101 lpCommConfig
->dwProviderSubType
= PST_RS232
;
2102 lpCommConfig
->dwProviderOffset
= 0;
2103 lpCommConfig
->dwProviderSize
= 0;
2108 /***********************************************************************
2109 * SetCommConfig (KERNEL32.@)
2111 * Sets the configuration of the communications device.
2115 * True on success, false if the handle was bad is not a communications device.
2117 BOOL WINAPI
SetCommConfig(
2118 HANDLE hFile
, /* [in] The communications device. */
2119 LPCOMMCONFIG lpCommConfig
, /* [in] The desired configuration. */
2120 DWORD dwSize
) /* [in] size of the lpCommConfig struct */
2122 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2123 return SetCommState(hFile
,&lpCommConfig
->dcb
);
2126 /***********************************************************************
2127 * SetDefaultCommConfigA (KERNEL32.@)
2129 * Initializes the default configuration for the specified communication
2134 * True if the device was found and the defaults set, false otherwise
2136 BOOL WINAPI
SetDefaultCommConfigA(
2137 LPCSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
2138 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2139 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2141 FARPROC lpfnSetDefaultCommConfig
;
2142 HMODULE hConfigModule
;
2145 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
2147 hConfigModule
= LoadLibraryA(lpszSerialUI
);
2151 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, (LPCSTR
)4L);
2153 if(! lpfnSetDefaultCommConfig
)
2156 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
2158 /* UnloadLibrary(hConfigModule); */
2164 /***********************************************************************
2165 * SetDefaultCommConfigW (KERNEL32.@)
2167 * Initializes the default configuration for the specified
2168 * communication device. (unicode)
2173 BOOL WINAPI
SetDefaultCommConfigW(
2174 LPCWSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
2175 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2176 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2181 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice
),lpCommConfig
,dwSize
);
2183 lpDeviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice
);
2186 r
= SetDefaultCommConfigA(lpDeviceA
,lpCommConfig
,dwSize
);
2187 HeapFree( GetProcessHeap(), 0, lpDeviceA
);
2192 /***********************************************************************
2193 * GetDefaultCommConfigW (KERNEL32.@)
2195 * Acquires the default configuration of the specified communication device. (unicode)
2199 * True on successful reading of the default configuration,
2200 * if the device is not found or the buffer is too small.
2202 BOOL WINAPI
GetDefaultCommConfigW(
2203 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
2204 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2205 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2206 afterwards the number of bytes copied to the buffer or
2207 the needed size of the buffer. */
2209 LPDCB lpdcb
= &(lpCC
->dcb
);
2211 const WCHAR comW
[] = {'C','O','M',0};
2212 const WCHAR formatW
[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2214 if (strncmpiW(lpszName
,comW
,3)) {
2215 ERR("not implemented for <%s>\n", debugstr_w(lpszName
));
2219 TRACE("(%s %p %ld)\n", debugstr_w(lpszName
), lpCC
, *lpdwSize
);
2220 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
2221 *lpdwSize
= sizeof(COMMCONFIG
);
2225 *lpdwSize
= sizeof(COMMCONFIG
);
2227 lpCC
->dwSize
= sizeof(COMMCONFIG
);
2229 lpCC
->dwProviderSubType
= PST_RS232
;
2230 lpCC
->dwProviderOffset
= 0L;
2231 lpCC
->dwProviderSize
= 0L;
2233 sprintfW( temp
, formatW
, lpszName
[3]);
2234 FIXME("setting %s as default\n", debugstr_w(temp
));
2236 return BuildCommDCBW( temp
, lpdcb
);
2239 /**************************************************************************
2240 * GetDefaultCommConfigA (KERNEL32.@)
2242 * Acquires the default configuration of the specified communication device. (ascii)
2246 * True on successful reading of the default configuration,
2247 * if the device is not found or the buffer is too small.
2249 BOOL WINAPI
GetDefaultCommConfigA(
2250 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
2251 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2252 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2253 afterwards the number of bytes copied to the buffer or
2254 the needed size of the buffer. */
2257 UNICODE_STRING lpszNameW
;
2259 TRACE("(%s,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
2260 if(lpszName
) RtlCreateUnicodeStringFromAsciiz(&lpszNameW
,lpszName
);
2261 else lpszNameW
.Buffer
= NULL
;
2263 if(lpszNameW
.Buffer
) ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
2265 RtlFreeUnicodeString(&lpszNameW
);