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"
68 #ifdef HAVE_SYS_STAT_H
69 # include <sys/stat.h>
71 #ifdef HAVE_SYS_FILIO_H
72 # include <sys/filio.h>
74 #ifdef HAVE_SYS_IOCTL_H
75 #include <sys/ioctl.h>
80 #ifdef HAVE_SYS_POLL_H
81 # include <sys/poll.h>
83 #ifdef HAVE_SYS_MODEM_H
84 # include <sys/modem.h>
86 #ifdef HAVE_SYS_STRTIO_H
87 # include <sys/strtio.h>
90 #define NONAMELESSUNION
91 #define NONAMELESSSTRUCT
98 #include "wine/server.h"
99 #include "wine/unicode.h"
101 #include "wine/debug.h"
103 #ifdef HAVE_LINUX_SERIAL_H
104 #include <linux/serial.h>
107 WINE_DEFAULT_DEBUG_CHANNEL(comm
);
109 /* retrieve the Unix handle corresponding to a comm handle */
110 static int get_comm_fd( HANDLE handle
, DWORD access
)
114 ret
= wine_server_handle_to_fd( handle
, access
, &fd
, NULL
);
115 if (ret
) SetLastError( RtlNtStatusToDosError(ret
) );
119 /* release the Unix handle returned by get_comm_fd */
120 static inline void release_comm_fd( HANDLE handle
, int fd
)
122 wine_server_release_fd( handle
, fd
);
126 /***********************************************************************
127 * Asynchronous I/O for asynchronous wait requests *
130 typedef struct async_commio
133 PIO_APC_ROUTINE apc_internal
;
139 /***********************************************************************/
141 #if !defined(TIOCINQ) && defined(FIONREAD)
142 #define TIOCINQ FIONREAD
145 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
148 unsigned int mstat
, okay
;
149 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
150 if (okay
) return okay
;
151 if (andy
) mstat
&= andy
;
153 return ioctl(fd
, TIOCMSET
, &mstat
);
159 /***********************************************************************
160 * COMM_Parse* (Internal)
162 * The following COMM_Parse* functions are used by the BuildCommDCB
163 * functions to help parse the various parts of the device control string.
165 static LPCWSTR
COMM_ParseStart(LPCWSTR ptr
)
167 static const WCHAR comW
[] = {'C','O','M',0};
169 /* The device control string may optionally start with "COMx" followed
170 by an optional ':' and spaces. */
171 if(!strncmpiW(ptr
, comW
, 3))
175 /* Allow any com port above 0 as Win 9x does (NT only allows
176 values for com ports which are actually present) */
177 if(*ptr
< '1' || *ptr
> '9')
180 /* Advance pointer past port number */
181 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
183 /* The com port number must be followed by a ':' or ' ' */
184 if(*ptr
!= ':' && *ptr
!= ' ')
187 /* Advance pointer to beginning of next parameter */
188 while(*ptr
== ' ') ptr
++;
192 while(*ptr
== ' ') ptr
++;
195 /* The device control string must not start with a space. */
202 static LPCWSTR
COMM_ParseNumber(LPCWSTR ptr
, LPDWORD lpnumber
)
204 if(*ptr
< '0' || *ptr
> '9') return NULL
;
205 *lpnumber
= strtoulW(ptr
, NULL
, 10);
206 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
210 static LPCWSTR
COMM_ParseParity(LPCWSTR ptr
, LPBYTE lpparity
)
212 /* Contrary to what you might expect, Windows only sets the Parity
213 member of DCB and not fParity even when parity is specified in the
214 device control string */
216 switch(toupperW(*ptr
++))
219 *lpparity
= EVENPARITY
;
222 *lpparity
= MARKPARITY
;
225 *lpparity
= NOPARITY
;
228 *lpparity
= ODDPARITY
;
231 *lpparity
= SPACEPARITY
;
240 static LPCWSTR
COMM_ParseByteSize(LPCWSTR ptr
, LPBYTE lpbytesize
)
244 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
247 if(temp
>= 5 && temp
<= 8)
256 static LPCWSTR
COMM_ParseStopBits(LPCWSTR ptr
, LPBYTE lpstopbits
)
259 static const WCHAR stopbits15W
[] = {'1','.','5',0};
261 if(!strncmpW(stopbits15W
, ptr
, 3))
264 *lpstopbits
= ONE5STOPBITS
;
268 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
272 *lpstopbits
= ONESTOPBIT
;
274 *lpstopbits
= TWOSTOPBITS
;
282 static LPCWSTR
COMM_ParseOnOff(LPCWSTR ptr
, LPDWORD lponoff
)
284 static const WCHAR onW
[] = {'o','n',0};
285 static const WCHAR offW
[] = {'o','f','f',0};
287 if(!strncmpiW(onW
, ptr
, 2))
292 else if(!strncmpiW(offW
, ptr
, 3))
303 /***********************************************************************
304 * COMM_BuildOldCommDCB (Internal)
306 * Build a DCB using the old style settings string eg: "96,n,8,1"
308 static BOOL
COMM_BuildOldCommDCB(LPCWSTR device
, LPDCB lpdcb
)
312 if(!(device
= COMM_ParseNumber(device
, &lpdcb
->BaudRate
)))
315 switch(lpdcb
->BaudRate
)
320 lpdcb
->BaudRate
*= 10;
326 lpdcb
->BaudRate
*= 100;
329 lpdcb
->BaudRate
= 19200;
333 while(*device
== ' ') device
++;
334 if(*device
++ != ',') return FALSE
;
335 while(*device
== ' ') device
++;
337 if(!(device
= COMM_ParseParity(device
, &lpdcb
->Parity
)))
340 while(*device
== ' ') device
++;
341 if(*device
++ != ',') return FALSE
;
342 while(*device
== ' ') device
++;
344 if(!(device
= COMM_ParseByteSize(device
, &lpdcb
->ByteSize
)))
347 while(*device
== ' ') device
++;
348 if(*device
++ != ',') return FALSE
;
349 while(*device
== ' ') device
++;
351 if(!(device
= COMM_ParseStopBits(device
, &lpdcb
->StopBits
)))
354 /* The last parameter for flow control is optional. */
355 while(*device
== ' ') device
++;
359 while(*device
== ' ') device
++;
360 if(*device
) last
= toupperW(*device
++);
361 while(*device
== ' ') device
++;
364 /* Win NT sets the flow control members based on (or lack of) the last
365 parameter. Win 9x does not set these members. */
370 lpdcb
->fOutX
= FALSE
;
371 lpdcb
->fOutxCtsFlow
= FALSE
;
372 lpdcb
->fOutxDsrFlow
= FALSE
;
373 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
374 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
379 lpdcb
->fOutxCtsFlow
= FALSE
;
380 lpdcb
->fOutxDsrFlow
= FALSE
;
381 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
382 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
386 lpdcb
->fOutX
= FALSE
;
387 lpdcb
->fOutxCtsFlow
= TRUE
;
388 lpdcb
->fOutxDsrFlow
= TRUE
;
389 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
390 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
396 /* This should be the end of the string. */
397 if(*device
) return FALSE
;
402 /***********************************************************************
403 * COMM_BuildNewCommDCB (Internal)
405 * Build a DCB using the new style settings string.
406 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
408 static BOOL
COMM_BuildNewCommDCB(LPCWSTR device
, LPDCB lpdcb
, LPCOMMTIMEOUTS lptimeouts
)
411 BOOL baud
= FALSE
, stop
= FALSE
;
412 static const WCHAR baudW
[] = {'b','a','u','d','=',0};
413 static const WCHAR parityW
[] = {'p','a','r','i','t','y','=',0};
414 static const WCHAR dataW
[] = {'d','a','t','a','=',0};
415 static const WCHAR stopW
[] = {'s','t','o','p','=',0};
416 static const WCHAR toW
[] = {'t','o','=',0};
417 static const WCHAR xonW
[] = {'x','o','n','=',0};
418 static const WCHAR odsrW
[] = {'o','d','s','r','=',0};
419 static const WCHAR octsW
[] = {'o','c','t','s','=',0};
420 static const WCHAR dtrW
[] = {'d','t','r','=',0};
421 static const WCHAR rtsW
[] = {'r','t','s','=',0};
422 static const WCHAR idsrW
[] = {'i','d','s','r','=',0};
426 while(*device
== ' ') device
++;
428 if(!strncmpiW(baudW
, device
, 5))
432 if(!(device
= COMM_ParseNumber(device
+ 5, &lpdcb
->BaudRate
)))
435 else if(!strncmpiW(parityW
, device
, 7))
437 if(!(device
= COMM_ParseParity(device
+ 7, &lpdcb
->Parity
)))
440 else if(!strncmpiW(dataW
, device
, 5))
442 if(!(device
= COMM_ParseByteSize(device
+ 5, &lpdcb
->ByteSize
)))
445 else if(!strncmpiW(stopW
, device
, 5))
449 if(!(device
= COMM_ParseStopBits(device
+ 5, &lpdcb
->StopBits
)))
452 else if(!strncmpiW(toW
, device
, 3))
454 if(!(device
= COMM_ParseOnOff(device
+ 3, &temp
)))
457 lptimeouts
->ReadIntervalTimeout
= 0;
458 lptimeouts
->ReadTotalTimeoutMultiplier
= 0;
459 lptimeouts
->ReadTotalTimeoutConstant
= 0;
460 lptimeouts
->WriteTotalTimeoutMultiplier
= 0;
461 lptimeouts
->WriteTotalTimeoutConstant
= temp
? 60000 : 0;
463 else if(!strncmpiW(xonW
, device
, 4))
465 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
471 else if(!strncmpiW(odsrW
, device
, 5))
473 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
476 lpdcb
->fOutxDsrFlow
= temp
;
478 else if(!strncmpiW(octsW
, device
, 5))
480 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
483 lpdcb
->fOutxCtsFlow
= temp
;
485 else if(!strncmpiW(dtrW
, device
, 4))
487 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
490 lpdcb
->fDtrControl
= temp
;
492 else if(!strncmpiW(rtsW
, device
, 4))
494 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
497 lpdcb
->fRtsControl
= temp
;
499 else if(!strncmpiW(idsrW
, device
, 5))
501 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
504 /* Win NT sets the fDsrSensitivity member based on the
505 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
506 lpdcb
->fDsrSensitivity
= temp
;
511 /* After the above parsing, the next character (if not the end of
512 the string) should be a space */
513 if(*device
&& *device
!= ' ')
517 /* If stop bits were not specified, a default is always supplied. */
520 if(baud
&& lpdcb
->BaudRate
== 110)
521 lpdcb
->StopBits
= TWOSTOPBITS
;
523 lpdcb
->StopBits
= ONESTOPBIT
;
529 /**************************************************************************
530 * BuildCommDCBA (KERNEL32.@)
532 * Updates a device control block data structure with values from an
533 * ascii device control string. The device control string has two forms
534 * normal and extended, it must be exclusively in one or the other form.
538 * True on success, false on a malformed control string.
540 BOOL WINAPI
BuildCommDCBA(
541 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
542 LPDCB lpdcb
) /* [out] The device control block to be updated. */
544 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
547 /**************************************************************************
548 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
550 * Updates a device control block data structure with values from an
551 * ascii device control string. Taking timeout values from a timeouts
552 * struct if desired by the control string.
556 * True on success, false bad handles etc.
558 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
559 LPCSTR device
, /* [in] The ascii device control string. */
560 LPDCB lpdcb
, /* [out] The device control block to be updated. */
561 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
564 UNICODE_STRING deviceW
;
566 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
567 if(device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
,device
);
568 else deviceW
.Buffer
= NULL
;
570 if(deviceW
.Buffer
) ret
= BuildCommDCBAndTimeoutsW(deviceW
.Buffer
,lpdcb
,lptimeouts
);
572 RtlFreeUnicodeString(&deviceW
);
576 /**************************************************************************
577 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
579 * Updates a device control block data structure with values from a
580 * unicode device control string. Taking timeout values from a timeouts
581 * struct if desired by the control string.
585 * True on success, false bad handles etc
587 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
588 LPCWSTR devid
, /* [in] The unicode device control string. */
589 LPDCB lpdcb
, /* [out] The device control block to be updated. */
590 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
593 COMMTIMEOUTS timeouts
;
597 TRACE("(%s,%p,%p)\n",debugstr_w(devid
),lpdcb
,lptimeouts
);
599 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
600 lpdcb
->DCBlength
= sizeof(DCB
);
602 /* Make a copy of the original data structures to work with since if
603 if there is an error in the device control string the originals
604 should not be modified (except possibly DCBlength) */
605 memcpy(&dcb
, lpdcb
, sizeof(DCB
));
606 if(lptimeouts
) memcpy(&timeouts
, lptimeouts
, sizeof(COMMTIMEOUTS
));
608 ptr
= COMM_ParseStart(ptr
);
612 else if(strchrW(ptr
, ','))
613 result
= COMM_BuildOldCommDCB(ptr
, &dcb
);
615 result
= COMM_BuildNewCommDCB(ptr
, &dcb
, &timeouts
);
619 memcpy(lpdcb
, &dcb
, sizeof(DCB
));
620 if(lptimeouts
) memcpy(lptimeouts
, &timeouts
, sizeof(COMMTIMEOUTS
));
625 WARN("Invalid device control string: %s\n", debugstr_w(devid
));
626 SetLastError(ERROR_INVALID_PARAMETER
);
631 /**************************************************************************
632 * BuildCommDCBW (KERNEL32.@)
634 * Updates a device control block structure with values from an
635 * unicode device control string. The device control string has two forms
636 * normal and extended, it must be exclusively in one or the other form.
640 * True on success, false on a malformed control string.
642 BOOL WINAPI
BuildCommDCBW(
643 LPCWSTR devid
, /* [in] The unicode device control string. */
644 LPDCB lpdcb
) /* [out] The device control block to be updated. */
646 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
649 static BOOL
COMM_SetCommError(HANDLE handle
, DWORD error
)
653 SERVER_START_REQ( set_serial_info
)
655 req
->handle
= handle
;
656 req
->flags
= SERIALINFO_SET_ERROR
;
657 req
->commerror
= error
;
658 ret
= !wine_server_call_err( req
);
664 static BOOL
COMM_GetCommError(HANDLE handle
, LPDWORD lperror
)
671 SERVER_START_REQ( get_serial_info
)
673 req
->handle
= handle
;
674 ret
= !wine_server_call_err( req
);
675 *lperror
= reply
->commerror
;
682 /*****************************************************************************
683 * SetCommBreak (KERNEL32.@)
685 * Halts the transmission of characters to a communications device.
689 * True on success, and false if the communications device could not be found,
690 * the control is not supported.
694 * Only TIOCSBRK and TIOCCBRK are supported.
696 BOOL WINAPI
SetCommBreak(
697 HANDLE handle
) /* [in] The communications device to suspend. */
699 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
702 fd
= get_comm_fd( handle
, GENERIC_READ
);
703 if(fd
<0) return FALSE
;
704 result
= ioctl(fd
,TIOCSBRK
,0);
705 release_comm_fd( handle
, fd
);
708 TRACE("ioctl failed\n");
709 SetLastError(ERROR_NOT_SUPPORTED
);
714 FIXME("ioctl not available\n");
715 SetLastError(ERROR_NOT_SUPPORTED
);
720 /*****************************************************************************
721 * ClearCommBreak (KERNEL32.@)
723 * Resumes character transmission from a communication device.
727 * True on success and false if the communications device could not be found.
731 * Only TIOCSBRK and TIOCCBRK are supported.
733 BOOL WINAPI
ClearCommBreak(
734 HANDLE handle
) /* [in] The halted communication device whose character transmission is to be resumed. */
736 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
739 fd
= get_comm_fd( handle
, GENERIC_READ
);
740 if(fd
<0) return FALSE
;
741 result
= ioctl(fd
,TIOCCBRK
,0);
742 release_comm_fd( handle
, fd
);
745 TRACE("ioctl failed\n");
746 SetLastError(ERROR_NOT_SUPPORTED
);
751 FIXME("ioctl not available\n");
752 SetLastError(ERROR_NOT_SUPPORTED
);
757 /*****************************************************************************
758 * EscapeCommFunction (KERNEL32.@)
760 * Directs a communication device to perform an extended function.
764 * True or requested data on successful completion of the command,
765 * false if the device is not present cannot execute the command
766 * or the command failed.
768 BOOL WINAPI
EscapeCommFunction(
769 HANDLE handle
, /* [in] The communication device to perform the extended function. */
770 UINT nFunction
) /* [in] The extended function to be performed. */
772 int fd
,direct
=FALSE
,result
=FALSE
;
775 TRACE("handle %p, function=%d\n", handle
, nFunction
);
776 fd
= get_comm_fd( handle
, GENERIC_READ
);
777 if(fd
<0) return FALSE
;
779 if (tcgetattr(fd
,&port
) == -1) {
780 COMM_SetCommError(handle
,CE_IOE
);
781 release_comm_fd( handle
, fd
);
794 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
802 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
810 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
818 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
824 port
.c_iflag
|= IXOFF
;
829 port
.c_iflag
|= IXON
;
835 result
= ioctl(fd
,TIOCSBRK
,0);
842 result
= ioctl(fd
,TIOCCBRK
,0);
846 WARN("(handle=%p,nFunction=%d): Unknown function\n",
852 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
853 release_comm_fd( handle
, fd
);
854 COMM_SetCommError(handle
,CE_IOE
);
863 COMM_SetCommError(handle
,CE_IOE
);
868 release_comm_fd( handle
, fd
);
872 /********************************************************************
873 * PurgeComm (KERNEL32.@)
875 * Terminates pending operations and/or discards buffers on a
876 * communication resource.
880 * True on success and false if the communications handle is bad.
882 BOOL WINAPI
PurgeComm(
883 HANDLE handle
, /* [in] The communication resource to be purged. */
884 DWORD flags
) /* [in] Flags for clear pending/buffer on input/output. */
888 TRACE("handle %p, flags %lx\n", handle
, flags
);
890 fd
= get_comm_fd( handle
, GENERIC_READ
);
891 if(fd
<0) return FALSE
;
894 ** not exactly sure how these are different
895 ** Perhaps if we had our own internal queues, one flushes them
896 ** and the other flushes the kernel's buffers.
898 if(flags
&PURGE_TXABORT
)
899 tcflush(fd
,TCOFLUSH
);
900 if(flags
&PURGE_RXABORT
)
901 tcflush(fd
,TCIFLUSH
);
902 if(flags
&PURGE_TXCLEAR
)
903 tcflush(fd
,TCOFLUSH
);
904 if(flags
&PURGE_RXCLEAR
)
905 tcflush(fd
,TCIFLUSH
);
906 release_comm_fd( handle
, fd
);
911 /*****************************************************************************
912 * ClearCommError (KERNEL32.@)
914 * Enables further I/O operations on a communications resource after
915 * supplying error and current status information.
919 * True on success, false if the communication resource handle is bad.
921 BOOL WINAPI
ClearCommError(
922 HANDLE handle
, /* [in] The communication resource with the error. */
923 LPDWORD errors
, /* [out] Flags indicating error the resource experienced. */
924 LPCOMSTAT lpStat
) /* [out] The status of the communication resource. */
928 fd
=get_comm_fd( handle
, GENERIC_READ
);
929 if(0>fd
) return FALSE
;
933 lpStat
->fCtsHold
= 0;
934 lpStat
->fDsrHold
= 0;
935 lpStat
->fRlsdHold
= 0;
936 lpStat
->fXoffHold
= 0;
937 lpStat
->fXoffSent
= 0;
940 lpStat
->fReserved
= 0;
943 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
944 WARN("ioctl returned error\n");
946 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
950 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
951 WARN("ioctl returned error\n");
954 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
955 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
958 release_comm_fd( handle
, fd
);
960 COMM_GetCommError(handle
, errors
);
961 COMM_SetCommError(handle
, 0);
966 /*****************************************************************************
967 * SetupComm (KERNEL32.@)
969 * Called after CreateFile to hint to the communication resource to use
970 * specified sizes for input and output buffers rather than the default values.
974 * True if successful, false if the communications resource handle is bad.
980 BOOL WINAPI
SetupComm(
981 HANDLE handle
, /* [in] The just created communication resource handle. */
982 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
983 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
987 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
988 fd
=get_comm_fd( handle
, GENERIC_READ
);
989 if(0>fd
) return FALSE
;
990 release_comm_fd( handle
, fd
);
994 /*****************************************************************************
995 * GetCommMask (KERNEL32.@)
997 * Obtain the events associated with a communication device that will cause
998 * a call WaitCommEvent to return.
1002 * True on success, fail on bad device handle etc.
1004 BOOL WINAPI
GetCommMask(
1005 HANDLE handle
, /* [in] The communications device. */
1006 LPDWORD evtmask
) /* [out] The events which cause WaitCommEvent to return. */
1010 TRACE("handle %p, mask %p\n", handle
, evtmask
);
1012 SERVER_START_REQ( get_serial_info
)
1014 req
->handle
= handle
;
1015 if ((ret
= !wine_server_call_err( req
)))
1017 if (evtmask
) *evtmask
= reply
->eventmask
;
1024 /*****************************************************************************
1025 * SetCommMask (KERNEL32.@)
1027 * There be some things we need to hear about yon there communications device.
1028 * (Set which events associated with a communication device should cause
1029 * a call WaitCommEvent to return.)
1033 * True on success, false on bad handle etc.
1035 BOOL WINAPI
SetCommMask(
1036 HANDLE handle
, /* [in] The communications device. */
1037 DWORD evtmask
) /* [in] The events that are to be monitored. */
1041 TRACE("handle %p, mask %lx\n", handle
, evtmask
);
1043 SERVER_START_REQ( set_serial_info
)
1045 req
->handle
= handle
;
1046 req
->flags
= SERIALINFO_SET_MASK
;
1047 req
->eventmask
= evtmask
;
1048 ret
= !wine_server_call_err( req
);
1054 /*****************************************************************************
1055 * SetCommState (KERNEL32.@)
1057 * Re-initializes all hardware and control settings of a communications device,
1058 * with values from a device control block without effecting the input and output
1063 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1065 BOOL WINAPI
SetCommState(
1066 HANDLE handle
, /* [in] The communications device. */
1067 LPDCB lpdcb
) /* [out] The device control block. */
1069 struct termios port
;
1070 int fd
, bytesize
, stopbits
;
1073 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1074 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1075 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1076 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1077 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1078 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1079 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1080 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1081 lpdcb
->fRtsControl
);
1082 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1083 lpdcb
->fDtrControl
);
1086 fd
= get_comm_fd( handle
, GENERIC_READ
);
1087 if (fd
< 0) return FALSE
;
1089 if ((tcgetattr(fd
,&port
)) == -1) {
1090 int save_error
= errno
;
1091 COMM_SetCommError(handle
,CE_IOE
);
1092 release_comm_fd( handle
, fd
);
1093 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1097 port
.c_cc
[VMIN
] = 0;
1098 port
.c_cc
[VTIME
] = 1;
1101 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1103 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1105 port
.c_iflag
|= (IGNBRK
);
1107 port
.c_oflag
&= ~(OPOST
);
1109 port
.c_cflag
&= ~(HUPCL
);
1110 port
.c_cflag
|= CLOCAL
| CREAD
;
1112 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1113 port
.c_lflag
|= NOFLSH
;
1116 port
.c_cflag
&= ~CBAUD
;
1117 switch (lpdcb
->BaudRate
) {
1122 port
.c_cflag
|= B50
;
1125 port
.c_cflag
|= B75
;
1129 port
.c_cflag
|= B110
;
1132 port
.c_cflag
|= B134
;
1135 port
.c_cflag
|= B150
;
1138 port
.c_cflag
|= B200
;
1142 port
.c_cflag
|= B300
;
1146 port
.c_cflag
|= B600
;
1150 port
.c_cflag
|= B1200
;
1153 port
.c_cflag
|= B1800
;
1157 port
.c_cflag
|= B2400
;
1161 port
.c_cflag
|= B4800
;
1165 port
.c_cflag
|= B9600
;
1169 port
.c_cflag
|= B19200
;
1173 port
.c_cflag
|= B38400
;
1177 port
.c_cflag
|= B57600
;
1182 port
.c_cflag
|= B115200
;
1187 port
.c_cflag
|= B230400
;
1192 port
.c_cflag
|= B460800
;
1196 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1197 { struct serial_struct nuts
;
1199 ioctl(fd
, TIOCGSERIAL
, &nuts
);
1200 nuts
.custom_divisor
= nuts
.baud_base
/ lpdcb
->BaudRate
;
1201 if (!(nuts
.custom_divisor
)) nuts
.custom_divisor
= 1;
1202 arby
= nuts
.baud_base
/ nuts
.custom_divisor
;
1203 nuts
.flags
&= ~ASYNC_SPD_MASK
;
1204 nuts
.flags
|= ASYNC_SPD_CUST
;
1205 WARN("You (or a program acting at your behest) have specified\n"
1206 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1207 "which is as close as we can get by our present understanding of your\n"
1208 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1209 "has caused to your linux system can be undone with setserial \n"
1210 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1211 "reset it and it will probably recover.\n", lpdcb
->BaudRate
, arby
);
1212 ioctl(fd
, TIOCSSERIAL
, &nuts
);
1213 port
.c_cflag
|= B38400
;
1216 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1219 COMM_SetCommError(handle
,IE_BAUDRATE
);
1220 release_comm_fd( handle
, fd
);
1221 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1224 #elif !defined(__EMX__)
1225 switch (lpdcb
->BaudRate
) {
1230 port
.c_ospeed
= B50
;
1233 port
.c_ospeed
= B75
;
1237 port
.c_ospeed
= B110
;
1240 port
.c_ospeed
= B134
;
1243 port
.c_ospeed
= B150
;
1246 port
.c_ospeed
= B200
;
1250 port
.c_ospeed
= B300
;
1254 port
.c_ospeed
= B600
;
1258 port
.c_ospeed
= B1200
;
1261 port
.c_ospeed
= B1800
;
1265 port
.c_ospeed
= B2400
;
1269 port
.c_ospeed
= B4800
;
1273 port
.c_ospeed
= B9600
;
1277 port
.c_ospeed
= B19200
;
1281 port
.c_ospeed
= B38400
;
1286 port
.c_cflag
|= B57600
;
1292 port
.c_cflag
|= B115200
;
1297 port
.c_cflag
|= B230400
;
1302 port
.c_cflag
|= B460800
;
1306 COMM_SetCommError(handle
,IE_BAUDRATE
);
1307 release_comm_fd( handle
, fd
);
1308 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1311 port
.c_ispeed
= port
.c_ospeed
;
1313 bytesize
=lpdcb
->ByteSize
;
1314 stopbits
=lpdcb
->StopBits
;
1317 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1319 port
.c_cflag
&= ~(PARENB
| PARODD
);
1322 port
.c_iflag
|= INPCK
;
1324 port
.c_iflag
&= ~INPCK
;
1325 switch (lpdcb
->Parity
) {
1329 port
.c_cflag
|= (PARENB
| PARODD
);
1332 port
.c_cflag
|= PARENB
;
1335 /* Linux defines mark/space (stick) parity */
1337 port
.c_cflag
|= (PARENB
| CMSPAR
);
1340 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1343 /* try the POSIX way */
1345 if( stopbits
== ONESTOPBIT
) {
1346 stopbits
= TWOSTOPBITS
;
1347 port
.c_iflag
&= ~INPCK
;
1349 COMM_SetCommError(handle
,IE_BYTESIZE
);
1350 release_comm_fd( handle
, fd
);
1351 ERR("Cannot set MARK Parity\n");
1358 port
.c_iflag
&= ~INPCK
;
1360 COMM_SetCommError(handle
,IE_BYTESIZE
);
1361 release_comm_fd( handle
, fd
);
1362 ERR("Cannot set SPACE Parity\n");
1368 COMM_SetCommError(handle
,IE_BYTESIZE
);
1369 release_comm_fd( handle
, fd
);
1375 port
.c_cflag
&= ~CSIZE
;
1378 port
.c_cflag
|= CS5
;
1381 port
.c_cflag
|= CS6
;
1384 port
.c_cflag
|= CS7
;
1387 port
.c_cflag
|= CS8
;
1390 COMM_SetCommError(handle
,IE_BYTESIZE
);
1391 release_comm_fd( handle
, fd
);
1398 port
.c_cflag
&= ~CSTOPB
;
1400 case ONE5STOPBITS
: /* will be selected if bytesize is 5 */
1402 port
.c_cflag
|= CSTOPB
;
1405 COMM_SetCommError(handle
,IE_BYTESIZE
);
1406 release_comm_fd( handle
, fd
);
1411 if ( lpdcb
->fOutxCtsFlow
||
1412 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1415 port
.c_cflag
|= CRTSCTS
;
1421 port
.c_iflag
|= IXON
;
1423 port
.c_iflag
&= ~IXON
;
1425 port
.c_iflag
|= IXOFF
;
1427 port
.c_iflag
&= ~IXOFF
;
1429 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
1430 ERR("tcsetattr error '%s'\n", strerror(errno
));
1431 COMM_SetCommError(handle
,CE_IOE
);
1434 COMM_SetCommError(handle
,0);
1438 /* note: change DTR/RTS lines after setting the comm attributes,
1439 * so flow control does not interfere. */
1441 if (lpdcb
->fDtrControl
== DTR_CONTROL_HANDSHAKE
)
1443 WARN("DSR/DTR flow control not supported\n");
1444 } else if(lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
1445 COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1447 COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1450 if(!lpdcb
->fOutxCtsFlow
)
1452 if(lpdcb
->fRtsControl
== RTS_CONTROL_DISABLE
)
1453 COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1455 COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1458 if(lpdcb
->fRtsControl
== RTS_CONTROL_TOGGLE
)
1459 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1460 release_comm_fd( handle
, fd
);
1466 /*****************************************************************************
1467 * GetCommState (KERNEL32.@)
1469 * Fills in a device control block with information from a communications device.
1473 * True on success, false if the communication device handle is bad etc
1477 * XonChar and XoffChar are not set.
1479 BOOL WINAPI
GetCommState(
1480 HANDLE handle
, /* [in] The communications device. */
1481 LPDCB lpdcb
) /* [out] The device control block. */
1483 struct termios port
;
1485 int stat
= DTR_CONTROL_ENABLE
| RTS_CONTROL_ENABLE
;
1487 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1489 fd
= get_comm_fd( handle
, GENERIC_READ
);
1490 if (fd
< 0) return FALSE
;
1491 if (tcgetattr(fd
, &port
) == -1
1493 || ioctl(fd
, TIOCMGET
, &stat
) == -1
1496 int save_error
=errno
;
1497 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error
));
1498 COMM_SetCommError(handle
,CE_IOE
);
1499 release_comm_fd( handle
, fd
);
1502 release_comm_fd( handle
, fd
);
1505 speed
= (port
.c_cflag
& CBAUD
);
1507 speed
= (cfgetospeed(&port
));
1511 lpdcb
->BaudRate
= 0;
1514 lpdcb
->BaudRate
= 50;
1517 lpdcb
->BaudRate
= 75;
1520 lpdcb
->BaudRate
= 110;
1523 lpdcb
->BaudRate
= 134;
1526 lpdcb
->BaudRate
= 150;
1529 lpdcb
->BaudRate
= 200;
1532 lpdcb
->BaudRate
= 300;
1535 lpdcb
->BaudRate
= 600;
1538 lpdcb
->BaudRate
= 1200;
1541 lpdcb
->BaudRate
= 1800;
1544 lpdcb
->BaudRate
= 2400;
1547 lpdcb
->BaudRate
= 4800;
1550 lpdcb
->BaudRate
= 9600;
1553 lpdcb
->BaudRate
= 19200;
1556 lpdcb
->BaudRate
= 38400;
1560 lpdcb
->BaudRate
= 57600;
1565 lpdcb
->BaudRate
= 115200;
1570 lpdcb
->BaudRate
= 230400;
1575 lpdcb
->BaudRate
= 460800;
1579 ERR("unknown speed %x \n",speed
);
1582 switch (port
.c_cflag
& CSIZE
) {
1584 lpdcb
->ByteSize
= 5;
1587 lpdcb
->ByteSize
= 6;
1590 lpdcb
->ByteSize
= 7;
1593 lpdcb
->ByteSize
= 8;
1596 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
1599 if(port
.c_iflag
& INPCK
)
1600 lpdcb
->fParity
= TRUE
;
1602 lpdcb
->fParity
= FALSE
;
1604 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1606 switch (port
.c_cflag
& (PARENB
| PARODD
))
1610 lpdcb
->Parity
= NOPARITY
;
1613 lpdcb
->Parity
= EVENPARITY
;
1615 case (PARENB
| PARODD
):
1616 lpdcb
->Parity
= ODDPARITY
;
1619 case (PARENB
| CMSPAR
):
1620 lpdcb
->Parity
= MARKPARITY
;
1622 case (PARENB
| PARODD
| CMSPAR
):
1623 lpdcb
->Parity
= SPACEPARITY
;
1628 if (port
.c_cflag
& CSTOPB
)
1629 if(lpdcb
->ByteSize
== 5)
1630 lpdcb
->StopBits
= ONE5STOPBITS
;
1632 lpdcb
->StopBits
= TWOSTOPBITS
;
1634 lpdcb
->StopBits
= ONESTOPBIT
;
1639 /* termios does not support DTR/DSR flow control */
1640 lpdcb
->fOutxDsrFlow
= 0;
1641 lpdcb
->fDtrControl
=
1643 !(stat
& TIOCM_DTR
) ? DTR_CONTROL_DISABLE
:
1645 DTR_CONTROL_ENABLE
;
1649 if (port
.c_cflag
& CRTSCTS
) {
1650 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1651 lpdcb
->fOutxCtsFlow
= 1;
1655 lpdcb
->fRtsControl
=
1657 !(stat
& TIOCM_RTS
) ? RTS_CONTROL_DISABLE
:
1659 RTS_CONTROL_ENABLE
;
1660 lpdcb
->fOutxCtsFlow
= 0;
1662 if (port
.c_iflag
& IXON
)
1667 if (port
.c_iflag
& IXOFF
)
1676 lpdcb
->XoffLim
= 10;
1678 COMM_SetCommError(handle
,0);
1682 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1683 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1684 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1685 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1686 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1687 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1688 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1689 lpdcb
->fRtsControl
);
1690 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1691 lpdcb
->fDtrControl
);
1693 if ( lpdcb
->fOutxCtsFlow
||
1694 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1699 TRACE("~CRTSCTS\n");
1704 /*****************************************************************************
1705 * TransmitCommChar (KERNEL32.@)
1707 * Transmits a single character in front of any pending characters in the
1708 * output buffer. Usually used to send an interrupt character to a host.
1712 * True if the call succeeded, false if the previous command character to the
1713 * same device has not been sent yet the handle is bad etc.
1719 BOOL WINAPI
TransmitCommChar(
1720 HANDLE hComm
, /* [in] The communication device in need of a command character. */
1721 CHAR chTransmit
) /* [in] The character to transmit. */
1724 WARN("(%p,'%c') not perfect!\n",hComm
,chTransmit
);
1726 return WriteFile( hComm
, &chTransmit
, 1, &w
, NULL
);
1730 /*****************************************************************************
1731 * GetCommTimeouts (KERNEL32.@)
1733 * Obtains the request timeout values for the communications device.
1737 * True on success, false if communications device handle is bad
1738 * or the target structure is null.
1740 BOOL WINAPI
GetCommTimeouts(
1741 HANDLE hComm
, /* [in] The communications device. */
1742 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request timeouts. */
1746 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1750 SetLastError(ERROR_INVALID_PARAMETER
);
1754 SERVER_START_REQ( get_serial_info
)
1756 req
->handle
= hComm
;
1757 if ((ret
= !wine_server_call_err( req
)))
1759 lptimeouts
->ReadIntervalTimeout
= reply
->readinterval
;
1760 lptimeouts
->ReadTotalTimeoutMultiplier
= reply
->readmult
;
1761 lptimeouts
->ReadTotalTimeoutConstant
= reply
->readconst
;
1762 lptimeouts
->WriteTotalTimeoutMultiplier
= reply
->writemult
;
1763 lptimeouts
->WriteTotalTimeoutConstant
= reply
->writeconst
;
1770 /*****************************************************************************
1771 * SetCommTimeouts (KERNEL32.@)
1773 * Sets the timeouts used when reading and writing data to/from COMM ports.
1775 * ReadIntervalTimeout
1776 * - converted and passes to linux kernel as c_cc[VTIME]
1777 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1778 * - used in ReadFile to calculate GetOverlappedResult's timeout
1779 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1780 * - used in WriteFile to calculate GetOverlappedResult's timeout
1784 * True if the timeouts were set, false otherwise.
1786 BOOL WINAPI
SetCommTimeouts(
1787 HANDLE hComm
, /* [in] handle of COMM device */
1788 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
1792 struct termios tios
;
1794 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1798 SetLastError(ERROR_INVALID_PARAMETER
);
1802 SERVER_START_REQ( set_serial_info
)
1804 req
->handle
= hComm
;
1805 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
1806 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
1807 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
1808 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
1809 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
1810 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
1811 ret
= !wine_server_call_err( req
);
1814 if (!ret
) return FALSE
;
1816 /* FIXME: move this stuff to the server */
1817 fd
= get_comm_fd( hComm
, GENERIC_READ
);
1818 if (fd
< 0) return FALSE
;
1820 if (-1==tcgetattr(fd
,&tios
)) {
1821 FIXME("tcgetattr on fd %d failed!\n",fd
);
1822 release_comm_fd( hComm
, fd
);
1826 /* VTIME is in 1/10 seconds */
1828 unsigned int ux_timeout
;
1830 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
1836 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
1839 ux_timeout
= 1; /* must be at least some timeout */
1842 tios
.c_cc
[VTIME
] = ux_timeout
;
1845 if (-1==tcsetattr(fd
,0,&tios
)) {
1846 FIXME("tcsetattr on fd %d failed!\n",fd
);
1847 release_comm_fd( hComm
, fd
);
1850 release_comm_fd( hComm
, fd
);
1854 /***********************************************************************
1855 * GetCommModemStatus (KERNEL32.@)
1857 * Obtains the four control register bits if supported by the hardware.
1861 * True if the communications handle was good and for hardware that
1862 * control register access, false otherwise.
1864 BOOL WINAPI
GetCommModemStatus(
1865 HANDLE hFile
, /* [in] The communications device. */
1866 LPDWORD lpModemStat
) /* [out] The control register bits. */
1868 int fd
,mstat
, result
=FALSE
;
1872 fd
= get_comm_fd( hFile
, GENERIC_READ
);
1875 result
= ioctl(fd
, TIOCMGET
, &mstat
);
1876 release_comm_fd( hFile
, fd
);
1879 WARN("ioctl failed\n");
1883 if (mstat
& TIOCM_CTS
)
1884 *lpModemStat
|= MS_CTS_ON
;
1887 if (mstat
& TIOCM_DSR
)
1888 *lpModemStat
|= MS_DSR_ON
;
1891 if (mstat
& TIOCM_RNG
)
1892 *lpModemStat
|= MS_RING_ON
;
1895 /*FIXME: Not really sure about RLSD UB 990810*/
1896 if (mstat
& TIOCM_CAR
)
1897 *lpModemStat
|= MS_RLSD_ON
;
1899 TRACE("%04x -> %s%s%s%s\n", mstat
,
1900 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
1901 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
1902 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
1903 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
1910 /***********************************************************************
1911 * COMM_WaitCommEventService (INTERNAL)
1913 * This function is called while the client is waiting on the
1914 * server, so we can't make any server calls here.
1916 static void WINAPI
COMM_WaitCommEventService(void* ovp
, IO_STATUS_BLOCK
* iosb
, ULONG status
)
1918 async_commio
*commio
= (async_commio
*) ovp
;
1920 TRACE("iosb %p\n", iosb
);
1924 case STATUS_ALERTED
: /* got some new stuff */
1925 /* FIXME: detect other events */
1926 *commio
->buffer
= EV_RXCHAR
;
1927 iosb
->u
.Status
= STATUS_SUCCESS
;
1930 iosb
->u
.Status
= status
;
1933 wine_server_release_fd( commio
->handle
, commio
->fd
);
1934 if ( ((LPOVERLAPPED
)iosb
)->hEvent
!= INVALID_HANDLE_VALUE
)
1935 NtSetEvent( ((LPOVERLAPPED
)iosb
)->hEvent
, NULL
);
1936 HeapFree(GetProcessHeap(), 0, commio
);
1940 /***********************************************************************
1941 * COMM_WaitCommEvent (INTERNAL)
1943 * This function must have an lpOverlapped.
1945 static BOOL
COMM_WaitCommEvent(
1946 HANDLE hFile
, /* [in] handle of comm port to wait for */
1947 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1948 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1951 async_commio
* commio
;
1956 SetLastError(ERROR_INVALID_PARAMETER
);
1960 if (NtResetEvent(lpOverlapped
->hEvent
,NULL
))
1963 fd
= get_comm_fd( hFile
, GENERIC_WRITE
);
1964 if (fd
< 0) return FALSE
;
1966 commio
= HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio
));
1969 release_comm_fd( hFile
, fd
);
1973 commio
->handle
= hFile
;
1974 commio
->type
= ASYNC_TYPE_WAIT
;
1975 commio
->apc_internal
= COMM_WaitCommEventService
;
1976 commio
->buffer
= (char *)lpdwEvents
;
1977 commio
->fd
= fd
; /* FIXME */
1979 lpOverlapped
->InternalHigh
= 0;
1980 lpOverlapped
->u
.s
.Offset
= 0;
1981 lpOverlapped
->u
.s
.OffsetHigh
= 0;
1983 SERVER_START_REQ( register_async
)
1985 req
->handle
= hFile
;
1986 req
->io_apc
= COMM_WaitCommEventService
;
1987 req
->io_user
= commio
;
1988 req
->io_sb
= (IO_STATUS_BLOCK
*)lpOverlapped
;
1990 status
= wine_server_call( req
);
1994 if ( status
) SetLastError( RtlNtStatusToDosError(status
) );
1995 else NtCurrentTeb()->num_async_io
++;
2000 /***********************************************************************
2001 * WaitCommEvent (KERNEL32.@)
2003 * Wait until something interesting happens on a COMM port.
2004 * Interesting things (events) are set by calling SetCommMask before
2005 * this function is called.
2008 * TRUE if successful
2011 * The set of detected events will be written to *lpdwEventMask
2012 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2015 * Only supports EV_RXCHAR and EV_TXEMPTY
2017 BOOL WINAPI
WaitCommEvent(
2018 HANDLE hFile
, /* [in] handle of comm port to wait for */
2019 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2020 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2025 TRACE("(%p %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
2028 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
2030 /* if there is no overlapped structure, create our own */
2031 ov
.hEvent
= CreateEventW(NULL
,FALSE
,FALSE
,NULL
);
2033 COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
2035 /* wait for the overlapped to complete */
2036 ret
= GetOverlappedResult(hFile
, &ov
, NULL
, TRUE
);
2037 CloseHandle(ov
.hEvent
);
2042 /***********************************************************************
2043 * GetCommProperties (KERNEL32.@)
2045 * This function fills in a structure with the capabilities of the
2046 * communications port driver.
2050 * TRUE on success, FALSE on failure
2051 * If successful, the lpCommProp structure be filled in with
2052 * properties of the comm port.
2054 BOOL WINAPI
GetCommProperties(
2055 HANDLE hFile
, /* [in] handle of the comm port */
2056 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
2058 FIXME("(%p %p )\n",hFile
,lpCommProp
);
2063 * These values should be valid for LINUX's serial driver
2064 * FIXME: Perhaps they deserve an #ifdef LINUX
2066 memset(lpCommProp
,0,sizeof(COMMPROP
));
2067 lpCommProp
->wPacketLength
= 1;
2068 lpCommProp
->wPacketVersion
= 1;
2069 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
2070 lpCommProp
->dwReserved1
= 0;
2071 lpCommProp
->dwMaxTxQueue
= 4096;
2072 lpCommProp
->dwMaxRxQueue
= 4096;
2073 lpCommProp
->dwMaxBaud
= BAUD_115200
;
2074 lpCommProp
->dwProvSubType
= PST_RS232
;
2075 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
| PCF_TOTALTIMEOUTS
;
2076 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
2077 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
2078 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
2079 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
2080 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
2081 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
2082 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
2083 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
2084 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
2085 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
2090 /***********************************************************************
2092 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2093 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2094 * This is dependent on the type of COMM port, but since it is doubtful
2095 * anybody will get around to implementing support for fancy serial
2096 * ports in WINE, this is hardcoded for the time being. The name of
2097 * this DLL should be stored in and read from the system registry in
2098 * the hive HKEY_LOCAL_MACHINE, key
2099 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2100 * where ???? is the port number... that is determined by PNP
2101 * The DLL should be loaded when the COMM port is opened, and closed
2102 * when the COMM port is closed. - MJM 20 June 2000
2103 ***********************************************************************/
2104 static WCHAR lpszSerialUI
[] = {
2105 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2108 /***********************************************************************
2109 * CommConfigDialogA (KERNEL32.@)
2111 * Raises a dialog that allows the user to configure a comm port.
2112 * Fills the COMMCONFIG struct with information specified by the user.
2113 * This function should call a similar routine in the COMM driver...
2117 * TRUE on success, FALSE on failure
2118 * If successful, the lpCommConfig structure will contain a new
2119 * configuration for the comm port, as specified by the user.
2122 * The library with the CommConfigDialog code is never unloaded.
2123 * Perhaps this should be done when the comm port is closed?
2125 BOOL WINAPI
CommConfigDialogA(
2126 LPCSTR lpszDevice
, /* [in] name of communications device */
2127 HWND hWnd
, /* [in] parent window for the dialog */
2128 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2130 FARPROC lpfnCommDialog
;
2131 HMODULE hConfigModule
;
2134 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2136 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2140 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogA");
2143 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2145 FreeLibrary(hConfigModule
);
2150 /***********************************************************************
2151 * CommConfigDialogW (KERNEL32.@)
2153 * see CommConfigDialogA for more info
2155 BOOL WINAPI
CommConfigDialogW(
2156 LPCWSTR lpszDevice
, /* [in] name of communications device */
2157 HWND hWnd
, /* [in] parent window for the dialog */
2158 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2160 FARPROC lpfnCommDialog
;
2161 HMODULE hConfigModule
;
2164 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2166 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2170 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogW");
2173 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2175 FreeLibrary(hConfigModule
);
2180 /***********************************************************************
2181 * GetCommConfig (KERNEL32.@)
2183 * Fill in the COMMCONFIG structure for the comm port hFile
2187 * TRUE on success, FALSE on failure
2188 * If successful, lpCommConfig contains the comm port configuration.
2193 BOOL WINAPI
GetCommConfig(
2194 HANDLE hFile
, /* [in] The communications device. */
2195 LPCOMMCONFIG lpCommConfig
, /* [out] The communications configuration of the device (if it fits). */
2196 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
2197 afterwards the number of bytes copied to the buffer or
2198 the needed size of the buffer. */
2202 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2204 if(lpCommConfig
== NULL
)
2206 r
= *lpdwSize
< sizeof(COMMCONFIG
); /* TRUE if not enough space */
2207 *lpdwSize
= sizeof(COMMCONFIG
);
2211 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
2212 lpCommConfig
->wVersion
= 1;
2213 lpCommConfig
->wReserved
= 0;
2214 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
2215 lpCommConfig
->dwProviderSubType
= PST_RS232
;
2216 lpCommConfig
->dwProviderOffset
= 0;
2217 lpCommConfig
->dwProviderSize
= 0;
2222 /***********************************************************************
2223 * SetCommConfig (KERNEL32.@)
2225 * Sets the configuration of the communications device.
2229 * True on success, false if the handle was bad is not a communications device.
2231 BOOL WINAPI
SetCommConfig(
2232 HANDLE hFile
, /* [in] The communications device. */
2233 LPCOMMCONFIG lpCommConfig
, /* [in] The desired configuration. */
2234 DWORD dwSize
) /* [in] size of the lpCommConfig struct */
2236 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2237 return SetCommState(hFile
,&lpCommConfig
->dcb
);
2240 /***********************************************************************
2241 * SetDefaultCommConfigA (KERNEL32.@)
2243 * Initializes the default configuration for the specified communication
2248 * True if the device was found and the defaults set, false otherwise
2250 BOOL WINAPI
SetDefaultCommConfigW(
2251 LPCWSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
2252 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2253 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2255 FARPROC lpfnSetDefaultCommConfig
;
2256 HMODULE hConfigModule
;
2259 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
2261 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2265 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvSetDefaultCommConfigW");
2266 if (lpfnSetDefaultCommConfig
)
2267 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
2269 FreeLibrary(hConfigModule
);
2275 /***********************************************************************
2276 * SetDefaultCommConfigW (KERNEL32.@)
2278 * Initializes the default configuration for the specified
2279 * communication device. (unicode)
2284 BOOL WINAPI
SetDefaultCommConfigA(
2285 LPCSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
2286 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2287 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2290 LPWSTR lpDeviceW
= NULL
;
2293 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice
),lpCommConfig
,dwSize
);
2297 len
= MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, NULL
, 0 );
2298 lpDeviceW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
2299 MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, lpDeviceW
, len
);
2301 r
= SetDefaultCommConfigW(lpDeviceW
,lpCommConfig
,dwSize
);
2302 HeapFree( GetProcessHeap(), 0, lpDeviceW
);
2307 /***********************************************************************
2308 * GetDefaultCommConfigW (KERNEL32.@)
2310 * Acquires the default configuration of the specified communication device. (unicode)
2314 * True on successful reading of the default configuration,
2315 * if the device is not found or the buffer is too small.
2317 BOOL WINAPI
GetDefaultCommConfigW(
2318 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
2319 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2320 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2321 afterwards the number of bytes copied to the buffer or
2322 the needed size of the buffer. */
2324 LPDCB lpdcb
= &(lpCC
->dcb
);
2326 static const WCHAR comW
[] = {'C','O','M',0};
2327 static const WCHAR formatW
[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2329 if (strncmpiW(lpszName
,comW
,3)) {
2330 ERR("not implemented for <%s>\n", debugstr_w(lpszName
));
2334 TRACE("(%s %p %ld)\n", debugstr_w(lpszName
), lpCC
, *lpdwSize
);
2335 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
2336 *lpdwSize
= sizeof(COMMCONFIG
);
2340 *lpdwSize
= sizeof(COMMCONFIG
);
2342 lpCC
->dwSize
= sizeof(COMMCONFIG
);
2344 lpCC
->dwProviderSubType
= PST_RS232
;
2345 lpCC
->dwProviderOffset
= 0L;
2346 lpCC
->dwProviderSize
= 0L;
2348 sprintfW( temp
, formatW
, lpszName
[3]);
2349 FIXME("setting %s as default\n", debugstr_w(temp
));
2351 return BuildCommDCBW( temp
, lpdcb
);
2354 /**************************************************************************
2355 * GetDefaultCommConfigA (KERNEL32.@)
2357 * Acquires the default configuration of the specified communication device. (ascii)
2361 * True on successful reading of the default configuration,
2362 * if the device is not found or the buffer is too small.
2364 BOOL WINAPI
GetDefaultCommConfigA(
2365 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
2366 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2367 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2368 afterwards the number of bytes copied to the buffer or
2369 the needed size of the buffer. */
2372 UNICODE_STRING lpszNameW
;
2374 TRACE("(%s,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
2375 if(lpszName
) RtlCreateUnicodeStringFromAsciiz(&lpszNameW
,lpszName
);
2376 else lpszNameW
.Buffer
= NULL
;
2378 if(lpszNameW
.Buffer
) ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
2380 RtlFreeUnicodeString(&lpszNameW
);