2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
23 * - Fixed the modem control part of EscapeCommFunction16.
25 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
26 * - Implemented buffers and EnableCommNotification.
28 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
29 * - Use port indices instead of unixfds for win16
30 * - Moved things around (separated win16 and win32 routines)
31 * - Added some hints on how to implement buffers and EnableCommNotification.
33 * Oktober 98, Rein Klazes [RHK]
34 * A program that wants to monitor the modem status line (RLSD/DCD) may
35 * poll the modem status register in the commMask structure. I update the bit
36 * in GetCommError, waiting for an implementation of communication events.
38 * July 6, 1998. Fixes and comments by Valentijn Sessink
39 * <vsessink@ic.uva.nl> [V]
41 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
42 * <lawson_whitney@juno.com>
44 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
45 * - ptr->fd wasn't getting cleared on close.
46 * - GetCommEventMask() and GetCommError() didn't do much of anything.
47 * IMHO, they are still wrong, but they at least implement the RXCHAR
48 * event and return I/O queue sizes, which makes the app I'm interested
49 * in (analog devices EZKIT DSP development system) work.
53 #include "wine/port.h"
69 #ifdef HAVE_SYS_FILIO_H
70 # include <sys/filio.h>
72 #ifdef HAVE_SYS_IOCTL_H
73 #include <sys/ioctl.h>
78 #ifdef HAVE_SYS_POLL_H
79 # include <sys/poll.h>
81 #ifdef HAVE_SYS_MODEM_H
82 # include <sys/modem.h>
84 #ifdef HAVE_SYS_STRTIO_H
85 # include <sys/strtio.h>
88 #define NONAMELESSUNION
89 #define NONAMELESSSTRUCT
95 #include "wine/server.h"
98 #include "wine/unicode.h"
100 #include "wine/debug.h"
102 #ifdef HAVE_LINUX_SERIAL_H
103 #include <linux/serial.h>
106 WINE_DEFAULT_DEBUG_CHANNEL(comm);
108 /* retrieve the Unix handle corresponding to a comm handle */
109 static int get_comm_fd( HANDLE handle, DWORD access )
113 ret = wine_server_handle_to_fd( handle, access, &fd, NULL, NULL );
114 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
118 /* release the Unix handle returned by get_comm_fd */
119 static inline void release_comm_fd( HANDLE handle, int fd )
121 wine_server_release_fd( handle, fd );
125 /***********************************************************************
126 * Asynchronous I/O for asynchronous wait requests *
129 static DWORD commio_get_async_count (const async_private *ovp);
130 static void commio_async_cleanup (async_private *ovp);
132 static async_ops commio_async_ops =
134 commio_get_async_count, /* get_count */
135 NULL, /* call_completion */
136 commio_async_cleanup /* cleanup */
139 typedef struct async_commio
141 struct async_private async;
145 static DWORD commio_get_async_count (const struct async_private *ovp)
150 static void commio_async_cleanup (async_private *ovp)
152 HeapFree(GetProcessHeap(), 0, ovp );
155 /***********************************************************************/
157 #if !defined(TIOCINQ) && defined(FIONREAD)
158 #define TIOCINQ FIONREAD
161 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
164 unsigned int mstat, okay;
165 okay = ioctl(fd, TIOCMGET, &mstat);
166 if (okay) return okay;
167 if (andy) mstat &= andy;
169 return ioctl(fd, TIOCMSET, &mstat);
175 /***********************************************************************
176 * COMM_Parse* (Internal)
178 * The following COMM_Parse* functions are used by the BuildCommDCB
179 * functions to help parse the various parts of the device control string.
181 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
183 const WCHAR comW[] = {'C','O','M',0};
185 /* The device control string may optionally start with "COMx" followed
186 by an optional ':' and spaces. */
187 if(!strncmpiW(ptr, comW, 3))
191 /* Allow any com port above 0 as Win 9x does (NT only allows
192 values for com ports which are actually present) */
193 if(*ptr < '1' || *ptr > '9')
196 /* Advance pointer past port number */
197 while(*ptr >= '0' && *ptr <= '9') ptr++;
199 /* The com port number must be followed by a ':' or ' ' */
200 if(*ptr != ':' && *ptr != ' ')
203 /* Advance pointer to beginning of next parameter */
204 while(*ptr == ' ') ptr++;
208 while(*ptr == ' ') ptr++;
211 /* The device control string must not start with a space. */
218 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
220 if(*ptr < '0' || *ptr > '9') return NULL;
221 *lpnumber = strtoulW(ptr, NULL, 10);
222 while(*ptr >= '0' && *ptr <= '9') ptr++;
226 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
228 /* Contrary to what you might expect, Windows only sets the Parity
229 member of DCB and not fParity even when parity is specified in the
230 device control string */
232 switch(toupperW(*ptr++))
235 *lpparity = EVENPARITY;
238 *lpparity = MARKPARITY;
241 *lpparity = NOPARITY;
244 *lpparity = ODDPARITY;
247 *lpparity = SPACEPARITY;
256 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
260 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
263 if(temp >= 5 && temp <= 8)
272 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
275 const WCHAR stopbits15W[] = {'1','.','5',0};
277 if(!strncmpW(stopbits15W, ptr, 3))
280 *lpstopbits = ONE5STOPBITS;
284 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
288 *lpstopbits = ONESTOPBIT;
290 *lpstopbits = TWOSTOPBITS;
298 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
300 const WCHAR onW[] = {'o','n',0};
301 const WCHAR offW[] = {'o','f','f',0};
303 if(!strncmpiW(onW, ptr, 2))
308 else if(!strncmpiW(offW, ptr, 3))
319 /***********************************************************************
320 * COMM_BuildOldCommDCB (Internal)
322 * Build a DCB using the old style settings string eg: "96,n,8,1"
324 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
328 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
331 switch(lpdcb->BaudRate)
336 lpdcb->BaudRate *= 10;
342 lpdcb->BaudRate *= 100;
345 lpdcb->BaudRate = 19200;
349 while(*device == ' ') device++;
350 if(*device++ != ',') return FALSE;
351 while(*device == ' ') device++;
353 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
356 while(*device == ' ') device++;
357 if(*device++ != ',') return FALSE;
358 while(*device == ' ') device++;
360 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
363 while(*device == ' ') device++;
364 if(*device++ != ',') return FALSE;
365 while(*device == ' ') device++;
367 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
370 /* The last parameter for flow control is optional. */
371 while(*device == ' ') device++;
375 while(*device == ' ') device++;
376 if(*device) last = toupperW(*device++);
377 while(*device == ' ') device++;
380 /* Win NT sets the flow control members based on (or lack of) the last
381 parameter. Win 9x does not set these members. */
386 lpdcb->fOutX = FALSE;
387 lpdcb->fOutxCtsFlow = FALSE;
388 lpdcb->fOutxDsrFlow = FALSE;
389 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
390 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
395 lpdcb->fOutxCtsFlow = FALSE;
396 lpdcb->fOutxDsrFlow = FALSE;
397 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
398 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
402 lpdcb->fOutX = FALSE;
403 lpdcb->fOutxCtsFlow = TRUE;
404 lpdcb->fOutxDsrFlow = TRUE;
405 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
406 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
412 /* This should be the end of the string. */
413 if(*device) return FALSE;
418 /***********************************************************************
419 * COMM_BuildNewCommDCB (Internal)
421 * Build a DCB using the new style settings string.
422 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
424 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
427 BOOL baud = FALSE, stop = FALSE;
428 const WCHAR baudW[] = {'b','a','u','d','=',0};
429 const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
430 const WCHAR dataW[] = {'d','a','t','a','=',0};
431 const WCHAR stopW[] = {'s','t','o','p','=',0};
432 const WCHAR toW[] = {'t','o','=',0};
433 const WCHAR xonW[] = {'x','o','n','=',0};
434 const WCHAR odsrW[] = {'o','d','s','r','=',0};
435 const WCHAR octsW[] = {'o','c','t','s','=',0};
436 const WCHAR dtrW[] = {'d','t','r','=',0};
437 const WCHAR rtsW[] = {'r','t','s','=',0};
438 const WCHAR idsrW[] = {'i','d','s','r','=',0};
442 while(*device == ' ') device++;
444 if(!strncmpiW(baudW, device, 5))
448 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
451 else if(!strncmpiW(parityW, device, 7))
453 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
456 else if(!strncmpiW(dataW, device, 5))
458 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
461 else if(!strncmpiW(stopW, device, 5))
465 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
468 else if(!strncmpiW(toW, device, 3))
470 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
473 lptimeouts->ReadIntervalTimeout = 0;
474 lptimeouts->ReadTotalTimeoutMultiplier = 0;
475 lptimeouts->ReadTotalTimeoutConstant = 0;
476 lptimeouts->WriteTotalTimeoutMultiplier = 0;
477 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
479 else if(!strncmpiW(xonW, device, 4))
481 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
487 else if(!strncmpiW(odsrW, device, 5))
489 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
492 lpdcb->fOutxDsrFlow = temp;
494 else if(!strncmpiW(octsW, device, 5))
496 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
499 lpdcb->fOutxCtsFlow = temp;
501 else if(!strncmpiW(dtrW, device, 4))
503 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
506 lpdcb->fDtrControl = temp;
508 else if(!strncmpiW(rtsW, device, 4))
510 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
513 lpdcb->fRtsControl = temp;
515 else if(!strncmpiW(idsrW, device, 5))
517 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
520 /* Win NT sets the fDsrSensitivity member based on the
521 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
522 lpdcb->fDsrSensitivity = temp;
527 /* After the above parsing, the next character (if not the end of
528 the string) should be a space */
529 if(*device && *device != ' ')
533 /* If stop bits were not specified, a default is always supplied. */
536 if(baud && lpdcb->BaudRate == 110)
537 lpdcb->StopBits = TWOSTOPBITS;
539 lpdcb->StopBits = ONESTOPBIT;
545 /**************************************************************************
546 * BuildCommDCBA (KERNEL32.@)
548 * Updates a device control block data structure with values from an
549 * ascii device control string. The device control string has two forms
550 * normal and extended, it must be exclusively in one or the other form.
554 * True on success, false on a malformed control string.
556 BOOL WINAPI BuildCommDCBA(
557 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
558 LPDCB lpdcb) /* [out] The device control block to be updated. */
560 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
563 /**************************************************************************
564 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
566 * Updates a device control block data structure with values from an
567 * ascii device control string. Taking timeout values from a timeouts
568 * struct if desired by the control string.
572 * True on success, false bad handles etc.
574 BOOL WINAPI BuildCommDCBAndTimeoutsA(
575 LPCSTR device, /* [in] The ascii device control string. */
576 LPDCB lpdcb, /* [out] The device control block to be updated. */
577 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
580 UNICODE_STRING deviceW;
582 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
583 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
584 else deviceW.Buffer = NULL;
586 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
588 RtlFreeUnicodeString(&deviceW);
592 /**************************************************************************
593 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
595 * Updates a device control block data structure with values from a
596 * unicode device control string. Taking timeout values from a timeouts
597 * struct if desired by the control string.
601 * True on success, false bad handles etc
603 BOOL WINAPI BuildCommDCBAndTimeoutsW(
604 LPCWSTR devid, /* [in] The unicode device control string. */
605 LPDCB lpdcb, /* [out] The device control block to be updated. */
606 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
609 COMMTIMEOUTS timeouts;
613 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
615 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
616 lpdcb->DCBlength = sizeof(DCB);
618 /* Make a copy of the original data structures to work with since if
619 if there is an error in the device control string the originals
620 should not be modified (except possibly DCBlength) */
621 memcpy(&dcb, lpdcb, sizeof(DCB));
622 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
624 ptr = COMM_ParseStart(ptr);
628 else if(strchrW(ptr, ','))
629 result = COMM_BuildOldCommDCB(ptr, &dcb);
631 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
635 memcpy(lpdcb, &dcb, sizeof(DCB));
636 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
641 WARN("Invalid device control string: %s\n", debugstr_w(devid));
642 SetLastError(ERROR_INVALID_PARAMETER);
647 /**************************************************************************
648 * BuildCommDCBW (KERNEL32.@)
650 * Updates a device control block structure with values from an
651 * unicode device control string. The device control string has two forms
652 * normal and extended, it must be exclusively in one or the other form.
656 * True on success, false on an malformed control string.
658 BOOL WINAPI BuildCommDCBW(
659 LPCWSTR devid, /* [in] The unicode device control string. */
660 LPDCB lpdcb) /* [out] The device control block to be updated. */
662 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
665 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
669 SERVER_START_REQ( set_serial_info )
671 req->handle = handle;
672 req->flags = SERIALINFO_SET_ERROR;
673 req->commerror = error;
674 ret = !wine_server_call_err( req );
680 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
687 SERVER_START_REQ( get_serial_info )
689 req->handle = handle;
690 ret = !wine_server_call_err( req );
691 *lperror = reply->commerror;
698 /*****************************************************************************
699 * SetCommBreak (KERNEL32.@)
701 * Halts the transmission of characters to a communications device.
705 * True on success, and false if the communications device could not be found,
706 * the control is not supported.
710 * Only TIOCSBRK and TIOCCBRK are supported.
712 BOOL WINAPI SetCommBreak(
713 HANDLE handle) /* [in] The communictions device to suspend. */
715 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
718 fd = get_comm_fd( handle, GENERIC_READ );
719 if(fd<0) return FALSE;
720 result = ioctl(fd,TIOCSBRK,0);
721 release_comm_fd( handle, fd );
724 TRACE("ioctl failed\n");
725 SetLastError(ERROR_NOT_SUPPORTED);
730 FIXME("ioctl not available\n");
731 SetLastError(ERROR_NOT_SUPPORTED);
736 /*****************************************************************************
737 * ClearCommBreak (KERNEL32.@)
739 * Resumes character transmission from a communication device.
743 * True on success and false if the communications device could not be found.
747 * Only TIOCSBRK and TIOCCBRK are supported.
749 BOOL WINAPI ClearCommBreak(
750 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
752 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
755 fd = get_comm_fd( handle, GENERIC_READ );
756 if(fd<0) return FALSE;
757 result = ioctl(fd,TIOCCBRK,0);
758 release_comm_fd( handle, fd );
761 TRACE("ioctl failed\n");
762 SetLastError(ERROR_NOT_SUPPORTED);
767 FIXME("ioctl not available\n");
768 SetLastError(ERROR_NOT_SUPPORTED);
773 /*****************************************************************************
774 * EscapeCommFunction (KERNEL32.@)
776 * Directs a communication device to perform an extended function.
780 * True or requested data on successful completion of the command,
781 * false if the device is not present cannot execute the command
782 * or the command failed.
784 BOOL WINAPI EscapeCommFunction(
785 HANDLE handle, /* [in] The communication device to perform the extended function. */
786 UINT nFunction) /* [in] The extended function to be performed. */
788 int fd,direct=FALSE,result=FALSE;
791 TRACE("handle %p, function=%d\n", handle, nFunction);
792 fd = get_comm_fd( handle, GENERIC_READ );
793 if(fd<0) return FALSE;
795 if (tcgetattr(fd,&port) == -1) {
796 COMM_SetCommError(handle,CE_IOE);
797 release_comm_fd( handle, fd );
810 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
818 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
826 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
834 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
840 port.c_iflag |= IXOFF;
845 port.c_iflag |= IXON;
851 result = ioctl(fd,TIOCSBRK,0);
858 result = ioctl(fd,TIOCCBRK,0);
862 WARN("(handle=%p,nFunction=%d): Unknown function\n",
868 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
869 release_comm_fd( handle, fd );
870 COMM_SetCommError(handle,CE_IOE);
879 COMM_SetCommError(handle,CE_IOE);
884 release_comm_fd( handle, fd );
888 /********************************************************************
889 * PurgeComm (KERNEL32.@)
891 * Terminates pending operations and/or discards buffers on a
892 * communication resource.
896 * True on success and false if the communications handle is bad.
898 BOOL WINAPI PurgeComm(
899 HANDLE handle, /* [in] The communication resource to be purged. */
900 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
904 TRACE("handle %p, flags %lx\n", handle, flags);
906 fd = get_comm_fd( handle, GENERIC_READ );
907 if(fd<0) return FALSE;
910 ** not exactly sure how these are different
911 ** Perhaps if we had our own internal queues, one flushes them
912 ** and the other flushes the kernel's buffers.
914 if(flags&PURGE_TXABORT)
915 tcflush(fd,TCOFLUSH);
916 if(flags&PURGE_RXABORT)
917 tcflush(fd,TCIFLUSH);
918 if(flags&PURGE_TXCLEAR)
919 tcflush(fd,TCOFLUSH);
920 if(flags&PURGE_RXCLEAR)
921 tcflush(fd,TCIFLUSH);
922 release_comm_fd( handle, fd );
927 /*****************************************************************************
928 * ClearCommError (KERNEL32.@)
930 * Enables further I/O operations on a communications resource after
931 * supplying error and current status information.
935 * True on success, false if the communication resource handle is bad.
937 BOOL WINAPI ClearCommError(
938 HANDLE handle, /* [in] The communication resource with the error. */
939 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
940 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
944 fd=get_comm_fd( handle, GENERIC_READ );
945 if(0>fd) return FALSE;
949 lpStat->fCtsHold = 0;
950 lpStat->fDsrHold = 0;
951 lpStat->fRlsdHold = 0;
952 lpStat->fXoffHold = 0;
953 lpStat->fXoffSent = 0;
956 lpStat->fReserved = 0;
959 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
960 WARN("ioctl returned error\n");
962 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
966 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
967 WARN("ioctl returned error\n");
970 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
971 handle, lpStat->cbInQue, lpStat->cbOutQue);
974 release_comm_fd( handle, fd );
976 COMM_GetCommError(handle, errors);
977 COMM_SetCommError(handle, 0);
982 /*****************************************************************************
983 * SetupComm (KERNEL32.@)
985 * Called after CreateFile to hint to the communication resource to use
986 * specified sizes for input and output buffers rather than the default values.
990 * True if successful, false if the communications resource handle is bad.
996 BOOL WINAPI SetupComm(
997 HANDLE handle, /* [in] The just created communication resource handle. */
998 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
999 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
1003 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1004 fd=get_comm_fd( handle, GENERIC_READ );
1005 if(0>fd) return FALSE;
1006 release_comm_fd( handle, fd );
1010 /*****************************************************************************
1011 * GetCommMask (KERNEL32.@)
1013 * Obtain the events associated with a communication device that will cause
1014 * a call WaitCommEvent to return.
1018 * True on success, fail on bad device handle etc.
1020 BOOL WINAPI GetCommMask(
1021 HANDLE handle, /* [in] The communications device. */
1022 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1026 TRACE("handle %p, mask %p\n", handle, evtmask);
1028 SERVER_START_REQ( get_serial_info )
1030 req->handle = handle;
1031 if ((ret = !wine_server_call_err( req )))
1033 if (evtmask) *evtmask = reply->eventmask;
1040 /*****************************************************************************
1041 * SetCommMask (KERNEL32.@)
1043 * There be some things we need to hear about yon there communications device.
1044 * (Set which events associated with a communication device should cause
1045 * a call WaitCommEvent to return.)
1049 * True on success, false on bad handle etc.
1051 BOOL WINAPI SetCommMask(
1052 HANDLE handle, /* [in] The communications device. */
1053 DWORD evtmask) /* [in] The events that are to be monitored. */
1057 TRACE("handle %p, mask %lx\n", handle, evtmask);
1059 SERVER_START_REQ( set_serial_info )
1061 req->handle = handle;
1062 req->flags = SERIALINFO_SET_MASK;
1063 req->eventmask = evtmask;
1064 ret = !wine_server_call_err( req );
1070 /*****************************************************************************
1071 * SetCommState (KERNEL32.@)
1073 * Re-initializes all hardware and control settings of a communications device,
1074 * with values from a device control block without effecting the input and output
1079 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1081 BOOL WINAPI SetCommState(
1082 HANDLE handle, /* [in] The communications device. */
1083 LPDCB lpdcb) /* [out] The device control block. */
1085 struct termios port;
1086 int fd, bytesize, stopbits;
1089 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1090 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1091 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1092 (lpdcb->StopBits == ONESTOPBIT)?1:
1093 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1094 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1095 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1096 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1097 lpdcb->fRtsControl);
1098 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1099 lpdcb->fDtrControl);
1102 fd = get_comm_fd( handle, GENERIC_READ );
1103 if (fd < 0) return FALSE;
1105 if ((tcgetattr(fd,&port)) == -1) {
1106 int save_error = errno;
1107 COMM_SetCommError(handle,CE_IOE);
1108 release_comm_fd( handle, fd );
1109 ERR("tcgetattr error '%s'\n", strerror(save_error));
1113 port.c_cc[VMIN] = 0;
1114 port.c_cc[VTIME] = 1;
1117 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1119 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1121 port.c_iflag |= (IGNBRK);
1123 port.c_oflag &= ~(OPOST);
1125 port.c_cflag &= ~(HUPCL);
1126 port.c_cflag |= CLOCAL | CREAD;
1128 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1129 port.c_lflag |= NOFLSH;
1132 port.c_cflag &= ~CBAUD;
1133 switch (lpdcb->BaudRate) {
1136 port.c_cflag |= B110;
1140 port.c_cflag |= B300;
1144 port.c_cflag |= B600;
1148 port.c_cflag |= B1200;
1152 port.c_cflag |= B2400;
1156 port.c_cflag |= B4800;
1160 port.c_cflag |= B9600;
1164 port.c_cflag |= B19200;
1168 port.c_cflag |= B38400;
1172 port.c_cflag |= B57600;
1177 port.c_cflag |= B115200;
1182 port.c_cflag |= B230400;
1187 port.c_cflag |= B460800;
1191 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1192 { struct serial_struct nuts;
1194 ioctl(fd, TIOCGSERIAL, &nuts);
1195 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1196 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1197 arby = nuts.baud_base / nuts.custom_divisor;
1198 nuts.flags &= ~ASYNC_SPD_MASK;
1199 nuts.flags |= ASYNC_SPD_CUST;
1200 WARN("You (or a program acting at your behest) have specified\n"
1201 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1202 "which is as close as we can get by our present understanding of your\n"
1203 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1204 "has caused to your linux system can be undone with setserial \n"
1205 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1206 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1207 ioctl(fd, TIOCSSERIAL, &nuts);
1208 port.c_cflag |= B38400;
1211 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1214 COMM_SetCommError(handle,IE_BAUDRATE);
1215 release_comm_fd( handle, fd );
1216 ERR("baudrate %ld\n",lpdcb->BaudRate);
1219 #elif !defined(__EMX__)
1220 switch (lpdcb->BaudRate) {
1223 port.c_ospeed = B110;
1227 port.c_ospeed = B300;
1231 port.c_ospeed = B600;
1235 port.c_ospeed = B1200;
1239 port.c_ospeed = B2400;
1243 port.c_ospeed = B4800;
1247 port.c_ospeed = B9600;
1251 port.c_ospeed = B19200;
1255 port.c_ospeed = B38400;
1260 port.c_cflag |= B57600;
1266 port.c_cflag |= B115200;
1271 port.c_cflag |= B230400;
1276 port.c_cflag |= B460800;
1280 COMM_SetCommError(handle,IE_BAUDRATE);
1281 release_comm_fd( handle, fd );
1282 ERR("baudrate %ld\n",lpdcb->BaudRate);
1285 port.c_ispeed = port.c_ospeed;
1287 bytesize=lpdcb->ByteSize;
1288 stopbits=lpdcb->StopBits;
1291 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1293 port.c_cflag &= ~(PARENB | PARODD);
1296 port.c_iflag |= INPCK;
1298 port.c_iflag &= ~INPCK;
1299 switch (lpdcb->Parity) {
1303 port.c_cflag |= (PARENB | PARODD);
1306 port.c_cflag |= PARENB;
1309 /* Linux defines mark/space (stick) parity */
1311 port.c_cflag |= (PARENB | CMSPAR);
1314 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1317 /* try the POSIX way */
1319 if( stopbits == ONESTOPBIT) {
1320 stopbits = TWOSTOPBITS;
1321 port.c_iflag &= ~INPCK;
1323 COMM_SetCommError(handle,IE_BYTESIZE);
1324 release_comm_fd( handle, fd );
1325 ERR("Cannot set MARK Parity\n");
1332 port.c_iflag &= ~INPCK;
1334 COMM_SetCommError(handle,IE_BYTESIZE);
1335 release_comm_fd( handle, fd );
1336 ERR("Cannot set SPACE Parity\n");
1342 COMM_SetCommError(handle,IE_BYTESIZE);
1343 release_comm_fd( handle, fd );
1349 port.c_cflag &= ~CSIZE;
1352 port.c_cflag |= CS5;
1355 port.c_cflag |= CS6;
1358 port.c_cflag |= CS7;
1361 port.c_cflag |= CS8;
1364 COMM_SetCommError(handle,IE_BYTESIZE);
1365 release_comm_fd( handle, fd );
1372 port.c_cflag &= ~CSTOPB;
1374 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1376 port.c_cflag |= CSTOPB;
1379 COMM_SetCommError(handle,IE_BYTESIZE);
1380 release_comm_fd( handle, fd );
1385 if ( lpdcb->fOutxCtsFlow ||
1386 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1389 port.c_cflag |= CRTSCTS;
1395 port.c_iflag |= IXON;
1397 port.c_iflag &= ~IXON;
1399 port.c_iflag |= IXOFF;
1401 port.c_iflag &= ~IXOFF;
1403 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1404 ERR("tcsetattr error '%s'\n", strerror(errno));
1405 COMM_SetCommError(handle,CE_IOE);
1408 COMM_SetCommError(handle,0);
1412 /* note: change DTR/RTS lines after setting the comm attributes,
1413 * so flow control does not interfere. */
1415 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1417 WARN("DSR/DTR flow control not supported\n");
1418 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1419 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1421 COMM_WhackModem(fd, 0, TIOCM_DTR);
1424 if(!lpdcb->fOutxCtsFlow )
1426 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1427 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1429 COMM_WhackModem(fd, 0, TIOCM_RTS);
1432 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1433 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1434 release_comm_fd( handle, fd );
1440 /*****************************************************************************
1441 * GetCommState (KERNEL32.@)
1443 * Fills in a device control block with information from a communications device.
1447 * True on success, false if the communication device handle is bad etc
1451 * XonChar and XoffChar are not set.
1453 BOOL WINAPI GetCommState(
1454 HANDLE handle, /* [in] The communications device. */
1455 LPDCB lpdcb) /* [out] The device control block. */
1457 struct termios port;
1459 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1461 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1463 fd = get_comm_fd( handle, GENERIC_READ );
1464 if (fd < 0) return FALSE;
1465 if (tcgetattr(fd, &port) == -1
1467 || ioctl(fd, TIOCMGET, &stat) == -1
1470 int save_error=errno;
1471 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1472 COMM_SetCommError(handle,CE_IOE);
1473 release_comm_fd( handle, fd );
1476 release_comm_fd( handle, fd );
1479 speed= (port.c_cflag & CBAUD);
1481 speed= (cfgetospeed(&port));
1485 lpdcb->BaudRate = 110;
1488 lpdcb->BaudRate = 300;
1491 lpdcb->BaudRate = 600;
1494 lpdcb->BaudRate = 1200;
1497 lpdcb->BaudRate = 2400;
1500 lpdcb->BaudRate = 4800;
1503 lpdcb->BaudRate = 9600;
1506 lpdcb->BaudRate = 19200;
1509 lpdcb->BaudRate = 38400;
1513 lpdcb->BaudRate = 57600;
1518 lpdcb->BaudRate = 115200;
1523 lpdcb->BaudRate = 230400;
1528 lpdcb->BaudRate = 460800;
1532 ERR("unknown speed %x \n",speed);
1535 switch (port.c_cflag & CSIZE) {
1537 lpdcb->ByteSize = 5;
1540 lpdcb->ByteSize = 6;
1543 lpdcb->ByteSize = 7;
1546 lpdcb->ByteSize = 8;
1549 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1552 if(port.c_iflag & INPCK)
1553 lpdcb->fParity = TRUE;
1555 lpdcb->fParity = FALSE;
1557 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1559 switch (port.c_cflag & (PARENB | PARODD))
1563 lpdcb->Parity = NOPARITY;
1566 lpdcb->Parity = EVENPARITY;
1568 case (PARENB | PARODD):
1569 lpdcb->Parity = ODDPARITY;
1572 case (PARENB | CMSPAR):
1573 lpdcb->Parity = MARKPARITY;
1575 case (PARENB | PARODD | CMSPAR):
1576 lpdcb->Parity = SPACEPARITY;
1581 if (port.c_cflag & CSTOPB)
1582 if(lpdcb->ByteSize == 5)
1583 lpdcb->StopBits = ONE5STOPBITS;
1585 lpdcb->StopBits = TWOSTOPBITS;
1587 lpdcb->StopBits = ONESTOPBIT;
1592 /* termios does not support DTR/DSR flow control */
1593 lpdcb->fOutxDsrFlow = 0;
1594 lpdcb->fDtrControl =
1596 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1598 DTR_CONTROL_ENABLE ;
1602 if (port.c_cflag & CRTSCTS) {
1603 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1604 lpdcb->fOutxCtsFlow = 1;
1608 lpdcb->fRtsControl =
1610 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1612 RTS_CONTROL_ENABLE ;
1613 lpdcb->fOutxCtsFlow = 0;
1615 if (port.c_iflag & IXON)
1620 if (port.c_iflag & IXOFF)
1629 lpdcb->XoffLim = 10;
1631 COMM_SetCommError(handle,0);
1635 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1636 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1637 (lpdcb->StopBits == ONESTOPBIT)?1:
1638 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1639 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1640 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1641 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1642 lpdcb->fRtsControl);
1643 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1644 lpdcb->fDtrControl);
1646 if ( lpdcb->fOutxCtsFlow ||
1647 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1652 TRACE("~CRTSCTS\n");
1657 /*****************************************************************************
1658 * TransmitCommChar (KERNEL32.@)
1660 * Transmits a single character in front of any pending characters in the
1661 * output buffer. Usually used to send an interrupt character to a host.
1665 * True if the call succeeded, false if the previous command character to the
1666 * same device has not been sent yet the handle is bad etc.
1672 BOOL WINAPI TransmitCommChar(
1673 HANDLE hComm, /* [in] The communication device in need of a command character. */
1674 CHAR chTransmit) /* [in] The character to transmit. */
1676 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1678 return WriteFile( hComm, &chTransmit, 1, NULL, NULL );
1682 /*****************************************************************************
1683 * GetCommTimeouts (KERNEL32.@)
1685 * Obtains the request timeout values for the communications device.
1689 * True on success, false if communications device handle is bad
1690 * or the target structure is null.
1692 BOOL WINAPI GetCommTimeouts(
1693 HANDLE hComm, /* [in] The communications device. */
1694 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1698 TRACE("(%p,%p)\n",hComm,lptimeouts);
1702 SetLastError(ERROR_INVALID_PARAMETER);
1706 SERVER_START_REQ( get_serial_info )
1708 req->handle = hComm;
1709 if ((ret = !wine_server_call_err( req )))
1711 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1712 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1713 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1714 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1715 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1722 /*****************************************************************************
1723 * SetCommTimeouts (KERNEL32.@)
1725 * Sets the timeouts used when reading and writing data to/from COMM ports.
1727 * ReadIntervalTimeout
1728 * - converted and passes to linux kernel as c_cc[VTIME]
1729 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1730 * - used in ReadFile to calculate GetOverlappedResult's timeout
1731 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1732 * - used in WriteFile to calculate GetOverlappedResult's timeout
1736 * True if the timeouts were set, false otherwise.
1738 BOOL WINAPI SetCommTimeouts(
1739 HANDLE hComm, /* [in] handle of COMM device */
1740 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1744 struct termios tios;
1746 TRACE("(%p,%p)\n",hComm,lptimeouts);
1750 SetLastError(ERROR_INVALID_PARAMETER);
1754 SERVER_START_REQ( set_serial_info )
1756 req->handle = hComm;
1757 req->flags = SERIALINFO_SET_TIMEOUTS;
1758 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1759 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1760 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1761 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1762 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1763 ret = !wine_server_call_err( req );
1766 if (!ret) return FALSE;
1768 /* FIXME: move this stuff to the server */
1769 fd = get_comm_fd( hComm, GENERIC_READ );
1770 if (fd < 0) return FALSE;
1772 if (-1==tcgetattr(fd,&tios)) {
1773 FIXME("tcgetattr on fd %d failed!\n",fd);
1774 release_comm_fd( hComm, fd );
1778 /* VTIME is in 1/10 seconds */
1780 unsigned int ux_timeout;
1782 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1788 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1791 ux_timeout = 1; /* must be at least some timeout */
1794 tios.c_cc[VTIME] = ux_timeout;
1797 if (-1==tcsetattr(fd,0,&tios)) {
1798 FIXME("tcsetattr on fd %d failed!\n",fd);
1799 release_comm_fd( hComm, fd );
1802 release_comm_fd( hComm, fd );
1806 /***********************************************************************
1807 * GetCommModemStatus (KERNEL32.@)
1809 * Obtains the four control register bits if supported by the hardware.
1813 * True if the communications handle was good and for hardware that
1814 * control register access, false otherwise.
1816 BOOL WINAPI GetCommModemStatus(
1817 HANDLE hFile, /* [in] The communications device. */
1818 LPDWORD lpModemStat) /* [out] The control register bits. */
1820 int fd,mstat, result=FALSE;
1824 fd = get_comm_fd( hFile, GENERIC_READ );
1827 result = ioctl(fd, TIOCMGET, &mstat);
1828 release_comm_fd( hFile, fd );
1831 WARN("ioctl failed\n");
1835 if (mstat & TIOCM_CTS)
1836 *lpModemStat |= MS_CTS_ON;
1839 if (mstat & TIOCM_DSR)
1840 *lpModemStat |= MS_DSR_ON;
1843 if (mstat & TIOCM_RNG)
1844 *lpModemStat |= MS_RING_ON;
1847 /*FIXME: Not really sure about RLSD UB 990810*/
1848 if (mstat & TIOCM_CAR)
1849 *lpModemStat |= MS_RLSD_ON;
1851 TRACE("%04x -> %s%s%s%s\n", mstat,
1852 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1853 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1854 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1855 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1862 /***********************************************************************
1863 * COMM_WaitCommEventService (INTERNAL)
1865 * This function is called while the client is waiting on the
1866 * server, so we can't make any server calls here.
1868 static void COMM_WaitCommEventService(async_private *ovp)
1870 async_commio *commio = (async_commio*) ovp;
1871 IO_STATUS_BLOCK* iosb = commio->async.iosb;
1873 TRACE("iosb %p\n",iosb);
1875 /* FIXME: detect other events */
1876 *commio->buffer = EV_RXCHAR;
1878 iosb->u.Status = STATUS_SUCCESS;
1882 /***********************************************************************
1883 * COMM_WaitCommEvent (INTERNAL)
1885 * This function must have an lpOverlapped.
1887 static BOOL COMM_WaitCommEvent(
1888 HANDLE hFile, /* [in] handle of comm port to wait for */
1889 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1890 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1897 SetLastError(ERROR_INVALID_PARAMETER);
1901 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1904 fd = get_comm_fd( hFile, GENERIC_WRITE );
1908 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1911 release_comm_fd( hFile, fd );
1915 ovp->async.ops = &commio_async_ops;
1916 ovp->async.handle = hFile;
1917 ovp->async.fd = fd; /* FIXME */
1918 ovp->async.type = ASYNC_TYPE_WAIT;
1919 ovp->async.func = COMM_WaitCommEventService;
1920 ovp->async.event = lpOverlapped->hEvent;
1921 ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1922 ovp->buffer = (char *)lpdwEvents;
1924 lpOverlapped->InternalHigh = 0;
1925 lpOverlapped->Offset = 0;
1926 lpOverlapped->OffsetHigh = 0;
1928 if ( !register_new_async (&ovp->async) )
1929 SetLastError( ERROR_IO_PENDING );
1934 /***********************************************************************
1935 * WaitCommEvent (KERNEL32.@)
1937 * Wait until something interesting happens on a COMM port.
1938 * Interesting things (events) are set by calling SetCommMask before
1939 * this function is called.
1942 * TRUE if successful
1945 * The set of detected events will be written to *lpdwEventMask
1946 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1949 * Only supports EV_RXCHAR and EV_TXEMPTY
1951 BOOL WINAPI WaitCommEvent(
1952 HANDLE hFile, /* [in] handle of comm port to wait for */
1953 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1954 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1959 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1962 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1964 /* if there is no overlapped structure, create our own */
1965 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1967 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1969 /* wait for the overlapped to complete */
1970 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1971 CloseHandle(ov.hEvent);
1976 /***********************************************************************
1977 * GetCommProperties (KERNEL32.@)
1979 * This function fills in a structure with the capabilities of the
1980 * communications port driver.
1984 * TRUE on success, FALSE on failure
1985 * If successful, the lpCommProp structure be filled in with
1986 * properties of the comm port.
1988 BOOL WINAPI GetCommProperties(
1989 HANDLE hFile, /* [in] handle of the comm port */
1990 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1992 FIXME("(%p %p )\n",hFile,lpCommProp);
1997 * These values should be valid for LINUX's serial driver
1998 * FIXME: Perhaps they deserve an #ifdef LINUX
2000 memset(lpCommProp,0,sizeof(COMMPROP));
2001 lpCommProp->wPacketLength = 1;
2002 lpCommProp->wPacketVersion = 1;
2003 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2004 lpCommProp->dwReserved1 = 0;
2005 lpCommProp->dwMaxTxQueue = 4096;
2006 lpCommProp->dwMaxRxQueue = 4096;
2007 lpCommProp->dwMaxBaud = BAUD_115200;
2008 lpCommProp->dwProvSubType = PST_RS232;
2009 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2010 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2011 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2012 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2013 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2014 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2015 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2016 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2017 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2018 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2019 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2024 /***********************************************************************
2026 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2027 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2028 * This is dependent on the type of COMM port, but since it is doubtful
2029 * anybody will get around to implementing support for fancy serial
2030 * ports in WINE, this is hardcoded for the time being. The name of
2031 * this DLL should be stored in and read from the system registry in
2032 * the hive HKEY_LOCAL_MACHINE, key
2033 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2034 * where ???? is the port number... that is determined by PNP
2035 * The DLL should be loaded when the COMM port is opened, and closed
2036 * when the COMM port is closed. - MJM 20 June 2000
2037 ***********************************************************************/
2038 static CHAR lpszSerialUI[] = "serialui.dll";
2041 /***********************************************************************
2042 * CommConfigDialogA (KERNEL32.@)
2044 * Raises a dialog that allows the user to configure a comm port.
2045 * Fills the COMMCONFIG struct with information specified by the user.
2046 * This function should call a similar routine in the COMM driver...
2050 * TRUE on success, FALSE on failure
2051 * If successful, the lpCommConfig structure will contain a new
2052 * configuration for the comm port, as specified by the user.
2055 * The library with the CommConfigDialog code is never unloaded.
2056 * Perhaps this should be done when the comm port is closed?
2058 BOOL WINAPI CommConfigDialogA(
2059 LPCSTR lpszDevice, /* [in] name of communications device */
2060 HANDLE hWnd, /* [in] parent window for the dialog */
2061 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2063 FARPROC lpfnCommDialog;
2064 HMODULE hConfigModule;
2067 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2069 hConfigModule = LoadLibraryA(lpszSerialUI);
2073 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2078 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2080 /* UnloadLibrary(hConfigModule); */
2085 /***********************************************************************
2086 * CommConfigDialogW (KERNEL32.@)
2088 * see CommConfigDialogA for more info
2090 BOOL WINAPI CommConfigDialogW(
2091 LPCWSTR lpszDevice, /* [in] name of communications device */
2092 HANDLE hWnd, /* [in] parent window for the dialog */
2093 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2098 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2101 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2102 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2106 /***********************************************************************
2107 * GetCommConfig (KERNEL32.@)
2109 * Fill in the COMMCONFIG structure for the comm port hFile
2113 * TRUE on success, FALSE on failure
2114 * If successful, lpCommConfig contains the comm port configuration.
2119 BOOL WINAPI GetCommConfig(
2120 HANDLE hFile, /* [in] The communications device. */
2121 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2122 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2123 afterwards the number of bytes copied to the buffer or
2124 the needed size of the buffer. */
2128 TRACE("(%p %p)\n",hFile,lpCommConfig);
2130 if(lpCommConfig == NULL)
2132 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2133 *lpdwSize = sizeof(COMMCONFIG);
2137 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2138 lpCommConfig->wVersion = 1;
2139 lpCommConfig->wReserved = 0;
2140 r = GetCommState(hFile,&lpCommConfig->dcb);
2141 lpCommConfig->dwProviderSubType = PST_RS232;
2142 lpCommConfig->dwProviderOffset = 0;
2143 lpCommConfig->dwProviderSize = 0;
2148 /***********************************************************************
2149 * SetCommConfig (KERNEL32.@)
2151 * Sets the configuration of the communications device.
2155 * True on success, false if the handle was bad is not a communications device.
2157 BOOL WINAPI SetCommConfig(
2158 HANDLE hFile, /* [in] The communications device. */
2159 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2160 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2162 TRACE("(%p %p)\n",hFile,lpCommConfig);
2163 return SetCommState(hFile,&lpCommConfig->dcb);
2166 /***********************************************************************
2167 * SetDefaultCommConfigA (KERNEL32.@)
2169 * Initializes the default configuration for the specified communication
2174 * True if the device was found and the defaults set, false otherwise
2176 BOOL WINAPI SetDefaultCommConfigA(
2177 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2178 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2179 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2181 FARPROC lpfnSetDefaultCommConfig;
2182 HMODULE hConfigModule;
2185 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2187 hConfigModule = LoadLibraryA(lpszSerialUI);
2191 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2193 if(! lpfnSetDefaultCommConfig)
2196 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2198 /* UnloadLibrary(hConfigModule); */
2204 /***********************************************************************
2205 * SetDefaultCommConfigW (KERNEL32.@)
2207 * Initializes the default configuration for the specified
2208 * communication device. (unicode)
2213 BOOL WINAPI SetDefaultCommConfigW(
2214 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2215 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2216 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2221 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2223 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2226 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2227 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2232 /***********************************************************************
2233 * GetDefaultCommConfigW (KERNEL32.@)
2235 * Acquires the default configuration of the specified communication device. (unicode)
2239 * True on successful reading of the default configuration,
2240 * if the device is not found or the buffer is too small.
2242 BOOL WINAPI GetDefaultCommConfigW(
2243 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2244 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2245 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2246 afterwards the number of bytes copied to the buffer or
2247 the needed size of the buffer. */
2249 LPDCB lpdcb = &(lpCC->dcb);
2251 const WCHAR comW[] = {'C','O','M',0};
2252 const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2254 if (strncmpiW(lpszName,comW,3)) {
2255 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2259 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2260 if (*lpdwSize < sizeof(COMMCONFIG)) {
2261 *lpdwSize = sizeof(COMMCONFIG);
2265 *lpdwSize = sizeof(COMMCONFIG);
2267 lpCC->dwSize = sizeof(COMMCONFIG);
2269 lpCC->dwProviderSubType = PST_RS232;
2270 lpCC->dwProviderOffset = 0L;
2271 lpCC->dwProviderSize = 0L;
2273 sprintfW( temp, formatW, lpszName[3]);
2274 FIXME("setting %s as default\n", debugstr_w(temp));
2276 return BuildCommDCBW( temp, lpdcb);
2279 /**************************************************************************
2280 * GetDefaultCommConfigA (KERNEL32.@)
2282 * Acquires the default configuration of the specified communication device. (ascii)
2286 * True on successful reading of the default configuration,
2287 * if the device is not found or the buffer is too small.
2289 BOOL WINAPI GetDefaultCommConfigA(
2290 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2291 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2292 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2293 afterwards the number of bytes copied to the buffer or
2294 the needed size of the buffer. */
2297 UNICODE_STRING lpszNameW;
2299 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2300 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2301 else lpszNameW.Buffer = NULL;
2303 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2305 RtlFreeUnicodeString(&lpszNameW);