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 #include "wine/port.h"
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
49 #ifdef HAVE_SYS_POLL_H
50 # include <sys/poll.h>
52 #ifdef HAVE_SYS_MODEM_H
53 # include <sys/modem.h>
55 #ifdef HAVE_SYS_STRTIO_H
56 # include <sys/strtio.h>
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
65 #include "wine/server.h"
66 #include "wine/unicode.h"
68 #include "wine/debug.h"
70 #ifdef HAVE_LINUX_SERIAL_H
71 #include <linux/serial.h>
74 WINE_DEFAULT_DEBUG_CHANNEL(comm);
76 /* retrieve the Unix handle corresponding to a comm handle */
77 static int get_comm_fd( HANDLE handle, DWORD access )
81 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
82 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
86 /* release the Unix handle returned by get_comm_fd */
87 static inline void release_comm_fd( HANDLE handle, int fd )
89 wine_server_release_fd( handle, fd );
93 * local structure holding the irq values we need for WaitCommEvent()
95 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
96 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
97 * no need to carry them in the internal structure
100 typedef struct serial_irq_info
102 int rx , tx, frame, overrun, parity, brk, buf_overrun;
105 /***********************************************************************
106 * Data needed by the thread polling for the changing CommEvent
108 typedef struct async_commio
115 serial_irq_info irq_info;
118 /***********************************************************************/
120 #if !defined(TIOCINQ) && defined(FIONREAD)
121 #define TIOCINQ FIONREAD
124 /***********************************************************************
125 * Get extended interrupt count info, needed for WaitCommEvent
127 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
130 struct serial_icounter_struct einfo;
131 if (!ioctl(fd,TIOCGICOUNT, &einfo))
133 irq_info->rx = einfo.rx;
134 irq_info->tx = einfo.tx;
135 irq_info->frame = einfo.frame;
136 irq_info->overrun = einfo.overrun;
137 irq_info->parity = einfo.parity;
138 irq_info->brk = einfo.brk;
139 irq_info->buf_overrun = einfo.buf_overrun;
143 memset(irq_info,0, sizeof(serial_irq_info));
147 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
150 unsigned int mstat, okay;
151 okay = ioctl(fd, TIOCMGET, &mstat);
152 if (okay) return okay;
153 if (andy) mstat &= andy;
155 return ioctl(fd, TIOCMSET, &mstat);
161 /***********************************************************************
162 * COMM_Parse* (Internal)
164 * The following COMM_Parse* functions are used by the BuildCommDCB
165 * functions to help parse the various parts of the device control string.
167 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
169 static const WCHAR comW[] = {'C','O','M',0};
171 /* The device control string may optionally start with "COMx" followed
172 by an optional ':' and spaces. */
173 if(!strncmpiW(ptr, comW, 3))
177 /* Allow any com port above 0 as Win 9x does (NT only allows
178 values for com ports which are actually present) */
179 if(*ptr < '1' || *ptr > '9')
182 /* Advance pointer past port number */
183 while(*ptr >= '0' && *ptr <= '9') ptr++;
185 /* The com port number must be followed by a ':' or ' ' */
186 if(*ptr != ':' && *ptr != ' ')
189 /* Advance pointer to beginning of next parameter */
190 while(*ptr == ' ') ptr++;
194 while(*ptr == ' ') ptr++;
197 /* The device control string must not start with a space. */
204 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
206 if(*ptr < '0' || *ptr > '9') return NULL;
207 *lpnumber = strtoulW(ptr, NULL, 10);
208 while(*ptr >= '0' && *ptr <= '9') ptr++;
212 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
214 /* Contrary to what you might expect, Windows only sets the Parity
215 member of DCB and not fParity even when parity is specified in the
216 device control string */
218 switch(toupperW(*ptr++))
221 *lpparity = EVENPARITY;
224 *lpparity = MARKPARITY;
227 *lpparity = NOPARITY;
230 *lpparity = ODDPARITY;
233 *lpparity = SPACEPARITY;
242 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
246 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
249 if(temp >= 5 && temp <= 8)
258 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
261 static const WCHAR stopbits15W[] = {'1','.','5',0};
263 if(!strncmpW(stopbits15W, ptr, 3))
266 *lpstopbits = ONE5STOPBITS;
270 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
274 *lpstopbits = ONESTOPBIT;
276 *lpstopbits = TWOSTOPBITS;
284 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
286 static const WCHAR onW[] = {'o','n',0};
287 static const WCHAR offW[] = {'o','f','f',0};
289 if(!strncmpiW(onW, ptr, 2))
294 else if(!strncmpiW(offW, ptr, 3))
305 /***********************************************************************
306 * COMM_BuildOldCommDCB (Internal)
308 * Build a DCB using the old style settings string eg: "96,n,8,1"
310 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
314 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
317 switch(lpdcb->BaudRate)
322 lpdcb->BaudRate *= 10;
328 lpdcb->BaudRate *= 100;
331 lpdcb->BaudRate = 19200;
335 while(*device == ' ') device++;
336 if(*device++ != ',') return FALSE;
337 while(*device == ' ') device++;
339 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
342 while(*device == ' ') device++;
343 if(*device++ != ',') return FALSE;
344 while(*device == ' ') device++;
346 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
349 while(*device == ' ') device++;
350 if(*device++ != ',') return FALSE;
351 while(*device == ' ') device++;
353 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
356 /* The last parameter for flow control is optional. */
357 while(*device == ' ') device++;
361 while(*device == ' ') device++;
362 if(*device) last = toupperW(*device++);
363 while(*device == ' ') device++;
366 /* Win NT sets the flow control members based on (or lack of) the last
367 parameter. Win 9x does not set these members. */
372 lpdcb->fOutX = FALSE;
373 lpdcb->fOutxCtsFlow = FALSE;
374 lpdcb->fOutxDsrFlow = FALSE;
375 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
376 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
381 lpdcb->fOutxCtsFlow = FALSE;
382 lpdcb->fOutxDsrFlow = FALSE;
383 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
384 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
388 lpdcb->fOutX = FALSE;
389 lpdcb->fOutxCtsFlow = TRUE;
390 lpdcb->fOutxDsrFlow = TRUE;
391 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
392 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
398 /* This should be the end of the string. */
399 if(*device) return FALSE;
404 /***********************************************************************
405 * COMM_BuildNewCommDCB (Internal)
407 * Build a DCB using the new style settings string.
408 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
410 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
413 BOOL baud = FALSE, stop = FALSE;
414 static const WCHAR baudW[] = {'b','a','u','d','=',0};
415 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
416 static const WCHAR dataW[] = {'d','a','t','a','=',0};
417 static const WCHAR stopW[] = {'s','t','o','p','=',0};
418 static const WCHAR toW[] = {'t','o','=',0};
419 static const WCHAR xonW[] = {'x','o','n','=',0};
420 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
421 static const WCHAR octsW[] = {'o','c','t','s','=',0};
422 static const WCHAR dtrW[] = {'d','t','r','=',0};
423 static const WCHAR rtsW[] = {'r','t','s','=',0};
424 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
428 while(*device == ' ') device++;
430 if(!strncmpiW(baudW, device, 5))
434 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
437 else if(!strncmpiW(parityW, device, 7))
439 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
442 else if(!strncmpiW(dataW, device, 5))
444 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
447 else if(!strncmpiW(stopW, device, 5))
451 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
454 else if(!strncmpiW(toW, device, 3))
456 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
459 lptimeouts->ReadIntervalTimeout = 0;
460 lptimeouts->ReadTotalTimeoutMultiplier = 0;
461 lptimeouts->ReadTotalTimeoutConstant = 0;
462 lptimeouts->WriteTotalTimeoutMultiplier = 0;
463 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
465 else if(!strncmpiW(xonW, device, 4))
467 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
473 else if(!strncmpiW(odsrW, device, 5))
475 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
478 lpdcb->fOutxDsrFlow = temp;
480 else if(!strncmpiW(octsW, device, 5))
482 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
485 lpdcb->fOutxCtsFlow = temp;
487 else if(!strncmpiW(dtrW, device, 4))
489 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
492 lpdcb->fDtrControl = temp;
494 else if(!strncmpiW(rtsW, device, 4))
496 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
499 lpdcb->fRtsControl = temp;
501 else if(!strncmpiW(idsrW, device, 5))
503 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
506 /* Win NT sets the fDsrSensitivity member based on the
507 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
508 lpdcb->fDsrSensitivity = temp;
513 /* After the above parsing, the next character (if not the end of
514 the string) should be a space */
515 if(*device && *device != ' ')
519 /* If stop bits were not specified, a default is always supplied. */
522 if(baud && lpdcb->BaudRate == 110)
523 lpdcb->StopBits = TWOSTOPBITS;
525 lpdcb->StopBits = ONESTOPBIT;
531 /**************************************************************************
532 * BuildCommDCBA (KERNEL32.@)
534 * Updates a device control block data structure with values from an
535 * ascii device control string. The device control string has two forms
536 * normal and extended, it must be exclusively in one or the other form.
540 * True on success, false on a malformed control string.
542 BOOL WINAPI BuildCommDCBA(
543 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
544 LPDCB lpdcb) /* [out] The device control block to be updated. */
546 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
549 /**************************************************************************
550 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
552 * Updates a device control block data structure with values from an
553 * ascii device control string. Taking timeout values from a timeouts
554 * struct if desired by the control string.
558 * True on success, false bad handles etc.
560 BOOL WINAPI BuildCommDCBAndTimeoutsA(
561 LPCSTR device, /* [in] The ascii device control string. */
562 LPDCB lpdcb, /* [out] The device control block to be updated. */
563 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
566 UNICODE_STRING deviceW;
568 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
569 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
570 else deviceW.Buffer = NULL;
572 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
574 RtlFreeUnicodeString(&deviceW);
578 /**************************************************************************
579 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
581 * Updates a device control block data structure with values from a
582 * unicode device control string. Taking timeout values from a timeouts
583 * struct if desired by the control string.
587 * True on success, false bad handles etc
589 BOOL WINAPI BuildCommDCBAndTimeoutsW(
590 LPCWSTR devid, /* [in] The unicode device control string. */
591 LPDCB lpdcb, /* [out] The device control block to be updated. */
592 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
595 COMMTIMEOUTS timeouts;
599 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
601 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
602 lpdcb->DCBlength = sizeof(DCB);
604 /* Make a copy of the original data structures to work with since if
605 if there is an error in the device control string the originals
606 should not be modified (except possibly DCBlength) */
607 memcpy(&dcb, lpdcb, sizeof(DCB));
608 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
610 ptr = COMM_ParseStart(ptr);
614 else if(strchrW(ptr, ','))
615 result = COMM_BuildOldCommDCB(ptr, &dcb);
617 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
621 memcpy(lpdcb, &dcb, sizeof(DCB));
622 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
627 WARN("Invalid device control string: %s\n", debugstr_w(devid));
628 SetLastError(ERROR_INVALID_PARAMETER);
633 /**************************************************************************
634 * BuildCommDCBW (KERNEL32.@)
636 * Updates a device control block structure with values from an
637 * unicode device control string. The device control string has two forms
638 * normal and extended, it must be exclusively in one or the other form.
642 * True on success, false on a malformed control string.
644 BOOL WINAPI BuildCommDCBW(
645 LPCWSTR devid, /* [in] The unicode device control string. */
646 LPDCB lpdcb) /* [out] The device control block to be updated. */
648 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
651 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
655 SERVER_START_REQ( set_serial_info )
657 req->handle = handle;
658 req->flags = SERIALINFO_SET_ERROR;
659 req->commerror = error;
660 ret = !wine_server_call_err( req );
666 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
673 SERVER_START_REQ( get_serial_info )
675 req->handle = handle;
676 ret = !wine_server_call_err( req );
677 *lperror = reply->commerror;
684 /*****************************************************************************
685 * SetCommBreak (KERNEL32.@)
687 * Halts the transmission of characters to a communications device.
691 * True on success, and false if the communications device could not be found,
692 * the control is not supported.
696 * Only TIOCSBRK and TIOCCBRK are supported.
698 BOOL WINAPI SetCommBreak(
699 HANDLE handle) /* [in] The communications device to suspend. */
701 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
704 fd = get_comm_fd( handle, GENERIC_READ );
705 if(fd<0) return FALSE;
706 result = ioctl(fd,TIOCSBRK,0);
707 release_comm_fd( handle, fd );
710 TRACE("ioctl failed\n");
711 SetLastError(ERROR_NOT_SUPPORTED);
716 FIXME("ioctl not available\n");
717 SetLastError(ERROR_NOT_SUPPORTED);
722 /*****************************************************************************
723 * ClearCommBreak (KERNEL32.@)
725 * Resumes character transmission from a communication device.
729 * True on success and false if the communications device could not be found.
733 * Only TIOCSBRK and TIOCCBRK are supported.
735 BOOL WINAPI ClearCommBreak(
736 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
738 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
741 fd = get_comm_fd( handle, GENERIC_READ );
742 if(fd<0) return FALSE;
743 result = ioctl(fd,TIOCCBRK,0);
744 release_comm_fd( handle, fd );
747 TRACE("ioctl failed\n");
748 SetLastError(ERROR_NOT_SUPPORTED);
753 FIXME("ioctl not available\n");
754 SetLastError(ERROR_NOT_SUPPORTED);
759 /*****************************************************************************
760 * EscapeCommFunction (KERNEL32.@)
762 * Directs a communication device to perform an extended function.
766 * True or requested data on successful completion of the command,
767 * false if the device is not present cannot execute the command
768 * or the command failed.
770 BOOL WINAPI EscapeCommFunction(
771 HANDLE handle, /* [in] The communication device to perform the extended function. */
772 UINT nFunction) /* [in] The extended function to be performed. */
774 int fd,direct=FALSE,result=FALSE;
777 TRACE("handle %p, function=%d\n", handle, nFunction);
778 fd = get_comm_fd( handle, GENERIC_READ );
779 if(fd<0) return FALSE;
781 if (tcgetattr(fd,&port) == -1) {
782 COMM_SetCommError(handle,CE_IOE);
783 release_comm_fd( handle, fd );
796 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
804 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
812 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
820 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
826 port.c_iflag |= IXOFF;
831 port.c_iflag |= IXON;
837 result = ioctl(fd,TIOCSBRK,0);
844 result = ioctl(fd,TIOCCBRK,0);
848 WARN("(handle=%p,nFunction=%d): Unknown function\n",
854 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
855 release_comm_fd( handle, fd );
856 COMM_SetCommError(handle,CE_IOE);
865 COMM_SetCommError(handle,CE_IOE);
870 release_comm_fd( handle, fd );
874 /********************************************************************
875 * PurgeComm (KERNEL32.@)
877 * Terminates pending operations and/or discards buffers on a
878 * communication resource.
882 * True on success and false if the communications handle is bad.
884 BOOL WINAPI PurgeComm(
885 HANDLE handle, /* [in] The communication resource to be purged. */
886 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
890 TRACE("handle %p, flags %lx\n", handle, flags);
892 fd = get_comm_fd( handle, GENERIC_READ );
893 if(fd<0) return FALSE;
896 ** not exactly sure how these are different
897 ** Perhaps if we had our own internal queues, one flushes them
898 ** and the other flushes the kernel's buffers.
900 if(flags&PURGE_TXABORT)
901 tcflush(fd,TCOFLUSH);
902 if(flags&PURGE_RXABORT)
903 tcflush(fd,TCIFLUSH);
904 if(flags&PURGE_TXCLEAR)
905 tcflush(fd,TCOFLUSH);
906 if(flags&PURGE_RXCLEAR)
907 tcflush(fd,TCIFLUSH);
908 release_comm_fd( handle, fd );
913 /*****************************************************************************
914 * ClearCommError (KERNEL32.@)
916 * Enables further I/O operations on a communications resource after
917 * supplying error and current status information.
921 * True on success, false if the communication resource handle is bad.
923 BOOL WINAPI ClearCommError(
924 HANDLE handle, /* [in] The communication resource with the error. */
925 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
926 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
930 fd=get_comm_fd( handle, GENERIC_READ );
931 if(0>fd) return FALSE;
935 lpStat->fCtsHold = 0;
936 lpStat->fDsrHold = 0;
937 lpStat->fRlsdHold = 0;
938 lpStat->fXoffHold = 0;
939 lpStat->fXoffSent = 0;
942 lpStat->fReserved = 0;
945 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
946 WARN("ioctl returned error\n");
948 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
952 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
953 WARN("ioctl returned error\n");
956 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
957 handle, lpStat->cbInQue, lpStat->cbOutQue);
960 release_comm_fd( handle, fd );
962 COMM_GetCommError(handle, errors);
963 COMM_SetCommError(handle, 0);
968 /*****************************************************************************
969 * SetupComm (KERNEL32.@)
971 * Called after CreateFile to hint to the communication resource to use
972 * specified sizes for input and output buffers rather than the default values.
976 * True if successful, false if the communications resource handle is bad.
982 BOOL WINAPI SetupComm(
983 HANDLE handle, /* [in] The just created communication resource handle. */
984 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
985 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
989 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
990 fd=get_comm_fd( handle, GENERIC_READ );
991 if(0>fd) return FALSE;
992 release_comm_fd( handle, fd );
996 /*****************************************************************************
997 * GetCommMask (KERNEL32.@)
999 * Obtain the events associated with a communication device that will cause
1000 * a call WaitCommEvent to return.
1004 * True on success, fail on bad device handle etc.
1006 BOOL WINAPI GetCommMask(
1007 HANDLE handle, /* [in] The communications device. */
1008 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1012 TRACE("handle %p, mask %p\n", handle, evtmask);
1014 SERVER_START_REQ( get_serial_info )
1016 req->handle = handle;
1017 if ((ret = !wine_server_call_err( req )))
1019 if (evtmask) *evtmask = reply->eventmask;
1026 /*****************************************************************************
1027 * SetCommMask (KERNEL32.@)
1029 * There be some things we need to hear about yon there communications device.
1030 * (Set which events associated with a communication device should cause
1031 * a call WaitCommEvent to return.)
1035 * True on success, false on bad handle etc.
1037 BOOL WINAPI SetCommMask(
1038 HANDLE handle, /* [in] The communications device. */
1039 DWORD evtmask) /* [in] The events that are to be monitored. */
1043 TRACE("handle %p, mask %lx\n", handle, evtmask);
1045 SERVER_START_REQ( set_serial_info )
1047 req->handle = handle;
1048 req->flags = SERIALINFO_SET_MASK;
1049 req->eventmask = evtmask;
1050 ret = !wine_server_call_err( req );
1056 /*****************************************************************************
1057 * SetCommState (KERNEL32.@)
1059 * Re-initializes all hardware and control settings of a communications device,
1060 * with values from a device control block without effecting the input and output
1065 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1067 BOOL WINAPI SetCommState(
1068 HANDLE handle, /* [in] The communications device. */
1069 LPDCB lpdcb) /* [out] The device control block. */
1071 struct termios port;
1072 int fd, bytesize, stopbits;
1075 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1076 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1077 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1078 (lpdcb->StopBits == ONESTOPBIT)?1:
1079 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1080 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1081 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1082 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1083 lpdcb->fRtsControl);
1084 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1085 lpdcb->fDtrControl);
1088 fd = get_comm_fd( handle, GENERIC_READ );
1089 if (fd < 0) return FALSE;
1091 if ((tcgetattr(fd,&port)) == -1) {
1092 int save_error = errno;
1093 COMM_SetCommError(handle,CE_IOE);
1094 release_comm_fd( handle, fd );
1095 ERR("tcgetattr error '%s'\n", strerror(save_error));
1099 port.c_cc[VMIN] = 0;
1100 port.c_cc[VTIME] = 1;
1103 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
1105 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
1107 port.c_iflag |= (IGNBRK);
1109 port.c_oflag &= ~(OPOST);
1111 port.c_cflag &= ~(HUPCL);
1112 port.c_cflag |= CLOCAL | CREAD;
1114 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1115 port.c_lflag |= NOFLSH;
1118 port.c_cflag &= ~CBAUD;
1119 switch (lpdcb->BaudRate) {
1124 port.c_cflag |= B50;
1127 port.c_cflag |= B75;
1131 port.c_cflag |= B110;
1134 port.c_cflag |= B134;
1137 port.c_cflag |= B150;
1140 port.c_cflag |= B200;
1144 port.c_cflag |= B300;
1148 port.c_cflag |= B600;
1152 port.c_cflag |= B1200;
1155 port.c_cflag |= B1800;
1159 port.c_cflag |= B2400;
1163 port.c_cflag |= B4800;
1167 port.c_cflag |= B9600;
1171 port.c_cflag |= B19200;
1175 port.c_cflag |= B38400;
1179 port.c_cflag |= B57600;
1184 port.c_cflag |= B115200;
1189 port.c_cflag |= B230400;
1194 port.c_cflag |= B460800;
1198 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1199 { struct serial_struct nuts;
1201 ioctl(fd, TIOCGSERIAL, &nuts);
1202 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1203 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1204 arby = nuts.baud_base / nuts.custom_divisor;
1205 nuts.flags &= ~ASYNC_SPD_MASK;
1206 nuts.flags |= ASYNC_SPD_CUST;
1207 WARN("You (or a program acting at your behest) have specified\n"
1208 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1209 "which is as close as we can get by our present understanding of your\n"
1210 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1211 "has caused to your linux system can be undone with setserial \n"
1212 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1213 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1214 ioctl(fd, TIOCSSERIAL, &nuts);
1215 port.c_cflag |= B38400;
1218 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1221 COMM_SetCommError(handle,IE_BAUDRATE);
1222 release_comm_fd( handle, fd );
1223 ERR("baudrate %ld\n",lpdcb->BaudRate);
1226 #elif !defined(__EMX__)
1227 switch (lpdcb->BaudRate) {
1232 port.c_ospeed = B50;
1235 port.c_ospeed = B75;
1239 port.c_ospeed = B110;
1242 port.c_ospeed = B134;
1245 port.c_ospeed = B150;
1248 port.c_ospeed = B200;
1252 port.c_ospeed = B300;
1256 port.c_ospeed = B600;
1260 port.c_ospeed = B1200;
1263 port.c_ospeed = B1800;
1267 port.c_ospeed = B2400;
1271 port.c_ospeed = B4800;
1275 port.c_ospeed = B9600;
1279 port.c_ospeed = B19200;
1283 port.c_ospeed = B38400;
1288 port.c_cflag |= B57600;
1294 port.c_cflag |= B115200;
1299 port.c_cflag |= B230400;
1304 port.c_cflag |= B460800;
1308 COMM_SetCommError(handle,IE_BAUDRATE);
1309 release_comm_fd( handle, fd );
1310 ERR("baudrate %ld\n",lpdcb->BaudRate);
1313 port.c_ispeed = port.c_ospeed;
1315 bytesize=lpdcb->ByteSize;
1316 stopbits=lpdcb->StopBits;
1319 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1321 port.c_cflag &= ~(PARENB | PARODD);
1324 port.c_iflag |= INPCK;
1326 port.c_iflag &= ~INPCK;
1327 switch (lpdcb->Parity) {
1331 port.c_cflag |= (PARENB | PARODD);
1334 port.c_cflag |= PARENB;
1337 /* Linux defines mark/space (stick) parity */
1339 port.c_cflag |= (PARENB | CMSPAR);
1342 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1345 /* try the POSIX way */
1347 if( stopbits == ONESTOPBIT) {
1348 stopbits = TWOSTOPBITS;
1349 port.c_iflag &= ~INPCK;
1351 COMM_SetCommError(handle,IE_BYTESIZE);
1352 release_comm_fd( handle, fd );
1353 ERR("Cannot set MARK Parity\n");
1360 port.c_iflag &= ~INPCK;
1362 COMM_SetCommError(handle,IE_BYTESIZE);
1363 release_comm_fd( handle, fd );
1364 ERR("Cannot set SPACE Parity\n");
1370 COMM_SetCommError(handle,IE_BYTESIZE);
1371 release_comm_fd( handle, fd );
1377 port.c_cflag &= ~CSIZE;
1380 port.c_cflag |= CS5;
1383 port.c_cflag |= CS6;
1386 port.c_cflag |= CS7;
1389 port.c_cflag |= CS8;
1392 COMM_SetCommError(handle,IE_BYTESIZE);
1393 release_comm_fd( handle, fd );
1400 port.c_cflag &= ~CSTOPB;
1402 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1404 port.c_cflag |= CSTOPB;
1407 COMM_SetCommError(handle,IE_BYTESIZE);
1408 release_comm_fd( handle, fd );
1413 if ( lpdcb->fOutxCtsFlow ||
1414 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1417 port.c_cflag |= CRTSCTS;
1423 port.c_iflag |= IXON;
1425 port.c_iflag &= ~IXON;
1427 port.c_iflag |= IXOFF;
1429 port.c_iflag &= ~IXOFF;
1431 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1432 ERR("tcsetattr error '%s'\n", strerror(errno));
1433 COMM_SetCommError(handle,CE_IOE);
1436 COMM_SetCommError(handle,0);
1440 /* note: change DTR/RTS lines after setting the comm attributes,
1441 * so flow control does not interfere. */
1443 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1445 WARN("DSR/DTR flow control not supported\n");
1446 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1447 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1449 COMM_WhackModem(fd, 0, TIOCM_DTR);
1452 if(!lpdcb->fOutxCtsFlow )
1454 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1455 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1457 COMM_WhackModem(fd, 0, TIOCM_RTS);
1460 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1461 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1462 release_comm_fd( handle, fd );
1468 /*****************************************************************************
1469 * GetCommState (KERNEL32.@)
1471 * Fills in a device control block with information from a communications device.
1475 * True on success, false if the communication device handle is bad etc
1479 * XonChar and XoffChar are not set.
1481 BOOL WINAPI GetCommState(
1482 HANDLE handle, /* [in] The communications device. */
1483 LPDCB lpdcb) /* [out] The device control block. */
1485 struct termios port;
1487 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1489 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1491 fd = get_comm_fd( handle, GENERIC_READ );
1492 if (fd < 0) return FALSE;
1493 if (tcgetattr(fd, &port) == -1) {
1494 int save_error=errno;
1495 ERR("tcgetattr error '%s'\n", strerror(save_error));
1496 COMM_SetCommError(handle,CE_IOE);
1497 release_comm_fd( handle, fd );
1502 if (ioctl(fd, TIOCMGET, &stat) == -1)
1504 int save_error=errno;
1505 WARN("ioctl error '%s'\n", strerror(save_error));
1506 stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1509 release_comm_fd( handle, fd );
1512 speed= (port.c_cflag & CBAUD);
1514 speed= (cfgetospeed(&port));
1518 lpdcb->BaudRate = 0;
1521 lpdcb->BaudRate = 50;
1524 lpdcb->BaudRate = 75;
1527 lpdcb->BaudRate = 110;
1530 lpdcb->BaudRate = 134;
1533 lpdcb->BaudRate = 150;
1536 lpdcb->BaudRate = 200;
1539 lpdcb->BaudRate = 300;
1542 lpdcb->BaudRate = 600;
1545 lpdcb->BaudRate = 1200;
1548 lpdcb->BaudRate = 1800;
1551 lpdcb->BaudRate = 2400;
1554 lpdcb->BaudRate = 4800;
1557 lpdcb->BaudRate = 9600;
1560 lpdcb->BaudRate = 19200;
1563 lpdcb->BaudRate = 38400;
1567 lpdcb->BaudRate = 57600;
1572 lpdcb->BaudRate = 115200;
1577 lpdcb->BaudRate = 230400;
1582 lpdcb->BaudRate = 460800;
1586 ERR("unknown speed %x\n", speed);
1589 switch (port.c_cflag & CSIZE) {
1591 lpdcb->ByteSize = 5;
1594 lpdcb->ByteSize = 6;
1597 lpdcb->ByteSize = 7;
1600 lpdcb->ByteSize = 8;
1603 ERR("unknown size %x\n", port.c_cflag & CSIZE);
1606 if(port.c_iflag & INPCK)
1607 lpdcb->fParity = TRUE;
1609 lpdcb->fParity = FALSE;
1611 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1613 switch (port.c_cflag & (PARENB | PARODD))
1617 lpdcb->Parity = NOPARITY;
1620 lpdcb->Parity = EVENPARITY;
1622 case (PARENB | PARODD):
1623 lpdcb->Parity = ODDPARITY;
1626 case (PARENB | CMSPAR):
1627 lpdcb->Parity = MARKPARITY;
1629 case (PARENB | PARODD | CMSPAR):
1630 lpdcb->Parity = SPACEPARITY;
1635 if (port.c_cflag & CSTOPB)
1636 if(lpdcb->ByteSize == 5)
1637 lpdcb->StopBits = ONE5STOPBITS;
1639 lpdcb->StopBits = TWOSTOPBITS;
1641 lpdcb->StopBits = ONESTOPBIT;
1646 /* termios does not support DTR/DSR flow control */
1647 lpdcb->fOutxDsrFlow = 0;
1648 lpdcb->fDtrControl =
1650 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1652 DTR_CONTROL_ENABLE ;
1656 if (port.c_cflag & CRTSCTS) {
1657 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1658 lpdcb->fOutxCtsFlow = 1;
1662 lpdcb->fRtsControl =
1664 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1666 RTS_CONTROL_ENABLE ;
1667 lpdcb->fOutxCtsFlow = 0;
1669 if (port.c_iflag & IXON)
1674 if (port.c_iflag & IXOFF)
1683 lpdcb->XoffLim = 10;
1685 COMM_SetCommError(handle,0);
1689 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1690 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1691 (lpdcb->StopBits == ONESTOPBIT)?1:
1692 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1693 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1694 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1695 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1696 lpdcb->fRtsControl);
1697 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1698 lpdcb->fDtrControl);
1700 if ( lpdcb->fOutxCtsFlow ||
1701 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1706 TRACE("~CRTSCTS\n");
1711 /*****************************************************************************
1712 * TransmitCommChar (KERNEL32.@)
1714 * Transmits a single character in front of any pending characters in the
1715 * output buffer. Usually used to send an interrupt character to a host.
1719 * True if the call succeeded, false if the previous command character to the
1720 * same device has not been sent yet the handle is bad etc.
1726 BOOL WINAPI TransmitCommChar(
1727 HANDLE hComm, /* [in] The communication device in need of a command character. */
1728 CHAR chTransmit) /* [in] The character to transmit. */
1731 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1733 return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1737 /*****************************************************************************
1738 * GetCommTimeouts (KERNEL32.@)
1740 * Obtains the request timeout values for the communications device.
1744 * True on success, false if communications device handle is bad
1745 * or the target structure is null.
1747 BOOL WINAPI GetCommTimeouts(
1748 HANDLE hComm, /* [in] The communications device. */
1749 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1753 TRACE("(%p,%p)\n",hComm,lptimeouts);
1757 SetLastError(ERROR_INVALID_PARAMETER);
1761 SERVER_START_REQ( get_serial_info )
1763 req->handle = hComm;
1764 if ((ret = !wine_server_call_err( req )))
1766 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1767 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1768 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1769 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1770 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1777 /*****************************************************************************
1778 * SetCommTimeouts (KERNEL32.@)
1780 * Sets the timeouts used when reading and writing data to/from COMM ports.
1782 * ReadIntervalTimeout
1783 * - converted and passes to linux kernel as c_cc[VTIME]
1784 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1785 * - used in ReadFile to calculate GetOverlappedResult's timeout
1786 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1787 * - used in WriteFile to calculate GetOverlappedResult's timeout
1791 * True if the timeouts were set, false otherwise.
1793 BOOL WINAPI SetCommTimeouts(
1794 HANDLE hComm, /* [in] handle of COMM device */
1795 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1799 struct termios tios;
1801 TRACE("(%p,%p)\n",hComm,lptimeouts);
1805 SetLastError(ERROR_INVALID_PARAMETER);
1809 SERVER_START_REQ( set_serial_info )
1811 req->handle = hComm;
1812 req->flags = SERIALINFO_SET_TIMEOUTS;
1813 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1814 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1815 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1816 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1817 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1818 ret = !wine_server_call_err( req );
1821 if (!ret) return FALSE;
1823 /* FIXME: move this stuff to the server */
1824 fd = get_comm_fd( hComm, GENERIC_READ );
1825 if (fd < 0) return FALSE;
1827 if (-1==tcgetattr(fd,&tios)) {
1828 FIXME("tcgetattr on fd %d failed!\n",fd);
1829 release_comm_fd( hComm, fd );
1833 /* VTIME is in 1/10 seconds */
1835 unsigned int ux_timeout;
1837 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1843 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1846 ux_timeout = 1; /* must be at least some timeout */
1849 tios.c_cc[VTIME] = ux_timeout;
1852 if (-1==tcsetattr(fd,0,&tios)) {
1853 FIXME("tcsetattr on fd %d failed!\n",fd);
1854 release_comm_fd( hComm, fd );
1857 release_comm_fd( hComm, fd );
1861 /***********************************************************************
1862 * GetCommModemStatus (KERNEL32.@)
1864 * Obtains the four control register bits if supported by the hardware.
1868 * True if the communications handle was good and for hardware that
1869 * control register access, false otherwise.
1871 BOOL WINAPI GetCommModemStatus(
1872 HANDLE hFile, /* [in] The communications device. */
1873 LPDWORD lpModemStat) /* [out] The control register bits. */
1875 int fd,mstat, result=FALSE;
1879 fd = get_comm_fd( hFile, GENERIC_READ );
1882 result = ioctl(fd, TIOCMGET, &mstat);
1883 release_comm_fd( hFile, fd );
1886 WARN("ioctl failed\n");
1890 if (mstat & TIOCM_CTS)
1891 *lpModemStat |= MS_CTS_ON;
1894 if (mstat & TIOCM_DSR)
1895 *lpModemStat |= MS_DSR_ON;
1898 if (mstat & TIOCM_RNG)
1899 *lpModemStat |= MS_RING_ON;
1902 /*FIXME: Not really sure about RLSD UB 990810*/
1903 if (mstat & TIOCM_CAR)
1904 *lpModemStat |= MS_RLSD_ON;
1906 TRACE("%04x -> %s%s%s%s\n", mstat,
1907 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1908 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1909 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1910 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1917 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1919 DWORD ret = 0, queue;
1921 TRACE("mask 0x%08lx\n", mask);
1922 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old->rx, new->rx);
1923 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old->tx, new->tx);
1924 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old->frame, new->frame);
1925 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old->overrun, new->overrun);
1926 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old->parity, new->parity);
1927 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old->brk, new->brk);
1928 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1930 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1931 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1932 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1933 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1934 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1935 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1936 || (old->parity != new->parity)) )?EV_ERR :0;
1937 if (mask & EV_RXCHAR)
1941 if(ioctl(fd, TIOCINQ, &queue))
1942 WARN("TIOCINQ returned error\n");
1947 if (mask & EV_TXEMPTY)
1950 /* We really want to know when all characters have gone out of the transmitter */
1951 #if defined(TIOCSERGETLSR)
1952 if(ioctl(fd, TIOCSERGETLSR, &queue))
1953 WARN("TIOCSERGETLSR returned error\n");
1955 /* TIOCINQ only checks for an empty buffer */
1956 #elif defined(TIOCINQ)
1957 if(ioctl(fd, TIOCOUTQ, &queue))
1958 WARN("TIOCOUTQ returned error\n");
1963 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1968 /***********************************************************************
1969 * COMM_WaitCommEventService (INTERNAL)
1971 * We need to poll for what is interesting
1972 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1975 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1977 async_commio *commio = (async_commio*) arg;
1980 serial_irq_info new_irq_info;
1981 DWORD new_mstat, new_evtmask;
1983 fd=get_comm_fd( commio->handle, GENERIC_READ );
1985 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1986 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1990 * TIOCMIWAIT is not adequate
1993 * We don't handle the EV_RXFLAG (the eventchar)
1996 rc= COMM_GetEInfo(fd,&new_irq_info);
1998 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1999 rc = GetCommModemStatus(commio->handle, &new_mstat);
2001 TRACE("GetCommModemStatus failed\n");
2002 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
2003 GetCommMask(commio->handle, &new_evtmask);
2004 abort = (commio->evtmask != new_evtmask);
2005 TRACE("resulting Eventmask 0x%08x\n", rc);
2006 } while (!rc && ! abort);
2008 release_comm_fd( commio->handle, fd );
2009 *commio->buffer = rc;
2010 if (commio->hEvent != INVALID_HANDLE_VALUE )
2011 NtSetEvent( commio->hEvent, NULL );
2012 HeapFree(GetProcessHeap(), 0, commio );
2017 /***********************************************************************
2018 * COMM_WaitCommEvent (INTERNAL)
2020 * This function must have an lpOverlapped.
2022 static BOOL COMM_WaitCommEvent(
2023 HANDLE hFile, /* [in] handle of comm port to wait for */
2024 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2025 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2028 async_commio* commio;
2034 SetLastError(ERROR_INVALID_PARAMETER);
2038 if (NtResetEvent(lpOverlapped->hEvent,NULL))
2041 fd = get_comm_fd( hFile, GENERIC_WRITE );
2042 if (fd < 0) return FALSE;
2044 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
2047 release_comm_fd( hFile, fd );
2051 commio->handle = hFile;
2052 commio->buffer = (char *)lpdwEvents;
2053 commio->hEvent = lpOverlapped->hEvent;
2054 GetCommMask(hFile, &commio->evtmask);
2056 /* We may never return, if some capabilities miss
2057 * Return error in that case
2059 #if !defined(TIOCINQ)
2060 if(commio->evtmask & EV_RXCHAR)
2063 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
2064 if(commio->evtmask & EV_TXEMPTY)
2067 #if !defined(TIOCMGET)
2068 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
2071 #if !defined(TIOCM_CTS)
2072 if(commio->evtmask & EV_CTS)
2075 #if !defined(TIOCM_DSR)
2076 if(commio->evtmask & EV_DSR)
2079 #if !defined(TIOCM_RNG)
2080 if(commio->evtmask & EV_RING)
2083 #if !defined(TIOCM_CAR)
2084 if(commio->evtmask & EV_RLSD)
2087 if(commio->evtmask & EV_RXFLAG)
2088 FIXME("EV_RXFLAG not handled\n");
2089 COMM_GetEInfo(fd,&commio->irq_info);
2090 GetCommModemStatus(hFile, &commio->mstat);
2091 /* We might have received something or the TX bufffer is delivered*/
2092 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
2095 TRACE("Event already met\n");
2096 *lpdwEvents = result_mask;
2097 HeapFree(GetProcessHeap(), 0, commio );
2102 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2103 SetLastError(ERROR_IO_PENDING);
2106 release_comm_fd( hFile, fd );
2108 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2110 FIXME("Returning error because of missing capabilities\n");
2111 release_comm_fd( hFile, fd );
2112 HeapFree(GetProcessHeap(), 0, commio );
2113 SetLastError(ERROR_INVALID_PARAMETER);
2117 /***********************************************************************
2118 * WaitCommEvent (KERNEL32.@)
2120 * Wait until something interesting happens on a COMM port.
2121 * Interesting things (events) are set by calling SetCommMask before
2122 * this function is called.
2125 * TRUE if successful
2128 * The set of detected events will be written to *lpdwEventMask
2129 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2132 * Only supports EV_RXCHAR and EV_TXEMPTY
2134 BOOL WINAPI WaitCommEvent(
2135 HANDLE hFile, /* [in] handle of comm port to wait for */
2136 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2137 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2143 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2146 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2148 /* if there is no overlapped structure, create our own */
2149 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2151 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2152 err = GetLastError();
2155 if (err == ERROR_IO_PENDING)
2159 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2160 } while (res != WAIT_OBJECT_0);
2161 TRACE("Event met\n:");
2166 FIXME("Unknown error 0x%08lx\n", err);
2172 CloseHandle(ov.hEvent);
2177 /***********************************************************************
2178 * GetCommProperties (KERNEL32.@)
2180 * This function fills in a structure with the capabilities of the
2181 * communications port driver.
2185 * TRUE on success, FALSE on failure
2186 * If successful, the lpCommProp structure be filled in with
2187 * properties of the comm port.
2189 BOOL WINAPI GetCommProperties(
2190 HANDLE hFile, /* [in] handle of the comm port */
2191 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2193 FIXME("(%p %p )\n",hFile,lpCommProp);
2198 * These values should be valid for LINUX's serial driver
2199 * FIXME: Perhaps they deserve an #ifdef LINUX
2201 memset(lpCommProp,0,sizeof(COMMPROP));
2202 lpCommProp->wPacketLength = 1;
2203 lpCommProp->wPacketVersion = 1;
2204 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2205 lpCommProp->dwReserved1 = 0;
2206 lpCommProp->dwMaxTxQueue = 4096;
2207 lpCommProp->dwMaxRxQueue = 4096;
2208 lpCommProp->dwMaxBaud = BAUD_115200;
2209 lpCommProp->dwProvSubType = PST_RS232;
2210 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2211 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2212 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2213 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2214 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2215 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2216 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2217 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2218 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2219 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2220 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2225 /***********************************************************************
2227 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2228 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2229 * This is dependent on the type of COMM port, but since it is doubtful
2230 * anybody will get around to implementing support for fancy serial
2231 * ports in WINE, this is hardcoded for the time being. The name of
2232 * this DLL should be stored in and read from the system registry in
2233 * the hive HKEY_LOCAL_MACHINE, key
2234 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2235 * where ???? is the port number... that is determined by PNP
2236 * The DLL should be loaded when the COMM port is opened, and closed
2237 * when the COMM port is closed. - MJM 20 June 2000
2238 ***********************************************************************/
2239 static WCHAR lpszSerialUI[] = {
2240 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2243 /***********************************************************************
2244 * CommConfigDialogA (KERNEL32.@)
2246 * Raises a dialog that allows the user to configure a comm port.
2247 * Fills the COMMCONFIG struct with information specified by the user.
2248 * This function should call a similar routine in the COMM driver...
2252 * TRUE on success, FALSE on failure
2253 * If successful, the lpCommConfig structure will contain a new
2254 * configuration for the comm port, as specified by the user.
2257 * The library with the CommConfigDialog code is never unloaded.
2258 * Perhaps this should be done when the comm port is closed?
2260 BOOL WINAPI CommConfigDialogA(
2261 LPCSTR lpszDevice, /* [in] name of communications device */
2262 HWND hWnd, /* [in] parent window for the dialog */
2263 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2265 FARPROC lpfnCommDialog;
2266 HMODULE hConfigModule;
2269 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2271 hConfigModule = LoadLibraryW(lpszSerialUI);
2275 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2278 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2280 FreeLibrary(hConfigModule);
2285 /***********************************************************************
2286 * CommConfigDialogW (KERNEL32.@)
2288 * See CommConfigDialogA.
2290 BOOL WINAPI CommConfigDialogW(
2291 LPCWSTR lpszDevice, /* [in] name of communications device */
2292 HWND hWnd, /* [in] parent window for the dialog */
2293 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2295 FARPROC lpfnCommDialog;
2296 HMODULE hConfigModule;
2299 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2301 hConfigModule = LoadLibraryW(lpszSerialUI);
2305 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2308 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2310 FreeLibrary(hConfigModule);
2315 /***********************************************************************
2316 * GetCommConfig (KERNEL32.@)
2318 * Fill in the COMMCONFIG structure for the comm port hFile
2322 * TRUE on success, FALSE on failure
2323 * If successful, lpCommConfig contains the comm port configuration.
2328 BOOL WINAPI GetCommConfig(
2329 HANDLE hFile, /* [in] The communications device. */
2330 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2331 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2332 afterwards the number of bytes copied to the buffer or
2333 the needed size of the buffer. */
2337 TRACE("(%p %p)\n",hFile,lpCommConfig);
2339 if(lpCommConfig == NULL)
2341 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2342 *lpdwSize = sizeof(COMMCONFIG);
2346 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2347 lpCommConfig->wVersion = 1;
2348 lpCommConfig->wReserved = 0;
2349 r = GetCommState(hFile,&lpCommConfig->dcb);
2350 lpCommConfig->dwProviderSubType = PST_RS232;
2351 lpCommConfig->dwProviderOffset = 0;
2352 lpCommConfig->dwProviderSize = 0;
2357 /***********************************************************************
2358 * SetCommConfig (KERNEL32.@)
2360 * Sets the configuration of the communications device.
2364 * True on success, false if the handle was bad is not a communications device.
2366 BOOL WINAPI SetCommConfig(
2367 HANDLE hFile, /* [in] The communications device. */
2368 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2369 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2371 TRACE("(%p %p)\n",hFile,lpCommConfig);
2372 return SetCommState(hFile,&lpCommConfig->dcb);
2375 /***********************************************************************
2376 * SetDefaultCommConfigA (KERNEL32.@)
2378 * Initializes the default configuration for the specified communication
2383 * True if the device was found and the defaults set, false otherwise
2385 BOOL WINAPI SetDefaultCommConfigW(
2386 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2387 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2388 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2390 FARPROC lpfnSetDefaultCommConfig;
2391 HMODULE hConfigModule;
2394 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2396 hConfigModule = LoadLibraryW(lpszSerialUI);
2400 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2401 if (lpfnSetDefaultCommConfig)
2402 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2404 FreeLibrary(hConfigModule);
2410 /***********************************************************************
2411 * SetDefaultCommConfigW (KERNEL32.@)
2413 * Initializes the default configuration for the specified
2414 * communication device. (unicode)
2419 BOOL WINAPI SetDefaultCommConfigA(
2420 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2421 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2422 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2425 LPWSTR lpDeviceW = NULL;
2428 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2432 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2433 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2434 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2436 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2437 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2442 /***********************************************************************
2443 * GetDefaultCommConfigW (KERNEL32.@)
2445 * Acquires the default configuration of the specified communication device. (unicode)
2449 * True on successful reading of the default configuration,
2450 * if the device is not found or the buffer is too small.
2452 BOOL WINAPI GetDefaultCommConfigW(
2453 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2454 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2455 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2456 afterwards the number of bytes copied to the buffer or
2457 the needed size of the buffer. */
2459 LPDCB lpdcb = &(lpCC->dcb);
2461 static const WCHAR comW[] = {'C','O','M',0};
2462 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2464 if (strncmpiW(lpszName,comW,3)) {
2465 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2469 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2470 if (*lpdwSize < sizeof(COMMCONFIG)) {
2471 *lpdwSize = sizeof(COMMCONFIG);
2475 *lpdwSize = sizeof(COMMCONFIG);
2477 lpCC->dwSize = sizeof(COMMCONFIG);
2479 lpCC->dwProviderSubType = PST_RS232;
2480 lpCC->dwProviderOffset = 0L;
2481 lpCC->dwProviderSize = 0L;
2483 sprintfW( temp, formatW, lpszName[3]);
2484 FIXME("setting %s as default\n", debugstr_w(temp));
2486 return BuildCommDCBW( temp, lpdcb);
2489 /**************************************************************************
2490 * GetDefaultCommConfigA (KERNEL32.@)
2492 * Acquires the default configuration of the specified communication device. (ascii)
2496 * True on successful reading of the default configuration,
2497 * if the device is not found or the buffer is too small.
2499 BOOL WINAPI GetDefaultCommConfigA(
2500 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2501 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2502 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2503 afterwards the number of bytes copied to the buffer or
2504 the needed size of the buffer. */
2507 UNICODE_STRING lpszNameW;
2509 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2510 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2511 else lpszNameW.Buffer = NULL;
2513 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2515 RtlFreeUnicodeString(&lpszNameW);