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"
96 #include "wine/unicode.h"
99 #include "wine/debug.h"
101 #ifdef HAVE_LINUX_SERIAL_H
102 #include <linux/serial.h>
105 WINE_DEFAULT_DEBUG_CHANNEL(comm
);
107 /* retrieve the Unix handle corresponding to a comm handle */
108 static int get_comm_fd( HANDLE handle
, DWORD access
)
112 ret
= wine_server_handle_to_fd( handle
, access
, &fd
, NULL
);
113 if (ret
) SetLastError( RtlNtStatusToDosError(ret
) );
117 /* release the Unix handle returned by get_comm_fd */
118 static inline void release_comm_fd( HANDLE handle
, int fd
)
120 wine_server_release_fd( handle
, fd
);
124 /***********************************************************************
125 * Asynchronous I/O for asynchronous wait requests *
128 typedef struct async_commio
131 PIO_APC_ROUTINE apc_internal
;
137 /***********************************************************************/
139 #if !defined(TIOCINQ) && defined(FIONREAD)
140 #define TIOCINQ FIONREAD
143 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
146 unsigned int mstat
, okay
;
147 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
148 if (okay
) return okay
;
149 if (andy
) mstat
&= andy
;
151 return ioctl(fd
, TIOCMSET
, &mstat
);
157 /***********************************************************************
158 * COMM_Parse* (Internal)
160 * The following COMM_Parse* functions are used by the BuildCommDCB
161 * functions to help parse the various parts of the device control string.
163 static LPCWSTR
COMM_ParseStart(LPCWSTR ptr
)
165 static const WCHAR comW
[] = {'C','O','M',0};
167 /* The device control string may optionally start with "COMx" followed
168 by an optional ':' and spaces. */
169 if(!strncmpiW(ptr
, comW
, 3))
173 /* Allow any com port above 0 as Win 9x does (NT only allows
174 values for com ports which are actually present) */
175 if(*ptr
< '1' || *ptr
> '9')
178 /* Advance pointer past port number */
179 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
181 /* The com port number must be followed by a ':' or ' ' */
182 if(*ptr
!= ':' && *ptr
!= ' ')
185 /* Advance pointer to beginning of next parameter */
186 while(*ptr
== ' ') ptr
++;
190 while(*ptr
== ' ') ptr
++;
193 /* The device control string must not start with a space. */
200 static LPCWSTR
COMM_ParseNumber(LPCWSTR ptr
, LPDWORD lpnumber
)
202 if(*ptr
< '0' || *ptr
> '9') return NULL
;
203 *lpnumber
= strtoulW(ptr
, NULL
, 10);
204 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
208 static LPCWSTR
COMM_ParseParity(LPCWSTR ptr
, LPBYTE lpparity
)
210 /* Contrary to what you might expect, Windows only sets the Parity
211 member of DCB and not fParity even when parity is specified in the
212 device control string */
214 switch(toupperW(*ptr
++))
217 *lpparity
= EVENPARITY
;
220 *lpparity
= MARKPARITY
;
223 *lpparity
= NOPARITY
;
226 *lpparity
= ODDPARITY
;
229 *lpparity
= SPACEPARITY
;
238 static LPCWSTR
COMM_ParseByteSize(LPCWSTR ptr
, LPBYTE lpbytesize
)
242 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
245 if(temp
>= 5 && temp
<= 8)
254 static LPCWSTR
COMM_ParseStopBits(LPCWSTR ptr
, LPBYTE lpstopbits
)
257 static const WCHAR stopbits15W
[] = {'1','.','5',0};
259 if(!strncmpW(stopbits15W
, ptr
, 3))
262 *lpstopbits
= ONE5STOPBITS
;
266 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
270 *lpstopbits
= ONESTOPBIT
;
272 *lpstopbits
= TWOSTOPBITS
;
280 static LPCWSTR
COMM_ParseOnOff(LPCWSTR ptr
, LPDWORD lponoff
)
282 static const WCHAR onW
[] = {'o','n',0};
283 static const WCHAR offW
[] = {'o','f','f',0};
285 if(!strncmpiW(onW
, ptr
, 2))
290 else if(!strncmpiW(offW
, ptr
, 3))
301 /***********************************************************************
302 * COMM_BuildOldCommDCB (Internal)
304 * Build a DCB using the old style settings string eg: "96,n,8,1"
306 static BOOL
COMM_BuildOldCommDCB(LPCWSTR device
, LPDCB lpdcb
)
310 if(!(device
= COMM_ParseNumber(device
, &lpdcb
->BaudRate
)))
313 switch(lpdcb
->BaudRate
)
318 lpdcb
->BaudRate
*= 10;
324 lpdcb
->BaudRate
*= 100;
327 lpdcb
->BaudRate
= 19200;
331 while(*device
== ' ') device
++;
332 if(*device
++ != ',') return FALSE
;
333 while(*device
== ' ') device
++;
335 if(!(device
= COMM_ParseParity(device
, &lpdcb
->Parity
)))
338 while(*device
== ' ') device
++;
339 if(*device
++ != ',') return FALSE
;
340 while(*device
== ' ') device
++;
342 if(!(device
= COMM_ParseByteSize(device
, &lpdcb
->ByteSize
)))
345 while(*device
== ' ') device
++;
346 if(*device
++ != ',') return FALSE
;
347 while(*device
== ' ') device
++;
349 if(!(device
= COMM_ParseStopBits(device
, &lpdcb
->StopBits
)))
352 /* The last parameter for flow control is optional. */
353 while(*device
== ' ') device
++;
357 while(*device
== ' ') device
++;
358 if(*device
) last
= toupperW(*device
++);
359 while(*device
== ' ') device
++;
362 /* Win NT sets the flow control members based on (or lack of) the last
363 parameter. Win 9x does not set these members. */
368 lpdcb
->fOutX
= FALSE
;
369 lpdcb
->fOutxCtsFlow
= FALSE
;
370 lpdcb
->fOutxDsrFlow
= FALSE
;
371 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
372 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
377 lpdcb
->fOutxCtsFlow
= FALSE
;
378 lpdcb
->fOutxDsrFlow
= FALSE
;
379 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
380 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
384 lpdcb
->fOutX
= FALSE
;
385 lpdcb
->fOutxCtsFlow
= TRUE
;
386 lpdcb
->fOutxDsrFlow
= TRUE
;
387 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
388 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
394 /* This should be the end of the string. */
395 if(*device
) return FALSE
;
400 /***********************************************************************
401 * COMM_BuildNewCommDCB (Internal)
403 * Build a DCB using the new style settings string.
404 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
406 static BOOL
COMM_BuildNewCommDCB(LPCWSTR device
, LPDCB lpdcb
, LPCOMMTIMEOUTS lptimeouts
)
409 BOOL baud
= FALSE
, stop
= FALSE
;
410 static const WCHAR baudW
[] = {'b','a','u','d','=',0};
411 static const WCHAR parityW
[] = {'p','a','r','i','t','y','=',0};
412 static const WCHAR dataW
[] = {'d','a','t','a','=',0};
413 static const WCHAR stopW
[] = {'s','t','o','p','=',0};
414 static const WCHAR toW
[] = {'t','o','=',0};
415 static const WCHAR xonW
[] = {'x','o','n','=',0};
416 static const WCHAR odsrW
[] = {'o','d','s','r','=',0};
417 static const WCHAR octsW
[] = {'o','c','t','s','=',0};
418 static const WCHAR dtrW
[] = {'d','t','r','=',0};
419 static const WCHAR rtsW
[] = {'r','t','s','=',0};
420 static const WCHAR idsrW
[] = {'i','d','s','r','=',0};
424 while(*device
== ' ') device
++;
426 if(!strncmpiW(baudW
, device
, 5))
430 if(!(device
= COMM_ParseNumber(device
+ 5, &lpdcb
->BaudRate
)))
433 else if(!strncmpiW(parityW
, device
, 7))
435 if(!(device
= COMM_ParseParity(device
+ 7, &lpdcb
->Parity
)))
438 else if(!strncmpiW(dataW
, device
, 5))
440 if(!(device
= COMM_ParseByteSize(device
+ 5, &lpdcb
->ByteSize
)))
443 else if(!strncmpiW(stopW
, device
, 5))
447 if(!(device
= COMM_ParseStopBits(device
+ 5, &lpdcb
->StopBits
)))
450 else if(!strncmpiW(toW
, device
, 3))
452 if(!(device
= COMM_ParseOnOff(device
+ 3, &temp
)))
455 lptimeouts
->ReadIntervalTimeout
= 0;
456 lptimeouts
->ReadTotalTimeoutMultiplier
= 0;
457 lptimeouts
->ReadTotalTimeoutConstant
= 0;
458 lptimeouts
->WriteTotalTimeoutMultiplier
= 0;
459 lptimeouts
->WriteTotalTimeoutConstant
= temp
? 60000 : 0;
461 else if(!strncmpiW(xonW
, device
, 4))
463 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
469 else if(!strncmpiW(odsrW
, device
, 5))
471 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
474 lpdcb
->fOutxDsrFlow
= temp
;
476 else if(!strncmpiW(octsW
, device
, 5))
478 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
481 lpdcb
->fOutxCtsFlow
= temp
;
483 else if(!strncmpiW(dtrW
, device
, 4))
485 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
488 lpdcb
->fDtrControl
= temp
;
490 else if(!strncmpiW(rtsW
, device
, 4))
492 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
495 lpdcb
->fRtsControl
= temp
;
497 else if(!strncmpiW(idsrW
, device
, 5))
499 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
502 /* Win NT sets the fDsrSensitivity member based on the
503 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
504 lpdcb
->fDsrSensitivity
= temp
;
509 /* After the above parsing, the next character (if not the end of
510 the string) should be a space */
511 if(*device
&& *device
!= ' ')
515 /* If stop bits were not specified, a default is always supplied. */
518 if(baud
&& lpdcb
->BaudRate
== 110)
519 lpdcb
->StopBits
= TWOSTOPBITS
;
521 lpdcb
->StopBits
= ONESTOPBIT
;
527 /**************************************************************************
528 * BuildCommDCBA (KERNEL32.@)
530 * Updates a device control block data structure with values from an
531 * ascii device control string. The device control string has two forms
532 * normal and extended, it must be exclusively in one or the other form.
536 * True on success, false on a malformed control string.
538 BOOL WINAPI
BuildCommDCBA(
539 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
540 LPDCB lpdcb
) /* [out] The device control block to be updated. */
542 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
545 /**************************************************************************
546 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
548 * Updates a device control block data structure with values from an
549 * ascii device control string. Taking timeout values from a timeouts
550 * struct if desired by the control string.
554 * True on success, false bad handles etc.
556 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
557 LPCSTR device
, /* [in] The ascii device control string. */
558 LPDCB lpdcb
, /* [out] The device control block to be updated. */
559 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
562 UNICODE_STRING deviceW
;
564 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
565 if(device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
,device
);
566 else deviceW
.Buffer
= NULL
;
568 if(deviceW
.Buffer
) ret
= BuildCommDCBAndTimeoutsW(deviceW
.Buffer
,lpdcb
,lptimeouts
);
570 RtlFreeUnicodeString(&deviceW
);
574 /**************************************************************************
575 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
577 * Updates a device control block data structure with values from a
578 * unicode device control string. Taking timeout values from a timeouts
579 * struct if desired by the control string.
583 * True on success, false bad handles etc
585 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
586 LPCWSTR devid
, /* [in] The unicode device control string. */
587 LPDCB lpdcb
, /* [out] The device control block to be updated. */
588 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
591 COMMTIMEOUTS timeouts
;
595 TRACE("(%s,%p,%p)\n",debugstr_w(devid
),lpdcb
,lptimeouts
);
597 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
598 lpdcb
->DCBlength
= sizeof(DCB
);
600 /* Make a copy of the original data structures to work with since if
601 if there is an error in the device control string the originals
602 should not be modified (except possibly DCBlength) */
603 memcpy(&dcb
, lpdcb
, sizeof(DCB
));
604 if(lptimeouts
) memcpy(&timeouts
, lptimeouts
, sizeof(COMMTIMEOUTS
));
606 ptr
= COMM_ParseStart(ptr
);
610 else if(strchrW(ptr
, ','))
611 result
= COMM_BuildOldCommDCB(ptr
, &dcb
);
613 result
= COMM_BuildNewCommDCB(ptr
, &dcb
, &timeouts
);
617 memcpy(lpdcb
, &dcb
, sizeof(DCB
));
618 if(lptimeouts
) memcpy(lptimeouts
, &timeouts
, sizeof(COMMTIMEOUTS
));
623 WARN("Invalid device control string: %s\n", debugstr_w(devid
));
624 SetLastError(ERROR_INVALID_PARAMETER
);
629 /**************************************************************************
630 * BuildCommDCBW (KERNEL32.@)
632 * Updates a device control block structure with values from an
633 * unicode device control string. The device control string has two forms
634 * normal and extended, it must be exclusively in one or the other form.
638 * True on success, false on a malformed control string.
640 BOOL WINAPI
BuildCommDCBW(
641 LPCWSTR devid
, /* [in] The unicode device control string. */
642 LPDCB lpdcb
) /* [out] The device control block to be updated. */
644 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
647 static BOOL
COMM_SetCommError(HANDLE handle
, DWORD error
)
651 SERVER_START_REQ( set_serial_info
)
653 req
->handle
= handle
;
654 req
->flags
= SERIALINFO_SET_ERROR
;
655 req
->commerror
= error
;
656 ret
= !wine_server_call_err( req
);
662 static BOOL
COMM_GetCommError(HANDLE handle
, LPDWORD lperror
)
669 SERVER_START_REQ( get_serial_info
)
671 req
->handle
= handle
;
672 ret
= !wine_server_call_err( req
);
673 *lperror
= reply
->commerror
;
680 /*****************************************************************************
681 * SetCommBreak (KERNEL32.@)
683 * Halts the transmission of characters to a communications device.
687 * True on success, and false if the communications device could not be found,
688 * the control is not supported.
692 * Only TIOCSBRK and TIOCCBRK are supported.
694 BOOL WINAPI
SetCommBreak(
695 HANDLE handle
) /* [in] The communications device to suspend. */
697 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
700 fd
= get_comm_fd( handle
, GENERIC_READ
);
701 if(fd
<0) return FALSE
;
702 result
= ioctl(fd
,TIOCSBRK
,0);
703 release_comm_fd( handle
, fd
);
706 TRACE("ioctl failed\n");
707 SetLastError(ERROR_NOT_SUPPORTED
);
712 FIXME("ioctl not available\n");
713 SetLastError(ERROR_NOT_SUPPORTED
);
718 /*****************************************************************************
719 * ClearCommBreak (KERNEL32.@)
721 * Resumes character transmission from a communication device.
725 * True on success and false if the communications device could not be found.
729 * Only TIOCSBRK and TIOCCBRK are supported.
731 BOOL WINAPI
ClearCommBreak(
732 HANDLE handle
) /* [in] The halted communication device whose character transmission is to be resumed. */
734 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
737 fd
= get_comm_fd( handle
, GENERIC_READ
);
738 if(fd
<0) return FALSE
;
739 result
= ioctl(fd
,TIOCCBRK
,0);
740 release_comm_fd( handle
, fd
);
743 TRACE("ioctl failed\n");
744 SetLastError(ERROR_NOT_SUPPORTED
);
749 FIXME("ioctl not available\n");
750 SetLastError(ERROR_NOT_SUPPORTED
);
755 /*****************************************************************************
756 * EscapeCommFunction (KERNEL32.@)
758 * Directs a communication device to perform an extended function.
762 * True or requested data on successful completion of the command,
763 * false if the device is not present cannot execute the command
764 * or the command failed.
766 BOOL WINAPI
EscapeCommFunction(
767 HANDLE handle
, /* [in] The communication device to perform the extended function. */
768 UINT nFunction
) /* [in] The extended function to be performed. */
770 int fd
,direct
=FALSE
,result
=FALSE
;
773 TRACE("handle %p, function=%d\n", handle
, nFunction
);
774 fd
= get_comm_fd( handle
, GENERIC_READ
);
775 if(fd
<0) return FALSE
;
777 if (tcgetattr(fd
,&port
) == -1) {
778 COMM_SetCommError(handle
,CE_IOE
);
779 release_comm_fd( handle
, fd
);
792 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
800 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
808 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
816 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
822 port
.c_iflag
|= IXOFF
;
827 port
.c_iflag
|= IXON
;
833 result
= ioctl(fd
,TIOCSBRK
,0);
840 result
= ioctl(fd
,TIOCCBRK
,0);
844 WARN("(handle=%p,nFunction=%d): Unknown function\n",
850 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
851 release_comm_fd( handle
, fd
);
852 COMM_SetCommError(handle
,CE_IOE
);
861 COMM_SetCommError(handle
,CE_IOE
);
866 release_comm_fd( handle
, fd
);
870 /********************************************************************
871 * PurgeComm (KERNEL32.@)
873 * Terminates pending operations and/or discards buffers on a
874 * communication resource.
878 * True on success and false if the communications handle is bad.
880 BOOL WINAPI
PurgeComm(
881 HANDLE handle
, /* [in] The communication resource to be purged. */
882 DWORD flags
) /* [in] Flags for clear pending/buffer on input/output. */
886 TRACE("handle %p, flags %lx\n", handle
, flags
);
888 fd
= get_comm_fd( handle
, GENERIC_READ
);
889 if(fd
<0) return FALSE
;
892 ** not exactly sure how these are different
893 ** Perhaps if we had our own internal queues, one flushes them
894 ** and the other flushes the kernel's buffers.
896 if(flags
&PURGE_TXABORT
)
897 tcflush(fd
,TCOFLUSH
);
898 if(flags
&PURGE_RXABORT
)
899 tcflush(fd
,TCIFLUSH
);
900 if(flags
&PURGE_TXCLEAR
)
901 tcflush(fd
,TCOFLUSH
);
902 if(flags
&PURGE_RXCLEAR
)
903 tcflush(fd
,TCIFLUSH
);
904 release_comm_fd( handle
, fd
);
909 /*****************************************************************************
910 * ClearCommError (KERNEL32.@)
912 * Enables further I/O operations on a communications resource after
913 * supplying error and current status information.
917 * True on success, false if the communication resource handle is bad.
919 BOOL WINAPI
ClearCommError(
920 HANDLE handle
, /* [in] The communication resource with the error. */
921 LPDWORD errors
, /* [out] Flags indicating error the resource experienced. */
922 LPCOMSTAT lpStat
) /* [out] The status of the communication resource. */
926 fd
=get_comm_fd( handle
, GENERIC_READ
);
927 if(0>fd
) return FALSE
;
931 lpStat
->fCtsHold
= 0;
932 lpStat
->fDsrHold
= 0;
933 lpStat
->fRlsdHold
= 0;
934 lpStat
->fXoffHold
= 0;
935 lpStat
->fXoffSent
= 0;
938 lpStat
->fReserved
= 0;
941 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
942 WARN("ioctl returned error\n");
944 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
948 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
949 WARN("ioctl returned error\n");
952 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
953 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
956 release_comm_fd( handle
, fd
);
958 COMM_GetCommError(handle
, errors
);
959 COMM_SetCommError(handle
, 0);
964 /*****************************************************************************
965 * SetupComm (KERNEL32.@)
967 * Called after CreateFile to hint to the communication resource to use
968 * specified sizes for input and output buffers rather than the default values.
972 * True if successful, false if the communications resource handle is bad.
978 BOOL WINAPI
SetupComm(
979 HANDLE handle
, /* [in] The just created communication resource handle. */
980 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
981 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
985 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
986 fd
=get_comm_fd( handle
, GENERIC_READ
);
987 if(0>fd
) return FALSE
;
988 release_comm_fd( handle
, fd
);
992 /*****************************************************************************
993 * GetCommMask (KERNEL32.@)
995 * Obtain the events associated with a communication device that will cause
996 * a call WaitCommEvent to return.
1000 * True on success, fail on bad device handle etc.
1002 BOOL WINAPI
GetCommMask(
1003 HANDLE handle
, /* [in] The communications device. */
1004 LPDWORD evtmask
) /* [out] The events which cause WaitCommEvent to return. */
1008 TRACE("handle %p, mask %p\n", handle
, evtmask
);
1010 SERVER_START_REQ( get_serial_info
)
1012 req
->handle
= handle
;
1013 if ((ret
= !wine_server_call_err( req
)))
1015 if (evtmask
) *evtmask
= reply
->eventmask
;
1022 /*****************************************************************************
1023 * SetCommMask (KERNEL32.@)
1025 * There be some things we need to hear about yon there communications device.
1026 * (Set which events associated with a communication device should cause
1027 * a call WaitCommEvent to return.)
1031 * True on success, false on bad handle etc.
1033 BOOL WINAPI
SetCommMask(
1034 HANDLE handle
, /* [in] The communications device. */
1035 DWORD evtmask
) /* [in] The events that are to be monitored. */
1039 TRACE("handle %p, mask %lx\n", handle
, evtmask
);
1041 SERVER_START_REQ( set_serial_info
)
1043 req
->handle
= handle
;
1044 req
->flags
= SERIALINFO_SET_MASK
;
1045 req
->eventmask
= evtmask
;
1046 ret
= !wine_server_call_err( req
);
1052 /*****************************************************************************
1053 * SetCommState (KERNEL32.@)
1055 * Re-initializes all hardware and control settings of a communications device,
1056 * with values from a device control block without effecting the input and output
1061 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1063 BOOL WINAPI
SetCommState(
1064 HANDLE handle
, /* [in] The communications device. */
1065 LPDCB lpdcb
) /* [out] The device control block. */
1067 struct termios port
;
1068 int fd
, bytesize
, stopbits
;
1071 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1072 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1073 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1074 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1075 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1076 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1077 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1078 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1079 lpdcb
->fRtsControl
);
1080 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1081 lpdcb
->fDtrControl
);
1084 fd
= get_comm_fd( handle
, GENERIC_READ
);
1085 if (fd
< 0) return FALSE
;
1087 if ((tcgetattr(fd
,&port
)) == -1) {
1088 int save_error
= errno
;
1089 COMM_SetCommError(handle
,CE_IOE
);
1090 release_comm_fd( handle
, fd
);
1091 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1095 port
.c_cc
[VMIN
] = 0;
1096 port
.c_cc
[VTIME
] = 1;
1099 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1101 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1103 port
.c_iflag
|= (IGNBRK
);
1105 port
.c_oflag
&= ~(OPOST
);
1107 port
.c_cflag
&= ~(HUPCL
);
1108 port
.c_cflag
|= CLOCAL
| CREAD
;
1110 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1111 port
.c_lflag
|= NOFLSH
;
1114 port
.c_cflag
&= ~CBAUD
;
1115 switch (lpdcb
->BaudRate
) {
1120 port
.c_cflag
|= B50
;
1123 port
.c_cflag
|= B75
;
1127 port
.c_cflag
|= B110
;
1130 port
.c_cflag
|= B134
;
1133 port
.c_cflag
|= B150
;
1136 port
.c_cflag
|= B200
;
1140 port
.c_cflag
|= B300
;
1144 port
.c_cflag
|= B600
;
1148 port
.c_cflag
|= B1200
;
1151 port
.c_cflag
|= B1800
;
1155 port
.c_cflag
|= B2400
;
1159 port
.c_cflag
|= B4800
;
1163 port
.c_cflag
|= B9600
;
1167 port
.c_cflag
|= B19200
;
1171 port
.c_cflag
|= B38400
;
1175 port
.c_cflag
|= B57600
;
1180 port
.c_cflag
|= B115200
;
1185 port
.c_cflag
|= B230400
;
1190 port
.c_cflag
|= B460800
;
1194 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1195 { struct serial_struct nuts
;
1197 ioctl(fd
, TIOCGSERIAL
, &nuts
);
1198 nuts
.custom_divisor
= nuts
.baud_base
/ lpdcb
->BaudRate
;
1199 if (!(nuts
.custom_divisor
)) nuts
.custom_divisor
= 1;
1200 arby
= nuts
.baud_base
/ nuts
.custom_divisor
;
1201 nuts
.flags
&= ~ASYNC_SPD_MASK
;
1202 nuts
.flags
|= ASYNC_SPD_CUST
;
1203 WARN("You (or a program acting at your behest) have specified\n"
1204 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1205 "which is as close as we can get by our present understanding of your\n"
1206 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1207 "has caused to your linux system can be undone with setserial \n"
1208 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1209 "reset it and it will probably recover.\n", lpdcb
->BaudRate
, arby
);
1210 ioctl(fd
, TIOCSSERIAL
, &nuts
);
1211 port
.c_cflag
|= B38400
;
1214 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1217 COMM_SetCommError(handle
,IE_BAUDRATE
);
1218 release_comm_fd( handle
, fd
);
1219 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1222 #elif !defined(__EMX__)
1223 switch (lpdcb
->BaudRate
) {
1228 port
.c_ospeed
= B50
;
1231 port
.c_ospeed
= B75
;
1235 port
.c_ospeed
= B110
;
1238 port
.c_ospeed
= B134
;
1241 port
.c_ospeed
= B150
;
1244 port
.c_ospeed
= B200
;
1248 port
.c_ospeed
= B300
;
1252 port
.c_ospeed
= B600
;
1256 port
.c_ospeed
= B1200
;
1259 port
.c_ospeed
= B1800
;
1263 port
.c_ospeed
= B2400
;
1267 port
.c_ospeed
= B4800
;
1271 port
.c_ospeed
= B9600
;
1275 port
.c_ospeed
= B19200
;
1279 port
.c_ospeed
= B38400
;
1284 port
.c_cflag
|= B57600
;
1290 port
.c_cflag
|= B115200
;
1295 port
.c_cflag
|= B230400
;
1300 port
.c_cflag
|= B460800
;
1304 COMM_SetCommError(handle
,IE_BAUDRATE
);
1305 release_comm_fd( handle
, fd
);
1306 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1309 port
.c_ispeed
= port
.c_ospeed
;
1311 bytesize
=lpdcb
->ByteSize
;
1312 stopbits
=lpdcb
->StopBits
;
1315 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1317 port
.c_cflag
&= ~(PARENB
| PARODD
);
1320 port
.c_iflag
|= INPCK
;
1322 port
.c_iflag
&= ~INPCK
;
1323 switch (lpdcb
->Parity
) {
1327 port
.c_cflag
|= (PARENB
| PARODD
);
1330 port
.c_cflag
|= PARENB
;
1333 /* Linux defines mark/space (stick) parity */
1335 port
.c_cflag
|= (PARENB
| CMSPAR
);
1338 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1341 /* try the POSIX way */
1343 if( stopbits
== ONESTOPBIT
) {
1344 stopbits
= TWOSTOPBITS
;
1345 port
.c_iflag
&= ~INPCK
;
1347 COMM_SetCommError(handle
,IE_BYTESIZE
);
1348 release_comm_fd( handle
, fd
);
1349 ERR("Cannot set MARK Parity\n");
1356 port
.c_iflag
&= ~INPCK
;
1358 COMM_SetCommError(handle
,IE_BYTESIZE
);
1359 release_comm_fd( handle
, fd
);
1360 ERR("Cannot set SPACE Parity\n");
1366 COMM_SetCommError(handle
,IE_BYTESIZE
);
1367 release_comm_fd( handle
, fd
);
1373 port
.c_cflag
&= ~CSIZE
;
1376 port
.c_cflag
|= CS5
;
1379 port
.c_cflag
|= CS6
;
1382 port
.c_cflag
|= CS7
;
1385 port
.c_cflag
|= CS8
;
1388 COMM_SetCommError(handle
,IE_BYTESIZE
);
1389 release_comm_fd( handle
, fd
);
1396 port
.c_cflag
&= ~CSTOPB
;
1398 case ONE5STOPBITS
: /* will be selected if bytesize is 5 */
1400 port
.c_cflag
|= CSTOPB
;
1403 COMM_SetCommError(handle
,IE_BYTESIZE
);
1404 release_comm_fd( handle
, fd
);
1409 if ( lpdcb
->fOutxCtsFlow
||
1410 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1413 port
.c_cflag
|= CRTSCTS
;
1419 port
.c_iflag
|= IXON
;
1421 port
.c_iflag
&= ~IXON
;
1423 port
.c_iflag
|= IXOFF
;
1425 port
.c_iflag
&= ~IXOFF
;
1427 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
1428 ERR("tcsetattr error '%s'\n", strerror(errno
));
1429 COMM_SetCommError(handle
,CE_IOE
);
1432 COMM_SetCommError(handle
,0);
1436 /* note: change DTR/RTS lines after setting the comm attributes,
1437 * so flow control does not interfere. */
1439 if (lpdcb
->fDtrControl
== DTR_CONTROL_HANDSHAKE
)
1441 WARN("DSR/DTR flow control not supported\n");
1442 } else if(lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
1443 COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1445 COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1448 if(!lpdcb
->fOutxCtsFlow
)
1450 if(lpdcb
->fRtsControl
== RTS_CONTROL_DISABLE
)
1451 COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1453 COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1456 if(lpdcb
->fRtsControl
== RTS_CONTROL_TOGGLE
)
1457 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1458 release_comm_fd( handle
, fd
);
1464 /*****************************************************************************
1465 * GetCommState (KERNEL32.@)
1467 * Fills in a device control block with information from a communications device.
1471 * True on success, false if the communication device handle is bad etc
1475 * XonChar and XoffChar are not set.
1477 BOOL WINAPI
GetCommState(
1478 HANDLE handle
, /* [in] The communications device. */
1479 LPDCB lpdcb
) /* [out] The device control block. */
1481 struct termios port
;
1483 int stat
= DTR_CONTROL_ENABLE
| RTS_CONTROL_ENABLE
;
1485 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1487 fd
= get_comm_fd( handle
, GENERIC_READ
);
1488 if (fd
< 0) return FALSE
;
1489 if (tcgetattr(fd
, &port
) == -1
1491 || ioctl(fd
, TIOCMGET
, &stat
) == -1
1494 int save_error
=errno
;
1495 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error
));
1496 COMM_SetCommError(handle
,CE_IOE
);
1497 release_comm_fd( handle
, fd
);
1500 release_comm_fd( handle
, fd
);
1503 speed
= (port
.c_cflag
& CBAUD
);
1505 speed
= (cfgetospeed(&port
));
1509 lpdcb
->BaudRate
= 0;
1512 lpdcb
->BaudRate
= 50;
1515 lpdcb
->BaudRate
= 75;
1518 lpdcb
->BaudRate
= 110;
1521 lpdcb
->BaudRate
= 134;
1524 lpdcb
->BaudRate
= 150;
1527 lpdcb
->BaudRate
= 200;
1530 lpdcb
->BaudRate
= 300;
1533 lpdcb
->BaudRate
= 600;
1536 lpdcb
->BaudRate
= 1200;
1539 lpdcb
->BaudRate
= 1800;
1542 lpdcb
->BaudRate
= 2400;
1545 lpdcb
->BaudRate
= 4800;
1548 lpdcb
->BaudRate
= 9600;
1551 lpdcb
->BaudRate
= 19200;
1554 lpdcb
->BaudRate
= 38400;
1558 lpdcb
->BaudRate
= 57600;
1563 lpdcb
->BaudRate
= 115200;
1568 lpdcb
->BaudRate
= 230400;
1573 lpdcb
->BaudRate
= 460800;
1577 ERR("unknown speed %x \n",speed
);
1580 switch (port
.c_cflag
& CSIZE
) {
1582 lpdcb
->ByteSize
= 5;
1585 lpdcb
->ByteSize
= 6;
1588 lpdcb
->ByteSize
= 7;
1591 lpdcb
->ByteSize
= 8;
1594 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
1597 if(port
.c_iflag
& INPCK
)
1598 lpdcb
->fParity
= TRUE
;
1600 lpdcb
->fParity
= FALSE
;
1602 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1604 switch (port
.c_cflag
& (PARENB
| PARODD
))
1608 lpdcb
->Parity
= NOPARITY
;
1611 lpdcb
->Parity
= EVENPARITY
;
1613 case (PARENB
| PARODD
):
1614 lpdcb
->Parity
= ODDPARITY
;
1617 case (PARENB
| CMSPAR
):
1618 lpdcb
->Parity
= MARKPARITY
;
1620 case (PARENB
| PARODD
| CMSPAR
):
1621 lpdcb
->Parity
= SPACEPARITY
;
1626 if (port
.c_cflag
& CSTOPB
)
1627 if(lpdcb
->ByteSize
== 5)
1628 lpdcb
->StopBits
= ONE5STOPBITS
;
1630 lpdcb
->StopBits
= TWOSTOPBITS
;
1632 lpdcb
->StopBits
= ONESTOPBIT
;
1637 /* termios does not support DTR/DSR flow control */
1638 lpdcb
->fOutxDsrFlow
= 0;
1639 lpdcb
->fDtrControl
=
1641 !(stat
& TIOCM_DTR
) ? DTR_CONTROL_DISABLE
:
1643 DTR_CONTROL_ENABLE
;
1647 if (port
.c_cflag
& CRTSCTS
) {
1648 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1649 lpdcb
->fOutxCtsFlow
= 1;
1653 lpdcb
->fRtsControl
=
1655 !(stat
& TIOCM_RTS
) ? RTS_CONTROL_DISABLE
:
1657 RTS_CONTROL_ENABLE
;
1658 lpdcb
->fOutxCtsFlow
= 0;
1660 if (port
.c_iflag
& IXON
)
1665 if (port
.c_iflag
& IXOFF
)
1674 lpdcb
->XoffLim
= 10;
1676 COMM_SetCommError(handle
,0);
1680 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1681 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1682 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1683 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1684 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1685 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1686 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1687 lpdcb
->fRtsControl
);
1688 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1689 lpdcb
->fDtrControl
);
1691 if ( lpdcb
->fOutxCtsFlow
||
1692 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1697 TRACE("~CRTSCTS\n");
1702 /*****************************************************************************
1703 * TransmitCommChar (KERNEL32.@)
1705 * Transmits a single character in front of any pending characters in the
1706 * output buffer. Usually used to send an interrupt character to a host.
1710 * True if the call succeeded, false if the previous command character to the
1711 * same device has not been sent yet the handle is bad etc.
1717 BOOL WINAPI
TransmitCommChar(
1718 HANDLE hComm
, /* [in] The communication device in need of a command character. */
1719 CHAR chTransmit
) /* [in] The character to transmit. */
1722 WARN("(%p,'%c') not perfect!\n",hComm
,chTransmit
);
1724 return WriteFile( hComm
, &chTransmit
, 1, &w
, NULL
);
1728 /*****************************************************************************
1729 * GetCommTimeouts (KERNEL32.@)
1731 * Obtains the request timeout values for the communications device.
1735 * True on success, false if communications device handle is bad
1736 * or the target structure is null.
1738 BOOL WINAPI
GetCommTimeouts(
1739 HANDLE hComm
, /* [in] The communications device. */
1740 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request timeouts. */
1744 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1748 SetLastError(ERROR_INVALID_PARAMETER
);
1752 SERVER_START_REQ( get_serial_info
)
1754 req
->handle
= hComm
;
1755 if ((ret
= !wine_server_call_err( req
)))
1757 lptimeouts
->ReadIntervalTimeout
= reply
->readinterval
;
1758 lptimeouts
->ReadTotalTimeoutMultiplier
= reply
->readmult
;
1759 lptimeouts
->ReadTotalTimeoutConstant
= reply
->readconst
;
1760 lptimeouts
->WriteTotalTimeoutMultiplier
= reply
->writemult
;
1761 lptimeouts
->WriteTotalTimeoutConstant
= reply
->writeconst
;
1768 /*****************************************************************************
1769 * SetCommTimeouts (KERNEL32.@)
1771 * Sets the timeouts used when reading and writing data to/from COMM ports.
1773 * ReadIntervalTimeout
1774 * - converted and passes to linux kernel as c_cc[VTIME]
1775 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1776 * - used in ReadFile to calculate GetOverlappedResult's timeout
1777 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1778 * - used in WriteFile to calculate GetOverlappedResult's timeout
1782 * True if the timeouts were set, false otherwise.
1784 BOOL WINAPI
SetCommTimeouts(
1785 HANDLE hComm
, /* [in] handle of COMM device */
1786 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
1790 struct termios tios
;
1792 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1796 SetLastError(ERROR_INVALID_PARAMETER
);
1800 SERVER_START_REQ( set_serial_info
)
1802 req
->handle
= hComm
;
1803 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
1804 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
1805 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
1806 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
1807 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
1808 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
1809 ret
= !wine_server_call_err( req
);
1812 if (!ret
) return FALSE
;
1814 /* FIXME: move this stuff to the server */
1815 fd
= get_comm_fd( hComm
, GENERIC_READ
);
1816 if (fd
< 0) return FALSE
;
1818 if (-1==tcgetattr(fd
,&tios
)) {
1819 FIXME("tcgetattr on fd %d failed!\n",fd
);
1820 release_comm_fd( hComm
, fd
);
1824 /* VTIME is in 1/10 seconds */
1826 unsigned int ux_timeout
;
1828 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
1834 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
1837 ux_timeout
= 1; /* must be at least some timeout */
1840 tios
.c_cc
[VTIME
] = ux_timeout
;
1843 if (-1==tcsetattr(fd
,0,&tios
)) {
1844 FIXME("tcsetattr on fd %d failed!\n",fd
);
1845 release_comm_fd( hComm
, fd
);
1848 release_comm_fd( hComm
, fd
);
1852 /***********************************************************************
1853 * GetCommModemStatus (KERNEL32.@)
1855 * Obtains the four control register bits if supported by the hardware.
1859 * True if the communications handle was good and for hardware that
1860 * control register access, false otherwise.
1862 BOOL WINAPI
GetCommModemStatus(
1863 HANDLE hFile
, /* [in] The communications device. */
1864 LPDWORD lpModemStat
) /* [out] The control register bits. */
1866 int fd
,mstat
, result
=FALSE
;
1870 fd
= get_comm_fd( hFile
, GENERIC_READ
);
1873 result
= ioctl(fd
, TIOCMGET
, &mstat
);
1874 release_comm_fd( hFile
, fd
);
1877 WARN("ioctl failed\n");
1881 if (mstat
& TIOCM_CTS
)
1882 *lpModemStat
|= MS_CTS_ON
;
1885 if (mstat
& TIOCM_DSR
)
1886 *lpModemStat
|= MS_DSR_ON
;
1889 if (mstat
& TIOCM_RNG
)
1890 *lpModemStat
|= MS_RING_ON
;
1893 /*FIXME: Not really sure about RLSD UB 990810*/
1894 if (mstat
& TIOCM_CAR
)
1895 *lpModemStat
|= MS_RLSD_ON
;
1897 TRACE("%04x -> %s%s%s%s\n", mstat
,
1898 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
1899 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
1900 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
1901 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
1908 /***********************************************************************
1909 * COMM_WaitCommEventService (INTERNAL)
1911 * This function is called while the client is waiting on the
1912 * server, so we can't make any server calls here.
1914 static void WINAPI
COMM_WaitCommEventService(void* ovp
, IO_STATUS_BLOCK
* iosb
, ULONG status
)
1916 async_commio
*commio
= (async_commio
*) ovp
;
1918 TRACE("iosb %p\n", iosb
);
1922 case STATUS_ALERTED
: /* got some new stuff */
1923 /* FIXME: detect other events */
1924 *commio
->buffer
= EV_RXCHAR
;
1925 iosb
->u
.Status
= STATUS_SUCCESS
;
1928 iosb
->u
.Status
= status
;
1931 wine_server_release_fd( commio
->handle
, commio
->fd
);
1932 if ( ((LPOVERLAPPED
)iosb
)->hEvent
!= INVALID_HANDLE_VALUE
)
1933 NtSetEvent( ((LPOVERLAPPED
)iosb
)->hEvent
, NULL
);
1934 HeapFree(GetProcessHeap(), 0, commio
);
1938 /***********************************************************************
1939 * COMM_WaitCommEvent (INTERNAL)
1941 * This function must have an lpOverlapped.
1943 static BOOL
COMM_WaitCommEvent(
1944 HANDLE hFile
, /* [in] handle of comm port to wait for */
1945 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1946 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1949 async_commio
* commio
;
1954 SetLastError(ERROR_INVALID_PARAMETER
);
1958 if (NtResetEvent(lpOverlapped
->hEvent
,NULL
))
1961 fd
= get_comm_fd( hFile
, GENERIC_WRITE
);
1962 if (fd
< 0) return FALSE
;
1964 commio
= HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio
));
1967 release_comm_fd( hFile
, fd
);
1971 commio
->handle
= hFile
;
1972 commio
->type
= ASYNC_TYPE_WAIT
;
1973 commio
->apc_internal
= COMM_WaitCommEventService
;
1974 commio
->buffer
= (char *)lpdwEvents
;
1975 commio
->fd
= fd
; /* FIXME */
1977 lpOverlapped
->InternalHigh
= 0;
1978 lpOverlapped
->u
.s
.Offset
= 0;
1979 lpOverlapped
->u
.s
.OffsetHigh
= 0;
1981 SERVER_START_REQ( register_async
)
1983 req
->handle
= hFile
;
1984 req
->io_apc
= COMM_WaitCommEventService
;
1985 req
->io_user
= commio
;
1986 req
->io_sb
= (IO_STATUS_BLOCK
*)lpOverlapped
;
1988 status
= wine_server_call( req
);
1992 if ( status
) SetLastError( RtlNtStatusToDosError(status
) );
1993 else NtCurrentTeb()->num_async_io
++;
1998 /***********************************************************************
1999 * WaitCommEvent (KERNEL32.@)
2001 * Wait until something interesting happens on a COMM port.
2002 * Interesting things (events) are set by calling SetCommMask before
2003 * this function is called.
2006 * TRUE if successful
2009 * The set of detected events will be written to *lpdwEventMask
2010 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2013 * Only supports EV_RXCHAR and EV_TXEMPTY
2015 BOOL WINAPI
WaitCommEvent(
2016 HANDLE hFile
, /* [in] handle of comm port to wait for */
2017 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2018 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2023 TRACE("(%p %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
2026 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
2028 /* if there is no overlapped structure, create our own */
2029 ov
.hEvent
= CreateEventW(NULL
,FALSE
,FALSE
,NULL
);
2031 COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
2033 /* wait for the overlapped to complete */
2034 ret
= GetOverlappedResult(hFile
, &ov
, NULL
, TRUE
);
2035 CloseHandle(ov
.hEvent
);
2040 /***********************************************************************
2041 * GetCommProperties (KERNEL32.@)
2043 * This function fills in a structure with the capabilities of the
2044 * communications port driver.
2048 * TRUE on success, FALSE on failure
2049 * If successful, the lpCommProp structure be filled in with
2050 * properties of the comm port.
2052 BOOL WINAPI
GetCommProperties(
2053 HANDLE hFile
, /* [in] handle of the comm port */
2054 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
2056 FIXME("(%p %p )\n",hFile
,lpCommProp
);
2061 * These values should be valid for LINUX's serial driver
2062 * FIXME: Perhaps they deserve an #ifdef LINUX
2064 memset(lpCommProp
,0,sizeof(COMMPROP
));
2065 lpCommProp
->wPacketLength
= 1;
2066 lpCommProp
->wPacketVersion
= 1;
2067 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
2068 lpCommProp
->dwReserved1
= 0;
2069 lpCommProp
->dwMaxTxQueue
= 4096;
2070 lpCommProp
->dwMaxRxQueue
= 4096;
2071 lpCommProp
->dwMaxBaud
= BAUD_115200
;
2072 lpCommProp
->dwProvSubType
= PST_RS232
;
2073 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
| PCF_TOTALTIMEOUTS
;
2074 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
2075 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
2076 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
2077 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
2078 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
2079 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
2080 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
2081 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
2082 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
2083 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
2088 /***********************************************************************
2090 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2091 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2092 * This is dependent on the type of COMM port, but since it is doubtful
2093 * anybody will get around to implementing support for fancy serial
2094 * ports in WINE, this is hardcoded for the time being. The name of
2095 * this DLL should be stored in and read from the system registry in
2096 * the hive HKEY_LOCAL_MACHINE, key
2097 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2098 * where ???? is the port number... that is determined by PNP
2099 * The DLL should be loaded when the COMM port is opened, and closed
2100 * when the COMM port is closed. - MJM 20 June 2000
2101 ***********************************************************************/
2102 static WCHAR lpszSerialUI
[] = {
2103 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2106 /***********************************************************************
2107 * CommConfigDialogA (KERNEL32.@)
2109 * Raises a dialog that allows the user to configure a comm port.
2110 * Fills the COMMCONFIG struct with information specified by the user.
2111 * This function should call a similar routine in the COMM driver...
2115 * TRUE on success, FALSE on failure
2116 * If successful, the lpCommConfig structure will contain a new
2117 * configuration for the comm port, as specified by the user.
2120 * The library with the CommConfigDialog code is never unloaded.
2121 * Perhaps this should be done when the comm port is closed?
2123 BOOL WINAPI
CommConfigDialogA(
2124 LPCSTR lpszDevice
, /* [in] name of communications device */
2125 HANDLE hWnd
, /* [in] parent window for the dialog */
2126 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2128 FARPROC lpfnCommDialog
;
2129 HMODULE hConfigModule
;
2132 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2134 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2138 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogA");
2141 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2143 FreeLibrary(hConfigModule
);
2148 /***********************************************************************
2149 * CommConfigDialogW (KERNEL32.@)
2151 * see CommConfigDialogA for more info
2153 BOOL WINAPI
CommConfigDialogW(
2154 LPCWSTR lpszDevice
, /* [in] name of communications device */
2155 HANDLE hWnd
, /* [in] parent window for the dialog */
2156 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2158 FARPROC lpfnCommDialog
;
2159 HMODULE hConfigModule
;
2162 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2164 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2168 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogW");
2171 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2173 FreeLibrary(hConfigModule
);
2178 /***********************************************************************
2179 * GetCommConfig (KERNEL32.@)
2181 * Fill in the COMMCONFIG structure for the comm port hFile
2185 * TRUE on success, FALSE on failure
2186 * If successful, lpCommConfig contains the comm port configuration.
2191 BOOL WINAPI
GetCommConfig(
2192 HANDLE hFile
, /* [in] The communications device. */
2193 LPCOMMCONFIG lpCommConfig
, /* [out] The communications configuration of the device (if it fits). */
2194 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
2195 afterwards the number of bytes copied to the buffer or
2196 the needed size of the buffer. */
2200 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2202 if(lpCommConfig
== NULL
)
2204 r
= *lpdwSize
< sizeof(COMMCONFIG
); /* TRUE if not enough space */
2205 *lpdwSize
= sizeof(COMMCONFIG
);
2209 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
2210 lpCommConfig
->wVersion
= 1;
2211 lpCommConfig
->wReserved
= 0;
2212 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
2213 lpCommConfig
->dwProviderSubType
= PST_RS232
;
2214 lpCommConfig
->dwProviderOffset
= 0;
2215 lpCommConfig
->dwProviderSize
= 0;
2220 /***********************************************************************
2221 * SetCommConfig (KERNEL32.@)
2223 * Sets the configuration of the communications device.
2227 * True on success, false if the handle was bad is not a communications device.
2229 BOOL WINAPI
SetCommConfig(
2230 HANDLE hFile
, /* [in] The communications device. */
2231 LPCOMMCONFIG lpCommConfig
, /* [in] The desired configuration. */
2232 DWORD dwSize
) /* [in] size of the lpCommConfig struct */
2234 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2235 return SetCommState(hFile
,&lpCommConfig
->dcb
);
2238 /***********************************************************************
2239 * SetDefaultCommConfigA (KERNEL32.@)
2241 * Initializes the default configuration for the specified communication
2246 * True if the device was found and the defaults set, false otherwise
2248 BOOL WINAPI
SetDefaultCommConfigW(
2249 LPCWSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
2250 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2251 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2253 FARPROC lpfnSetDefaultCommConfig
;
2254 HMODULE hConfigModule
;
2257 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
2259 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2263 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvSetDefaultCommConfigW");
2264 if (lpfnSetDefaultCommConfig
)
2265 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
2267 FreeLibrary(hConfigModule
);
2273 /***********************************************************************
2274 * SetDefaultCommConfigW (KERNEL32.@)
2276 * Initializes the default configuration for the specified
2277 * communication device. (unicode)
2282 BOOL WINAPI
SetDefaultCommConfigA(
2283 LPCSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
2284 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2285 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2288 LPWSTR lpDeviceW
= NULL
;
2291 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice
),lpCommConfig
,dwSize
);
2295 len
= MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, NULL
, 0 );
2296 lpDeviceW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
2297 MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, lpDeviceW
, len
);
2299 r
= SetDefaultCommConfigW(lpDeviceW
,lpCommConfig
,dwSize
);
2300 HeapFree( GetProcessHeap(), 0, lpDeviceW
);
2305 /***********************************************************************
2306 * GetDefaultCommConfigW (KERNEL32.@)
2308 * Acquires the default configuration of the specified communication device. (unicode)
2312 * True on successful reading of the default configuration,
2313 * if the device is not found or the buffer is too small.
2315 BOOL WINAPI
GetDefaultCommConfigW(
2316 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
2317 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2318 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2319 afterwards the number of bytes copied to the buffer or
2320 the needed size of the buffer. */
2322 LPDCB lpdcb
= &(lpCC
->dcb
);
2324 static const WCHAR comW
[] = {'C','O','M',0};
2325 static const WCHAR formatW
[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2327 if (strncmpiW(lpszName
,comW
,3)) {
2328 ERR("not implemented for <%s>\n", debugstr_w(lpszName
));
2332 TRACE("(%s %p %ld)\n", debugstr_w(lpszName
), lpCC
, *lpdwSize
);
2333 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
2334 *lpdwSize
= sizeof(COMMCONFIG
);
2338 *lpdwSize
= sizeof(COMMCONFIG
);
2340 lpCC
->dwSize
= sizeof(COMMCONFIG
);
2342 lpCC
->dwProviderSubType
= PST_RS232
;
2343 lpCC
->dwProviderOffset
= 0L;
2344 lpCC
->dwProviderSize
= 0L;
2346 sprintfW( temp
, formatW
, lpszName
[3]);
2347 FIXME("setting %s as default\n", debugstr_w(temp
));
2349 return BuildCommDCBW( temp
, lpdcb
);
2352 /**************************************************************************
2353 * GetDefaultCommConfigA (KERNEL32.@)
2355 * Acquires the default configuration of the specified communication device. (ascii)
2359 * True on successful reading of the default configuration,
2360 * if the device is not found or the buffer is too small.
2362 BOOL WINAPI
GetDefaultCommConfigA(
2363 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
2364 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2365 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2366 afterwards the number of bytes copied to the buffer or
2367 the needed size of the buffer. */
2370 UNICODE_STRING lpszNameW
;
2372 TRACE("(%s,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
2373 if(lpszName
) RtlCreateUnicodeStringFromAsciiz(&lpszNameW
,lpszName
);
2374 else lpszNameW
.Buffer
= NULL
;
2376 if(lpszNameW
.Buffer
) ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
2378 RtlFreeUnicodeString(&lpszNameW
);