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"
97 #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 static DWORD
commio_get_async_count (const async_private
*ovp
);
129 static void commio_async_cleanup (async_private
*ovp
);
131 static async_ops commio_async_ops
=
133 commio_get_async_count
, /* get_count */
134 NULL
, /* call_completion */
135 commio_async_cleanup
/* cleanup */
138 typedef struct async_commio
140 struct async_private async
;
144 static DWORD
commio_get_async_count (const struct async_private
*ovp
)
149 static void commio_async_cleanup (async_private
*ovp
)
151 HeapFree(GetProcessHeap(), 0, ovp
);
154 /***********************************************************************/
156 #if !defined(TIOCINQ) && defined(FIONREAD)
157 #define TIOCINQ FIONREAD
160 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
163 unsigned int mstat
, okay
;
164 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
165 if (okay
) return okay
;
166 if (andy
) mstat
&= andy
;
168 return ioctl(fd
, TIOCMSET
, &mstat
);
174 /***********************************************************************
175 * COMM_Parse* (Internal)
177 * The following COMM_Parse* functions are used by the BuildCommDCB
178 * functions to help parse the various parts of the device control string.
180 static LPCWSTR
COMM_ParseStart(LPCWSTR ptr
)
182 static const WCHAR comW
[] = {'C','O','M',0};
184 /* The device control string may optionally start with "COMx" followed
185 by an optional ':' and spaces. */
186 if(!strncmpiW(ptr
, comW
, 3))
190 /* Allow any com port above 0 as Win 9x does (NT only allows
191 values for com ports which are actually present) */
192 if(*ptr
< '1' || *ptr
> '9')
195 /* Advance pointer past port number */
196 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
198 /* The com port number must be followed by a ':' or ' ' */
199 if(*ptr
!= ':' && *ptr
!= ' ')
202 /* Advance pointer to beginning of next parameter */
203 while(*ptr
== ' ') ptr
++;
207 while(*ptr
== ' ') ptr
++;
210 /* The device control string must not start with a space. */
217 static LPCWSTR
COMM_ParseNumber(LPCWSTR ptr
, LPDWORD lpnumber
)
219 if(*ptr
< '0' || *ptr
> '9') return NULL
;
220 *lpnumber
= strtoulW(ptr
, NULL
, 10);
221 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
225 static LPCWSTR
COMM_ParseParity(LPCWSTR ptr
, LPBYTE lpparity
)
227 /* Contrary to what you might expect, Windows only sets the Parity
228 member of DCB and not fParity even when parity is specified in the
229 device control string */
231 switch(toupperW(*ptr
++))
234 *lpparity
= EVENPARITY
;
237 *lpparity
= MARKPARITY
;
240 *lpparity
= NOPARITY
;
243 *lpparity
= ODDPARITY
;
246 *lpparity
= SPACEPARITY
;
255 static LPCWSTR
COMM_ParseByteSize(LPCWSTR ptr
, LPBYTE lpbytesize
)
259 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
262 if(temp
>= 5 && temp
<= 8)
271 static LPCWSTR
COMM_ParseStopBits(LPCWSTR ptr
, LPBYTE lpstopbits
)
274 static const WCHAR stopbits15W
[] = {'1','.','5',0};
276 if(!strncmpW(stopbits15W
, ptr
, 3))
279 *lpstopbits
= ONE5STOPBITS
;
283 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
287 *lpstopbits
= ONESTOPBIT
;
289 *lpstopbits
= TWOSTOPBITS
;
297 static LPCWSTR
COMM_ParseOnOff(LPCWSTR ptr
, LPDWORD lponoff
)
299 static const WCHAR onW
[] = {'o','n',0};
300 static const WCHAR offW
[] = {'o','f','f',0};
302 if(!strncmpiW(onW
, ptr
, 2))
307 else if(!strncmpiW(offW
, ptr
, 3))
318 /***********************************************************************
319 * COMM_BuildOldCommDCB (Internal)
321 * Build a DCB using the old style settings string eg: "96,n,8,1"
323 static BOOL
COMM_BuildOldCommDCB(LPCWSTR device
, LPDCB lpdcb
)
327 if(!(device
= COMM_ParseNumber(device
, &lpdcb
->BaudRate
)))
330 switch(lpdcb
->BaudRate
)
335 lpdcb
->BaudRate
*= 10;
341 lpdcb
->BaudRate
*= 100;
344 lpdcb
->BaudRate
= 19200;
348 while(*device
== ' ') device
++;
349 if(*device
++ != ',') return FALSE
;
350 while(*device
== ' ') device
++;
352 if(!(device
= COMM_ParseParity(device
, &lpdcb
->Parity
)))
355 while(*device
== ' ') device
++;
356 if(*device
++ != ',') return FALSE
;
357 while(*device
== ' ') device
++;
359 if(!(device
= COMM_ParseByteSize(device
, &lpdcb
->ByteSize
)))
362 while(*device
== ' ') device
++;
363 if(*device
++ != ',') return FALSE
;
364 while(*device
== ' ') device
++;
366 if(!(device
= COMM_ParseStopBits(device
, &lpdcb
->StopBits
)))
369 /* The last parameter for flow control is optional. */
370 while(*device
== ' ') device
++;
374 while(*device
== ' ') device
++;
375 if(*device
) last
= toupperW(*device
++);
376 while(*device
== ' ') device
++;
379 /* Win NT sets the flow control members based on (or lack of) the last
380 parameter. Win 9x does not set these members. */
385 lpdcb
->fOutX
= FALSE
;
386 lpdcb
->fOutxCtsFlow
= FALSE
;
387 lpdcb
->fOutxDsrFlow
= FALSE
;
388 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
389 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
394 lpdcb
->fOutxCtsFlow
= FALSE
;
395 lpdcb
->fOutxDsrFlow
= FALSE
;
396 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
397 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
401 lpdcb
->fOutX
= FALSE
;
402 lpdcb
->fOutxCtsFlow
= TRUE
;
403 lpdcb
->fOutxDsrFlow
= TRUE
;
404 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
405 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
411 /* This should be the end of the string. */
412 if(*device
) return FALSE
;
417 /***********************************************************************
418 * COMM_BuildNewCommDCB (Internal)
420 * Build a DCB using the new style settings string.
421 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
423 static BOOL
COMM_BuildNewCommDCB(LPCWSTR device
, LPDCB lpdcb
, LPCOMMTIMEOUTS lptimeouts
)
426 BOOL baud
= FALSE
, stop
= FALSE
;
427 static const WCHAR baudW
[] = {'b','a','u','d','=',0};
428 static const WCHAR parityW
[] = {'p','a','r','i','t','y','=',0};
429 static const WCHAR dataW
[] = {'d','a','t','a','=',0};
430 static const WCHAR stopW
[] = {'s','t','o','p','=',0};
431 static const WCHAR toW
[] = {'t','o','=',0};
432 static const WCHAR xonW
[] = {'x','o','n','=',0};
433 static const WCHAR odsrW
[] = {'o','d','s','r','=',0};
434 static const WCHAR octsW
[] = {'o','c','t','s','=',0};
435 static const WCHAR dtrW
[] = {'d','t','r','=',0};
436 static const WCHAR rtsW
[] = {'r','t','s','=',0};
437 static const WCHAR idsrW
[] = {'i','d','s','r','=',0};
441 while(*device
== ' ') device
++;
443 if(!strncmpiW(baudW
, device
, 5))
447 if(!(device
= COMM_ParseNumber(device
+ 5, &lpdcb
->BaudRate
)))
450 else if(!strncmpiW(parityW
, device
, 7))
452 if(!(device
= COMM_ParseParity(device
+ 7, &lpdcb
->Parity
)))
455 else if(!strncmpiW(dataW
, device
, 5))
457 if(!(device
= COMM_ParseByteSize(device
+ 5, &lpdcb
->ByteSize
)))
460 else if(!strncmpiW(stopW
, device
, 5))
464 if(!(device
= COMM_ParseStopBits(device
+ 5, &lpdcb
->StopBits
)))
467 else if(!strncmpiW(toW
, device
, 3))
469 if(!(device
= COMM_ParseOnOff(device
+ 3, &temp
)))
472 lptimeouts
->ReadIntervalTimeout
= 0;
473 lptimeouts
->ReadTotalTimeoutMultiplier
= 0;
474 lptimeouts
->ReadTotalTimeoutConstant
= 0;
475 lptimeouts
->WriteTotalTimeoutMultiplier
= 0;
476 lptimeouts
->WriteTotalTimeoutConstant
= temp
? 60000 : 0;
478 else if(!strncmpiW(xonW
, device
, 4))
480 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
486 else if(!strncmpiW(odsrW
, device
, 5))
488 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
491 lpdcb
->fOutxDsrFlow
= temp
;
493 else if(!strncmpiW(octsW
, device
, 5))
495 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
498 lpdcb
->fOutxCtsFlow
= temp
;
500 else if(!strncmpiW(dtrW
, device
, 4))
502 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
505 lpdcb
->fDtrControl
= temp
;
507 else if(!strncmpiW(rtsW
, device
, 4))
509 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
512 lpdcb
->fRtsControl
= temp
;
514 else if(!strncmpiW(idsrW
, device
, 5))
516 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
519 /* Win NT sets the fDsrSensitivity member based on the
520 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
521 lpdcb
->fDsrSensitivity
= temp
;
526 /* After the above parsing, the next character (if not the end of
527 the string) should be a space */
528 if(*device
&& *device
!= ' ')
532 /* If stop bits were not specified, a default is always supplied. */
535 if(baud
&& lpdcb
->BaudRate
== 110)
536 lpdcb
->StopBits
= TWOSTOPBITS
;
538 lpdcb
->StopBits
= ONESTOPBIT
;
544 /**************************************************************************
545 * BuildCommDCBA (KERNEL32.@)
547 * Updates a device control block data structure with values from an
548 * ascii device control string. The device control string has two forms
549 * normal and extended, it must be exclusively in one or the other form.
553 * True on success, false on a malformed control string.
555 BOOL WINAPI
BuildCommDCBA(
556 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
557 LPDCB lpdcb
) /* [out] The device control block to be updated. */
559 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
562 /**************************************************************************
563 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
565 * Updates a device control block data structure with values from an
566 * ascii device control string. Taking timeout values from a timeouts
567 * struct if desired by the control string.
571 * True on success, false bad handles etc.
573 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
574 LPCSTR device
, /* [in] The ascii device control string. */
575 LPDCB lpdcb
, /* [out] The device control block to be updated. */
576 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
579 UNICODE_STRING deviceW
;
581 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
582 if(device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
,device
);
583 else deviceW
.Buffer
= NULL
;
585 if(deviceW
.Buffer
) ret
= BuildCommDCBAndTimeoutsW(deviceW
.Buffer
,lpdcb
,lptimeouts
);
587 RtlFreeUnicodeString(&deviceW
);
591 /**************************************************************************
592 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
594 * Updates a device control block data structure with values from a
595 * unicode device control string. Taking timeout values from a timeouts
596 * struct if desired by the control string.
600 * True on success, false bad handles etc
602 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
603 LPCWSTR devid
, /* [in] The unicode device control string. */
604 LPDCB lpdcb
, /* [out] The device control block to be updated. */
605 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
608 COMMTIMEOUTS timeouts
;
612 TRACE("(%s,%p,%p)\n",debugstr_w(devid
),lpdcb
,lptimeouts
);
614 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
615 lpdcb
->DCBlength
= sizeof(DCB
);
617 /* Make a copy of the original data structures to work with since if
618 if there is an error in the device control string the originals
619 should not be modified (except possibly DCBlength) */
620 memcpy(&dcb
, lpdcb
, sizeof(DCB
));
621 if(lptimeouts
) memcpy(&timeouts
, lptimeouts
, sizeof(COMMTIMEOUTS
));
623 ptr
= COMM_ParseStart(ptr
);
627 else if(strchrW(ptr
, ','))
628 result
= COMM_BuildOldCommDCB(ptr
, &dcb
);
630 result
= COMM_BuildNewCommDCB(ptr
, &dcb
, &timeouts
);
634 memcpy(lpdcb
, &dcb
, sizeof(DCB
));
635 if(lptimeouts
) memcpy(lptimeouts
, &timeouts
, sizeof(COMMTIMEOUTS
));
640 WARN("Invalid device control string: %s\n", debugstr_w(devid
));
641 SetLastError(ERROR_INVALID_PARAMETER
);
646 /**************************************************************************
647 * BuildCommDCBW (KERNEL32.@)
649 * Updates a device control block structure with values from an
650 * unicode device control string. The device control string has two forms
651 * normal and extended, it must be exclusively in one or the other form.
655 * True on success, false on an malformed control string.
657 BOOL WINAPI
BuildCommDCBW(
658 LPCWSTR devid
, /* [in] The unicode device control string. */
659 LPDCB lpdcb
) /* [out] The device control block to be updated. */
661 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
664 static BOOL
COMM_SetCommError(HANDLE handle
, DWORD error
)
668 SERVER_START_REQ( set_serial_info
)
670 req
->handle
= handle
;
671 req
->flags
= SERIALINFO_SET_ERROR
;
672 req
->commerror
= error
;
673 ret
= !wine_server_call_err( req
);
679 static BOOL
COMM_GetCommError(HANDLE handle
, LPDWORD lperror
)
686 SERVER_START_REQ( get_serial_info
)
688 req
->handle
= handle
;
689 ret
= !wine_server_call_err( req
);
690 *lperror
= reply
->commerror
;
697 /*****************************************************************************
698 * SetCommBreak (KERNEL32.@)
700 * Halts the transmission of characters to a communications device.
704 * True on success, and false if the communications device could not be found,
705 * the control is not supported.
709 * Only TIOCSBRK and TIOCCBRK are supported.
711 BOOL WINAPI
SetCommBreak(
712 HANDLE handle
) /* [in] The communictions device to suspend. */
714 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
717 fd
= get_comm_fd( handle
, GENERIC_READ
);
718 if(fd
<0) return FALSE
;
719 result
= ioctl(fd
,TIOCSBRK
,0);
720 release_comm_fd( handle
, fd
);
723 TRACE("ioctl failed\n");
724 SetLastError(ERROR_NOT_SUPPORTED
);
729 FIXME("ioctl not available\n");
730 SetLastError(ERROR_NOT_SUPPORTED
);
735 /*****************************************************************************
736 * ClearCommBreak (KERNEL32.@)
738 * Resumes character transmission from a communication device.
742 * True on success and false if the communications device could not be found.
746 * Only TIOCSBRK and TIOCCBRK are supported.
748 BOOL WINAPI
ClearCommBreak(
749 HANDLE handle
) /* [in] The halted communication device whose character transmission is to be resumed. */
751 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
754 fd
= get_comm_fd( handle
, GENERIC_READ
);
755 if(fd
<0) return FALSE
;
756 result
= ioctl(fd
,TIOCCBRK
,0);
757 release_comm_fd( handle
, fd
);
760 TRACE("ioctl failed\n");
761 SetLastError(ERROR_NOT_SUPPORTED
);
766 FIXME("ioctl not available\n");
767 SetLastError(ERROR_NOT_SUPPORTED
);
772 /*****************************************************************************
773 * EscapeCommFunction (KERNEL32.@)
775 * Directs a communication device to perform an extended function.
779 * True or requested data on successful completion of the command,
780 * false if the device is not present cannot execute the command
781 * or the command failed.
783 BOOL WINAPI
EscapeCommFunction(
784 HANDLE handle
, /* [in] The communication device to perform the extended function. */
785 UINT nFunction
) /* [in] The extended function to be performed. */
787 int fd
,direct
=FALSE
,result
=FALSE
;
790 TRACE("handle %p, function=%d\n", handle
, nFunction
);
791 fd
= get_comm_fd( handle
, GENERIC_READ
);
792 if(fd
<0) return FALSE
;
794 if (tcgetattr(fd
,&port
) == -1) {
795 COMM_SetCommError(handle
,CE_IOE
);
796 release_comm_fd( handle
, fd
);
809 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
817 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
825 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
833 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
839 port
.c_iflag
|= IXOFF
;
844 port
.c_iflag
|= IXON
;
850 result
= ioctl(fd
,TIOCSBRK
,0);
857 result
= ioctl(fd
,TIOCCBRK
,0);
861 WARN("(handle=%p,nFunction=%d): Unknown function\n",
867 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
868 release_comm_fd( handle
, fd
);
869 COMM_SetCommError(handle
,CE_IOE
);
878 COMM_SetCommError(handle
,CE_IOE
);
883 release_comm_fd( handle
, fd
);
887 /********************************************************************
888 * PurgeComm (KERNEL32.@)
890 * Terminates pending operations and/or discards buffers on a
891 * communication resource.
895 * True on success and false if the communications handle is bad.
897 BOOL WINAPI
PurgeComm(
898 HANDLE handle
, /* [in] The communication resource to be purged. */
899 DWORD flags
) /* [in] Flags for clear pending/buffer on input/output. */
903 TRACE("handle %p, flags %lx\n", handle
, flags
);
905 fd
= get_comm_fd( handle
, GENERIC_READ
);
906 if(fd
<0) return FALSE
;
909 ** not exactly sure how these are different
910 ** Perhaps if we had our own internal queues, one flushes them
911 ** and the other flushes the kernel's buffers.
913 if(flags
&PURGE_TXABORT
)
914 tcflush(fd
,TCOFLUSH
);
915 if(flags
&PURGE_RXABORT
)
916 tcflush(fd
,TCIFLUSH
);
917 if(flags
&PURGE_TXCLEAR
)
918 tcflush(fd
,TCOFLUSH
);
919 if(flags
&PURGE_RXCLEAR
)
920 tcflush(fd
,TCIFLUSH
);
921 release_comm_fd( handle
, fd
);
926 /*****************************************************************************
927 * ClearCommError (KERNEL32.@)
929 * Enables further I/O operations on a communications resource after
930 * supplying error and current status information.
934 * True on success, false if the communication resource handle is bad.
936 BOOL WINAPI
ClearCommError(
937 HANDLE handle
, /* [in] The communication resource with the error. */
938 LPDWORD errors
, /* [out] Flags indicating error the resource experienced. */
939 LPCOMSTAT lpStat
) /* [out] The status of the communication resource. */
943 fd
=get_comm_fd( handle
, GENERIC_READ
);
944 if(0>fd
) return FALSE
;
948 lpStat
->fCtsHold
= 0;
949 lpStat
->fDsrHold
= 0;
950 lpStat
->fRlsdHold
= 0;
951 lpStat
->fXoffHold
= 0;
952 lpStat
->fXoffSent
= 0;
955 lpStat
->fReserved
= 0;
958 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
959 WARN("ioctl returned error\n");
961 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
965 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
966 WARN("ioctl returned error\n");
969 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
970 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
973 release_comm_fd( handle
, fd
);
975 COMM_GetCommError(handle
, errors
);
976 COMM_SetCommError(handle
, 0);
981 /*****************************************************************************
982 * SetupComm (KERNEL32.@)
984 * Called after CreateFile to hint to the communication resource to use
985 * specified sizes for input and output buffers rather than the default values.
989 * True if successful, false if the communications resource handle is bad.
995 BOOL WINAPI
SetupComm(
996 HANDLE handle
, /* [in] The just created communication resource handle. */
997 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
998 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
1002 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1003 fd
=get_comm_fd( handle
, GENERIC_READ
);
1004 if(0>fd
) return FALSE
;
1005 release_comm_fd( handle
, fd
);
1009 /*****************************************************************************
1010 * GetCommMask (KERNEL32.@)
1012 * Obtain the events associated with a communication device that will cause
1013 * a call WaitCommEvent to return.
1017 * True on success, fail on bad device handle etc.
1019 BOOL WINAPI
GetCommMask(
1020 HANDLE handle
, /* [in] The communications device. */
1021 LPDWORD evtmask
) /* [out] The events which cause WaitCommEvent to return. */
1025 TRACE("handle %p, mask %p\n", handle
, evtmask
);
1027 SERVER_START_REQ( get_serial_info
)
1029 req
->handle
= handle
;
1030 if ((ret
= !wine_server_call_err( req
)))
1032 if (evtmask
) *evtmask
= reply
->eventmask
;
1039 /*****************************************************************************
1040 * SetCommMask (KERNEL32.@)
1042 * There be some things we need to hear about yon there communications device.
1043 * (Set which events associated with a communication device should cause
1044 * a call WaitCommEvent to return.)
1048 * True on success, false on bad handle etc.
1050 BOOL WINAPI
SetCommMask(
1051 HANDLE handle
, /* [in] The communications device. */
1052 DWORD evtmask
) /* [in] The events that are to be monitored. */
1056 TRACE("handle %p, mask %lx\n", handle
, evtmask
);
1058 SERVER_START_REQ( set_serial_info
)
1060 req
->handle
= handle
;
1061 req
->flags
= SERIALINFO_SET_MASK
;
1062 req
->eventmask
= evtmask
;
1063 ret
= !wine_server_call_err( req
);
1069 /*****************************************************************************
1070 * SetCommState (KERNEL32.@)
1072 * Re-initializes all hardware and control settings of a communications device,
1073 * with values from a device control block without effecting the input and output
1078 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1080 BOOL WINAPI
SetCommState(
1081 HANDLE handle
, /* [in] The communications device. */
1082 LPDCB lpdcb
) /* [out] The device control block. */
1084 struct termios port
;
1085 int fd
, bytesize
, stopbits
;
1088 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1089 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1090 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1091 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1092 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1093 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1094 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1095 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1096 lpdcb
->fRtsControl
);
1097 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1098 lpdcb
->fDtrControl
);
1101 fd
= get_comm_fd( handle
, GENERIC_READ
);
1102 if (fd
< 0) return FALSE
;
1104 if ((tcgetattr(fd
,&port
)) == -1) {
1105 int save_error
= errno
;
1106 COMM_SetCommError(handle
,CE_IOE
);
1107 release_comm_fd( handle
, fd
);
1108 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1112 port
.c_cc
[VMIN
] = 0;
1113 port
.c_cc
[VTIME
] = 1;
1116 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1118 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1120 port
.c_iflag
|= (IGNBRK
);
1122 port
.c_oflag
&= ~(OPOST
);
1124 port
.c_cflag
&= ~(HUPCL
);
1125 port
.c_cflag
|= CLOCAL
| CREAD
;
1127 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1128 port
.c_lflag
|= NOFLSH
;
1131 port
.c_cflag
&= ~CBAUD
;
1132 switch (lpdcb
->BaudRate
) {
1137 port
.c_cflag
|= B50
;
1140 port
.c_cflag
|= B75
;
1144 port
.c_cflag
|= B110
;
1147 port
.c_cflag
|= B134
;
1150 port
.c_cflag
|= B150
;
1153 port
.c_cflag
|= B200
;
1157 port
.c_cflag
|= B300
;
1161 port
.c_cflag
|= B600
;
1165 port
.c_cflag
|= B1200
;
1168 port
.c_cflag
|= B1800
;
1172 port
.c_cflag
|= B2400
;
1176 port
.c_cflag
|= B4800
;
1180 port
.c_cflag
|= B9600
;
1184 port
.c_cflag
|= B19200
;
1188 port
.c_cflag
|= B38400
;
1192 port
.c_cflag
|= B57600
;
1197 port
.c_cflag
|= B115200
;
1202 port
.c_cflag
|= B230400
;
1207 port
.c_cflag
|= B460800
;
1211 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1212 { struct serial_struct nuts
;
1214 ioctl(fd
, TIOCGSERIAL
, &nuts
);
1215 nuts
.custom_divisor
= nuts
.baud_base
/ lpdcb
->BaudRate
;
1216 if (!(nuts
.custom_divisor
)) nuts
.custom_divisor
= 1;
1217 arby
= nuts
.baud_base
/ nuts
.custom_divisor
;
1218 nuts
.flags
&= ~ASYNC_SPD_MASK
;
1219 nuts
.flags
|= ASYNC_SPD_CUST
;
1220 WARN("You (or a program acting at your behest) have specified\n"
1221 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1222 "which is as close as we can get by our present understanding of your\n"
1223 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1224 "has caused to your linux system can be undone with setserial \n"
1225 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1226 "reset it and it will probably recover.\n", lpdcb
->BaudRate
, arby
);
1227 ioctl(fd
, TIOCSSERIAL
, &nuts
);
1228 port
.c_cflag
|= B38400
;
1231 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1234 COMM_SetCommError(handle
,IE_BAUDRATE
);
1235 release_comm_fd( handle
, fd
);
1236 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1239 #elif !defined(__EMX__)
1240 switch (lpdcb
->BaudRate
) {
1245 port
.c_ospeed
= B50
;
1248 port
.c_ospeed
= B75
;
1252 port
.c_ospeed
= B110
;
1255 port
.c_ospeed
= B134
;
1258 port
.c_ospeed
= B150
;
1261 port
.c_ospeed
= B200
;
1265 port
.c_ospeed
= B300
;
1269 port
.c_ospeed
= B600
;
1273 port
.c_ospeed
= B1200
;
1276 port
.c_ospeed
= B1800
;
1280 port
.c_ospeed
= B2400
;
1284 port
.c_ospeed
= B4800
;
1288 port
.c_ospeed
= B9600
;
1292 port
.c_ospeed
= B19200
;
1296 port
.c_ospeed
= B38400
;
1301 port
.c_cflag
|= B57600
;
1307 port
.c_cflag
|= B115200
;
1312 port
.c_cflag
|= B230400
;
1317 port
.c_cflag
|= B460800
;
1321 COMM_SetCommError(handle
,IE_BAUDRATE
);
1322 release_comm_fd( handle
, fd
);
1323 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1326 port
.c_ispeed
= port
.c_ospeed
;
1328 bytesize
=lpdcb
->ByteSize
;
1329 stopbits
=lpdcb
->StopBits
;
1332 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1334 port
.c_cflag
&= ~(PARENB
| PARODD
);
1337 port
.c_iflag
|= INPCK
;
1339 port
.c_iflag
&= ~INPCK
;
1340 switch (lpdcb
->Parity
) {
1344 port
.c_cflag
|= (PARENB
| PARODD
);
1347 port
.c_cflag
|= PARENB
;
1350 /* Linux defines mark/space (stick) parity */
1352 port
.c_cflag
|= (PARENB
| CMSPAR
);
1355 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1358 /* try the POSIX way */
1360 if( stopbits
== ONESTOPBIT
) {
1361 stopbits
= TWOSTOPBITS
;
1362 port
.c_iflag
&= ~INPCK
;
1364 COMM_SetCommError(handle
,IE_BYTESIZE
);
1365 release_comm_fd( handle
, fd
);
1366 ERR("Cannot set MARK Parity\n");
1373 port
.c_iflag
&= ~INPCK
;
1375 COMM_SetCommError(handle
,IE_BYTESIZE
);
1376 release_comm_fd( handle
, fd
);
1377 ERR("Cannot set SPACE Parity\n");
1383 COMM_SetCommError(handle
,IE_BYTESIZE
);
1384 release_comm_fd( handle
, fd
);
1390 port
.c_cflag
&= ~CSIZE
;
1393 port
.c_cflag
|= CS5
;
1396 port
.c_cflag
|= CS6
;
1399 port
.c_cflag
|= CS7
;
1402 port
.c_cflag
|= CS8
;
1405 COMM_SetCommError(handle
,IE_BYTESIZE
);
1406 release_comm_fd( handle
, fd
);
1413 port
.c_cflag
&= ~CSTOPB
;
1415 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
1417 port
.c_cflag
|= CSTOPB
;
1420 COMM_SetCommError(handle
,IE_BYTESIZE
);
1421 release_comm_fd( handle
, fd
);
1426 if ( lpdcb
->fOutxCtsFlow
||
1427 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1430 port
.c_cflag
|= CRTSCTS
;
1436 port
.c_iflag
|= IXON
;
1438 port
.c_iflag
&= ~IXON
;
1440 port
.c_iflag
|= IXOFF
;
1442 port
.c_iflag
&= ~IXOFF
;
1444 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
1445 ERR("tcsetattr error '%s'\n", strerror(errno
));
1446 COMM_SetCommError(handle
,CE_IOE
);
1449 COMM_SetCommError(handle
,0);
1453 /* note: change DTR/RTS lines after setting the comm attributes,
1454 * so flow control does not interfere. */
1456 if (lpdcb
->fDtrControl
== DTR_CONTROL_HANDSHAKE
)
1458 WARN("DSR/DTR flow control not supported\n");
1459 } else if(lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
1460 COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1462 COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1465 if(!lpdcb
->fOutxCtsFlow
)
1467 if(lpdcb
->fRtsControl
== RTS_CONTROL_DISABLE
)
1468 COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1470 COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1473 if(lpdcb
->fRtsControl
== RTS_CONTROL_TOGGLE
)
1474 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1475 release_comm_fd( handle
, fd
);
1481 /*****************************************************************************
1482 * GetCommState (KERNEL32.@)
1484 * Fills in a device control block with information from a communications device.
1488 * True on success, false if the communication device handle is bad etc
1492 * XonChar and XoffChar are not set.
1494 BOOL WINAPI
GetCommState(
1495 HANDLE handle
, /* [in] The communications device. */
1496 LPDCB lpdcb
) /* [out] The device control block. */
1498 struct termios port
;
1500 int stat
= DTR_CONTROL_ENABLE
| RTS_CONTROL_ENABLE
;
1502 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1504 fd
= get_comm_fd( handle
, GENERIC_READ
);
1505 if (fd
< 0) return FALSE
;
1506 if (tcgetattr(fd
, &port
) == -1
1508 || ioctl(fd
, TIOCMGET
, &stat
) == -1
1511 int save_error
=errno
;
1512 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error
));
1513 COMM_SetCommError(handle
,CE_IOE
);
1514 release_comm_fd( handle
, fd
);
1517 release_comm_fd( handle
, fd
);
1520 speed
= (port
.c_cflag
& CBAUD
);
1522 speed
= (cfgetospeed(&port
));
1526 lpdcb
->BaudRate
= 0;
1529 lpdcb
->BaudRate
= 50;
1532 lpdcb
->BaudRate
= 75;
1535 lpdcb
->BaudRate
= 110;
1538 lpdcb
->BaudRate
= 134;
1541 lpdcb
->BaudRate
= 150;
1544 lpdcb
->BaudRate
= 200;
1547 lpdcb
->BaudRate
= 300;
1550 lpdcb
->BaudRate
= 600;
1553 lpdcb
->BaudRate
= 1200;
1556 lpdcb
->BaudRate
= 1800;
1559 lpdcb
->BaudRate
= 2400;
1562 lpdcb
->BaudRate
= 4800;
1565 lpdcb
->BaudRate
= 9600;
1568 lpdcb
->BaudRate
= 19200;
1571 lpdcb
->BaudRate
= 38400;
1575 lpdcb
->BaudRate
= 57600;
1580 lpdcb
->BaudRate
= 115200;
1585 lpdcb
->BaudRate
= 230400;
1590 lpdcb
->BaudRate
= 460800;
1594 ERR("unknown speed %x \n",speed
);
1597 switch (port
.c_cflag
& CSIZE
) {
1599 lpdcb
->ByteSize
= 5;
1602 lpdcb
->ByteSize
= 6;
1605 lpdcb
->ByteSize
= 7;
1608 lpdcb
->ByteSize
= 8;
1611 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
1614 if(port
.c_iflag
& INPCK
)
1615 lpdcb
->fParity
= TRUE
;
1617 lpdcb
->fParity
= FALSE
;
1619 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1621 switch (port
.c_cflag
& (PARENB
| PARODD
))
1625 lpdcb
->Parity
= NOPARITY
;
1628 lpdcb
->Parity
= EVENPARITY
;
1630 case (PARENB
| PARODD
):
1631 lpdcb
->Parity
= ODDPARITY
;
1634 case (PARENB
| CMSPAR
):
1635 lpdcb
->Parity
= MARKPARITY
;
1637 case (PARENB
| PARODD
| CMSPAR
):
1638 lpdcb
->Parity
= SPACEPARITY
;
1643 if (port
.c_cflag
& CSTOPB
)
1644 if(lpdcb
->ByteSize
== 5)
1645 lpdcb
->StopBits
= ONE5STOPBITS
;
1647 lpdcb
->StopBits
= TWOSTOPBITS
;
1649 lpdcb
->StopBits
= ONESTOPBIT
;
1654 /* termios does not support DTR/DSR flow control */
1655 lpdcb
->fOutxDsrFlow
= 0;
1656 lpdcb
->fDtrControl
=
1658 !(stat
& TIOCM_DTR
) ? DTR_CONTROL_DISABLE
:
1660 DTR_CONTROL_ENABLE
;
1664 if (port
.c_cflag
& CRTSCTS
) {
1665 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1666 lpdcb
->fOutxCtsFlow
= 1;
1670 lpdcb
->fRtsControl
=
1672 !(stat
& TIOCM_RTS
) ? RTS_CONTROL_DISABLE
:
1674 RTS_CONTROL_ENABLE
;
1675 lpdcb
->fOutxCtsFlow
= 0;
1677 if (port
.c_iflag
& IXON
)
1682 if (port
.c_iflag
& IXOFF
)
1691 lpdcb
->XoffLim
= 10;
1693 COMM_SetCommError(handle
,0);
1697 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1698 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1699 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1700 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1701 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1702 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1703 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1704 lpdcb
->fRtsControl
);
1705 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1706 lpdcb
->fDtrControl
);
1708 if ( lpdcb
->fOutxCtsFlow
||
1709 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1714 TRACE("~CRTSCTS\n");
1719 /*****************************************************************************
1720 * TransmitCommChar (KERNEL32.@)
1722 * Transmits a single character in front of any pending characters in the
1723 * output buffer. Usually used to send an interrupt character to a host.
1727 * True if the call succeeded, false if the previous command character to the
1728 * same device has not been sent yet the handle is bad etc.
1734 BOOL WINAPI
TransmitCommChar(
1735 HANDLE hComm
, /* [in] The communication device in need of a command character. */
1736 CHAR chTransmit
) /* [in] The character to transmit. */
1739 WARN("(%p,'%c') not perfect!\n",hComm
,chTransmit
);
1741 return WriteFile( hComm
, &chTransmit
, 1, &w
, NULL
);
1745 /*****************************************************************************
1746 * GetCommTimeouts (KERNEL32.@)
1748 * Obtains the request timeout values for the communications device.
1752 * True on success, false if communications device handle is bad
1753 * or the target structure is null.
1755 BOOL WINAPI
GetCommTimeouts(
1756 HANDLE hComm
, /* [in] The communications device. */
1757 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request timeouts. */
1761 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1765 SetLastError(ERROR_INVALID_PARAMETER
);
1769 SERVER_START_REQ( get_serial_info
)
1771 req
->handle
= hComm
;
1772 if ((ret
= !wine_server_call_err( req
)))
1774 lptimeouts
->ReadIntervalTimeout
= reply
->readinterval
;
1775 lptimeouts
->ReadTotalTimeoutMultiplier
= reply
->readmult
;
1776 lptimeouts
->ReadTotalTimeoutConstant
= reply
->readconst
;
1777 lptimeouts
->WriteTotalTimeoutMultiplier
= reply
->writemult
;
1778 lptimeouts
->WriteTotalTimeoutConstant
= reply
->writeconst
;
1785 /*****************************************************************************
1786 * SetCommTimeouts (KERNEL32.@)
1788 * Sets the timeouts used when reading and writing data to/from COMM ports.
1790 * ReadIntervalTimeout
1791 * - converted and passes to linux kernel as c_cc[VTIME]
1792 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1793 * - used in ReadFile to calculate GetOverlappedResult's timeout
1794 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1795 * - used in WriteFile to calculate GetOverlappedResult's timeout
1799 * True if the timeouts were set, false otherwise.
1801 BOOL WINAPI
SetCommTimeouts(
1802 HANDLE hComm
, /* [in] handle of COMM device */
1803 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
1807 struct termios tios
;
1809 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1813 SetLastError(ERROR_INVALID_PARAMETER
);
1817 SERVER_START_REQ( set_serial_info
)
1819 req
->handle
= hComm
;
1820 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
1821 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
1822 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
1823 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
1824 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
1825 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
1826 ret
= !wine_server_call_err( req
);
1829 if (!ret
) return FALSE
;
1831 /* FIXME: move this stuff to the server */
1832 fd
= get_comm_fd( hComm
, GENERIC_READ
);
1833 if (fd
< 0) return FALSE
;
1835 if (-1==tcgetattr(fd
,&tios
)) {
1836 FIXME("tcgetattr on fd %d failed!\n",fd
);
1837 release_comm_fd( hComm
, fd
);
1841 /* VTIME is in 1/10 seconds */
1843 unsigned int ux_timeout
;
1845 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
1851 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
1854 ux_timeout
= 1; /* must be at least some timeout */
1857 tios
.c_cc
[VTIME
] = ux_timeout
;
1860 if (-1==tcsetattr(fd
,0,&tios
)) {
1861 FIXME("tcsetattr on fd %d failed!\n",fd
);
1862 release_comm_fd( hComm
, fd
);
1865 release_comm_fd( hComm
, fd
);
1869 /***********************************************************************
1870 * GetCommModemStatus (KERNEL32.@)
1872 * Obtains the four control register bits if supported by the hardware.
1876 * True if the communications handle was good and for hardware that
1877 * control register access, false otherwise.
1879 BOOL WINAPI
GetCommModemStatus(
1880 HANDLE hFile
, /* [in] The communications device. */
1881 LPDWORD lpModemStat
) /* [out] The control register bits. */
1883 int fd
,mstat
, result
=FALSE
;
1887 fd
= get_comm_fd( hFile
, GENERIC_READ
);
1890 result
= ioctl(fd
, TIOCMGET
, &mstat
);
1891 release_comm_fd( hFile
, fd
);
1894 WARN("ioctl failed\n");
1898 if (mstat
& TIOCM_CTS
)
1899 *lpModemStat
|= MS_CTS_ON
;
1902 if (mstat
& TIOCM_DSR
)
1903 *lpModemStat
|= MS_DSR_ON
;
1906 if (mstat
& TIOCM_RNG
)
1907 *lpModemStat
|= MS_RING_ON
;
1910 /*FIXME: Not really sure about RLSD UB 990810*/
1911 if (mstat
& TIOCM_CAR
)
1912 *lpModemStat
|= MS_RLSD_ON
;
1914 TRACE("%04x -> %s%s%s%s\n", mstat
,
1915 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
1916 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
1917 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
1918 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
1925 /***********************************************************************
1926 * COMM_WaitCommEventService (INTERNAL)
1928 * This function is called while the client is waiting on the
1929 * server, so we can't make any server calls here.
1931 static void COMM_WaitCommEventService(async_private
*ovp
)
1933 async_commio
*commio
= (async_commio
*) ovp
;
1934 IO_STATUS_BLOCK
* iosb
= commio
->async
.iosb
;
1936 TRACE("iosb %p\n",iosb
);
1938 /* FIXME: detect other events */
1939 *commio
->buffer
= EV_RXCHAR
;
1941 iosb
->u
.Status
= STATUS_SUCCESS
;
1945 /***********************************************************************
1946 * COMM_WaitCommEvent (INTERNAL)
1948 * This function must have an lpOverlapped.
1950 static BOOL
COMM_WaitCommEvent(
1951 HANDLE hFile
, /* [in] handle of comm port to wait for */
1952 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1953 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1960 SetLastError(ERROR_INVALID_PARAMETER
);
1964 if(NtResetEvent(lpOverlapped
->hEvent
,NULL
))
1967 fd
= get_comm_fd( hFile
, GENERIC_WRITE
);
1971 ovp
= (async_commio
*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio
));
1974 release_comm_fd( hFile
, fd
);
1978 ovp
->async
.ops
= &commio_async_ops
;
1979 ovp
->async
.handle
= hFile
;
1980 ovp
->async
.fd
= fd
; /* FIXME */
1981 ovp
->async
.type
= ASYNC_TYPE_WAIT
;
1982 ovp
->async
.func
= COMM_WaitCommEventService
;
1983 ovp
->async
.event
= lpOverlapped
->hEvent
;
1984 ovp
->async
.iosb
= (IO_STATUS_BLOCK
*)lpOverlapped
;
1985 ovp
->buffer
= (char *)lpdwEvents
;
1987 lpOverlapped
->InternalHigh
= 0;
1988 lpOverlapped
->Offset
= 0;
1989 lpOverlapped
->OffsetHigh
= 0;
1991 if ( !register_new_async (&ovp
->async
) )
1992 SetLastError( ERROR_IO_PENDING
);
1997 /***********************************************************************
1998 * WaitCommEvent (KERNEL32.@)
2000 * Wait until something interesting happens on a COMM port.
2001 * Interesting things (events) are set by calling SetCommMask before
2002 * this function is called.
2005 * TRUE if successful
2008 * The set of detected events will be written to *lpdwEventMask
2009 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2012 * Only supports EV_RXCHAR and EV_TXEMPTY
2014 BOOL WINAPI
WaitCommEvent(
2015 HANDLE hFile
, /* [in] handle of comm port to wait for */
2016 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2017 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2022 TRACE("(%p %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
2025 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
2027 /* if there is no overlapped structure, create our own */
2028 ov
.hEvent
= CreateEventW(NULL
,FALSE
,FALSE
,NULL
);
2030 COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
2032 /* wait for the overlapped to complete */
2033 ret
= GetOverlappedResult(hFile
, &ov
, NULL
, TRUE
);
2034 CloseHandle(ov
.hEvent
);
2039 /***********************************************************************
2040 * GetCommProperties (KERNEL32.@)
2042 * This function fills in a structure with the capabilities of the
2043 * communications port driver.
2047 * TRUE on success, FALSE on failure
2048 * If successful, the lpCommProp structure be filled in with
2049 * properties of the comm port.
2051 BOOL WINAPI
GetCommProperties(
2052 HANDLE hFile
, /* [in] handle of the comm port */
2053 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
2055 FIXME("(%p %p )\n",hFile
,lpCommProp
);
2060 * These values should be valid for LINUX's serial driver
2061 * FIXME: Perhaps they deserve an #ifdef LINUX
2063 memset(lpCommProp
,0,sizeof(COMMPROP
));
2064 lpCommProp
->wPacketLength
= 1;
2065 lpCommProp
->wPacketVersion
= 1;
2066 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
2067 lpCommProp
->dwReserved1
= 0;
2068 lpCommProp
->dwMaxTxQueue
= 4096;
2069 lpCommProp
->dwMaxRxQueue
= 4096;
2070 lpCommProp
->dwMaxBaud
= BAUD_115200
;
2071 lpCommProp
->dwProvSubType
= PST_RS232
;
2072 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
| PCF_TOTALTIMEOUTS
;
2073 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
2074 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
2075 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
2076 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
2077 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
2078 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
2079 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
2080 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
2081 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
2082 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
2087 /***********************************************************************
2089 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2090 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2091 * This is dependent on the type of COMM port, but since it is doubtful
2092 * anybody will get around to implementing support for fancy serial
2093 * ports in WINE, this is hardcoded for the time being. The name of
2094 * this DLL should be stored in and read from the system registry in
2095 * the hive HKEY_LOCAL_MACHINE, key
2096 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2097 * where ???? is the port number... that is determined by PNP
2098 * The DLL should be loaded when the COMM port is opened, and closed
2099 * when the COMM port is closed. - MJM 20 June 2000
2100 ***********************************************************************/
2101 static WCHAR lpszSerialUI
[] = {
2102 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2105 /***********************************************************************
2106 * CommConfigDialogA (KERNEL32.@)
2108 * Raises a dialog that allows the user to configure a comm port.
2109 * Fills the COMMCONFIG struct with information specified by the user.
2110 * This function should call a similar routine in the COMM driver...
2114 * TRUE on success, FALSE on failure
2115 * If successful, the lpCommConfig structure will contain a new
2116 * configuration for the comm port, as specified by the user.
2119 * The library with the CommConfigDialog code is never unloaded.
2120 * Perhaps this should be done when the comm port is closed?
2122 BOOL WINAPI
CommConfigDialogA(
2123 LPCSTR lpszDevice
, /* [in] name of communications device */
2124 HANDLE hWnd
, /* [in] parent window for the dialog */
2125 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2127 FARPROC lpfnCommDialog
;
2128 HMODULE hConfigModule
;
2131 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2133 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2137 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogA");
2140 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2142 FreeLibrary(hConfigModule
);
2147 /***********************************************************************
2148 * CommConfigDialogW (KERNEL32.@)
2150 * see CommConfigDialogA for more info
2152 BOOL WINAPI
CommConfigDialogW(
2153 LPCWSTR lpszDevice
, /* [in] name of communications device */
2154 HANDLE hWnd
, /* [in] parent window for the dialog */
2155 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2157 FARPROC lpfnCommDialog
;
2158 HMODULE hConfigModule
;
2161 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2163 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2167 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogW");
2170 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2172 FreeLibrary(hConfigModule
);
2177 /***********************************************************************
2178 * GetCommConfig (KERNEL32.@)
2180 * Fill in the COMMCONFIG structure for the comm port hFile
2184 * TRUE on success, FALSE on failure
2185 * If successful, lpCommConfig contains the comm port configuration.
2190 BOOL WINAPI
GetCommConfig(
2191 HANDLE hFile
, /* [in] The communications device. */
2192 LPCOMMCONFIG lpCommConfig
, /* [out] The communications configuration of the device (if it fits). */
2193 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
2194 afterwards the number of bytes copied to the buffer or
2195 the needed size of the buffer. */
2199 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2201 if(lpCommConfig
== NULL
)
2203 r
= *lpdwSize
< sizeof(COMMCONFIG
); /* TRUE if not enough space */
2204 *lpdwSize
= sizeof(COMMCONFIG
);
2208 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
2209 lpCommConfig
->wVersion
= 1;
2210 lpCommConfig
->wReserved
= 0;
2211 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
2212 lpCommConfig
->dwProviderSubType
= PST_RS232
;
2213 lpCommConfig
->dwProviderOffset
= 0;
2214 lpCommConfig
->dwProviderSize
= 0;
2219 /***********************************************************************
2220 * SetCommConfig (KERNEL32.@)
2222 * Sets the configuration of the communications device.
2226 * True on success, false if the handle was bad is not a communications device.
2228 BOOL WINAPI
SetCommConfig(
2229 HANDLE hFile
, /* [in] The communications device. */
2230 LPCOMMCONFIG lpCommConfig
, /* [in] The desired configuration. */
2231 DWORD dwSize
) /* [in] size of the lpCommConfig struct */
2233 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2234 return SetCommState(hFile
,&lpCommConfig
->dcb
);
2237 /***********************************************************************
2238 * SetDefaultCommConfigA (KERNEL32.@)
2240 * Initializes the default configuration for the specified communication
2245 * True if the device was found and the defaults set, false otherwise
2247 BOOL WINAPI
SetDefaultCommConfigW(
2248 LPCWSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
2249 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2250 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2252 FARPROC lpfnSetDefaultCommConfig
;
2253 HMODULE hConfigModule
;
2256 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
2258 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2262 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvSetDefaultCommConfigW");
2263 if (lpfnSetDefaultCommConfig
)
2264 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
2266 FreeLibrary(hConfigModule
);
2272 /***********************************************************************
2273 * SetDefaultCommConfigW (KERNEL32.@)
2275 * Initializes the default configuration for the specified
2276 * communication device. (unicode)
2281 BOOL WINAPI
SetDefaultCommConfigA(
2282 LPCSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
2283 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2284 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2287 LPWSTR lpDeviceW
= NULL
;
2290 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice
),lpCommConfig
,dwSize
);
2294 len
= MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, NULL
, 0 );
2295 lpDeviceW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
2296 MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, lpDeviceW
, len
);
2298 r
= SetDefaultCommConfigW(lpDeviceW
,lpCommConfig
,dwSize
);
2299 HeapFree( GetProcessHeap(), 0, lpDeviceW
);
2304 /***********************************************************************
2305 * GetDefaultCommConfigW (KERNEL32.@)
2307 * Acquires the default configuration of the specified communication device. (unicode)
2311 * True on successful reading of the default configuration,
2312 * if the device is not found or the buffer is too small.
2314 BOOL WINAPI
GetDefaultCommConfigW(
2315 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
2316 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2317 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2318 afterwards the number of bytes copied to the buffer or
2319 the needed size of the buffer. */
2321 LPDCB lpdcb
= &(lpCC
->dcb
);
2323 static const WCHAR comW
[] = {'C','O','M',0};
2324 static const WCHAR formatW
[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2326 if (strncmpiW(lpszName
,comW
,3)) {
2327 ERR("not implemented for <%s>\n", debugstr_w(lpszName
));
2331 TRACE("(%s %p %ld)\n", debugstr_w(lpszName
), lpCC
, *lpdwSize
);
2332 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
2333 *lpdwSize
= sizeof(COMMCONFIG
);
2337 *lpdwSize
= sizeof(COMMCONFIG
);
2339 lpCC
->dwSize
= sizeof(COMMCONFIG
);
2341 lpCC
->dwProviderSubType
= PST_RS232
;
2342 lpCC
->dwProviderOffset
= 0L;
2343 lpCC
->dwProviderSize
= 0L;
2345 sprintfW( temp
, formatW
, lpszName
[3]);
2346 FIXME("setting %s as default\n", debugstr_w(temp
));
2348 return BuildCommDCBW( temp
, lpdcb
);
2351 /**************************************************************************
2352 * GetDefaultCommConfigA (KERNEL32.@)
2354 * Acquires the default configuration of the specified communication device. (ascii)
2358 * True on successful reading of the default configuration,
2359 * if the device is not found or the buffer is too small.
2361 BOOL WINAPI
GetDefaultCommConfigA(
2362 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
2363 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2364 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2365 afterwards the number of bytes copied to the buffer or
2366 the needed size of the buffer. */
2369 UNICODE_STRING lpszNameW
;
2371 TRACE("(%s,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
2372 if(lpszName
) RtlCreateUnicodeStringFromAsciiz(&lpszNameW
,lpszName
);
2373 else lpszNameW
.Buffer
= NULL
;
2375 if(lpszNameW
.Buffer
) ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
2377 RtlFreeUnicodeString(&lpszNameW
);