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 "ddk/ntddser.h"
67 #include "wine/server.h"
68 #include "wine/unicode.h"
70 #include "wine/debug.h"
72 #ifdef HAVE_LINUX_SERIAL_H
73 #include <linux/serial.h>
76 WINE_DEFAULT_DEBUG_CHANNEL(comm);
78 /* retrieve the Unix handle corresponding to a comm handle */
79 static int get_comm_fd( HANDLE handle, DWORD access )
83 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
84 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
88 /* release the Unix handle returned by get_comm_fd */
89 static inline void release_comm_fd( HANDLE handle, int fd )
91 wine_server_release_fd( handle, fd );
95 * local structure holding the irq values we need for WaitCommEvent()
97 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
98 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
99 * no need to carry them in the internal structure
102 typedef struct serial_irq_info
104 int rx , tx, frame, overrun, parity, brk, buf_overrun;
107 /***********************************************************************
108 * Data needed by the thread polling for the changing CommEvent
110 typedef struct async_commio
117 serial_irq_info irq_info;
120 /***********************************************************************/
122 #if !defined(TIOCINQ) && defined(FIONREAD)
123 #define TIOCINQ FIONREAD
126 /***********************************************************************
127 * Get extended interrupt count info, needed for WaitCommEvent
129 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
132 struct serial_icounter_struct einfo;
133 if (!ioctl(fd,TIOCGICOUNT, &einfo))
135 irq_info->rx = einfo.rx;
136 irq_info->tx = einfo.tx;
137 irq_info->frame = einfo.frame;
138 irq_info->overrun = einfo.overrun;
139 irq_info->parity = einfo.parity;
140 irq_info->brk = einfo.brk;
141 irq_info->buf_overrun = einfo.buf_overrun;
145 memset(irq_info,0, sizeof(serial_irq_info));
149 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
152 unsigned int mstat, okay;
153 okay = ioctl(fd, TIOCMGET, &mstat);
154 if (okay) return okay;
155 if (andy) mstat &= andy;
157 return ioctl(fd, TIOCMSET, &mstat);
163 /***********************************************************************
164 * COMM_Parse* (Internal)
166 * The following COMM_Parse* functions are used by the BuildCommDCB
167 * functions to help parse the various parts of the device control string.
169 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
171 static const WCHAR comW[] = {'C','O','M',0};
173 /* The device control string may optionally start with "COMx" followed
174 by an optional ':' and spaces. */
175 if(!strncmpiW(ptr, comW, 3))
179 /* Allow any com port above 0 as Win 9x does (NT only allows
180 values for com ports which are actually present) */
181 if(*ptr < '1' || *ptr > '9')
184 /* Advance pointer past port number */
185 while(*ptr >= '0' && *ptr <= '9') ptr++;
187 /* The com port number must be followed by a ':' or ' ' */
188 if(*ptr != ':' && *ptr != ' ')
191 /* Advance pointer to beginning of next parameter */
192 while(*ptr == ' ') ptr++;
196 while(*ptr == ' ') ptr++;
199 /* The device control string must not start with a space. */
206 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
208 if(*ptr < '0' || *ptr > '9') return NULL;
209 *lpnumber = strtoulW(ptr, NULL, 10);
210 while(*ptr >= '0' && *ptr <= '9') ptr++;
214 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
216 /* Contrary to what you might expect, Windows only sets the Parity
217 member of DCB and not fParity even when parity is specified in the
218 device control string */
220 switch(toupperW(*ptr++))
223 *lpparity = EVENPARITY;
226 *lpparity = MARKPARITY;
229 *lpparity = NOPARITY;
232 *lpparity = ODDPARITY;
235 *lpparity = SPACEPARITY;
244 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
248 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
251 if(temp >= 5 && temp <= 8)
260 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
263 static const WCHAR stopbits15W[] = {'1','.','5',0};
265 if(!strncmpW(stopbits15W, ptr, 3))
268 *lpstopbits = ONE5STOPBITS;
272 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
276 *lpstopbits = ONESTOPBIT;
278 *lpstopbits = TWOSTOPBITS;
286 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
288 static const WCHAR onW[] = {'o','n',0};
289 static const WCHAR offW[] = {'o','f','f',0};
291 if(!strncmpiW(onW, ptr, 2))
296 else if(!strncmpiW(offW, ptr, 3))
307 /***********************************************************************
308 * COMM_BuildOldCommDCB (Internal)
310 * Build a DCB using the old style settings string eg: "96,n,8,1"
312 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
316 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
319 switch(lpdcb->BaudRate)
324 lpdcb->BaudRate *= 10;
330 lpdcb->BaudRate *= 100;
333 lpdcb->BaudRate = 19200;
337 while(*device == ' ') device++;
338 if(*device++ != ',') return FALSE;
339 while(*device == ' ') device++;
341 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
344 while(*device == ' ') device++;
345 if(*device++ != ',') return FALSE;
346 while(*device == ' ') device++;
348 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
351 while(*device == ' ') device++;
352 if(*device++ != ',') return FALSE;
353 while(*device == ' ') device++;
355 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
358 /* The last parameter for flow control is optional. */
359 while(*device == ' ') device++;
363 while(*device == ' ') device++;
364 if(*device) last = toupperW(*device++);
365 while(*device == ' ') device++;
368 /* Win NT sets the flow control members based on (or lack of) the last
369 parameter. Win 9x does not set these members. */
374 lpdcb->fOutX = FALSE;
375 lpdcb->fOutxCtsFlow = FALSE;
376 lpdcb->fOutxDsrFlow = FALSE;
377 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
378 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
383 lpdcb->fOutxCtsFlow = FALSE;
384 lpdcb->fOutxDsrFlow = FALSE;
385 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
386 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
390 lpdcb->fOutX = FALSE;
391 lpdcb->fOutxCtsFlow = TRUE;
392 lpdcb->fOutxDsrFlow = TRUE;
393 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
394 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
400 /* This should be the end of the string. */
401 if(*device) return FALSE;
406 /***********************************************************************
407 * COMM_BuildNewCommDCB (Internal)
409 * Build a DCB using the new style settings string.
410 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
412 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
415 BOOL baud = FALSE, stop = FALSE;
416 static const WCHAR baudW[] = {'b','a','u','d','=',0};
417 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
418 static const WCHAR dataW[] = {'d','a','t','a','=',0};
419 static const WCHAR stopW[] = {'s','t','o','p','=',0};
420 static const WCHAR toW[] = {'t','o','=',0};
421 static const WCHAR xonW[] = {'x','o','n','=',0};
422 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
423 static const WCHAR octsW[] = {'o','c','t','s','=',0};
424 static const WCHAR dtrW[] = {'d','t','r','=',0};
425 static const WCHAR rtsW[] = {'r','t','s','=',0};
426 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
430 while(*device == ' ') device++;
432 if(!strncmpiW(baudW, device, 5))
436 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
439 else if(!strncmpiW(parityW, device, 7))
441 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
444 else if(!strncmpiW(dataW, device, 5))
446 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
449 else if(!strncmpiW(stopW, device, 5))
453 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
456 else if(!strncmpiW(toW, device, 3))
458 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
461 lptimeouts->ReadIntervalTimeout = 0;
462 lptimeouts->ReadTotalTimeoutMultiplier = 0;
463 lptimeouts->ReadTotalTimeoutConstant = 0;
464 lptimeouts->WriteTotalTimeoutMultiplier = 0;
465 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
467 else if(!strncmpiW(xonW, device, 4))
469 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
475 else if(!strncmpiW(odsrW, device, 5))
477 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
480 lpdcb->fOutxDsrFlow = temp;
482 else if(!strncmpiW(octsW, device, 5))
484 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
487 lpdcb->fOutxCtsFlow = temp;
489 else if(!strncmpiW(dtrW, device, 4))
491 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
494 lpdcb->fDtrControl = temp;
496 else if(!strncmpiW(rtsW, device, 4))
498 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
501 lpdcb->fRtsControl = temp;
503 else if(!strncmpiW(idsrW, device, 5))
505 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
508 /* Win NT sets the fDsrSensitivity member based on the
509 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
510 lpdcb->fDsrSensitivity = temp;
515 /* After the above parsing, the next character (if not the end of
516 the string) should be a space */
517 if(*device && *device != ' ')
521 /* If stop bits were not specified, a default is always supplied. */
524 if(baud && lpdcb->BaudRate == 110)
525 lpdcb->StopBits = TWOSTOPBITS;
527 lpdcb->StopBits = ONESTOPBIT;
533 /**************************************************************************
534 * BuildCommDCBA (KERNEL32.@)
536 * Updates a device control block data structure with values from an
537 * ascii device control string. The device control string has two forms
538 * normal and extended, it must be exclusively in one or the other form.
542 * True on success, false on a malformed control string.
544 BOOL WINAPI BuildCommDCBA(
545 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
546 LPDCB lpdcb) /* [out] The device control block to be updated. */
548 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
551 /**************************************************************************
552 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
554 * Updates a device control block data structure with values from an
555 * ascii device control string. Taking timeout values from a timeouts
556 * struct if desired by the control string.
560 * True on success, false bad handles etc.
562 BOOL WINAPI BuildCommDCBAndTimeoutsA(
563 LPCSTR device, /* [in] The ascii device control string. */
564 LPDCB lpdcb, /* [out] The device control block to be updated. */
565 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
568 UNICODE_STRING deviceW;
570 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
571 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
572 else deviceW.Buffer = NULL;
574 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
576 RtlFreeUnicodeString(&deviceW);
580 /**************************************************************************
581 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
583 * Updates a device control block data structure with values from a
584 * unicode device control string. Taking timeout values from a timeouts
585 * struct if desired by the control string.
589 * True on success, false bad handles etc
591 BOOL WINAPI BuildCommDCBAndTimeoutsW(
592 LPCWSTR devid, /* [in] The unicode device control string. */
593 LPDCB lpdcb, /* [out] The device control block to be updated. */
594 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
597 COMMTIMEOUTS timeouts;
601 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
603 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
604 lpdcb->DCBlength = sizeof(DCB);
606 /* Make a copy of the original data structures to work with since if
607 if there is an error in the device control string the originals
608 should not be modified (except possibly DCBlength) */
609 memcpy(&dcb, lpdcb, sizeof(DCB));
610 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
612 ptr = COMM_ParseStart(ptr);
616 else if(strchrW(ptr, ','))
617 result = COMM_BuildOldCommDCB(ptr, &dcb);
619 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
623 memcpy(lpdcb, &dcb, sizeof(DCB));
624 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
629 WARN("Invalid device control string: %s\n", debugstr_w(devid));
630 SetLastError(ERROR_INVALID_PARAMETER);
635 /**************************************************************************
636 * BuildCommDCBW (KERNEL32.@)
638 * Updates a device control block structure with values from an
639 * unicode device control string. The device control string has two forms
640 * normal and extended, it must be exclusively in one or the other form.
644 * True on success, false on a malformed control string.
646 BOOL WINAPI BuildCommDCBW(
647 LPCWSTR devid, /* [in] The unicode device control string. */
648 LPDCB lpdcb) /* [out] The device control block to be updated. */
650 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
653 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
657 SERVER_START_REQ( set_serial_info )
659 req->handle = handle;
660 req->flags = SERIALINFO_SET_ERROR;
661 req->commerror = error;
662 ret = !wine_server_call_err( req );
668 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
675 SERVER_START_REQ( get_serial_info )
677 req->handle = handle;
678 ret = !wine_server_call_err( req );
679 *lperror = reply->commerror;
686 /*****************************************************************************
687 * SetCommBreak (KERNEL32.@)
689 * Halts the transmission of characters to a communications device.
692 * handle [in] The communications device to suspend
696 * True on success, and false if the communications device could not be found,
697 * the control is not supported.
701 * Only TIOCSBRK and TIOCCBRK are supported.
703 BOOL WINAPI SetCommBreak(HANDLE handle)
705 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, NULL, NULL);
708 /*****************************************************************************
709 * ClearCommBreak (KERNEL32.@)
711 * Resumes character transmission from a communication device.
715 * handle [in] The halted communication device whose character transmission is to be resumed
719 * True on success and false if the communications device could not be found.
723 * Only TIOCSBRK and TIOCCBRK are supported.
725 BOOL WINAPI ClearCommBreak(HANDLE handle)
727 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, NULL, NULL);
730 /*****************************************************************************
731 * EscapeCommFunction (KERNEL32.@)
733 * Directs a communication device to perform an extended function.
737 * True or requested data on successful completion of the command,
738 * false if the device is not present cannot execute the command
739 * or the command failed.
741 BOOL WINAPI EscapeCommFunction(
742 HANDLE handle, /* [in] The communication device to perform the extended function. */
743 UINT nFunction) /* [in] The extended function to be performed. */
745 int fd,direct=FALSE,result=FALSE;
748 TRACE("handle %p, function=%d\n", handle, nFunction);
749 fd = get_comm_fd( handle, FILE_READ_DATA );
750 if(fd<0) return FALSE;
752 if (tcgetattr(fd,&port) == -1) {
753 COMM_SetCommError(handle,CE_IOE);
754 release_comm_fd( handle, fd );
767 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
775 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
783 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
791 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
797 port.c_iflag |= IXOFF;
802 port.c_iflag |= IXON;
808 result = ioctl(fd,TIOCSBRK,0);
815 result = ioctl(fd,TIOCCBRK,0);
819 WARN("(handle=%p,nFunction=%d): Unknown function\n",
825 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
826 release_comm_fd( handle, fd );
827 COMM_SetCommError(handle,CE_IOE);
836 COMM_SetCommError(handle,CE_IOE);
841 release_comm_fd( handle, fd );
845 /********************************************************************
846 * PurgeComm (KERNEL32.@)
848 * Terminates pending operations and/or discards buffers on a
849 * communication resource.
853 * handle [in] The communication resource to be purged
854 * flags [in] Flags for clear pending/buffer on input/output
858 * True on success and false if the communications handle is bad.
860 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
862 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
863 NULL, 0, NULL, NULL);
866 /*****************************************************************************
867 * ClearCommError (KERNEL32.@)
869 * Enables further I/O operations on a communications resource after
870 * supplying error and current status information.
874 * True on success, false if the communication resource handle is bad.
876 BOOL WINAPI ClearCommError(
877 HANDLE handle, /* [in] The communication resource with the error. */
878 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
879 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
883 fd=get_comm_fd( handle, FILE_READ_DATA );
884 if(0>fd) return FALSE;
888 lpStat->fCtsHold = 0;
889 lpStat->fDsrHold = 0;
890 lpStat->fRlsdHold = 0;
891 lpStat->fXoffHold = 0;
892 lpStat->fXoffSent = 0;
895 lpStat->fReserved = 0;
898 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
899 WARN("ioctl returned error\n");
901 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
905 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
906 WARN("ioctl returned error\n");
909 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
910 handle, lpStat->cbInQue, lpStat->cbOutQue);
913 release_comm_fd( handle, fd );
915 COMM_GetCommError(handle, errors);
916 COMM_SetCommError(handle, 0);
921 /*****************************************************************************
922 * SetupComm (KERNEL32.@)
924 * Called after CreateFile to hint to the communication resource to use
925 * specified sizes for input and output buffers rather than the default values.
929 * True if successful, false if the communications resource handle is bad.
935 BOOL WINAPI SetupComm(
936 HANDLE handle, /* [in] The just created communication resource handle. */
937 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
938 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
942 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
943 fd=get_comm_fd( handle, FILE_READ_DATA );
944 if(0>fd) return FALSE;
945 release_comm_fd( handle, fd );
949 /*****************************************************************************
950 * GetCommMask (KERNEL32.@)
952 * Obtain the events associated with a communication device that will cause
953 * a call WaitCommEvent to return.
957 * handle [in] The communications device
958 * evtmask [out] The events which cause WaitCommEvent to return
962 * True on success, fail on bad device handle etc.
964 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
966 TRACE("handle %p, mask %p\n", handle, evtmask);
967 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
968 NULL, 0, evtmask, sizeof(*evtmask), NULL, NULL);
971 /*****************************************************************************
972 * SetCommMask (KERNEL32.@)
974 * There be some things we need to hear about yon there communications device.
975 * (Set which events associated with a communication device should cause
976 * a call WaitCommEvent to return.)
980 * handle [in] The communications device
981 * evtmask [in] The events that are to be monitored
985 * True on success, false on bad handle etc.
987 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
989 TRACE("handle %p, mask %lx\n", handle, evtmask);
990 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
991 &evtmask, sizeof(evtmask), NULL, 0, NULL, NULL);
994 /*****************************************************************************
995 * SetCommState (KERNEL32.@)
997 * Re-initializes all hardware and control settings of a communications device,
998 * with values from a device control block without effecting the input and output
1003 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1005 BOOL WINAPI SetCommState(
1006 HANDLE handle, /* [in] The communications device. */
1007 LPDCB lpdcb) /* [out] The device control block. */
1009 struct termios port;
1010 int fd, bytesize, stopbits;
1013 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1014 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1015 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1016 (lpdcb->StopBits == ONESTOPBIT)?1:
1017 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1018 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1019 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1020 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1021 lpdcb->fRtsControl);
1022 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1023 lpdcb->fDtrControl);
1026 fd = get_comm_fd( handle, FILE_READ_DATA );
1027 if (fd < 0) return FALSE;
1029 if ((tcgetattr(fd,&port)) == -1) {
1030 int save_error = errno;
1031 COMM_SetCommError(handle,CE_IOE);
1032 release_comm_fd( handle, fd );
1033 ERR("tcgetattr error '%s'\n", strerror(save_error));
1037 port.c_cc[VMIN] = 0;
1038 port.c_cc[VTIME] = 1;
1041 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
1043 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
1045 port.c_iflag |= (IGNBRK);
1047 port.c_oflag &= ~(OPOST);
1049 port.c_cflag &= ~(HUPCL);
1050 port.c_cflag |= CLOCAL | CREAD;
1052 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1053 port.c_lflag |= NOFLSH;
1056 port.c_cflag &= ~CBAUD;
1057 switch (lpdcb->BaudRate) {
1062 port.c_cflag |= B50;
1065 port.c_cflag |= B75;
1069 port.c_cflag |= B110;
1072 port.c_cflag |= B134;
1075 port.c_cflag |= B150;
1078 port.c_cflag |= B200;
1082 port.c_cflag |= B300;
1086 port.c_cflag |= B600;
1090 port.c_cflag |= B1200;
1093 port.c_cflag |= B1800;
1097 port.c_cflag |= B2400;
1101 port.c_cflag |= B4800;
1105 port.c_cflag |= B9600;
1109 port.c_cflag |= B19200;
1113 port.c_cflag |= B38400;
1117 port.c_cflag |= B57600;
1122 port.c_cflag |= B115200;
1127 port.c_cflag |= B230400;
1132 port.c_cflag |= B460800;
1136 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1137 { struct serial_struct nuts;
1139 ioctl(fd, TIOCGSERIAL, &nuts);
1140 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1141 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1142 arby = nuts.baud_base / nuts.custom_divisor;
1143 nuts.flags &= ~ASYNC_SPD_MASK;
1144 nuts.flags |= ASYNC_SPD_CUST;
1145 WARN("You (or a program acting at your behest) have specified\n"
1146 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1147 "which is as close as we can get by our present understanding of your\n"
1148 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1149 "has caused to your linux system can be undone with setserial \n"
1150 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1151 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1152 ioctl(fd, TIOCSSERIAL, &nuts);
1153 port.c_cflag |= B38400;
1156 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1159 COMM_SetCommError(handle,IE_BAUDRATE);
1160 release_comm_fd( handle, fd );
1161 ERR("baudrate %ld\n",lpdcb->BaudRate);
1164 #elif !defined(__EMX__)
1165 switch (lpdcb->BaudRate) {
1170 port.c_ospeed = B50;
1173 port.c_ospeed = B75;
1177 port.c_ospeed = B110;
1180 port.c_ospeed = B134;
1183 port.c_ospeed = B150;
1186 port.c_ospeed = B200;
1190 port.c_ospeed = B300;
1194 port.c_ospeed = B600;
1198 port.c_ospeed = B1200;
1201 port.c_ospeed = B1800;
1205 port.c_ospeed = B2400;
1209 port.c_ospeed = B4800;
1213 port.c_ospeed = B9600;
1217 port.c_ospeed = B19200;
1221 port.c_ospeed = B38400;
1226 port.c_cflag |= B57600;
1232 port.c_cflag |= B115200;
1237 port.c_cflag |= B230400;
1242 port.c_cflag |= B460800;
1246 COMM_SetCommError(handle,IE_BAUDRATE);
1247 release_comm_fd( handle, fd );
1248 ERR("baudrate %ld\n",lpdcb->BaudRate);
1251 port.c_ispeed = port.c_ospeed;
1253 bytesize=lpdcb->ByteSize;
1254 stopbits=lpdcb->StopBits;
1257 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1259 port.c_cflag &= ~(PARENB | PARODD);
1262 port.c_iflag |= INPCK;
1264 port.c_iflag &= ~INPCK;
1265 switch (lpdcb->Parity) {
1269 port.c_cflag |= (PARENB | PARODD);
1272 port.c_cflag |= PARENB;
1275 /* Linux defines mark/space (stick) parity */
1277 port.c_cflag |= (PARENB | CMSPAR);
1280 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1283 /* try the POSIX way */
1285 if( stopbits == ONESTOPBIT) {
1286 stopbits = TWOSTOPBITS;
1287 port.c_iflag &= ~INPCK;
1289 COMM_SetCommError(handle,IE_BYTESIZE);
1290 release_comm_fd( handle, fd );
1291 ERR("Cannot set MARK Parity\n");
1298 port.c_iflag &= ~INPCK;
1300 COMM_SetCommError(handle,IE_BYTESIZE);
1301 release_comm_fd( handle, fd );
1302 ERR("Cannot set SPACE Parity\n");
1308 COMM_SetCommError(handle,IE_BYTESIZE);
1309 release_comm_fd( handle, fd );
1315 port.c_cflag &= ~CSIZE;
1318 port.c_cflag |= CS5;
1321 port.c_cflag |= CS6;
1324 port.c_cflag |= CS7;
1327 port.c_cflag |= CS8;
1330 COMM_SetCommError(handle,IE_BYTESIZE);
1331 release_comm_fd( handle, fd );
1338 port.c_cflag &= ~CSTOPB;
1340 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1342 port.c_cflag |= CSTOPB;
1345 COMM_SetCommError(handle,IE_BYTESIZE);
1346 release_comm_fd( handle, fd );
1351 if ( lpdcb->fOutxCtsFlow ||
1352 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1355 port.c_cflag |= CRTSCTS;
1361 port.c_iflag |= IXON;
1363 port.c_iflag &= ~IXON;
1365 port.c_iflag |= IXOFF;
1367 port.c_iflag &= ~IXOFF;
1369 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1370 ERR("tcsetattr error '%s'\n", strerror(errno));
1371 COMM_SetCommError(handle,CE_IOE);
1374 COMM_SetCommError(handle,0);
1378 /* note: change DTR/RTS lines after setting the comm attributes,
1379 * so flow control does not interfere. */
1381 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1383 WARN("DSR/DTR flow control not supported\n");
1384 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1385 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1387 COMM_WhackModem(fd, 0, TIOCM_DTR);
1390 if(!lpdcb->fOutxCtsFlow )
1392 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1393 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1395 COMM_WhackModem(fd, 0, TIOCM_RTS);
1398 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1399 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1400 release_comm_fd( handle, fd );
1406 /*****************************************************************************
1407 * GetCommState (KERNEL32.@)
1409 * Fills in a device control block with information from a communications device.
1413 * True on success, false if the communication device handle is bad etc
1417 * XonChar and XoffChar are not set.
1419 BOOL WINAPI GetCommState(
1420 HANDLE handle, /* [in] The communications device. */
1421 LPDCB lpdcb) /* [out] The device control block. */
1423 struct termios port;
1425 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1427 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1429 fd = get_comm_fd( handle, FILE_READ_DATA );
1430 if (fd < 0) return FALSE;
1431 if (tcgetattr(fd, &port) == -1) {
1432 int save_error=errno;
1433 ERR("tcgetattr error '%s'\n", strerror(save_error));
1434 COMM_SetCommError(handle,CE_IOE);
1435 release_comm_fd( handle, fd );
1440 if (ioctl(fd, TIOCMGET, &stat) == -1)
1442 int save_error=errno;
1443 WARN("ioctl error '%s'\n", strerror(save_error));
1444 stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1447 release_comm_fd( handle, fd );
1450 speed= (port.c_cflag & CBAUD);
1452 speed= (cfgetospeed(&port));
1456 lpdcb->BaudRate = 0;
1459 lpdcb->BaudRate = 50;
1462 lpdcb->BaudRate = 75;
1465 lpdcb->BaudRate = 110;
1468 lpdcb->BaudRate = 134;
1471 lpdcb->BaudRate = 150;
1474 lpdcb->BaudRate = 200;
1477 lpdcb->BaudRate = 300;
1480 lpdcb->BaudRate = 600;
1483 lpdcb->BaudRate = 1200;
1486 lpdcb->BaudRate = 1800;
1489 lpdcb->BaudRate = 2400;
1492 lpdcb->BaudRate = 4800;
1495 lpdcb->BaudRate = 9600;
1498 lpdcb->BaudRate = 19200;
1501 lpdcb->BaudRate = 38400;
1505 lpdcb->BaudRate = 57600;
1510 lpdcb->BaudRate = 115200;
1515 lpdcb->BaudRate = 230400;
1520 lpdcb->BaudRate = 460800;
1524 ERR("unknown speed %x\n", speed);
1527 switch (port.c_cflag & CSIZE) {
1529 lpdcb->ByteSize = 5;
1532 lpdcb->ByteSize = 6;
1535 lpdcb->ByteSize = 7;
1538 lpdcb->ByteSize = 8;
1541 ERR("unknown size %x\n", port.c_cflag & CSIZE);
1544 if(port.c_iflag & INPCK)
1545 lpdcb->fParity = TRUE;
1547 lpdcb->fParity = FALSE;
1549 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1551 switch (port.c_cflag & (PARENB | PARODD))
1555 lpdcb->Parity = NOPARITY;
1558 lpdcb->Parity = EVENPARITY;
1560 case (PARENB | PARODD):
1561 lpdcb->Parity = ODDPARITY;
1564 case (PARENB | CMSPAR):
1565 lpdcb->Parity = MARKPARITY;
1567 case (PARENB | PARODD | CMSPAR):
1568 lpdcb->Parity = SPACEPARITY;
1573 if (port.c_cflag & CSTOPB)
1574 if(lpdcb->ByteSize == 5)
1575 lpdcb->StopBits = ONE5STOPBITS;
1577 lpdcb->StopBits = TWOSTOPBITS;
1579 lpdcb->StopBits = ONESTOPBIT;
1584 /* termios does not support DTR/DSR flow control */
1585 lpdcb->fOutxDsrFlow = 0;
1586 lpdcb->fDtrControl =
1588 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1590 DTR_CONTROL_ENABLE ;
1594 if (port.c_cflag & CRTSCTS) {
1595 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1596 lpdcb->fOutxCtsFlow = 1;
1600 lpdcb->fRtsControl =
1602 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1604 RTS_CONTROL_ENABLE ;
1605 lpdcb->fOutxCtsFlow = 0;
1607 if (port.c_iflag & IXON)
1612 if (port.c_iflag & IXOFF)
1621 lpdcb->XoffLim = 10;
1623 COMM_SetCommError(handle,0);
1627 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1628 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1629 (lpdcb->StopBits == ONESTOPBIT)?1:
1630 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1631 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1632 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1633 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1634 lpdcb->fRtsControl);
1635 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1636 lpdcb->fDtrControl);
1638 if ( lpdcb->fOutxCtsFlow ||
1639 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1644 TRACE("~CRTSCTS\n");
1649 /*****************************************************************************
1650 * TransmitCommChar (KERNEL32.@)
1652 * Transmits a single character in front of any pending characters in the
1653 * output buffer. Usually used to send an interrupt character to a host.
1656 * hComm [in] The communication device in need of a command character
1657 * chTransmit [in] The character to transmit
1661 * True if the call succeeded, false if the previous command character to the
1662 * same device has not been sent yet the handle is bad etc.
1665 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
1667 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
1668 &chTransmit, sizeof(chTransmit), NULL, 0, NULL, NULL);
1672 /*****************************************************************************
1673 * GetCommTimeouts (KERNEL32.@)
1675 * Obtains the request timeout values for the communications device.
1679 * True on success, false if communications device handle is bad
1680 * or the target structure is null.
1682 BOOL WINAPI GetCommTimeouts(
1683 HANDLE hComm, /* [in] The communications device. */
1684 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1688 TRACE("(%p,%p)\n",hComm,lptimeouts);
1692 SetLastError(ERROR_INVALID_PARAMETER);
1696 SERVER_START_REQ( get_serial_info )
1698 req->handle = hComm;
1699 if ((ret = !wine_server_call_err( req )))
1701 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1702 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1703 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1704 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1705 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1712 /*****************************************************************************
1713 * SetCommTimeouts (KERNEL32.@)
1715 * Sets the timeouts used when reading and writing data to/from COMM ports.
1717 * ReadIntervalTimeout
1718 * - converted and passes to linux kernel as c_cc[VTIME]
1719 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1720 * - used in ReadFile to calculate GetOverlappedResult's timeout
1721 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1722 * - used in WriteFile to calculate GetOverlappedResult's timeout
1726 * True if the timeouts were set, false otherwise.
1728 BOOL WINAPI SetCommTimeouts(
1729 HANDLE hComm, /* [in] handle of COMM device */
1730 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1734 struct termios tios;
1736 TRACE("(%p,%p)\n",hComm,lptimeouts);
1740 SetLastError(ERROR_INVALID_PARAMETER);
1744 SERVER_START_REQ( set_serial_info )
1746 req->handle = hComm;
1747 req->flags = SERIALINFO_SET_TIMEOUTS;
1748 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1749 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1750 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1751 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1752 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1753 ret = !wine_server_call_err( req );
1756 if (!ret) return FALSE;
1758 /* FIXME: move this stuff to the server */
1759 fd = get_comm_fd( hComm, FILE_READ_DATA );
1760 if (fd < 0) return FALSE;
1762 if (-1==tcgetattr(fd,&tios)) {
1763 FIXME("tcgetattr on fd %d failed!\n",fd);
1764 release_comm_fd( hComm, fd );
1768 /* VTIME is in 1/10 seconds */
1770 unsigned int ux_timeout;
1772 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1778 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1781 ux_timeout = 1; /* must be at least some timeout */
1784 tios.c_cc[VTIME] = ux_timeout;
1787 if (-1==tcsetattr(fd,0,&tios)) {
1788 FIXME("tcsetattr on fd %d failed!\n",fd);
1789 release_comm_fd( hComm, fd );
1792 release_comm_fd( hComm, fd );
1796 /***********************************************************************
1797 * GetCommModemStatus (KERNEL32.@)
1799 * Obtains the four control register bits if supported by the hardware.
1803 * hFile [in] The communications device
1804 * lpModemStat [out] The control register bits
1808 * True if the communications handle was good and for hardware that
1809 * control register access, false otherwise.
1811 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1813 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1814 NULL, 0, lpModemStat, sizeof(DWORD), NULL, NULL);
1817 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1819 DWORD ret = 0, queue;
1821 TRACE("mask 0x%08lx\n", mask);
1822 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old->rx, new->rx);
1823 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old->tx, new->tx);
1824 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old->frame, new->frame);
1825 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old->overrun, new->overrun);
1826 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old->parity, new->parity);
1827 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old->brk, new->brk);
1828 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1830 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1831 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1832 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1833 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1834 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1835 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1836 || (old->parity != new->parity)) )?EV_ERR :0;
1837 if (mask & EV_RXCHAR)
1841 if(ioctl(fd, TIOCINQ, &queue))
1842 WARN("TIOCINQ returned error\n");
1847 if (mask & EV_TXEMPTY)
1850 /* We really want to know when all characters have gone out of the transmitter */
1851 #if defined(TIOCSERGETLSR)
1852 if(ioctl(fd, TIOCSERGETLSR, &queue))
1853 WARN("TIOCSERGETLSR returned error\n");
1855 /* TIOCINQ only checks for an empty buffer */
1856 #elif defined(TIOCINQ)
1857 if(ioctl(fd, TIOCOUTQ, &queue))
1858 WARN("TIOCOUTQ returned error\n");
1863 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1868 /***********************************************************************
1869 * COMM_WaitCommEventService (INTERNAL)
1871 * We need to poll for what is interesting
1872 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1875 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1877 async_commio *commio = (async_commio*) arg;
1880 serial_irq_info new_irq_info;
1881 DWORD new_mstat, new_evtmask;
1883 fd=get_comm_fd( commio->handle, FILE_READ_DATA );
1885 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1886 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1890 * TIOCMIWAIT is not adequate
1893 * We don't handle the EV_RXFLAG (the eventchar)
1896 rc= COMM_GetEInfo(fd,&new_irq_info);
1898 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1899 rc = GetCommModemStatus(commio->handle, &new_mstat);
1901 TRACE("GetCommModemStatus failed\n");
1902 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1903 GetCommMask(commio->handle, &new_evtmask);
1904 abort = (commio->evtmask != new_evtmask);
1905 TRACE("resulting Eventmask 0x%08x\n", rc);
1906 } while (!rc && ! abort);
1908 release_comm_fd( commio->handle, fd );
1909 *commio->buffer = rc;
1910 if (commio->hEvent != INVALID_HANDLE_VALUE )
1911 NtSetEvent( commio->hEvent, NULL );
1912 HeapFree(GetProcessHeap(), 0, commio );
1917 /***********************************************************************
1918 * COMM_WaitCommEvent (INTERNAL)
1920 * This function must have an lpOverlapped.
1922 static BOOL COMM_WaitCommEvent(
1923 HANDLE hFile, /* [in] handle of comm port to wait for */
1924 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1925 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1928 async_commio* commio;
1934 SetLastError(ERROR_INVALID_PARAMETER);
1938 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1941 fd = get_comm_fd( hFile, FILE_WRITE_DATA );
1942 if (fd < 0) return FALSE;
1944 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1947 release_comm_fd( hFile, fd );
1951 commio->handle = hFile;
1952 commio->buffer = (char *)lpdwEvents;
1953 commio->hEvent = lpOverlapped->hEvent;
1954 GetCommMask(hFile, &commio->evtmask);
1956 /* We may never return, if some capabilities miss
1957 * Return error in that case
1959 #if !defined(TIOCINQ)
1960 if(commio->evtmask & EV_RXCHAR)
1963 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1964 if(commio->evtmask & EV_TXEMPTY)
1967 #if !defined(TIOCMGET)
1968 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
1971 #if !defined(TIOCM_CTS)
1972 if(commio->evtmask & EV_CTS)
1975 #if !defined(TIOCM_DSR)
1976 if(commio->evtmask & EV_DSR)
1979 #if !defined(TIOCM_RNG)
1980 if(commio->evtmask & EV_RING)
1983 #if !defined(TIOCM_CAR)
1984 if(commio->evtmask & EV_RLSD)
1987 if(commio->evtmask & EV_RXFLAG)
1988 FIXME("EV_RXFLAG not handled\n");
1989 COMM_GetEInfo(fd,&commio->irq_info);
1990 GetCommModemStatus(hFile, &commio->mstat);
1991 /* We might have received something or the TX bufffer is delivered*/
1992 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
1995 TRACE("Event already met\n");
1996 *lpdwEvents = result_mask;
1997 HeapFree(GetProcessHeap(), 0, commio );
2002 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2003 SetLastError(ERROR_IO_PENDING);
2006 release_comm_fd( hFile, fd );
2008 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2010 FIXME("Returning error because of missing capabilities\n");
2011 release_comm_fd( hFile, fd );
2012 HeapFree(GetProcessHeap(), 0, commio );
2013 SetLastError(ERROR_INVALID_PARAMETER);
2017 /***********************************************************************
2018 * WaitCommEvent (KERNEL32.@)
2020 * Wait until something interesting happens on a COMM port.
2021 * Interesting things (events) are set by calling SetCommMask before
2022 * this function is called.
2025 * TRUE if successful
2028 * The set of detected events will be written to *lpdwEventMask
2029 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2032 * Only supports EV_RXCHAR and EV_TXEMPTY
2034 BOOL WINAPI WaitCommEvent(
2035 HANDLE hFile, /* [in] handle of comm port to wait for */
2036 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2037 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2043 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2046 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2048 /* if there is no overlapped structure, create our own */
2049 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2051 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2052 err = GetLastError();
2055 if (err == ERROR_IO_PENDING)
2059 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2060 } while (res != WAIT_OBJECT_0);
2061 TRACE("Event met\n:");
2066 FIXME("Unknown error 0x%08lx\n", err);
2072 CloseHandle(ov.hEvent);
2077 /***********************************************************************
2078 * GetCommProperties (KERNEL32.@)
2080 * This function fills in a structure with the capabilities of the
2081 * communications port driver.
2085 * TRUE on success, FALSE on failure
2086 * If successful, the lpCommProp structure be filled in with
2087 * properties of the comm port.
2089 BOOL WINAPI GetCommProperties(
2090 HANDLE hFile, /* [in] handle of the comm port */
2091 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2093 FIXME("(%p %p )\n",hFile,lpCommProp);
2098 * These values should be valid for LINUX's serial driver
2099 * FIXME: Perhaps they deserve an #ifdef LINUX
2101 memset(lpCommProp,0,sizeof(COMMPROP));
2102 lpCommProp->wPacketLength = 1;
2103 lpCommProp->wPacketVersion = 1;
2104 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2105 lpCommProp->dwReserved1 = 0;
2106 lpCommProp->dwMaxTxQueue = 4096;
2107 lpCommProp->dwMaxRxQueue = 4096;
2108 lpCommProp->dwMaxBaud = BAUD_115200;
2109 lpCommProp->dwProvSubType = PST_RS232;
2110 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2111 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2112 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2113 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2114 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2115 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2116 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2117 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2118 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2119 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2120 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2125 /***********************************************************************
2127 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2128 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2129 * This is dependent on the type of COMM port, but since it is doubtful
2130 * anybody will get around to implementing support for fancy serial
2131 * ports in WINE, this is hardcoded for the time being. The name of
2132 * this DLL should be stored in and read from the system registry in
2133 * the hive HKEY_LOCAL_MACHINE, key
2134 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2135 * where ???? is the port number... that is determined by PNP
2136 * The DLL should be loaded when the COMM port is opened, and closed
2137 * when the COMM port is closed. - MJM 20 June 2000
2138 ***********************************************************************/
2139 static const WCHAR lpszSerialUI[] = {
2140 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2143 /***********************************************************************
2144 * CommConfigDialogA (KERNEL32.@)
2146 * Raises a dialog that allows the user to configure a comm port.
2147 * Fills the COMMCONFIG struct with information specified by the user.
2148 * This function should call a similar routine in the COMM driver...
2152 * TRUE on success, FALSE on failure
2153 * If successful, the lpCommConfig structure will contain a new
2154 * configuration for the comm port, as specified by the user.
2157 * The library with the CommConfigDialog code is never unloaded.
2158 * Perhaps this should be done when the comm port is closed?
2160 BOOL WINAPI CommConfigDialogA(
2161 LPCSTR lpszDevice, /* [in] name of communications device */
2162 HWND hWnd, /* [in] parent window for the dialog */
2163 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2165 FARPROC lpfnCommDialog;
2166 HMODULE hConfigModule;
2169 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2171 hConfigModule = LoadLibraryW(lpszSerialUI);
2175 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2178 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2180 FreeLibrary(hConfigModule);
2185 /***********************************************************************
2186 * CommConfigDialogW (KERNEL32.@)
2188 * See CommConfigDialogA.
2190 BOOL WINAPI CommConfigDialogW(
2191 LPCWSTR lpszDevice, /* [in] name of communications device */
2192 HWND hWnd, /* [in] parent window for the dialog */
2193 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2195 FARPROC lpfnCommDialog;
2196 HMODULE hConfigModule;
2199 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2201 hConfigModule = LoadLibraryW(lpszSerialUI);
2205 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2208 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2210 FreeLibrary(hConfigModule);
2215 /***********************************************************************
2216 * GetCommConfig (KERNEL32.@)
2218 * Fill in the COMMCONFIG structure for the comm port hFile
2222 * TRUE on success, FALSE on failure
2223 * If successful, lpCommConfig contains the comm port configuration.
2228 BOOL WINAPI GetCommConfig(
2229 HANDLE hFile, /* [in] The communications device. */
2230 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2231 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2232 afterwards the number of bytes copied to the buffer or
2233 the needed size of the buffer. */
2237 TRACE("(%p %p)\n",hFile,lpCommConfig);
2239 if(lpCommConfig == NULL)
2241 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2242 *lpdwSize = sizeof(COMMCONFIG);
2246 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2247 lpCommConfig->wVersion = 1;
2248 lpCommConfig->wReserved = 0;
2249 r = GetCommState(hFile,&lpCommConfig->dcb);
2250 lpCommConfig->dwProviderSubType = PST_RS232;
2251 lpCommConfig->dwProviderOffset = 0;
2252 lpCommConfig->dwProviderSize = 0;
2257 /***********************************************************************
2258 * SetCommConfig (KERNEL32.@)
2260 * Sets the configuration of the communications device.
2264 * True on success, false if the handle was bad is not a communications device.
2266 BOOL WINAPI SetCommConfig(
2267 HANDLE hFile, /* [in] The communications device. */
2268 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2269 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2271 TRACE("(%p %p)\n",hFile,lpCommConfig);
2272 return SetCommState(hFile,&lpCommConfig->dcb);
2275 /***********************************************************************
2276 * SetDefaultCommConfigA (KERNEL32.@)
2278 * Initializes the default configuration for the specified communication
2283 * True if the device was found and the defaults set, false otherwise
2285 BOOL WINAPI SetDefaultCommConfigW(
2286 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2287 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2288 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2290 FARPROC lpfnSetDefaultCommConfig;
2291 HMODULE hConfigModule;
2294 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2296 hConfigModule = LoadLibraryW(lpszSerialUI);
2300 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2301 if (lpfnSetDefaultCommConfig)
2302 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2304 FreeLibrary(hConfigModule);
2310 /***********************************************************************
2311 * SetDefaultCommConfigW (KERNEL32.@)
2313 * Initializes the default configuration for the specified
2314 * communication device. (unicode)
2319 BOOL WINAPI SetDefaultCommConfigA(
2320 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2321 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2322 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2325 LPWSTR lpDeviceW = NULL;
2328 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2332 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2333 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2334 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2336 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2337 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2342 /***********************************************************************
2343 * GetDefaultCommConfigW (KERNEL32.@)
2345 * Acquires the default configuration of the specified communication device. (unicode)
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 GetDefaultCommConfigW(
2353 LPCWSTR lpszName, /* [in] The unicode 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. */
2359 LPDCB lpdcb = &(lpCC->dcb);
2361 static const WCHAR comW[] = {'C','O','M',0};
2362 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2364 if (strncmpiW(lpszName,comW,3)) {
2365 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2369 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2370 if (*lpdwSize < sizeof(COMMCONFIG)) {
2371 *lpdwSize = sizeof(COMMCONFIG);
2375 *lpdwSize = sizeof(COMMCONFIG);
2377 lpCC->dwSize = sizeof(COMMCONFIG);
2379 lpCC->dwProviderSubType = PST_RS232;
2380 lpCC->dwProviderOffset = 0L;
2381 lpCC->dwProviderSize = 0L;
2383 sprintfW( temp, formatW, lpszName[3]);
2384 FIXME("setting %s as default\n", debugstr_w(temp));
2386 return BuildCommDCBW( temp, lpdcb);
2389 /**************************************************************************
2390 * GetDefaultCommConfigA (KERNEL32.@)
2392 * Acquires the default configuration of the specified communication device. (ascii)
2396 * True on successful reading of the default configuration,
2397 * if the device is not found or the buffer is too small.
2399 BOOL WINAPI GetDefaultCommConfigA(
2400 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2401 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2402 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2403 afterwards the number of bytes copied to the buffer or
2404 the needed size of the buffer. */
2407 UNICODE_STRING lpszNameW;
2409 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2410 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2411 else lpszNameW.Buffer = NULL;
2413 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2415 RtlFreeUnicodeString(&lpszNameW);