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 * True on success and false if the communications handle is bad.
855 BOOL WINAPI PurgeComm(
856 HANDLE handle, /* [in] The communication resource to be purged. */
857 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
861 TRACE("handle %p, flags %lx\n", handle, flags);
863 fd = get_comm_fd( handle, FILE_READ_DATA );
864 if(fd<0) return FALSE;
867 ** not exactly sure how these are different
868 ** Perhaps if we had our own internal queues, one flushes them
869 ** and the other flushes the kernel's buffers.
871 if(flags&PURGE_TXABORT)
872 tcflush(fd,TCOFLUSH);
873 if(flags&PURGE_RXABORT)
874 tcflush(fd,TCIFLUSH);
875 if(flags&PURGE_TXCLEAR)
876 tcflush(fd,TCOFLUSH);
877 if(flags&PURGE_RXCLEAR)
878 tcflush(fd,TCIFLUSH);
879 release_comm_fd( handle, fd );
884 /*****************************************************************************
885 * ClearCommError (KERNEL32.@)
887 * Enables further I/O operations on a communications resource after
888 * supplying error and current status information.
892 * True on success, false if the communication resource handle is bad.
894 BOOL WINAPI ClearCommError(
895 HANDLE handle, /* [in] The communication resource with the error. */
896 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
897 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
901 fd=get_comm_fd( handle, FILE_READ_DATA );
902 if(0>fd) return FALSE;
906 lpStat->fCtsHold = 0;
907 lpStat->fDsrHold = 0;
908 lpStat->fRlsdHold = 0;
909 lpStat->fXoffHold = 0;
910 lpStat->fXoffSent = 0;
913 lpStat->fReserved = 0;
916 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
917 WARN("ioctl returned error\n");
919 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
923 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
924 WARN("ioctl returned error\n");
927 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
928 handle, lpStat->cbInQue, lpStat->cbOutQue);
931 release_comm_fd( handle, fd );
933 COMM_GetCommError(handle, errors);
934 COMM_SetCommError(handle, 0);
939 /*****************************************************************************
940 * SetupComm (KERNEL32.@)
942 * Called after CreateFile to hint to the communication resource to use
943 * specified sizes for input and output buffers rather than the default values.
947 * True if successful, false if the communications resource handle is bad.
953 BOOL WINAPI SetupComm(
954 HANDLE handle, /* [in] The just created communication resource handle. */
955 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
956 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
960 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
961 fd=get_comm_fd( handle, FILE_READ_DATA );
962 if(0>fd) return FALSE;
963 release_comm_fd( handle, fd );
967 /*****************************************************************************
968 * GetCommMask (KERNEL32.@)
970 * Obtain the events associated with a communication device that will cause
971 * a call WaitCommEvent to return.
975 * True on success, fail on bad device handle etc.
977 BOOL WINAPI GetCommMask(
978 HANDLE handle, /* [in] The communications device. */
979 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
983 TRACE("handle %p, mask %p\n", handle, evtmask);
985 SERVER_START_REQ( get_serial_info )
987 req->handle = handle;
988 if ((ret = !wine_server_call_err( req )))
990 if (evtmask) *evtmask = reply->eventmask;
997 /*****************************************************************************
998 * SetCommMask (KERNEL32.@)
1000 * There be some things we need to hear about yon there communications device.
1001 * (Set which events associated with a communication device should cause
1002 * a call WaitCommEvent to return.)
1006 * True on success, false on bad handle etc.
1008 BOOL WINAPI SetCommMask(
1009 HANDLE handle, /* [in] The communications device. */
1010 DWORD evtmask) /* [in] The events that are to be monitored. */
1014 TRACE("handle %p, mask %lx\n", handle, evtmask);
1016 SERVER_START_REQ( set_serial_info )
1018 req->handle = handle;
1019 req->flags = SERIALINFO_SET_MASK;
1020 req->eventmask = evtmask;
1021 ret = !wine_server_call_err( req );
1027 /*****************************************************************************
1028 * SetCommState (KERNEL32.@)
1030 * Re-initializes all hardware and control settings of a communications device,
1031 * with values from a device control block without effecting the input and output
1036 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1038 BOOL WINAPI SetCommState(
1039 HANDLE handle, /* [in] The communications device. */
1040 LPDCB lpdcb) /* [out] The device control block. */
1042 struct termios port;
1043 int fd, bytesize, stopbits;
1046 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1047 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1048 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1049 (lpdcb->StopBits == ONESTOPBIT)?1:
1050 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1051 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1052 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1053 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1054 lpdcb->fRtsControl);
1055 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1056 lpdcb->fDtrControl);
1059 fd = get_comm_fd( handle, FILE_READ_DATA );
1060 if (fd < 0) return FALSE;
1062 if ((tcgetattr(fd,&port)) == -1) {
1063 int save_error = errno;
1064 COMM_SetCommError(handle,CE_IOE);
1065 release_comm_fd( handle, fd );
1066 ERR("tcgetattr error '%s'\n", strerror(save_error));
1070 port.c_cc[VMIN] = 0;
1071 port.c_cc[VTIME] = 1;
1074 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
1076 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
1078 port.c_iflag |= (IGNBRK);
1080 port.c_oflag &= ~(OPOST);
1082 port.c_cflag &= ~(HUPCL);
1083 port.c_cflag |= CLOCAL | CREAD;
1085 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1086 port.c_lflag |= NOFLSH;
1089 port.c_cflag &= ~CBAUD;
1090 switch (lpdcb->BaudRate) {
1095 port.c_cflag |= B50;
1098 port.c_cflag |= B75;
1102 port.c_cflag |= B110;
1105 port.c_cflag |= B134;
1108 port.c_cflag |= B150;
1111 port.c_cflag |= B200;
1115 port.c_cflag |= B300;
1119 port.c_cflag |= B600;
1123 port.c_cflag |= B1200;
1126 port.c_cflag |= B1800;
1130 port.c_cflag |= B2400;
1134 port.c_cflag |= B4800;
1138 port.c_cflag |= B9600;
1142 port.c_cflag |= B19200;
1146 port.c_cflag |= B38400;
1150 port.c_cflag |= B57600;
1155 port.c_cflag |= B115200;
1160 port.c_cflag |= B230400;
1165 port.c_cflag |= B460800;
1169 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1170 { struct serial_struct nuts;
1172 ioctl(fd, TIOCGSERIAL, &nuts);
1173 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1174 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1175 arby = nuts.baud_base / nuts.custom_divisor;
1176 nuts.flags &= ~ASYNC_SPD_MASK;
1177 nuts.flags |= ASYNC_SPD_CUST;
1178 WARN("You (or a program acting at your behest) have specified\n"
1179 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1180 "which is as close as we can get by our present understanding of your\n"
1181 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1182 "has caused to your linux system can be undone with setserial \n"
1183 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1184 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1185 ioctl(fd, TIOCSSERIAL, &nuts);
1186 port.c_cflag |= B38400;
1189 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1192 COMM_SetCommError(handle,IE_BAUDRATE);
1193 release_comm_fd( handle, fd );
1194 ERR("baudrate %ld\n",lpdcb->BaudRate);
1197 #elif !defined(__EMX__)
1198 switch (lpdcb->BaudRate) {
1203 port.c_ospeed = B50;
1206 port.c_ospeed = B75;
1210 port.c_ospeed = B110;
1213 port.c_ospeed = B134;
1216 port.c_ospeed = B150;
1219 port.c_ospeed = B200;
1223 port.c_ospeed = B300;
1227 port.c_ospeed = B600;
1231 port.c_ospeed = B1200;
1234 port.c_ospeed = B1800;
1238 port.c_ospeed = B2400;
1242 port.c_ospeed = B4800;
1246 port.c_ospeed = B9600;
1250 port.c_ospeed = B19200;
1254 port.c_ospeed = B38400;
1259 port.c_cflag |= B57600;
1265 port.c_cflag |= B115200;
1270 port.c_cflag |= B230400;
1275 port.c_cflag |= B460800;
1279 COMM_SetCommError(handle,IE_BAUDRATE);
1280 release_comm_fd( handle, fd );
1281 ERR("baudrate %ld\n",lpdcb->BaudRate);
1284 port.c_ispeed = port.c_ospeed;
1286 bytesize=lpdcb->ByteSize;
1287 stopbits=lpdcb->StopBits;
1290 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1292 port.c_cflag &= ~(PARENB | PARODD);
1295 port.c_iflag |= INPCK;
1297 port.c_iflag &= ~INPCK;
1298 switch (lpdcb->Parity) {
1302 port.c_cflag |= (PARENB | PARODD);
1305 port.c_cflag |= PARENB;
1308 /* Linux defines mark/space (stick) parity */
1310 port.c_cflag |= (PARENB | CMSPAR);
1313 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1316 /* try the POSIX way */
1318 if( stopbits == ONESTOPBIT) {
1319 stopbits = TWOSTOPBITS;
1320 port.c_iflag &= ~INPCK;
1322 COMM_SetCommError(handle,IE_BYTESIZE);
1323 release_comm_fd( handle, fd );
1324 ERR("Cannot set MARK Parity\n");
1331 port.c_iflag &= ~INPCK;
1333 COMM_SetCommError(handle,IE_BYTESIZE);
1334 release_comm_fd( handle, fd );
1335 ERR("Cannot set SPACE Parity\n");
1341 COMM_SetCommError(handle,IE_BYTESIZE);
1342 release_comm_fd( handle, fd );
1348 port.c_cflag &= ~CSIZE;
1351 port.c_cflag |= CS5;
1354 port.c_cflag |= CS6;
1357 port.c_cflag |= CS7;
1360 port.c_cflag |= CS8;
1363 COMM_SetCommError(handle,IE_BYTESIZE);
1364 release_comm_fd( handle, fd );
1371 port.c_cflag &= ~CSTOPB;
1373 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1375 port.c_cflag |= CSTOPB;
1378 COMM_SetCommError(handle,IE_BYTESIZE);
1379 release_comm_fd( handle, fd );
1384 if ( lpdcb->fOutxCtsFlow ||
1385 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1388 port.c_cflag |= CRTSCTS;
1394 port.c_iflag |= IXON;
1396 port.c_iflag &= ~IXON;
1398 port.c_iflag |= IXOFF;
1400 port.c_iflag &= ~IXOFF;
1402 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1403 ERR("tcsetattr error '%s'\n", strerror(errno));
1404 COMM_SetCommError(handle,CE_IOE);
1407 COMM_SetCommError(handle,0);
1411 /* note: change DTR/RTS lines after setting the comm attributes,
1412 * so flow control does not interfere. */
1414 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1416 WARN("DSR/DTR flow control not supported\n");
1417 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1418 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1420 COMM_WhackModem(fd, 0, TIOCM_DTR);
1423 if(!lpdcb->fOutxCtsFlow )
1425 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1426 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1428 COMM_WhackModem(fd, 0, TIOCM_RTS);
1431 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1432 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1433 release_comm_fd( handle, fd );
1439 /*****************************************************************************
1440 * GetCommState (KERNEL32.@)
1442 * Fills in a device control block with information from a communications device.
1446 * True on success, false if the communication device handle is bad etc
1450 * XonChar and XoffChar are not set.
1452 BOOL WINAPI GetCommState(
1453 HANDLE handle, /* [in] The communications device. */
1454 LPDCB lpdcb) /* [out] The device control block. */
1456 struct termios port;
1458 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1460 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1462 fd = get_comm_fd( handle, FILE_READ_DATA );
1463 if (fd < 0) return FALSE;
1464 if (tcgetattr(fd, &port) == -1) {
1465 int save_error=errno;
1466 ERR("tcgetattr error '%s'\n", strerror(save_error));
1467 COMM_SetCommError(handle,CE_IOE);
1468 release_comm_fd( handle, fd );
1473 if (ioctl(fd, TIOCMGET, &stat) == -1)
1475 int save_error=errno;
1476 WARN("ioctl error '%s'\n", strerror(save_error));
1477 stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1480 release_comm_fd( handle, fd );
1483 speed= (port.c_cflag & CBAUD);
1485 speed= (cfgetospeed(&port));
1489 lpdcb->BaudRate = 0;
1492 lpdcb->BaudRate = 50;
1495 lpdcb->BaudRate = 75;
1498 lpdcb->BaudRate = 110;
1501 lpdcb->BaudRate = 134;
1504 lpdcb->BaudRate = 150;
1507 lpdcb->BaudRate = 200;
1510 lpdcb->BaudRate = 300;
1513 lpdcb->BaudRate = 600;
1516 lpdcb->BaudRate = 1200;
1519 lpdcb->BaudRate = 1800;
1522 lpdcb->BaudRate = 2400;
1525 lpdcb->BaudRate = 4800;
1528 lpdcb->BaudRate = 9600;
1531 lpdcb->BaudRate = 19200;
1534 lpdcb->BaudRate = 38400;
1538 lpdcb->BaudRate = 57600;
1543 lpdcb->BaudRate = 115200;
1548 lpdcb->BaudRate = 230400;
1553 lpdcb->BaudRate = 460800;
1557 ERR("unknown speed %x\n", speed);
1560 switch (port.c_cflag & CSIZE) {
1562 lpdcb->ByteSize = 5;
1565 lpdcb->ByteSize = 6;
1568 lpdcb->ByteSize = 7;
1571 lpdcb->ByteSize = 8;
1574 ERR("unknown size %x\n", port.c_cflag & CSIZE);
1577 if(port.c_iflag & INPCK)
1578 lpdcb->fParity = TRUE;
1580 lpdcb->fParity = FALSE;
1582 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1584 switch (port.c_cflag & (PARENB | PARODD))
1588 lpdcb->Parity = NOPARITY;
1591 lpdcb->Parity = EVENPARITY;
1593 case (PARENB | PARODD):
1594 lpdcb->Parity = ODDPARITY;
1597 case (PARENB | CMSPAR):
1598 lpdcb->Parity = MARKPARITY;
1600 case (PARENB | PARODD | CMSPAR):
1601 lpdcb->Parity = SPACEPARITY;
1606 if (port.c_cflag & CSTOPB)
1607 if(lpdcb->ByteSize == 5)
1608 lpdcb->StopBits = ONE5STOPBITS;
1610 lpdcb->StopBits = TWOSTOPBITS;
1612 lpdcb->StopBits = ONESTOPBIT;
1617 /* termios does not support DTR/DSR flow control */
1618 lpdcb->fOutxDsrFlow = 0;
1619 lpdcb->fDtrControl =
1621 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1623 DTR_CONTROL_ENABLE ;
1627 if (port.c_cflag & CRTSCTS) {
1628 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1629 lpdcb->fOutxCtsFlow = 1;
1633 lpdcb->fRtsControl =
1635 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1637 RTS_CONTROL_ENABLE ;
1638 lpdcb->fOutxCtsFlow = 0;
1640 if (port.c_iflag & IXON)
1645 if (port.c_iflag & IXOFF)
1654 lpdcb->XoffLim = 10;
1656 COMM_SetCommError(handle,0);
1660 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1661 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1662 (lpdcb->StopBits == ONESTOPBIT)?1:
1663 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1664 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1665 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1666 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1667 lpdcb->fRtsControl);
1668 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1669 lpdcb->fDtrControl);
1671 if ( lpdcb->fOutxCtsFlow ||
1672 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1677 TRACE("~CRTSCTS\n");
1682 /*****************************************************************************
1683 * TransmitCommChar (KERNEL32.@)
1685 * Transmits a single character in front of any pending characters in the
1686 * output buffer. Usually used to send an interrupt character to a host.
1690 * True if the call succeeded, false if the previous command character to the
1691 * same device has not been sent yet the handle is bad etc.
1697 BOOL WINAPI TransmitCommChar(
1698 HANDLE hComm, /* [in] The communication device in need of a command character. */
1699 CHAR chTransmit) /* [in] The character to transmit. */
1702 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1704 return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1708 /*****************************************************************************
1709 * GetCommTimeouts (KERNEL32.@)
1711 * Obtains the request timeout values for the communications device.
1715 * True on success, false if communications device handle is bad
1716 * or the target structure is null.
1718 BOOL WINAPI GetCommTimeouts(
1719 HANDLE hComm, /* [in] The communications device. */
1720 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1724 TRACE("(%p,%p)\n",hComm,lptimeouts);
1728 SetLastError(ERROR_INVALID_PARAMETER);
1732 SERVER_START_REQ( get_serial_info )
1734 req->handle = hComm;
1735 if ((ret = !wine_server_call_err( req )))
1737 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1738 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1739 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1740 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1741 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1748 /*****************************************************************************
1749 * SetCommTimeouts (KERNEL32.@)
1751 * Sets the timeouts used when reading and writing data to/from COMM ports.
1753 * ReadIntervalTimeout
1754 * - converted and passes to linux kernel as c_cc[VTIME]
1755 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1756 * - used in ReadFile to calculate GetOverlappedResult's timeout
1757 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1758 * - used in WriteFile to calculate GetOverlappedResult's timeout
1762 * True if the timeouts were set, false otherwise.
1764 BOOL WINAPI SetCommTimeouts(
1765 HANDLE hComm, /* [in] handle of COMM device */
1766 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1770 struct termios tios;
1772 TRACE("(%p,%p)\n",hComm,lptimeouts);
1776 SetLastError(ERROR_INVALID_PARAMETER);
1780 SERVER_START_REQ( set_serial_info )
1782 req->handle = hComm;
1783 req->flags = SERIALINFO_SET_TIMEOUTS;
1784 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1785 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1786 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1787 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1788 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1789 ret = !wine_server_call_err( req );
1792 if (!ret) return FALSE;
1794 /* FIXME: move this stuff to the server */
1795 fd = get_comm_fd( hComm, FILE_READ_DATA );
1796 if (fd < 0) return FALSE;
1798 if (-1==tcgetattr(fd,&tios)) {
1799 FIXME("tcgetattr on fd %d failed!\n",fd);
1800 release_comm_fd( hComm, fd );
1804 /* VTIME is in 1/10 seconds */
1806 unsigned int ux_timeout;
1808 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1814 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1817 ux_timeout = 1; /* must be at least some timeout */
1820 tios.c_cc[VTIME] = ux_timeout;
1823 if (-1==tcsetattr(fd,0,&tios)) {
1824 FIXME("tcsetattr on fd %d failed!\n",fd);
1825 release_comm_fd( hComm, fd );
1828 release_comm_fd( hComm, fd );
1832 /***********************************************************************
1833 * GetCommModemStatus (KERNEL32.@)
1835 * Obtains the four control register bits if supported by the hardware.
1839 * True if the communications handle was good and for hardware that
1840 * control register access, false otherwise.
1842 BOOL WINAPI GetCommModemStatus(
1843 HANDLE hFile, /* [in] The communications device. */
1844 LPDWORD lpModemStat) /* [out] The control register bits. */
1846 int fd,mstat, result=FALSE;
1850 fd = get_comm_fd( hFile, FILE_READ_DATA );
1853 result = ioctl(fd, TIOCMGET, &mstat);
1854 release_comm_fd( hFile, fd );
1857 WARN("ioctl failed\n");
1861 if (mstat & TIOCM_CTS)
1862 *lpModemStat |= MS_CTS_ON;
1865 if (mstat & TIOCM_DSR)
1866 *lpModemStat |= MS_DSR_ON;
1869 if (mstat & TIOCM_RNG)
1870 *lpModemStat |= MS_RING_ON;
1873 /*FIXME: Not really sure about RLSD UB 990810*/
1874 if (mstat & TIOCM_CAR)
1875 *lpModemStat |= MS_RLSD_ON;
1877 TRACE("%04x -> %s%s%s%s\n", mstat,
1878 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1879 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1880 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1881 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1888 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1890 DWORD ret = 0, queue;
1892 TRACE("mask 0x%08lx\n", mask);
1893 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old->rx, new->rx);
1894 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old->tx, new->tx);
1895 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old->frame, new->frame);
1896 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old->overrun, new->overrun);
1897 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old->parity, new->parity);
1898 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old->brk, new->brk);
1899 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1901 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1902 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1903 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1904 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1905 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1906 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1907 || (old->parity != new->parity)) )?EV_ERR :0;
1908 if (mask & EV_RXCHAR)
1912 if(ioctl(fd, TIOCINQ, &queue))
1913 WARN("TIOCINQ returned error\n");
1918 if (mask & EV_TXEMPTY)
1921 /* We really want to know when all characters have gone out of the transmitter */
1922 #if defined(TIOCSERGETLSR)
1923 if(ioctl(fd, TIOCSERGETLSR, &queue))
1924 WARN("TIOCSERGETLSR returned error\n");
1926 /* TIOCINQ only checks for an empty buffer */
1927 #elif defined(TIOCINQ)
1928 if(ioctl(fd, TIOCOUTQ, &queue))
1929 WARN("TIOCOUTQ returned error\n");
1934 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1939 /***********************************************************************
1940 * COMM_WaitCommEventService (INTERNAL)
1942 * We need to poll for what is interesting
1943 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1946 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1948 async_commio *commio = (async_commio*) arg;
1951 serial_irq_info new_irq_info;
1952 DWORD new_mstat, new_evtmask;
1954 fd=get_comm_fd( commio->handle, FILE_READ_DATA );
1956 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1957 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1961 * TIOCMIWAIT is not adequate
1964 * We don't handle the EV_RXFLAG (the eventchar)
1967 rc= COMM_GetEInfo(fd,&new_irq_info);
1969 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1970 rc = GetCommModemStatus(commio->handle, &new_mstat);
1972 TRACE("GetCommModemStatus failed\n");
1973 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1974 GetCommMask(commio->handle, &new_evtmask);
1975 abort = (commio->evtmask != new_evtmask);
1976 TRACE("resulting Eventmask 0x%08x\n", rc);
1977 } while (!rc && ! abort);
1979 release_comm_fd( commio->handle, fd );
1980 *commio->buffer = rc;
1981 if (commio->hEvent != INVALID_HANDLE_VALUE )
1982 NtSetEvent( commio->hEvent, NULL );
1983 HeapFree(GetProcessHeap(), 0, commio );
1988 /***********************************************************************
1989 * COMM_WaitCommEvent (INTERNAL)
1991 * This function must have an lpOverlapped.
1993 static BOOL COMM_WaitCommEvent(
1994 HANDLE hFile, /* [in] handle of comm port to wait for */
1995 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1996 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1999 async_commio* commio;
2005 SetLastError(ERROR_INVALID_PARAMETER);
2009 if (NtResetEvent(lpOverlapped->hEvent,NULL))
2012 fd = get_comm_fd( hFile, FILE_WRITE_DATA );
2013 if (fd < 0) return FALSE;
2015 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
2018 release_comm_fd( hFile, fd );
2022 commio->handle = hFile;
2023 commio->buffer = (char *)lpdwEvents;
2024 commio->hEvent = lpOverlapped->hEvent;
2025 GetCommMask(hFile, &commio->evtmask);
2027 /* We may never return, if some capabilities miss
2028 * Return error in that case
2030 #if !defined(TIOCINQ)
2031 if(commio->evtmask & EV_RXCHAR)
2034 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
2035 if(commio->evtmask & EV_TXEMPTY)
2038 #if !defined(TIOCMGET)
2039 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
2042 #if !defined(TIOCM_CTS)
2043 if(commio->evtmask & EV_CTS)
2046 #if !defined(TIOCM_DSR)
2047 if(commio->evtmask & EV_DSR)
2050 #if !defined(TIOCM_RNG)
2051 if(commio->evtmask & EV_RING)
2054 #if !defined(TIOCM_CAR)
2055 if(commio->evtmask & EV_RLSD)
2058 if(commio->evtmask & EV_RXFLAG)
2059 FIXME("EV_RXFLAG not handled\n");
2060 COMM_GetEInfo(fd,&commio->irq_info);
2061 GetCommModemStatus(hFile, &commio->mstat);
2062 /* We might have received something or the TX bufffer is delivered*/
2063 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
2066 TRACE("Event already met\n");
2067 *lpdwEvents = result_mask;
2068 HeapFree(GetProcessHeap(), 0, commio );
2073 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2074 SetLastError(ERROR_IO_PENDING);
2077 release_comm_fd( hFile, fd );
2079 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2081 FIXME("Returning error because of missing capabilities\n");
2082 release_comm_fd( hFile, fd );
2083 HeapFree(GetProcessHeap(), 0, commio );
2084 SetLastError(ERROR_INVALID_PARAMETER);
2088 /***********************************************************************
2089 * WaitCommEvent (KERNEL32.@)
2091 * Wait until something interesting happens on a COMM port.
2092 * Interesting things (events) are set by calling SetCommMask before
2093 * this function is called.
2096 * TRUE if successful
2099 * The set of detected events will be written to *lpdwEventMask
2100 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2103 * Only supports EV_RXCHAR and EV_TXEMPTY
2105 BOOL WINAPI WaitCommEvent(
2106 HANDLE hFile, /* [in] handle of comm port to wait for */
2107 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2108 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2114 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2117 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2119 /* if there is no overlapped structure, create our own */
2120 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2122 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2123 err = GetLastError();
2126 if (err == ERROR_IO_PENDING)
2130 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2131 } while (res != WAIT_OBJECT_0);
2132 TRACE("Event met\n:");
2137 FIXME("Unknown error 0x%08lx\n", err);
2143 CloseHandle(ov.hEvent);
2148 /***********************************************************************
2149 * GetCommProperties (KERNEL32.@)
2151 * This function fills in a structure with the capabilities of the
2152 * communications port driver.
2156 * TRUE on success, FALSE on failure
2157 * If successful, the lpCommProp structure be filled in with
2158 * properties of the comm port.
2160 BOOL WINAPI GetCommProperties(
2161 HANDLE hFile, /* [in] handle of the comm port */
2162 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2164 FIXME("(%p %p )\n",hFile,lpCommProp);
2169 * These values should be valid for LINUX's serial driver
2170 * FIXME: Perhaps they deserve an #ifdef LINUX
2172 memset(lpCommProp,0,sizeof(COMMPROP));
2173 lpCommProp->wPacketLength = 1;
2174 lpCommProp->wPacketVersion = 1;
2175 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2176 lpCommProp->dwReserved1 = 0;
2177 lpCommProp->dwMaxTxQueue = 4096;
2178 lpCommProp->dwMaxRxQueue = 4096;
2179 lpCommProp->dwMaxBaud = BAUD_115200;
2180 lpCommProp->dwProvSubType = PST_RS232;
2181 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2182 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2183 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2184 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2185 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2186 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2187 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2188 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2189 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2190 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2191 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2196 /***********************************************************************
2198 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2199 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2200 * This is dependent on the type of COMM port, but since it is doubtful
2201 * anybody will get around to implementing support for fancy serial
2202 * ports in WINE, this is hardcoded for the time being. The name of
2203 * this DLL should be stored in and read from the system registry in
2204 * the hive HKEY_LOCAL_MACHINE, key
2205 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2206 * where ???? is the port number... that is determined by PNP
2207 * The DLL should be loaded when the COMM port is opened, and closed
2208 * when the COMM port is closed. - MJM 20 June 2000
2209 ***********************************************************************/
2210 static const WCHAR lpszSerialUI[] = {
2211 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2214 /***********************************************************************
2215 * CommConfigDialogA (KERNEL32.@)
2217 * Raises a dialog that allows the user to configure a comm port.
2218 * Fills the COMMCONFIG struct with information specified by the user.
2219 * This function should call a similar routine in the COMM driver...
2223 * TRUE on success, FALSE on failure
2224 * If successful, the lpCommConfig structure will contain a new
2225 * configuration for the comm port, as specified by the user.
2228 * The library with the CommConfigDialog code is never unloaded.
2229 * Perhaps this should be done when the comm port is closed?
2231 BOOL WINAPI CommConfigDialogA(
2232 LPCSTR lpszDevice, /* [in] name of communications device */
2233 HWND hWnd, /* [in] parent window for the dialog */
2234 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2236 FARPROC lpfnCommDialog;
2237 HMODULE hConfigModule;
2240 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2242 hConfigModule = LoadLibraryW(lpszSerialUI);
2246 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2249 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2251 FreeLibrary(hConfigModule);
2256 /***********************************************************************
2257 * CommConfigDialogW (KERNEL32.@)
2259 * See CommConfigDialogA.
2261 BOOL WINAPI CommConfigDialogW(
2262 LPCWSTR lpszDevice, /* [in] name of communications device */
2263 HWND hWnd, /* [in] parent window for the dialog */
2264 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2266 FARPROC lpfnCommDialog;
2267 HMODULE hConfigModule;
2270 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2272 hConfigModule = LoadLibraryW(lpszSerialUI);
2276 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2279 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2281 FreeLibrary(hConfigModule);
2286 /***********************************************************************
2287 * GetCommConfig (KERNEL32.@)
2289 * Fill in the COMMCONFIG structure for the comm port hFile
2293 * TRUE on success, FALSE on failure
2294 * If successful, lpCommConfig contains the comm port configuration.
2299 BOOL WINAPI GetCommConfig(
2300 HANDLE hFile, /* [in] The communications device. */
2301 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2302 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2303 afterwards the number of bytes copied to the buffer or
2304 the needed size of the buffer. */
2308 TRACE("(%p %p)\n",hFile,lpCommConfig);
2310 if(lpCommConfig == NULL)
2312 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2313 *lpdwSize = sizeof(COMMCONFIG);
2317 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2318 lpCommConfig->wVersion = 1;
2319 lpCommConfig->wReserved = 0;
2320 r = GetCommState(hFile,&lpCommConfig->dcb);
2321 lpCommConfig->dwProviderSubType = PST_RS232;
2322 lpCommConfig->dwProviderOffset = 0;
2323 lpCommConfig->dwProviderSize = 0;
2328 /***********************************************************************
2329 * SetCommConfig (KERNEL32.@)
2331 * Sets the configuration of the communications device.
2335 * True on success, false if the handle was bad is not a communications device.
2337 BOOL WINAPI SetCommConfig(
2338 HANDLE hFile, /* [in] The communications device. */
2339 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2340 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2342 TRACE("(%p %p)\n",hFile,lpCommConfig);
2343 return SetCommState(hFile,&lpCommConfig->dcb);
2346 /***********************************************************************
2347 * SetDefaultCommConfigA (KERNEL32.@)
2349 * Initializes the default configuration for the specified communication
2354 * True if the device was found and the defaults set, false otherwise
2356 BOOL WINAPI SetDefaultCommConfigW(
2357 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2358 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2359 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2361 FARPROC lpfnSetDefaultCommConfig;
2362 HMODULE hConfigModule;
2365 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2367 hConfigModule = LoadLibraryW(lpszSerialUI);
2371 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2372 if (lpfnSetDefaultCommConfig)
2373 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2375 FreeLibrary(hConfigModule);
2381 /***********************************************************************
2382 * SetDefaultCommConfigW (KERNEL32.@)
2384 * Initializes the default configuration for the specified
2385 * communication device. (unicode)
2390 BOOL WINAPI SetDefaultCommConfigA(
2391 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2392 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2393 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2396 LPWSTR lpDeviceW = NULL;
2399 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2403 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2404 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2405 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2407 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2408 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2413 /***********************************************************************
2414 * GetDefaultCommConfigW (KERNEL32.@)
2416 * Acquires the default configuration of the specified communication device. (unicode)
2420 * True on successful reading of the default configuration,
2421 * if the device is not found or the buffer is too small.
2423 BOOL WINAPI GetDefaultCommConfigW(
2424 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2425 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2426 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2427 afterwards the number of bytes copied to the buffer or
2428 the needed size of the buffer. */
2430 LPDCB lpdcb = &(lpCC->dcb);
2432 static const WCHAR comW[] = {'C','O','M',0};
2433 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2435 if (strncmpiW(lpszName,comW,3)) {
2436 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2440 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2441 if (*lpdwSize < sizeof(COMMCONFIG)) {
2442 *lpdwSize = sizeof(COMMCONFIG);
2446 *lpdwSize = sizeof(COMMCONFIG);
2448 lpCC->dwSize = sizeof(COMMCONFIG);
2450 lpCC->dwProviderSubType = PST_RS232;
2451 lpCC->dwProviderOffset = 0L;
2452 lpCC->dwProviderSize = 0L;
2454 sprintfW( temp, formatW, lpszName[3]);
2455 FIXME("setting %s as default\n", debugstr_w(temp));
2457 return BuildCommDCBW( temp, lpdcb);
2460 /**************************************************************************
2461 * GetDefaultCommConfigA (KERNEL32.@)
2463 * Acquires the default configuration of the specified communication device. (ascii)
2467 * True on successful reading of the default configuration,
2468 * if the device is not found or the buffer is too small.
2470 BOOL WINAPI GetDefaultCommConfigA(
2471 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2472 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2473 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2474 afterwards the number of bytes copied to the buffer or
2475 the needed size of the buffer. */
2478 UNICODE_STRING lpszNameW;
2480 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2481 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2482 else lpszNameW.Buffer = NULL;
2484 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2486 RtlFreeUnicodeString(&lpszNameW);