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 static 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 static 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 static const WCHAR onW[] = {'o','n',0};
301 static 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 static const WCHAR baudW[] = {'b','a','u','d','=',0};
429 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
430 static const WCHAR dataW[] = {'d','a','t','a','=',0};
431 static const WCHAR stopW[] = {'s','t','o','p','=',0};
432 static const WCHAR toW[] = {'t','o','=',0};
433 static const WCHAR xonW[] = {'x','o','n','=',0};
434 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
435 static const WCHAR octsW[] = {'o','c','t','s','=',0};
436 static const WCHAR dtrW[] = {'d','t','r','=',0};
437 static const WCHAR rtsW[] = {'r','t','s','=',0};
438 static 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) {
1138 port.c_cflag |= B50;
1141 port.c_cflag |= B75;
1145 port.c_cflag |= B110;
1148 port.c_cflag |= B134;
1151 port.c_cflag |= B150;
1154 port.c_cflag |= B200;
1158 port.c_cflag |= B300;
1162 port.c_cflag |= B600;
1166 port.c_cflag |= B1200;
1169 port.c_cflag |= B1800;
1173 port.c_cflag |= B2400;
1177 port.c_cflag |= B4800;
1181 port.c_cflag |= B9600;
1185 port.c_cflag |= B19200;
1189 port.c_cflag |= B38400;
1193 port.c_cflag |= B57600;
1198 port.c_cflag |= B115200;
1203 port.c_cflag |= B230400;
1208 port.c_cflag |= B460800;
1212 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1213 { struct serial_struct nuts;
1215 ioctl(fd, TIOCGSERIAL, &nuts);
1216 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1217 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1218 arby = nuts.baud_base / nuts.custom_divisor;
1219 nuts.flags &= ~ASYNC_SPD_MASK;
1220 nuts.flags |= ASYNC_SPD_CUST;
1221 WARN("You (or a program acting at your behest) have specified\n"
1222 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1223 "which is as close as we can get by our present understanding of your\n"
1224 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1225 "has caused to your linux system can be undone with setserial \n"
1226 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1227 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1228 ioctl(fd, TIOCSSERIAL, &nuts);
1229 port.c_cflag |= B38400;
1232 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1235 COMM_SetCommError(handle,IE_BAUDRATE);
1236 release_comm_fd( handle, fd );
1237 ERR("baudrate %ld\n",lpdcb->BaudRate);
1240 #elif !defined(__EMX__)
1241 switch (lpdcb->BaudRate) {
1246 port.c_ospeed = B50;
1249 port.c_ospeed = B75;
1253 port.c_ospeed = B110;
1256 port.c_ospeed = B134;
1259 port.c_ospeed = B150;
1262 port.c_ospeed = B200;
1266 port.c_ospeed = B300;
1270 port.c_ospeed = B600;
1274 port.c_ospeed = B1200;
1277 port.c_ospeed = B1800;
1281 port.c_ospeed = B2400;
1285 port.c_ospeed = B4800;
1289 port.c_ospeed = B9600;
1293 port.c_ospeed = B19200;
1297 port.c_ospeed = B38400;
1302 port.c_cflag |= B57600;
1308 port.c_cflag |= B115200;
1313 port.c_cflag |= B230400;
1318 port.c_cflag |= B460800;
1322 COMM_SetCommError(handle,IE_BAUDRATE);
1323 release_comm_fd( handle, fd );
1324 ERR("baudrate %ld\n",lpdcb->BaudRate);
1327 port.c_ispeed = port.c_ospeed;
1329 bytesize=lpdcb->ByteSize;
1330 stopbits=lpdcb->StopBits;
1333 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1335 port.c_cflag &= ~(PARENB | PARODD);
1338 port.c_iflag |= INPCK;
1340 port.c_iflag &= ~INPCK;
1341 switch (lpdcb->Parity) {
1345 port.c_cflag |= (PARENB | PARODD);
1348 port.c_cflag |= PARENB;
1351 /* Linux defines mark/space (stick) parity */
1353 port.c_cflag |= (PARENB | CMSPAR);
1356 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1359 /* try the POSIX way */
1361 if( stopbits == ONESTOPBIT) {
1362 stopbits = TWOSTOPBITS;
1363 port.c_iflag &= ~INPCK;
1365 COMM_SetCommError(handle,IE_BYTESIZE);
1366 release_comm_fd( handle, fd );
1367 ERR("Cannot set MARK Parity\n");
1374 port.c_iflag &= ~INPCK;
1376 COMM_SetCommError(handle,IE_BYTESIZE);
1377 release_comm_fd( handle, fd );
1378 ERR("Cannot set SPACE Parity\n");
1384 COMM_SetCommError(handle,IE_BYTESIZE);
1385 release_comm_fd( handle, fd );
1391 port.c_cflag &= ~CSIZE;
1394 port.c_cflag |= CS5;
1397 port.c_cflag |= CS6;
1400 port.c_cflag |= CS7;
1403 port.c_cflag |= CS8;
1406 COMM_SetCommError(handle,IE_BYTESIZE);
1407 release_comm_fd( handle, fd );
1414 port.c_cflag &= ~CSTOPB;
1416 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1418 port.c_cflag |= CSTOPB;
1421 COMM_SetCommError(handle,IE_BYTESIZE);
1422 release_comm_fd( handle, fd );
1427 if ( lpdcb->fOutxCtsFlow ||
1428 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1431 port.c_cflag |= CRTSCTS;
1437 port.c_iflag |= IXON;
1439 port.c_iflag &= ~IXON;
1441 port.c_iflag |= IXOFF;
1443 port.c_iflag &= ~IXOFF;
1445 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1446 ERR("tcsetattr error '%s'\n", strerror(errno));
1447 COMM_SetCommError(handle,CE_IOE);
1450 COMM_SetCommError(handle,0);
1454 /* note: change DTR/RTS lines after setting the comm attributes,
1455 * so flow control does not interfere. */
1457 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1459 WARN("DSR/DTR flow control not supported\n");
1460 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1461 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1463 COMM_WhackModem(fd, 0, TIOCM_DTR);
1466 if(!lpdcb->fOutxCtsFlow )
1468 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1469 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1471 COMM_WhackModem(fd, 0, TIOCM_RTS);
1474 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1475 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1476 release_comm_fd( handle, fd );
1482 /*****************************************************************************
1483 * GetCommState (KERNEL32.@)
1485 * Fills in a device control block with information from a communications device.
1489 * True on success, false if the communication device handle is bad etc
1493 * XonChar and XoffChar are not set.
1495 BOOL WINAPI GetCommState(
1496 HANDLE handle, /* [in] The communications device. */
1497 LPDCB lpdcb) /* [out] The device control block. */
1499 struct termios port;
1501 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1503 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1505 fd = get_comm_fd( handle, GENERIC_READ );
1506 if (fd < 0) return FALSE;
1507 if (tcgetattr(fd, &port) == -1
1509 || ioctl(fd, TIOCMGET, &stat) == -1
1512 int save_error=errno;
1513 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1514 COMM_SetCommError(handle,CE_IOE);
1515 release_comm_fd( handle, fd );
1518 release_comm_fd( handle, fd );
1521 speed= (port.c_cflag & CBAUD);
1523 speed= (cfgetospeed(&port));
1527 lpdcb->BaudRate = 0;
1530 lpdcb->BaudRate = 50;
1533 lpdcb->BaudRate = 75;
1536 lpdcb->BaudRate = 110;
1539 lpdcb->BaudRate = 134;
1542 lpdcb->BaudRate = 150;
1545 lpdcb->BaudRate = 200;
1548 lpdcb->BaudRate = 300;
1551 lpdcb->BaudRate = 600;
1554 lpdcb->BaudRate = 1200;
1557 lpdcb->BaudRate = 1800;
1560 lpdcb->BaudRate = 2400;
1563 lpdcb->BaudRate = 4800;
1566 lpdcb->BaudRate = 9600;
1569 lpdcb->BaudRate = 19200;
1572 lpdcb->BaudRate = 38400;
1576 lpdcb->BaudRate = 57600;
1581 lpdcb->BaudRate = 115200;
1586 lpdcb->BaudRate = 230400;
1591 lpdcb->BaudRate = 460800;
1595 ERR("unknown speed %x \n",speed);
1598 switch (port.c_cflag & CSIZE) {
1600 lpdcb->ByteSize = 5;
1603 lpdcb->ByteSize = 6;
1606 lpdcb->ByteSize = 7;
1609 lpdcb->ByteSize = 8;
1612 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1615 if(port.c_iflag & INPCK)
1616 lpdcb->fParity = TRUE;
1618 lpdcb->fParity = FALSE;
1620 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1622 switch (port.c_cflag & (PARENB | PARODD))
1626 lpdcb->Parity = NOPARITY;
1629 lpdcb->Parity = EVENPARITY;
1631 case (PARENB | PARODD):
1632 lpdcb->Parity = ODDPARITY;
1635 case (PARENB | CMSPAR):
1636 lpdcb->Parity = MARKPARITY;
1638 case (PARENB | PARODD | CMSPAR):
1639 lpdcb->Parity = SPACEPARITY;
1644 if (port.c_cflag & CSTOPB)
1645 if(lpdcb->ByteSize == 5)
1646 lpdcb->StopBits = ONE5STOPBITS;
1648 lpdcb->StopBits = TWOSTOPBITS;
1650 lpdcb->StopBits = ONESTOPBIT;
1655 /* termios does not support DTR/DSR flow control */
1656 lpdcb->fOutxDsrFlow = 0;
1657 lpdcb->fDtrControl =
1659 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1661 DTR_CONTROL_ENABLE ;
1665 if (port.c_cflag & CRTSCTS) {
1666 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1667 lpdcb->fOutxCtsFlow = 1;
1671 lpdcb->fRtsControl =
1673 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1675 RTS_CONTROL_ENABLE ;
1676 lpdcb->fOutxCtsFlow = 0;
1678 if (port.c_iflag & IXON)
1683 if (port.c_iflag & IXOFF)
1692 lpdcb->XoffLim = 10;
1694 COMM_SetCommError(handle,0);
1698 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1699 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1700 (lpdcb->StopBits == ONESTOPBIT)?1:
1701 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1702 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1703 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1704 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1705 lpdcb->fRtsControl);
1706 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1707 lpdcb->fDtrControl);
1709 if ( lpdcb->fOutxCtsFlow ||
1710 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1715 TRACE("~CRTSCTS\n");
1720 /*****************************************************************************
1721 * TransmitCommChar (KERNEL32.@)
1723 * Transmits a single character in front of any pending characters in the
1724 * output buffer. Usually used to send an interrupt character to a host.
1728 * True if the call succeeded, false if the previous command character to the
1729 * same device has not been sent yet the handle is bad etc.
1735 BOOL WINAPI TransmitCommChar(
1736 HANDLE hComm, /* [in] The communication device in need of a command character. */
1737 CHAR chTransmit) /* [in] The character to transmit. */
1739 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1741 return WriteFile( hComm, &chTransmit, 1, NULL, 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 = CreateEventA(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 CHAR lpszSerialUI[] = "serialui.dll";
2104 /***********************************************************************
2105 * CommConfigDialogA (KERNEL32.@)
2107 * Raises a dialog that allows the user to configure a comm port.
2108 * Fills the COMMCONFIG struct with information specified by the user.
2109 * This function should call a similar routine in the COMM driver...
2113 * TRUE on success, FALSE on failure
2114 * If successful, the lpCommConfig structure will contain a new
2115 * configuration for the comm port, as specified by the user.
2118 * The library with the CommConfigDialog code is never unloaded.
2119 * Perhaps this should be done when the comm port is closed?
2121 BOOL WINAPI CommConfigDialogA(
2122 LPCSTR lpszDevice, /* [in] name of communications device */
2123 HANDLE hWnd, /* [in] parent window for the dialog */
2124 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2126 FARPROC lpfnCommDialog;
2127 HMODULE hConfigModule;
2130 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2132 hConfigModule = LoadLibraryA(lpszSerialUI);
2136 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2141 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2143 /* UnloadLibrary(hConfigModule); */
2148 /***********************************************************************
2149 * CommConfigDialogW (KERNEL32.@)
2151 * see CommConfigDialogA for more info
2153 BOOL WINAPI CommConfigDialogW(
2154 LPCWSTR lpszDevice, /* [in] name of communications device */
2155 HANDLE hWnd, /* [in] parent window for the dialog */
2156 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2161 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2164 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2165 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2169 /***********************************************************************
2170 * GetCommConfig (KERNEL32.@)
2172 * Fill in the COMMCONFIG structure for the comm port hFile
2176 * TRUE on success, FALSE on failure
2177 * If successful, lpCommConfig contains the comm port configuration.
2182 BOOL WINAPI GetCommConfig(
2183 HANDLE hFile, /* [in] The communications device. */
2184 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2185 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2186 afterwards the number of bytes copied to the buffer or
2187 the needed size of the buffer. */
2191 TRACE("(%p %p)\n",hFile,lpCommConfig);
2193 if(lpCommConfig == NULL)
2195 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2196 *lpdwSize = sizeof(COMMCONFIG);
2200 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2201 lpCommConfig->wVersion = 1;
2202 lpCommConfig->wReserved = 0;
2203 r = GetCommState(hFile,&lpCommConfig->dcb);
2204 lpCommConfig->dwProviderSubType = PST_RS232;
2205 lpCommConfig->dwProviderOffset = 0;
2206 lpCommConfig->dwProviderSize = 0;
2211 /***********************************************************************
2212 * SetCommConfig (KERNEL32.@)
2214 * Sets the configuration of the communications device.
2218 * True on success, false if the handle was bad is not a communications device.
2220 BOOL WINAPI SetCommConfig(
2221 HANDLE hFile, /* [in] The communications device. */
2222 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2223 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2225 TRACE("(%p %p)\n",hFile,lpCommConfig);
2226 return SetCommState(hFile,&lpCommConfig->dcb);
2229 /***********************************************************************
2230 * SetDefaultCommConfigA (KERNEL32.@)
2232 * Initializes the default configuration for the specified communication
2237 * True if the device was found and the defaults set, false otherwise
2239 BOOL WINAPI SetDefaultCommConfigA(
2240 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2241 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2242 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2244 FARPROC lpfnSetDefaultCommConfig;
2245 HMODULE hConfigModule;
2248 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2250 hConfigModule = LoadLibraryA(lpszSerialUI);
2254 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2256 if(! lpfnSetDefaultCommConfig)
2259 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2261 /* UnloadLibrary(hConfigModule); */
2267 /***********************************************************************
2268 * SetDefaultCommConfigW (KERNEL32.@)
2270 * Initializes the default configuration for the specified
2271 * communication device. (unicode)
2276 BOOL WINAPI SetDefaultCommConfigW(
2277 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2278 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2279 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2284 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2286 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2289 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2290 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2295 /***********************************************************************
2296 * GetDefaultCommConfigW (KERNEL32.@)
2298 * Acquires the default configuration of the specified communication device. (unicode)
2302 * True on successful reading of the default configuration,
2303 * if the device is not found or the buffer is too small.
2305 BOOL WINAPI GetDefaultCommConfigW(
2306 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2307 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2308 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2309 afterwards the number of bytes copied to the buffer or
2310 the needed size of the buffer. */
2312 LPDCB lpdcb = &(lpCC->dcb);
2314 static const WCHAR comW[] = {'C','O','M',0};
2315 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2317 if (strncmpiW(lpszName,comW,3)) {
2318 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2322 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2323 if (*lpdwSize < sizeof(COMMCONFIG)) {
2324 *lpdwSize = sizeof(COMMCONFIG);
2328 *lpdwSize = sizeof(COMMCONFIG);
2330 lpCC->dwSize = sizeof(COMMCONFIG);
2332 lpCC->dwProviderSubType = PST_RS232;
2333 lpCC->dwProviderOffset = 0L;
2334 lpCC->dwProviderSize = 0L;
2336 sprintfW( temp, formatW, lpszName[3]);
2337 FIXME("setting %s as default\n", debugstr_w(temp));
2339 return BuildCommDCBW( temp, lpdcb);
2342 /**************************************************************************
2343 * GetDefaultCommConfigA (KERNEL32.@)
2345 * Acquires the default configuration of the specified communication device. (ascii)
2349 * True on successful reading of the default configuration,
2350 * if the device is not found or the buffer is too small.
2352 BOOL WINAPI GetDefaultCommConfigA(
2353 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2354 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2355 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2356 afterwards the number of bytes copied to the buffer or
2357 the needed size of the buffer. */
2360 UNICODE_STRING lpszNameW;
2362 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2363 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2364 else lpszNameW.Buffer = NULL;
2366 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2368 RtlFreeUnicodeString(&lpszNameW);