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
66 #include "wine/server.h"
67 #include "wine/unicode.h"
69 #include "wine/debug.h"
71 #ifdef HAVE_LINUX_SERIAL_H
72 #include <linux/serial.h>
75 WINE_DEFAULT_DEBUG_CHANNEL(comm);
77 /* retrieve the Unix handle corresponding to a comm handle */
78 static int get_comm_fd( HANDLE handle, DWORD access )
82 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
83 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
87 /* release the Unix handle returned by get_comm_fd */
88 static inline void release_comm_fd( HANDLE handle, int fd )
90 wine_server_release_fd( handle, fd );
94 * local structure holding the irq values we need for WaitCommEvent()
96 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
97 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
98 * no need to carry them in the internal structure
101 typedef struct serial_irq_info
103 int rx , tx, frame, overrun, parity, brk, buf_overrun;
106 /***********************************************************************
107 * Data needed by the thread polling for the changing CommEvent
109 typedef struct async_commio
116 serial_irq_info irq_info;
119 /***********************************************************************/
121 #if !defined(TIOCINQ) && defined(FIONREAD)
122 #define TIOCINQ FIONREAD
125 /***********************************************************************
126 * Get extended interrupt count info, needed for WaitCommEvent
128 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
131 struct serial_icounter_struct einfo;
132 if (!ioctl(fd,TIOCGICOUNT, &einfo))
134 irq_info->rx = einfo.rx;
135 irq_info->tx = einfo.tx;
136 irq_info->frame = einfo.frame;
137 irq_info->overrun = einfo.overrun;
138 irq_info->parity = einfo.parity;
139 irq_info->brk = einfo.brk;
140 irq_info->buf_overrun = einfo.buf_overrun;
144 memset(irq_info,0, sizeof(serial_irq_info));
148 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
151 unsigned int mstat, okay;
152 okay = ioctl(fd, TIOCMGET, &mstat);
153 if (okay) return okay;
154 if (andy) mstat &= andy;
156 return ioctl(fd, TIOCMSET, &mstat);
162 /***********************************************************************
163 * COMM_Parse* (Internal)
165 * The following COMM_Parse* functions are used by the BuildCommDCB
166 * functions to help parse the various parts of the device control string.
168 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
170 static const WCHAR comW[] = {'C','O','M',0};
172 /* The device control string may optionally start with "COMx" followed
173 by an optional ':' and spaces. */
174 if(!strncmpiW(ptr, comW, 3))
178 /* Allow any com port above 0 as Win 9x does (NT only allows
179 values for com ports which are actually present) */
180 if(*ptr < '1' || *ptr > '9')
183 /* Advance pointer past port number */
184 while(*ptr >= '0' && *ptr <= '9') ptr++;
186 /* The com port number must be followed by a ':' or ' ' */
187 if(*ptr != ':' && *ptr != ' ')
190 /* Advance pointer to beginning of next parameter */
191 while(*ptr == ' ') ptr++;
195 while(*ptr == ' ') ptr++;
198 /* The device control string must not start with a space. */
205 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
207 if(*ptr < '0' || *ptr > '9') return NULL;
208 *lpnumber = strtoulW(ptr, NULL, 10);
209 while(*ptr >= '0' && *ptr <= '9') ptr++;
213 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
215 /* Contrary to what you might expect, Windows only sets the Parity
216 member of DCB and not fParity even when parity is specified in the
217 device control string */
219 switch(toupperW(*ptr++))
222 *lpparity = EVENPARITY;
225 *lpparity = MARKPARITY;
228 *lpparity = NOPARITY;
231 *lpparity = ODDPARITY;
234 *lpparity = SPACEPARITY;
243 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
247 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
250 if(temp >= 5 && temp <= 8)
259 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
262 static const WCHAR stopbits15W[] = {'1','.','5',0};
264 if(!strncmpW(stopbits15W, ptr, 3))
267 *lpstopbits = ONE5STOPBITS;
271 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
275 *lpstopbits = ONESTOPBIT;
277 *lpstopbits = TWOSTOPBITS;
285 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
287 static const WCHAR onW[] = {'o','n',0};
288 static const WCHAR offW[] = {'o','f','f',0};
290 if(!strncmpiW(onW, ptr, 2))
295 else if(!strncmpiW(offW, ptr, 3))
306 /***********************************************************************
307 * COMM_BuildOldCommDCB (Internal)
309 * Build a DCB using the old style settings string eg: "96,n,8,1"
311 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
315 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
318 switch(lpdcb->BaudRate)
323 lpdcb->BaudRate *= 10;
329 lpdcb->BaudRate *= 100;
332 lpdcb->BaudRate = 19200;
336 while(*device == ' ') device++;
337 if(*device++ != ',') return FALSE;
338 while(*device == ' ') device++;
340 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
343 while(*device == ' ') device++;
344 if(*device++ != ',') return FALSE;
345 while(*device == ' ') device++;
347 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
350 while(*device == ' ') device++;
351 if(*device++ != ',') return FALSE;
352 while(*device == ' ') device++;
354 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
357 /* The last parameter for flow control is optional. */
358 while(*device == ' ') device++;
362 while(*device == ' ') device++;
363 if(*device) last = toupperW(*device++);
364 while(*device == ' ') device++;
367 /* Win NT sets the flow control members based on (or lack of) the last
368 parameter. Win 9x does not set these members. */
373 lpdcb->fOutX = FALSE;
374 lpdcb->fOutxCtsFlow = FALSE;
375 lpdcb->fOutxDsrFlow = FALSE;
376 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
377 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
382 lpdcb->fOutxCtsFlow = FALSE;
383 lpdcb->fOutxDsrFlow = FALSE;
384 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
385 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
389 lpdcb->fOutX = FALSE;
390 lpdcb->fOutxCtsFlow = TRUE;
391 lpdcb->fOutxDsrFlow = TRUE;
392 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
393 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
399 /* This should be the end of the string. */
400 if(*device) return FALSE;
405 /***********************************************************************
406 * COMM_BuildNewCommDCB (Internal)
408 * Build a DCB using the new style settings string.
409 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
411 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
414 BOOL baud = FALSE, stop = FALSE;
415 static const WCHAR baudW[] = {'b','a','u','d','=',0};
416 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
417 static const WCHAR dataW[] = {'d','a','t','a','=',0};
418 static const WCHAR stopW[] = {'s','t','o','p','=',0};
419 static const WCHAR toW[] = {'t','o','=',0};
420 static const WCHAR xonW[] = {'x','o','n','=',0};
421 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
422 static const WCHAR octsW[] = {'o','c','t','s','=',0};
423 static const WCHAR dtrW[] = {'d','t','r','=',0};
424 static const WCHAR rtsW[] = {'r','t','s','=',0};
425 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
429 while(*device == ' ') device++;
431 if(!strncmpiW(baudW, device, 5))
435 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
438 else if(!strncmpiW(parityW, device, 7))
440 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
443 else if(!strncmpiW(dataW, device, 5))
445 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
448 else if(!strncmpiW(stopW, device, 5))
452 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
455 else if(!strncmpiW(toW, device, 3))
457 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
460 lptimeouts->ReadIntervalTimeout = 0;
461 lptimeouts->ReadTotalTimeoutMultiplier = 0;
462 lptimeouts->ReadTotalTimeoutConstant = 0;
463 lptimeouts->WriteTotalTimeoutMultiplier = 0;
464 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
466 else if(!strncmpiW(xonW, device, 4))
468 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
474 else if(!strncmpiW(odsrW, device, 5))
476 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
479 lpdcb->fOutxDsrFlow = temp;
481 else if(!strncmpiW(octsW, device, 5))
483 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
486 lpdcb->fOutxCtsFlow = temp;
488 else if(!strncmpiW(dtrW, device, 4))
490 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
493 lpdcb->fDtrControl = temp;
495 else if(!strncmpiW(rtsW, device, 4))
497 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
500 lpdcb->fRtsControl = temp;
502 else if(!strncmpiW(idsrW, device, 5))
504 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
507 /* Win NT sets the fDsrSensitivity member based on the
508 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
509 lpdcb->fDsrSensitivity = temp;
514 /* After the above parsing, the next character (if not the end of
515 the string) should be a space */
516 if(*device && *device != ' ')
520 /* If stop bits were not specified, a default is always supplied. */
523 if(baud && lpdcb->BaudRate == 110)
524 lpdcb->StopBits = TWOSTOPBITS;
526 lpdcb->StopBits = ONESTOPBIT;
532 /**************************************************************************
533 * BuildCommDCBA (KERNEL32.@)
535 * Updates a device control block data structure with values from an
536 * ascii device control string. The device control string has two forms
537 * normal and extended, it must be exclusively in one or the other form.
541 * True on success, false on a malformed control string.
543 BOOL WINAPI BuildCommDCBA(
544 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
545 LPDCB lpdcb) /* [out] The device control block to be updated. */
547 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
550 /**************************************************************************
551 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
553 * Updates a device control block data structure with values from an
554 * ascii device control string. Taking timeout values from a timeouts
555 * struct if desired by the control string.
559 * True on success, false bad handles etc.
561 BOOL WINAPI BuildCommDCBAndTimeoutsA(
562 LPCSTR device, /* [in] The ascii device control string. */
563 LPDCB lpdcb, /* [out] The device control block to be updated. */
564 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
567 UNICODE_STRING deviceW;
569 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
570 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
571 else deviceW.Buffer = NULL;
573 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
575 RtlFreeUnicodeString(&deviceW);
579 /**************************************************************************
580 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
582 * Updates a device control block data structure with values from a
583 * unicode device control string. Taking timeout values from a timeouts
584 * struct if desired by the control string.
588 * True on success, false bad handles etc
590 BOOL WINAPI BuildCommDCBAndTimeoutsW(
591 LPCWSTR devid, /* [in] The unicode device control string. */
592 LPDCB lpdcb, /* [out] The device control block to be updated. */
593 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
596 COMMTIMEOUTS timeouts;
600 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
602 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
603 lpdcb->DCBlength = sizeof(DCB);
605 /* Make a copy of the original data structures to work with since if
606 if there is an error in the device control string the originals
607 should not be modified (except possibly DCBlength) */
608 memcpy(&dcb, lpdcb, sizeof(DCB));
609 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
611 ptr = COMM_ParseStart(ptr);
615 else if(strchrW(ptr, ','))
616 result = COMM_BuildOldCommDCB(ptr, &dcb);
618 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
622 memcpy(lpdcb, &dcb, sizeof(DCB));
623 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
628 WARN("Invalid device control string: %s\n", debugstr_w(devid));
629 SetLastError(ERROR_INVALID_PARAMETER);
634 /**************************************************************************
635 * BuildCommDCBW (KERNEL32.@)
637 * Updates a device control block structure with values from an
638 * unicode device control string. The device control string has two forms
639 * normal and extended, it must be exclusively in one or the other form.
643 * True on success, false on a malformed control string.
645 BOOL WINAPI BuildCommDCBW(
646 LPCWSTR devid, /* [in] The unicode device control string. */
647 LPDCB lpdcb) /* [out] The device control block to be updated. */
649 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
652 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
656 SERVER_START_REQ( set_serial_info )
658 req->handle = handle;
659 req->flags = SERIALINFO_SET_ERROR;
660 req->commerror = error;
661 ret = !wine_server_call_err( req );
667 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
674 SERVER_START_REQ( get_serial_info )
676 req->handle = handle;
677 ret = !wine_server_call_err( req );
678 *lperror = reply->commerror;
685 /*****************************************************************************
686 * SetCommBreak (KERNEL32.@)
688 * Halts the transmission of characters to a communications device.
692 * True on success, and false if the communications device could not be found,
693 * the control is not supported.
697 * Only TIOCSBRK and TIOCCBRK are supported.
699 BOOL WINAPI SetCommBreak(
700 HANDLE handle) /* [in] The communications device to suspend. */
702 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
705 fd = get_comm_fd( handle, GENERIC_READ );
706 if(fd<0) return FALSE;
707 result = ioctl(fd,TIOCSBRK,0);
708 release_comm_fd( handle, fd );
711 TRACE("ioctl failed\n");
712 SetLastError(ERROR_NOT_SUPPORTED);
717 FIXME("ioctl not available\n");
718 SetLastError(ERROR_NOT_SUPPORTED);
723 /*****************************************************************************
724 * ClearCommBreak (KERNEL32.@)
726 * Resumes character transmission from a communication device.
730 * True on success and false if the communications device could not be found.
734 * Only TIOCSBRK and TIOCCBRK are supported.
736 BOOL WINAPI ClearCommBreak(
737 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
739 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
742 fd = get_comm_fd( handle, GENERIC_READ );
743 if(fd<0) return FALSE;
744 result = ioctl(fd,TIOCCBRK,0);
745 release_comm_fd( handle, fd );
748 TRACE("ioctl failed\n");
749 SetLastError(ERROR_NOT_SUPPORTED);
754 FIXME("ioctl not available\n");
755 SetLastError(ERROR_NOT_SUPPORTED);
760 /*****************************************************************************
761 * EscapeCommFunction (KERNEL32.@)
763 * Directs a communication device to perform an extended function.
767 * True or requested data on successful completion of the command,
768 * false if the device is not present cannot execute the command
769 * or the command failed.
771 BOOL WINAPI EscapeCommFunction(
772 HANDLE handle, /* [in] The communication device to perform the extended function. */
773 UINT nFunction) /* [in] The extended function to be performed. */
775 int fd,direct=FALSE,result=FALSE;
778 TRACE("handle %p, function=%d\n", handle, nFunction);
779 fd = get_comm_fd( handle, GENERIC_READ );
780 if(fd<0) return FALSE;
782 if (tcgetattr(fd,&port) == -1) {
783 COMM_SetCommError(handle,CE_IOE);
784 release_comm_fd( handle, fd );
797 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
805 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
813 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
821 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
827 port.c_iflag |= IXOFF;
832 port.c_iflag |= IXON;
838 result = ioctl(fd,TIOCSBRK,0);
845 result = ioctl(fd,TIOCCBRK,0);
849 WARN("(handle=%p,nFunction=%d): Unknown function\n",
855 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
856 release_comm_fd( handle, fd );
857 COMM_SetCommError(handle,CE_IOE);
866 COMM_SetCommError(handle,CE_IOE);
871 release_comm_fd( handle, fd );
875 /********************************************************************
876 * PurgeComm (KERNEL32.@)
878 * Terminates pending operations and/or discards buffers on a
879 * communication resource.
883 * True on success and false if the communications handle is bad.
885 BOOL WINAPI PurgeComm(
886 HANDLE handle, /* [in] The communication resource to be purged. */
887 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
891 TRACE("handle %p, flags %lx\n", handle, flags);
893 fd = get_comm_fd( handle, GENERIC_READ );
894 if(fd<0) return FALSE;
897 ** not exactly sure how these are different
898 ** Perhaps if we had our own internal queues, one flushes them
899 ** and the other flushes the kernel's buffers.
901 if(flags&PURGE_TXABORT)
902 tcflush(fd,TCOFLUSH);
903 if(flags&PURGE_RXABORT)
904 tcflush(fd,TCIFLUSH);
905 if(flags&PURGE_TXCLEAR)
906 tcflush(fd,TCOFLUSH);
907 if(flags&PURGE_RXCLEAR)
908 tcflush(fd,TCIFLUSH);
909 release_comm_fd( handle, fd );
914 /*****************************************************************************
915 * ClearCommError (KERNEL32.@)
917 * Enables further I/O operations on a communications resource after
918 * supplying error and current status information.
922 * True on success, false if the communication resource handle is bad.
924 BOOL WINAPI ClearCommError(
925 HANDLE handle, /* [in] The communication resource with the error. */
926 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
927 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
931 fd=get_comm_fd( handle, GENERIC_READ );
932 if(0>fd) return FALSE;
936 lpStat->fCtsHold = 0;
937 lpStat->fDsrHold = 0;
938 lpStat->fRlsdHold = 0;
939 lpStat->fXoffHold = 0;
940 lpStat->fXoffSent = 0;
943 lpStat->fReserved = 0;
946 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
947 WARN("ioctl returned error\n");
949 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
953 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
954 WARN("ioctl returned error\n");
957 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
958 handle, lpStat->cbInQue, lpStat->cbOutQue);
961 release_comm_fd( handle, fd );
963 COMM_GetCommError(handle, errors);
964 COMM_SetCommError(handle, 0);
969 /*****************************************************************************
970 * SetupComm (KERNEL32.@)
972 * Called after CreateFile to hint to the communication resource to use
973 * specified sizes for input and output buffers rather than the default values.
977 * True if successful, false if the communications resource handle is bad.
983 BOOL WINAPI SetupComm(
984 HANDLE handle, /* [in] The just created communication resource handle. */
985 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
986 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
990 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
991 fd=get_comm_fd( handle, GENERIC_READ );
992 if(0>fd) return FALSE;
993 release_comm_fd( handle, fd );
997 /*****************************************************************************
998 * GetCommMask (KERNEL32.@)
1000 * Obtain the events associated with a communication device that will cause
1001 * a call WaitCommEvent to return.
1005 * True on success, fail on bad device handle etc.
1007 BOOL WINAPI GetCommMask(
1008 HANDLE handle, /* [in] The communications device. */
1009 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1013 TRACE("handle %p, mask %p\n", handle, evtmask);
1015 SERVER_START_REQ( get_serial_info )
1017 req->handle = handle;
1018 if ((ret = !wine_server_call_err( req )))
1020 if (evtmask) *evtmask = reply->eventmask;
1027 /*****************************************************************************
1028 * SetCommMask (KERNEL32.@)
1030 * There be some things we need to hear about yon there communications device.
1031 * (Set which events associated with a communication device should cause
1032 * a call WaitCommEvent to return.)
1036 * True on success, false on bad handle etc.
1038 BOOL WINAPI SetCommMask(
1039 HANDLE handle, /* [in] The communications device. */
1040 DWORD evtmask) /* [in] The events that are to be monitored. */
1044 TRACE("handle %p, mask %lx\n", handle, evtmask);
1046 SERVER_START_REQ( set_serial_info )
1048 req->handle = handle;
1049 req->flags = SERIALINFO_SET_MASK;
1050 req->eventmask = evtmask;
1051 ret = !wine_server_call_err( req );
1057 /*****************************************************************************
1058 * SetCommState (KERNEL32.@)
1060 * Re-initializes all hardware and control settings of a communications device,
1061 * with values from a device control block without effecting the input and output
1066 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1068 BOOL WINAPI SetCommState(
1069 HANDLE handle, /* [in] The communications device. */
1070 LPDCB lpdcb) /* [out] The device control block. */
1072 struct termios port;
1073 int fd, bytesize, stopbits;
1076 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1077 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1078 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1079 (lpdcb->StopBits == ONESTOPBIT)?1:
1080 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1081 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1082 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1083 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1084 lpdcb->fRtsControl);
1085 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1086 lpdcb->fDtrControl);
1089 fd = get_comm_fd( handle, GENERIC_READ );
1090 if (fd < 0) return FALSE;
1092 if ((tcgetattr(fd,&port)) == -1) {
1093 int save_error = errno;
1094 COMM_SetCommError(handle,CE_IOE);
1095 release_comm_fd( handle, fd );
1096 ERR("tcgetattr error '%s'\n", strerror(save_error));
1100 port.c_cc[VMIN] = 0;
1101 port.c_cc[VTIME] = 1;
1104 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1106 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1108 port.c_iflag |= (IGNBRK);
1110 port.c_oflag &= ~(OPOST);
1112 port.c_cflag &= ~(HUPCL);
1113 port.c_cflag |= CLOCAL | CREAD;
1115 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1116 port.c_lflag |= NOFLSH;
1119 port.c_cflag &= ~CBAUD;
1120 switch (lpdcb->BaudRate) {
1125 port.c_cflag |= B50;
1128 port.c_cflag |= B75;
1132 port.c_cflag |= B110;
1135 port.c_cflag |= B134;
1138 port.c_cflag |= B150;
1141 port.c_cflag |= B200;
1145 port.c_cflag |= B300;
1149 port.c_cflag |= B600;
1153 port.c_cflag |= B1200;
1156 port.c_cflag |= B1800;
1160 port.c_cflag |= B2400;
1164 port.c_cflag |= B4800;
1168 port.c_cflag |= B9600;
1172 port.c_cflag |= B19200;
1176 port.c_cflag |= B38400;
1180 port.c_cflag |= B57600;
1185 port.c_cflag |= B115200;
1190 port.c_cflag |= B230400;
1195 port.c_cflag |= B460800;
1199 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1200 { struct serial_struct nuts;
1202 ioctl(fd, TIOCGSERIAL, &nuts);
1203 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1204 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1205 arby = nuts.baud_base / nuts.custom_divisor;
1206 nuts.flags &= ~ASYNC_SPD_MASK;
1207 nuts.flags |= ASYNC_SPD_CUST;
1208 WARN("You (or a program acting at your behest) have specified\n"
1209 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1210 "which is as close as we can get by our present understanding of your\n"
1211 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1212 "has caused to your linux system can be undone with setserial \n"
1213 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1214 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1215 ioctl(fd, TIOCSSERIAL, &nuts);
1216 port.c_cflag |= B38400;
1219 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1222 COMM_SetCommError(handle,IE_BAUDRATE);
1223 release_comm_fd( handle, fd );
1224 ERR("baudrate %ld\n",lpdcb->BaudRate);
1227 #elif !defined(__EMX__)
1228 switch (lpdcb->BaudRate) {
1233 port.c_ospeed = B50;
1236 port.c_ospeed = B75;
1240 port.c_ospeed = B110;
1243 port.c_ospeed = B134;
1246 port.c_ospeed = B150;
1249 port.c_ospeed = B200;
1253 port.c_ospeed = B300;
1257 port.c_ospeed = B600;
1261 port.c_ospeed = B1200;
1264 port.c_ospeed = B1800;
1268 port.c_ospeed = B2400;
1272 port.c_ospeed = B4800;
1276 port.c_ospeed = B9600;
1280 port.c_ospeed = B19200;
1284 port.c_ospeed = B38400;
1289 port.c_cflag |= B57600;
1295 port.c_cflag |= B115200;
1300 port.c_cflag |= B230400;
1305 port.c_cflag |= B460800;
1309 COMM_SetCommError(handle,IE_BAUDRATE);
1310 release_comm_fd( handle, fd );
1311 ERR("baudrate %ld\n",lpdcb->BaudRate);
1314 port.c_ispeed = port.c_ospeed;
1316 bytesize=lpdcb->ByteSize;
1317 stopbits=lpdcb->StopBits;
1320 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1322 port.c_cflag &= ~(PARENB | PARODD);
1325 port.c_iflag |= INPCK;
1327 port.c_iflag &= ~INPCK;
1328 switch (lpdcb->Parity) {
1332 port.c_cflag |= (PARENB | PARODD);
1335 port.c_cflag |= PARENB;
1338 /* Linux defines mark/space (stick) parity */
1340 port.c_cflag |= (PARENB | CMSPAR);
1343 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1346 /* try the POSIX way */
1348 if( stopbits == ONESTOPBIT) {
1349 stopbits = TWOSTOPBITS;
1350 port.c_iflag &= ~INPCK;
1352 COMM_SetCommError(handle,IE_BYTESIZE);
1353 release_comm_fd( handle, fd );
1354 ERR("Cannot set MARK Parity\n");
1361 port.c_iflag &= ~INPCK;
1363 COMM_SetCommError(handle,IE_BYTESIZE);
1364 release_comm_fd( handle, fd );
1365 ERR("Cannot set SPACE Parity\n");
1371 COMM_SetCommError(handle,IE_BYTESIZE);
1372 release_comm_fd( handle, fd );
1378 port.c_cflag &= ~CSIZE;
1381 port.c_cflag |= CS5;
1384 port.c_cflag |= CS6;
1387 port.c_cflag |= CS7;
1390 port.c_cflag |= CS8;
1393 COMM_SetCommError(handle,IE_BYTESIZE);
1394 release_comm_fd( handle, fd );
1401 port.c_cflag &= ~CSTOPB;
1403 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1405 port.c_cflag |= CSTOPB;
1408 COMM_SetCommError(handle,IE_BYTESIZE);
1409 release_comm_fd( handle, fd );
1414 if ( lpdcb->fOutxCtsFlow ||
1415 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1418 port.c_cflag |= CRTSCTS;
1424 port.c_iflag |= IXON;
1426 port.c_iflag &= ~IXON;
1428 port.c_iflag |= IXOFF;
1430 port.c_iflag &= ~IXOFF;
1432 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1433 ERR("tcsetattr error '%s'\n", strerror(errno));
1434 COMM_SetCommError(handle,CE_IOE);
1437 COMM_SetCommError(handle,0);
1441 /* note: change DTR/RTS lines after setting the comm attributes,
1442 * so flow control does not interfere. */
1444 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1446 WARN("DSR/DTR flow control not supported\n");
1447 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1448 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1450 COMM_WhackModem(fd, 0, TIOCM_DTR);
1453 if(!lpdcb->fOutxCtsFlow )
1455 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1456 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1458 COMM_WhackModem(fd, 0, TIOCM_RTS);
1461 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1462 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1463 release_comm_fd( handle, fd );
1469 /*****************************************************************************
1470 * GetCommState (KERNEL32.@)
1472 * Fills in a device control block with information from a communications device.
1476 * True on success, false if the communication device handle is bad etc
1480 * XonChar and XoffChar are not set.
1482 BOOL WINAPI GetCommState(
1483 HANDLE handle, /* [in] The communications device. */
1484 LPDCB lpdcb) /* [out] The device control block. */
1486 struct termios port;
1488 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1490 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1492 fd = get_comm_fd( handle, GENERIC_READ );
1493 if (fd < 0) return FALSE;
1494 if (tcgetattr(fd, &port) == -1
1496 || ioctl(fd, TIOCMGET, &stat) == -1
1499 int save_error=errno;
1500 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1501 COMM_SetCommError(handle,CE_IOE);
1502 release_comm_fd( handle, fd );
1505 release_comm_fd( handle, fd );
1508 speed= (port.c_cflag & CBAUD);
1510 speed= (cfgetospeed(&port));
1514 lpdcb->BaudRate = 0;
1517 lpdcb->BaudRate = 50;
1520 lpdcb->BaudRate = 75;
1523 lpdcb->BaudRate = 110;
1526 lpdcb->BaudRate = 134;
1529 lpdcb->BaudRate = 150;
1532 lpdcb->BaudRate = 200;
1535 lpdcb->BaudRate = 300;
1538 lpdcb->BaudRate = 600;
1541 lpdcb->BaudRate = 1200;
1544 lpdcb->BaudRate = 1800;
1547 lpdcb->BaudRate = 2400;
1550 lpdcb->BaudRate = 4800;
1553 lpdcb->BaudRate = 9600;
1556 lpdcb->BaudRate = 19200;
1559 lpdcb->BaudRate = 38400;
1563 lpdcb->BaudRate = 57600;
1568 lpdcb->BaudRate = 115200;
1573 lpdcb->BaudRate = 230400;
1578 lpdcb->BaudRate = 460800;
1582 ERR("unknown speed %x \n",speed);
1585 switch (port.c_cflag & CSIZE) {
1587 lpdcb->ByteSize = 5;
1590 lpdcb->ByteSize = 6;
1593 lpdcb->ByteSize = 7;
1596 lpdcb->ByteSize = 8;
1599 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1602 if(port.c_iflag & INPCK)
1603 lpdcb->fParity = TRUE;
1605 lpdcb->fParity = FALSE;
1607 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1609 switch (port.c_cflag & (PARENB | PARODD))
1613 lpdcb->Parity = NOPARITY;
1616 lpdcb->Parity = EVENPARITY;
1618 case (PARENB | PARODD):
1619 lpdcb->Parity = ODDPARITY;
1622 case (PARENB | CMSPAR):
1623 lpdcb->Parity = MARKPARITY;
1625 case (PARENB | PARODD | CMSPAR):
1626 lpdcb->Parity = SPACEPARITY;
1631 if (port.c_cflag & CSTOPB)
1632 if(lpdcb->ByteSize == 5)
1633 lpdcb->StopBits = ONE5STOPBITS;
1635 lpdcb->StopBits = TWOSTOPBITS;
1637 lpdcb->StopBits = ONESTOPBIT;
1642 /* termios does not support DTR/DSR flow control */
1643 lpdcb->fOutxDsrFlow = 0;
1644 lpdcb->fDtrControl =
1646 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1648 DTR_CONTROL_ENABLE ;
1652 if (port.c_cflag & CRTSCTS) {
1653 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1654 lpdcb->fOutxCtsFlow = 1;
1658 lpdcb->fRtsControl =
1660 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1662 RTS_CONTROL_ENABLE ;
1663 lpdcb->fOutxCtsFlow = 0;
1665 if (port.c_iflag & IXON)
1670 if (port.c_iflag & IXOFF)
1679 lpdcb->XoffLim = 10;
1681 COMM_SetCommError(handle,0);
1685 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1686 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1687 (lpdcb->StopBits == ONESTOPBIT)?1:
1688 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1689 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1690 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1691 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1692 lpdcb->fRtsControl);
1693 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1694 lpdcb->fDtrControl);
1696 if ( lpdcb->fOutxCtsFlow ||
1697 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1702 TRACE("~CRTSCTS\n");
1707 /*****************************************************************************
1708 * TransmitCommChar (KERNEL32.@)
1710 * Transmits a single character in front of any pending characters in the
1711 * output buffer. Usually used to send an interrupt character to a host.
1715 * True if the call succeeded, false if the previous command character to the
1716 * same device has not been sent yet the handle is bad etc.
1722 BOOL WINAPI TransmitCommChar(
1723 HANDLE hComm, /* [in] The communication device in need of a command character. */
1724 CHAR chTransmit) /* [in] The character to transmit. */
1727 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1729 return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1733 /*****************************************************************************
1734 * GetCommTimeouts (KERNEL32.@)
1736 * Obtains the request timeout values for the communications device.
1740 * True on success, false if communications device handle is bad
1741 * or the target structure is null.
1743 BOOL WINAPI GetCommTimeouts(
1744 HANDLE hComm, /* [in] The communications device. */
1745 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1749 TRACE("(%p,%p)\n",hComm,lptimeouts);
1753 SetLastError(ERROR_INVALID_PARAMETER);
1757 SERVER_START_REQ( get_serial_info )
1759 req->handle = hComm;
1760 if ((ret = !wine_server_call_err( req )))
1762 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1763 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1764 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1765 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1766 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1773 /*****************************************************************************
1774 * SetCommTimeouts (KERNEL32.@)
1776 * Sets the timeouts used when reading and writing data to/from COMM ports.
1778 * ReadIntervalTimeout
1779 * - converted and passes to linux kernel as c_cc[VTIME]
1780 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1781 * - used in ReadFile to calculate GetOverlappedResult's timeout
1782 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1783 * - used in WriteFile to calculate GetOverlappedResult's timeout
1787 * True if the timeouts were set, false otherwise.
1789 BOOL WINAPI SetCommTimeouts(
1790 HANDLE hComm, /* [in] handle of COMM device */
1791 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1795 struct termios tios;
1797 TRACE("(%p,%p)\n",hComm,lptimeouts);
1801 SetLastError(ERROR_INVALID_PARAMETER);
1805 SERVER_START_REQ( set_serial_info )
1807 req->handle = hComm;
1808 req->flags = SERIALINFO_SET_TIMEOUTS;
1809 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1810 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1811 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1812 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1813 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1814 ret = !wine_server_call_err( req );
1817 if (!ret) return FALSE;
1819 /* FIXME: move this stuff to the server */
1820 fd = get_comm_fd( hComm, GENERIC_READ );
1821 if (fd < 0) return FALSE;
1823 if (-1==tcgetattr(fd,&tios)) {
1824 FIXME("tcgetattr on fd %d failed!\n",fd);
1825 release_comm_fd( hComm, fd );
1829 /* VTIME is in 1/10 seconds */
1831 unsigned int ux_timeout;
1833 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1839 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1842 ux_timeout = 1; /* must be at least some timeout */
1845 tios.c_cc[VTIME] = ux_timeout;
1848 if (-1==tcsetattr(fd,0,&tios)) {
1849 FIXME("tcsetattr on fd %d failed!\n",fd);
1850 release_comm_fd( hComm, fd );
1853 release_comm_fd( hComm, fd );
1857 /***********************************************************************
1858 * GetCommModemStatus (KERNEL32.@)
1860 * Obtains the four control register bits if supported by the hardware.
1864 * True if the communications handle was good and for hardware that
1865 * control register access, false otherwise.
1867 BOOL WINAPI GetCommModemStatus(
1868 HANDLE hFile, /* [in] The communications device. */
1869 LPDWORD lpModemStat) /* [out] The control register bits. */
1871 int fd,mstat, result=FALSE;
1875 fd = get_comm_fd( hFile, GENERIC_READ );
1878 result = ioctl(fd, TIOCMGET, &mstat);
1879 release_comm_fd( hFile, fd );
1882 WARN("ioctl failed\n");
1886 if (mstat & TIOCM_CTS)
1887 *lpModemStat |= MS_CTS_ON;
1890 if (mstat & TIOCM_DSR)
1891 *lpModemStat |= MS_DSR_ON;
1894 if (mstat & TIOCM_RNG)
1895 *lpModemStat |= MS_RING_ON;
1898 /*FIXME: Not really sure about RLSD UB 990810*/
1899 if (mstat & TIOCM_CAR)
1900 *lpModemStat |= MS_RLSD_ON;
1902 TRACE("%04x -> %s%s%s%s\n", mstat,
1903 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1904 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1905 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1906 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1913 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1915 DWORD ret = 0, queue;
1917 TRACE("mask 0x%08lx\n", mask);
1918 TRACE("old->rx 0x%08x vs. new->rx 0x%08x \n", old->rx, new->rx);
1919 TRACE("old->tx 0x%08x vs. new->tx 0x%08x \n", old->tx, new->tx);
1920 TRACE("old->frame 0x%08x vs. new->frame 0x%08x \n", old->frame, new->frame);
1921 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x \n", old->overrun, new->overrun);
1922 TRACE("old->parity 0x%08x vs. new->parity 0x%08x \n", old->parity, new->parity);
1923 TRACE("old->brk 0x%08x vs. new->brk 0x%08x \n", old->brk, new->brk);
1924 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x \n", old->buf_overrun, new->buf_overrun);
1926 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1927 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1928 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1929 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1930 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1931 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1932 || (old->parity != new->parity)) )?EV_ERR :0;
1933 if (mask & EV_RXCHAR)
1937 if(ioctl(fd, TIOCINQ, &queue))
1938 WARN("TIOCINQ returned error\n");
1943 if (mask & EV_TXEMPTY)
1946 /* We really want to know when all characters have gone out of the transmitter */
1947 #if defined(TIOCSERGETLSR)
1948 if(ioctl(fd, TIOCSERGETLSR, &queue))
1949 WARN("TIOCSERGETLSR returned error\n");
1951 /* TIOCINQ only checks for an empty buffer */
1952 #elif defined(TIOCINQ)
1953 if(ioctl(fd, TIOCOUTQ, &queue))
1954 WARN("TIOCOUTQ returned error\n");
1959 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1964 /***********************************************************************
1965 * COMM_WaitCommEventService (INTERNAL)
1967 * We need to poll for what is interesting
1968 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1971 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1973 async_commio *commio = (async_commio*) arg;
1976 serial_irq_info new_irq_info;
1977 DWORD new_mstat, new_evtmask;
1979 fd=get_comm_fd( commio->handle, GENERIC_READ );
1981 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1982 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1986 * TIOCMIWAIT is not adequate
1989 * We don't handle the EV_RXFLAG (the eventchar)
1992 rc= COMM_GetEInfo(fd,&new_irq_info);
1994 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1995 rc = GetCommModemStatus(commio->handle, &new_mstat);
1997 TRACE("GetCommModemStatus failed\n");
1998 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1999 GetCommMask(commio->handle, &new_evtmask);
2000 abort = (commio->evtmask != new_evtmask);
2001 TRACE("resulting Eventmask 0x%08x\n", rc);
2002 } while (!rc && ! abort);
2004 release_comm_fd( commio->handle, fd );
2005 *commio->buffer = rc;
2006 if (commio->hEvent != INVALID_HANDLE_VALUE )
2007 NtSetEvent( commio->hEvent, NULL );
2008 HeapFree(GetProcessHeap(), 0, commio );
2013 /***********************************************************************
2014 * COMM_WaitCommEvent (INTERNAL)
2016 * This function must have an lpOverlapped.
2018 static BOOL COMM_WaitCommEvent(
2019 HANDLE hFile, /* [in] handle of comm port to wait for */
2020 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2021 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2024 async_commio* commio;
2030 SetLastError(ERROR_INVALID_PARAMETER);
2034 if (NtResetEvent(lpOverlapped->hEvent,NULL))
2037 fd = get_comm_fd( hFile, GENERIC_WRITE );
2038 if (fd < 0) return FALSE;
2040 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
2043 release_comm_fd( hFile, fd );
2047 commio->handle = hFile;
2048 commio->buffer = (char *)lpdwEvents;
2049 commio->hEvent = lpOverlapped->hEvent;
2050 GetCommMask(hFile, &commio->evtmask);
2052 /* We may never return, if some capabilities miss
2053 * Return error in that case
2055 #if !defined(TIOCINQ)
2056 if(commio->evtmask & EV_RXCHAR)
2059 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
2060 if(commio->evtmask & EV_TXEMPTY)
2063 #if !defined(TIOCMGET)
2064 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
2067 #if !defined(TIOCM_CTS)
2068 if(commio->evtmask & EV_CTS)
2071 #if !defined(TIOCM_DSR)
2072 if(commio->evtmask & EV_DSR)
2075 #if !defined(TIOCM_RNG)
2076 if(commio->evtmask & EV_RING)
2079 #if !defined(TIOCM_CAR)
2080 if(commio->evtmask & EV_RLSD)
2083 if(commio->evtmask & EV_RXFLAG)
2084 FIXME("EV_RXFLAG not handled\n");
2085 COMM_GetEInfo(fd,&commio->irq_info);
2086 GetCommModemStatus(hFile, &commio->mstat);
2087 /* We might have received something or the TX bufffer is delivered*/
2088 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
2091 TRACE("Event already met\n");
2092 *lpdwEvents = result_mask;
2093 release_comm_fd( commio->handle, fd );
2094 HeapFree(GetProcessHeap(), 0, commio );
2099 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2100 SetLastError(ERROR_IO_PENDING);
2104 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2106 FIXME("Returning error because of missing capabilities\n");
2107 HeapFree(GetProcessHeap(), 0, commio );
2108 SetLastError(ERROR_INVALID_PARAMETER);
2112 /***********************************************************************
2113 * WaitCommEvent (KERNEL32.@)
2115 * Wait until something interesting happens on a COMM port.
2116 * Interesting things (events) are set by calling SetCommMask before
2117 * this function is called.
2120 * TRUE if successful
2123 * The set of detected events will be written to *lpdwEventMask
2124 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2127 * Only supports EV_RXCHAR and EV_TXEMPTY
2129 BOOL WINAPI WaitCommEvent(
2130 HANDLE hFile, /* [in] handle of comm port to wait for */
2131 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2132 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2138 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2141 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2143 /* if there is no overlapped structure, create our own */
2144 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2146 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2147 err = GetLastError();
2150 if (err == ERROR_IO_PENDING)
2154 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2155 } while (res != WAIT_OBJECT_0);
2156 TRACE("Event met\n:");
2161 FIXME("Unknown error 0x%08lx\n", err);
2167 CloseHandle(ov.hEvent);
2172 /***********************************************************************
2173 * GetCommProperties (KERNEL32.@)
2175 * This function fills in a structure with the capabilities of the
2176 * communications port driver.
2180 * TRUE on success, FALSE on failure
2181 * If successful, the lpCommProp structure be filled in with
2182 * properties of the comm port.
2184 BOOL WINAPI GetCommProperties(
2185 HANDLE hFile, /* [in] handle of the comm port */
2186 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2188 FIXME("(%p %p )\n",hFile,lpCommProp);
2193 * These values should be valid for LINUX's serial driver
2194 * FIXME: Perhaps they deserve an #ifdef LINUX
2196 memset(lpCommProp,0,sizeof(COMMPROP));
2197 lpCommProp->wPacketLength = 1;
2198 lpCommProp->wPacketVersion = 1;
2199 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2200 lpCommProp->dwReserved1 = 0;
2201 lpCommProp->dwMaxTxQueue = 4096;
2202 lpCommProp->dwMaxRxQueue = 4096;
2203 lpCommProp->dwMaxBaud = BAUD_115200;
2204 lpCommProp->dwProvSubType = PST_RS232;
2205 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2206 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2207 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2208 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2209 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2210 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2211 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2212 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2213 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2214 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2215 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2220 /***********************************************************************
2222 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2223 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2224 * This is dependent on the type of COMM port, but since it is doubtful
2225 * anybody will get around to implementing support for fancy serial
2226 * ports in WINE, this is hardcoded for the time being. The name of
2227 * this DLL should be stored in and read from the system registry in
2228 * the hive HKEY_LOCAL_MACHINE, key
2229 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2230 * where ???? is the port number... that is determined by PNP
2231 * The DLL should be loaded when the COMM port is opened, and closed
2232 * when the COMM port is closed. - MJM 20 June 2000
2233 ***********************************************************************/
2234 static WCHAR lpszSerialUI[] = {
2235 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2238 /***********************************************************************
2239 * CommConfigDialogA (KERNEL32.@)
2241 * Raises a dialog that allows the user to configure a comm port.
2242 * Fills the COMMCONFIG struct with information specified by the user.
2243 * This function should call a similar routine in the COMM driver...
2247 * TRUE on success, FALSE on failure
2248 * If successful, the lpCommConfig structure will contain a new
2249 * configuration for the comm port, as specified by the user.
2252 * The library with the CommConfigDialog code is never unloaded.
2253 * Perhaps this should be done when the comm port is closed?
2255 BOOL WINAPI CommConfigDialogA(
2256 LPCSTR lpszDevice, /* [in] name of communications device */
2257 HWND hWnd, /* [in] parent window for the dialog */
2258 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2260 FARPROC lpfnCommDialog;
2261 HMODULE hConfigModule;
2264 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2266 hConfigModule = LoadLibraryW(lpszSerialUI);
2270 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2273 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2275 FreeLibrary(hConfigModule);
2280 /***********************************************************************
2281 * CommConfigDialogW (KERNEL32.@)
2283 * see CommConfigDialogA for more info
2285 BOOL WINAPI CommConfigDialogW(
2286 LPCWSTR lpszDevice, /* [in] name of communications device */
2287 HWND hWnd, /* [in] parent window for the dialog */
2288 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2290 FARPROC lpfnCommDialog;
2291 HMODULE hConfigModule;
2294 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2296 hConfigModule = LoadLibraryW(lpszSerialUI);
2300 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2303 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2305 FreeLibrary(hConfigModule);
2310 /***********************************************************************
2311 * GetCommConfig (KERNEL32.@)
2313 * Fill in the COMMCONFIG structure for the comm port hFile
2317 * TRUE on success, FALSE on failure
2318 * If successful, lpCommConfig contains the comm port configuration.
2323 BOOL WINAPI GetCommConfig(
2324 HANDLE hFile, /* [in] The communications device. */
2325 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2326 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2327 afterwards the number of bytes copied to the buffer or
2328 the needed size of the buffer. */
2332 TRACE("(%p %p)\n",hFile,lpCommConfig);
2334 if(lpCommConfig == NULL)
2336 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2337 *lpdwSize = sizeof(COMMCONFIG);
2341 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2342 lpCommConfig->wVersion = 1;
2343 lpCommConfig->wReserved = 0;
2344 r = GetCommState(hFile,&lpCommConfig->dcb);
2345 lpCommConfig->dwProviderSubType = PST_RS232;
2346 lpCommConfig->dwProviderOffset = 0;
2347 lpCommConfig->dwProviderSize = 0;
2352 /***********************************************************************
2353 * SetCommConfig (KERNEL32.@)
2355 * Sets the configuration of the communications device.
2359 * True on success, false if the handle was bad is not a communications device.
2361 BOOL WINAPI SetCommConfig(
2362 HANDLE hFile, /* [in] The communications device. */
2363 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2364 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2366 TRACE("(%p %p)\n",hFile,lpCommConfig);
2367 return SetCommState(hFile,&lpCommConfig->dcb);
2370 /***********************************************************************
2371 * SetDefaultCommConfigA (KERNEL32.@)
2373 * Initializes the default configuration for the specified communication
2378 * True if the device was found and the defaults set, false otherwise
2380 BOOL WINAPI SetDefaultCommConfigW(
2381 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2382 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2383 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2385 FARPROC lpfnSetDefaultCommConfig;
2386 HMODULE hConfigModule;
2389 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2391 hConfigModule = LoadLibraryW(lpszSerialUI);
2395 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2396 if (lpfnSetDefaultCommConfig)
2397 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2399 FreeLibrary(hConfigModule);
2405 /***********************************************************************
2406 * SetDefaultCommConfigW (KERNEL32.@)
2408 * Initializes the default configuration for the specified
2409 * communication device. (unicode)
2414 BOOL WINAPI SetDefaultCommConfigA(
2415 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2416 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2417 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2420 LPWSTR lpDeviceW = NULL;
2423 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2427 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2428 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2429 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2431 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2432 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2437 /***********************************************************************
2438 * GetDefaultCommConfigW (KERNEL32.@)
2440 * Acquires the default configuration of the specified communication device. (unicode)
2444 * True on successful reading of the default configuration,
2445 * if the device is not found or the buffer is too small.
2447 BOOL WINAPI GetDefaultCommConfigW(
2448 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2449 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2450 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2451 afterwards the number of bytes copied to the buffer or
2452 the needed size of the buffer. */
2454 LPDCB lpdcb = &(lpCC->dcb);
2456 static const WCHAR comW[] = {'C','O','M',0};
2457 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2459 if (strncmpiW(lpszName,comW,3)) {
2460 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2464 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2465 if (*lpdwSize < sizeof(COMMCONFIG)) {
2466 *lpdwSize = sizeof(COMMCONFIG);
2470 *lpdwSize = sizeof(COMMCONFIG);
2472 lpCC->dwSize = sizeof(COMMCONFIG);
2474 lpCC->dwProviderSubType = PST_RS232;
2475 lpCC->dwProviderOffset = 0L;
2476 lpCC->dwProviderSize = 0L;
2478 sprintfW( temp, formatW, lpszName[3]);
2479 FIXME("setting %s as default\n", debugstr_w(temp));
2481 return BuildCommDCBW( temp, lpdcb);
2484 /**************************************************************************
2485 * GetDefaultCommConfigA (KERNEL32.@)
2487 * Acquires the default configuration of the specified communication device. (ascii)
2491 * True on successful reading of the default configuration,
2492 * if the device is not found or the buffer is too small.
2494 BOOL WINAPI GetDefaultCommConfigA(
2495 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2496 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2497 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2498 afterwards the number of bytes copied to the buffer or
2499 the needed size of the buffer. */
2502 UNICODE_STRING lpszNameW;
2504 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2505 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2506 else lpszNameW.Buffer = NULL;
2508 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2510 RtlFreeUnicodeString(&lpszNameW);