ntdll/kernel32: SetCommState & IOCTL_SET_LINE_CONTROL
[wine/multimedia.git] / dlls / kernel / comm.c
blobf9aeb2a851b6d51d0025e07a439a0d82e4be2449
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #ifdef HAVE_TERMIOS_H
28 #include <termios.h>
29 #endif
30 #include <fcntl.h>
31 #include <string.h>
32 #ifdef HAVE_STRINGS_H
33 # include <strings.h>
34 #endif
35 #include <errno.h>
36 #include <ctype.h>
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
39 #endif
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
42 #endif
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
45 #endif
46 #ifdef HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
49 #ifdef HAVE_SYS_POLL_H
50 # include <sys/poll.h>
51 #endif
52 #ifdef HAVE_SYS_MODEM_H
53 # include <sys/modem.h>
54 #endif
55 #ifdef HAVE_SYS_STRTIO_H
56 # include <sys/strtio.h>
57 #endif
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
61 #include "windef.h"
62 #include "winbase.h"
63 #include "winerror.h"
64 #include "winioctl.h"
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>
74 #endif
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 )
81 int fd, ret;
83 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
84 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
85 return fd;
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 );
94 /* serial_irq_info
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;
105 }serial_irq_info;
107 /***********************************************************************
108 * Data needed by the thread polling for the changing CommEvent
110 typedef struct async_commio
112 HANDLE handle;
113 char* buffer;
114 HANDLE hEvent;
115 DWORD evtmask;
116 DWORD mstat;
117 serial_irq_info irq_info;
118 } async_commio;
120 /***********************************************************************/
122 #if !defined(TIOCINQ) && defined(FIONREAD)
123 #define TIOCINQ FIONREAD
124 #endif
126 /***********************************************************************
127 * Get extended interrupt count info, needed for WaitCommEvent
129 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
131 #ifdef TIOCGICOUNT
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;
142 return 0;
144 #endif
145 memset(irq_info,0, sizeof(serial_irq_info));
146 return -1;
149 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
151 #ifdef TIOCMGET
152 unsigned int mstat, okay;
153 okay = ioctl(fd, TIOCMGET, &mstat);
154 if (okay) return okay;
155 if (andy) mstat &= andy;
156 mstat |= orrie;
157 return ioctl(fd, TIOCMSET, &mstat);
158 #else
159 return 0;
160 #endif
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))
177 ptr += 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')
182 return NULL;
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 != ' ')
189 return NULL;
191 /* Advance pointer to beginning of next parameter */
192 while(*ptr == ' ') ptr++;
193 if(*ptr == ':')
195 ptr++;
196 while(*ptr == ' ') ptr++;
199 /* The device control string must not start with a space. */
200 else if(*ptr == ' ')
201 return NULL;
203 return ptr;
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++;
211 return 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++))
222 case 'E':
223 *lpparity = EVENPARITY;
224 break;
225 case 'M':
226 *lpparity = MARKPARITY;
227 break;
228 case 'N':
229 *lpparity = NOPARITY;
230 break;
231 case 'O':
232 *lpparity = ODDPARITY;
233 break;
234 case 'S':
235 *lpparity = SPACEPARITY;
236 break;
237 default:
238 return NULL;
241 return ptr;
244 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
246 DWORD temp;
248 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
249 return NULL;
251 if(temp >= 5 && temp <= 8)
253 *lpbytesize = temp;
254 return ptr;
256 else
257 return NULL;
260 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
262 DWORD temp;
263 static const WCHAR stopbits15W[] = {'1','.','5',0};
265 if(!strncmpW(stopbits15W, ptr, 3))
267 ptr += 3;
268 *lpstopbits = ONE5STOPBITS;
270 else
272 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
273 return NULL;
275 if(temp == 1)
276 *lpstopbits = ONESTOPBIT;
277 else if(temp == 2)
278 *lpstopbits = TWOSTOPBITS;
279 else
280 return NULL;
283 return ptr;
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))
293 ptr += 2;
294 *lponoff = 1;
296 else if(!strncmpiW(offW, ptr, 3))
298 ptr += 3;
299 *lponoff = 0;
301 else
302 return NULL;
304 return ptr;
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)
314 WCHAR last = 0;
316 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
317 return FALSE;
319 switch(lpdcb->BaudRate)
321 case 11:
322 case 30:
323 case 60:
324 lpdcb->BaudRate *= 10;
325 break;
326 case 12:
327 case 24:
328 case 48:
329 case 96:
330 lpdcb->BaudRate *= 100;
331 break;
332 case 19:
333 lpdcb->BaudRate = 19200;
334 break;
337 while(*device == ' ') device++;
338 if(*device++ != ',') return FALSE;
339 while(*device == ' ') device++;
341 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
342 return FALSE;
344 while(*device == ' ') device++;
345 if(*device++ != ',') return FALSE;
346 while(*device == ' ') device++;
348 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
349 return FALSE;
351 while(*device == ' ') device++;
352 if(*device++ != ',') return FALSE;
353 while(*device == ' ') device++;
355 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
356 return FALSE;
358 /* The last parameter for flow control is optional. */
359 while(*device == ' ') device++;
360 if(*device == ',')
362 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. */
370 switch(last)
372 case 0:
373 lpdcb->fInX = FALSE;
374 lpdcb->fOutX = FALSE;
375 lpdcb->fOutxCtsFlow = FALSE;
376 lpdcb->fOutxDsrFlow = FALSE;
377 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
378 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
379 break;
380 case 'X':
381 lpdcb->fInX = TRUE;
382 lpdcb->fOutX = TRUE;
383 lpdcb->fOutxCtsFlow = FALSE;
384 lpdcb->fOutxDsrFlow = FALSE;
385 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
386 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
387 break;
388 case 'P':
389 lpdcb->fInX = FALSE;
390 lpdcb->fOutX = FALSE;
391 lpdcb->fOutxCtsFlow = TRUE;
392 lpdcb->fOutxDsrFlow = TRUE;
393 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
394 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
395 break;
396 default:
397 return FALSE;
400 /* This should be the end of the string. */
401 if(*device) return FALSE;
403 return TRUE;
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)
414 DWORD temp;
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};
428 while(*device)
430 while(*device == ' ') device++;
432 if(!strncmpiW(baudW, device, 5))
434 baud = TRUE;
436 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
437 return FALSE;
439 else if(!strncmpiW(parityW, device, 7))
441 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
442 return FALSE;
444 else if(!strncmpiW(dataW, device, 5))
446 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
447 return FALSE;
449 else if(!strncmpiW(stopW, device, 5))
451 stop = TRUE;
453 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
454 return FALSE;
456 else if(!strncmpiW(toW, device, 3))
458 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
459 return FALSE;
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)))
470 return FALSE;
472 lpdcb->fOutX = temp;
473 lpdcb->fInX = temp;
475 else if(!strncmpiW(odsrW, device, 5))
477 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
478 return FALSE;
480 lpdcb->fOutxDsrFlow = temp;
482 else if(!strncmpiW(octsW, device, 5))
484 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
485 return FALSE;
487 lpdcb->fOutxCtsFlow = temp;
489 else if(!strncmpiW(dtrW, device, 4))
491 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
492 return FALSE;
494 lpdcb->fDtrControl = temp;
496 else if(!strncmpiW(rtsW, device, 4))
498 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
499 return FALSE;
501 lpdcb->fRtsControl = temp;
503 else if(!strncmpiW(idsrW, device, 5))
505 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
506 return FALSE;
508 /* Win NT sets the fDsrSensitivity member based on the
509 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
510 lpdcb->fDsrSensitivity = temp;
512 else
513 return FALSE;
515 /* After the above parsing, the next character (if not the end of
516 the string) should be a space */
517 if(*device && *device != ' ')
518 return FALSE;
521 /* If stop bits were not specified, a default is always supplied. */
522 if(!stop)
524 if(baud && lpdcb->BaudRate == 110)
525 lpdcb->StopBits = TWOSTOPBITS;
526 else
527 lpdcb->StopBits = ONESTOPBIT;
530 return TRUE;
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.
540 * RETURNS
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.
558 * RETURNS
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. */
567 BOOL ret = FALSE;
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);
577 return ret;
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.
587 * RETURNS
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. */
596 DCB dcb;
597 COMMTIMEOUTS timeouts;
598 BOOL result;
599 LPCWSTR ptr = devid;
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);
614 if(ptr == NULL)
615 result = FALSE;
616 else if(strchrW(ptr, ','))
617 result = COMM_BuildOldCommDCB(ptr, &dcb);
618 else
619 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
621 if(result)
623 memcpy(lpdcb, &dcb, sizeof(DCB));
624 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
625 return TRUE;
627 else
629 WARN("Invalid device control string: %s\n", debugstr_w(devid));
630 SetLastError(ERROR_INVALID_PARAMETER);
631 return FALSE;
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.
642 * RETURNS
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 /*****************************************************************************
654 * SetCommBreak (KERNEL32.@)
656 * Halts the transmission of characters to a communications device.
658 * PARAMS
659 * handle [in] The communications device to suspend
661 * RETURNS
663 * True on success, and false if the communications device could not be found,
664 * the control is not supported.
666 * BUGS
668 * Only TIOCSBRK and TIOCCBRK are supported.
670 BOOL WINAPI SetCommBreak(HANDLE handle)
672 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, NULL, NULL);
675 /*****************************************************************************
676 * ClearCommBreak (KERNEL32.@)
678 * Resumes character transmission from a communication device.
680 * PARAMS
682 * handle [in] The halted communication device whose character transmission is to be resumed
684 * RETURNS
686 * True on success and false if the communications device could not be found.
688 * BUGS
690 * Only TIOCSBRK and TIOCCBRK are supported.
692 BOOL WINAPI ClearCommBreak(HANDLE handle)
694 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, NULL, NULL);
697 /*****************************************************************************
698 * EscapeCommFunction (KERNEL32.@)
700 * Directs a communication device to perform an extended function.
702 * RETURNS
704 * True or requested data on successful completion of the command,
705 * false if the device is not present cannot execute the command
706 * or the command failed.
708 BOOL WINAPI EscapeCommFunction(
709 HANDLE handle, /* [in] The communication device to perform the extended function. */
710 UINT nFunction) /* [in] The extended function to be performed. */
712 int fd,direct=FALSE,result=FALSE;
713 struct termios port;
715 TRACE("handle %p, function=%d\n", handle, nFunction);
716 fd = get_comm_fd( handle, FILE_READ_DATA );
717 if(fd<0) return FALSE;
719 if (tcgetattr(fd,&port) == -1) {
720 release_comm_fd( handle, fd );
721 return FALSE;
724 switch (nFunction) {
725 case RESETDEV:
726 TRACE("\n");
727 break;
729 case CLRDTR:
730 TRACE("CLRDTR\n");
731 #ifdef TIOCM_DTR
732 direct=TRUE;
733 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
734 break;
735 #endif
737 case CLRRTS:
738 TRACE("CLRRTS\n");
739 #ifdef TIOCM_RTS
740 direct=TRUE;
741 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
742 break;
743 #endif
745 case SETDTR:
746 TRACE("SETDTR\n");
747 #ifdef TIOCM_DTR
748 direct=TRUE;
749 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
750 break;
751 #endif
753 case SETRTS:
754 TRACE("SETRTS\n");
755 #ifdef TIOCM_RTS
756 direct=TRUE;
757 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
758 break;
759 #endif
761 case SETXOFF:
762 TRACE("SETXOFF\n");
763 port.c_iflag |= IXOFF;
764 break;
766 case SETXON:
767 TRACE("SETXON\n");
768 port.c_iflag |= IXON;
769 break;
770 case SETBREAK:
771 TRACE("setbreak\n");
772 #ifdef TIOCSBRK
773 direct=TRUE;
774 result = ioctl(fd,TIOCSBRK,0);
775 break;
776 #endif
777 case CLRBREAK:
778 TRACE("clrbreak\n");
779 #ifdef TIOCSBRK
780 direct=TRUE;
781 result = ioctl(fd,TIOCCBRK,0);
782 break;
783 #endif
784 default:
785 WARN("(handle=%p,nFunction=%d): Unknown function\n",
786 handle, nFunction);
787 break;
790 if (!direct)
791 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
792 release_comm_fd( handle, fd );
793 return FALSE;
794 } else
795 result= TRUE;
796 else
798 if (result == -1)
800 result= FALSE;
802 else
803 result = TRUE;
805 release_comm_fd( handle, fd );
806 return result;
809 /********************************************************************
810 * PurgeComm (KERNEL32.@)
812 * Terminates pending operations and/or discards buffers on a
813 * communication resource.
815 * PARAMS
817 * handle [in] The communication resource to be purged
818 * flags [in] Flags for clear pending/buffer on input/output
820 * RETURNS
822 * True on success and false if the communications handle is bad.
824 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
826 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
827 NULL, 0, NULL, NULL);
830 /*****************************************************************************
831 * ClearCommError (KERNEL32.@)
833 * Enables further I/O operations on a communications resource after
834 * supplying error and current status information.
836 * PARAMS
838 * handle [in] The communication resource with the error
839 * errors [out] Flags indicating error the resource experienced
840 * lpStat [out] The status of the communication resource
841 * RETURNS
843 * True on success, false if the communication resource handle is bad.
845 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
847 SERIAL_STATUS ss;
849 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
850 &ss, sizeof(ss), NULL, NULL))
851 return FALSE;
853 if (errors)
855 *errors = 0;
856 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK;
857 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME;
858 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN;
859 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER;
860 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY;
863 if (lpStat)
865 memset(lpStat, 0, sizeof(*lpStat));
867 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE;
868 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE;
869 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE;
870 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE;
871 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE;
872 if (ss.EofReceived) lpStat->fEof = TRUE;
873 if (ss.WaitForImmediate) lpStat->fTxim = TRUE;
874 lpStat->cbInQue = ss.AmountInInQueue;
875 lpStat->cbOutQue = ss.AmountInOutQueue;
877 return TRUE;
880 /*****************************************************************************
881 * SetupComm (KERNEL32.@)
883 * Called after CreateFile to hint to the communication resource to use
884 * specified sizes for input and output buffers rather than the default values.
886 * RETURNS
888 * True if successful, false if the communications resource handle is bad.
890 * BUGS
892 * Stub.
894 BOOL WINAPI SetupComm(
895 HANDLE handle, /* [in] The just created communication resource handle. */
896 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
897 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
899 int fd;
901 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
902 fd=get_comm_fd( handle, FILE_READ_DATA );
903 if(0>fd) return FALSE;
904 release_comm_fd( handle, fd );
905 return TRUE;
908 /*****************************************************************************
909 * GetCommMask (KERNEL32.@)
911 * Obtain the events associated with a communication device that will cause
912 * a call WaitCommEvent to return.
914 * PARAMS
916 * handle [in] The communications device
917 * evtmask [out] The events which cause WaitCommEvent to return
919 * RETURNS
921 * True on success, fail on bad device handle etc.
923 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
925 TRACE("handle %p, mask %p\n", handle, evtmask);
926 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
927 NULL, 0, evtmask, sizeof(*evtmask), NULL, NULL);
930 /*****************************************************************************
931 * SetCommMask (KERNEL32.@)
933 * There be some things we need to hear about yon there communications device.
934 * (Set which events associated with a communication device should cause
935 * a call WaitCommEvent to return.)
937 * PARAMS
939 * handle [in] The communications device
940 * evtmask [in] The events that are to be monitored
942 * RETURNS
944 * True on success, false on bad handle etc.
946 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
948 TRACE("handle %p, mask %lx\n", handle, evtmask);
949 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
950 &evtmask, sizeof(evtmask), NULL, 0, NULL, NULL);
953 static void dump_dcb(const DCB* lpdcb)
955 TRACE("bytesize=%d baudrate=%ld fParity=%d Parity=%d stopbits=%d\n",
956 lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity,
957 (lpdcb->StopBits == ONESTOPBIT) ? 1 :
958 (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0);
959 TRACE("%sIXON %sIXOFF\n", (lpdcb->fInX) ? "" : "~", (lpdcb->fOutX) ? "" : "~");
960 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl);
961 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl);
962 if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE)
963 TRACE("CRTSCTS\n");
964 else
965 TRACE("~CRTSCTS\n");
968 /*****************************************************************************
969 * SetCommState (KERNEL32.@)
971 * Re-initializes all hardware and control settings of a communications device,
972 * with values from a device control block without effecting the input and output
973 * queues.
975 * PARAMS
977 * handle [in] The communications device
978 * lpdcb [out] The device control block
980 * RETURNS
982 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
984 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
986 struct termios port;
987 int fd;
988 BOOL ret;
990 SERIAL_BAUD_RATE sbr;
991 SERIAL_LINE_CONTROL slc;
993 if (lpdcb == NULL)
995 SetLastError(ERROR_INVALID_PARAMETER);
996 return FALSE;
998 dump_dcb(lpdcb);
1000 sbr.BaudRate = lpdcb->BaudRate;
1002 slc.StopBits = lpdcb->StopBits;
1003 slc.Parity = lpdcb->Parity;
1004 slc.WordLength = lpdcb->ByteSize;
1006 if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
1007 &sbr, sizeof(sbr), NULL, 0, NULL, NULL))
1008 return FALSE;
1009 if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
1010 &slc, sizeof(slc), NULL, 0, NULL, NULL))
1011 return FALSE;
1013 fd = get_comm_fd( handle, FILE_READ_DATA );
1014 if (fd < 0) return FALSE;
1016 if ((tcgetattr(fd,&port)) == -1) {
1017 int save_error = errno;
1018 release_comm_fd( handle, fd );
1019 ERR("tcgetattr error '%s'\n", strerror(save_error));
1020 return FALSE;
1023 port.c_cc[VMIN] = 0;
1024 port.c_cc[VTIME] = 1;
1026 #ifdef CRTSCTS
1027 if ( lpdcb->fOutxCtsFlow ||
1028 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1031 port.c_cflag |= CRTSCTS;
1032 TRACE("CRTSCTS\n");
1034 #endif
1036 if (lpdcb->fInX)
1037 port.c_iflag |= IXON;
1038 else
1039 port.c_iflag &= ~IXON;
1040 if (lpdcb->fOutX)
1041 port.c_iflag |= IXOFF;
1042 else
1043 port.c_iflag &= ~IXOFF;
1045 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1046 ERR("tcsetattr error '%s'\n", strerror(errno));
1047 ret = FALSE;
1048 } else {
1049 ClearCommError(handle, NULL, NULL);
1050 ret = TRUE;
1053 /* note: change DTR/RTS lines after setting the comm attributes,
1054 * so flow control does not interfere. */
1055 #ifdef TIOCM_DTR
1056 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1058 WARN("DSR/DTR flow control not supported\n");
1059 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1060 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1061 else
1062 COMM_WhackModem(fd, 0, TIOCM_DTR);
1063 #endif
1064 #ifdef TIOCM_RTS
1065 if(!lpdcb->fOutxCtsFlow )
1067 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1068 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1069 else
1070 COMM_WhackModem(fd, 0, TIOCM_RTS);
1072 #endif
1073 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1074 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1075 release_comm_fd( handle, fd );
1076 return ret;
1081 /*****************************************************************************
1082 * GetCommState (KERNEL32.@)
1084 * Fills in a device control block with information from a communications device.
1086 * RETURNS
1088 * True on success, false if the communication device handle is bad etc
1090 * BUGS
1092 * XonChar and XoffChar are not set.
1094 BOOL WINAPI GetCommState(
1095 HANDLE handle, /* [in] The communications device. */
1096 LPDCB lpdcb) /* [out] The device control block. */
1098 struct termios port;
1099 int fd,speed;
1100 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1102 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1104 fd = get_comm_fd( handle, FILE_READ_DATA );
1105 if (fd < 0) return FALSE;
1106 if (tcgetattr(fd, &port) == -1) {
1107 int save_error=errno;
1108 ERR("tcgetattr error '%s'\n", strerror(save_error));
1109 release_comm_fd( handle, fd );
1110 return FALSE;
1113 #ifdef TIOCMGET
1114 if (ioctl(fd, TIOCMGET, &stat) == -1)
1116 int save_error=errno;
1117 WARN("ioctl error '%s'\n", strerror(save_error));
1118 stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1120 #endif
1121 release_comm_fd( handle, fd );
1122 #ifndef __EMX__
1123 #ifdef CBAUD
1124 speed= (port.c_cflag & CBAUD);
1125 #else
1126 speed= (cfgetospeed(&port));
1127 #endif
1128 switch (speed) {
1129 case B0:
1130 lpdcb->BaudRate = 0;
1131 break;
1132 case B50:
1133 lpdcb->BaudRate = 50;
1134 break;
1135 case B75:
1136 lpdcb->BaudRate = 75;
1137 break;
1138 case B110:
1139 lpdcb->BaudRate = 110;
1140 break;
1141 case B134:
1142 lpdcb->BaudRate = 134;
1143 break;
1144 case B150:
1145 lpdcb->BaudRate = 150;
1146 break;
1147 case B200:
1148 lpdcb->BaudRate = 200;
1149 break;
1150 case B300:
1151 lpdcb->BaudRate = 300;
1152 break;
1153 case B600:
1154 lpdcb->BaudRate = 600;
1155 break;
1156 case B1200:
1157 lpdcb->BaudRate = 1200;
1158 break;
1159 case B1800:
1160 lpdcb->BaudRate = 1800;
1161 break;
1162 case B2400:
1163 lpdcb->BaudRate = 2400;
1164 break;
1165 case B4800:
1166 lpdcb->BaudRate = 4800;
1167 break;
1168 case B9600:
1169 lpdcb->BaudRate = 9600;
1170 break;
1171 case B19200:
1172 lpdcb->BaudRate = 19200;
1173 break;
1174 case B38400:
1175 lpdcb->BaudRate = 38400;
1176 break;
1177 #ifdef B57600
1178 case B57600:
1179 lpdcb->BaudRate = 57600;
1180 break;
1181 #endif
1182 #ifdef B115200
1183 case B115200:
1184 lpdcb->BaudRate = 115200;
1185 break;
1186 #endif
1187 #ifdef B230400
1188 case B230400:
1189 lpdcb->BaudRate = 230400;
1190 break;
1191 #endif
1192 #ifdef B460800
1193 case B460800:
1194 lpdcb->BaudRate = 460800;
1195 break;
1196 #endif
1197 default:
1198 ERR("unknown speed %x\n", speed);
1200 #endif
1201 switch (port.c_cflag & CSIZE) {
1202 case CS5:
1203 lpdcb->ByteSize = 5;
1204 break;
1205 case CS6:
1206 lpdcb->ByteSize = 6;
1207 break;
1208 case CS7:
1209 lpdcb->ByteSize = 7;
1210 break;
1211 case CS8:
1212 lpdcb->ByteSize = 8;
1213 break;
1214 default:
1215 ERR("unknown size %x\n", port.c_cflag & CSIZE);
1218 if(port.c_iflag & INPCK)
1219 lpdcb->fParity = TRUE;
1220 else
1221 lpdcb->fParity = FALSE;
1222 #ifdef CMSPAR
1223 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1224 #else
1225 switch (port.c_cflag & (PARENB | PARODD))
1226 #endif
1228 case 0:
1229 lpdcb->Parity = NOPARITY;
1230 break;
1231 case PARENB:
1232 lpdcb->Parity = EVENPARITY;
1233 break;
1234 case (PARENB | PARODD):
1235 lpdcb->Parity = ODDPARITY;
1236 break;
1237 #ifdef CMSPAR
1238 case (PARENB | CMSPAR):
1239 lpdcb->Parity = MARKPARITY;
1240 break;
1241 case (PARENB | PARODD | CMSPAR):
1242 lpdcb->Parity = SPACEPARITY;
1243 break;
1244 #endif
1247 if (port.c_cflag & CSTOPB)
1248 if(lpdcb->ByteSize == 5)
1249 lpdcb->StopBits = ONE5STOPBITS;
1250 else
1251 lpdcb->StopBits = TWOSTOPBITS;
1252 else
1253 lpdcb->StopBits = ONESTOPBIT;
1255 lpdcb->fNull = 0;
1256 lpdcb->fBinary = 1;
1258 /* termios does not support DTR/DSR flow control */
1259 lpdcb->fOutxDsrFlow = 0;
1260 lpdcb->fDtrControl =
1261 #ifdef TIOCM_DTR
1262 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1263 #endif
1264 DTR_CONTROL_ENABLE ;
1266 #ifdef CRTSCTS
1268 if (port.c_cflag & CRTSCTS) {
1269 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1270 lpdcb->fOutxCtsFlow = 1;
1271 } else
1272 #endif
1274 lpdcb->fRtsControl =
1275 #ifdef TIOCM_RTS
1276 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1277 #endif
1278 RTS_CONTROL_ENABLE ;
1279 lpdcb->fOutxCtsFlow = 0;
1281 if (port.c_iflag & IXON)
1282 lpdcb->fInX = 1;
1283 else
1284 lpdcb->fInX = 0;
1286 if (port.c_iflag & IXOFF)
1287 lpdcb->fOutX = 1;
1288 else
1289 lpdcb->fOutX = 0;
1291 lpdcb->XonChar =
1292 lpdcb->XoffChar =
1294 lpdcb->XonLim = 10;
1295 lpdcb->XoffLim = 10;
1297 TRACE("OK\n");
1299 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1300 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1301 (lpdcb->StopBits == ONESTOPBIT)?1:
1302 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1303 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1304 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1305 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1306 lpdcb->fRtsControl);
1307 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1308 lpdcb->fDtrControl);
1309 #ifdef CRTSCTS
1310 if ( lpdcb->fOutxCtsFlow ||
1311 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1313 TRACE("CRTSCTS\n");
1314 else
1316 TRACE("~CRTSCTS\n");
1317 #endif
1318 return TRUE;
1321 /*****************************************************************************
1322 * TransmitCommChar (KERNEL32.@)
1324 * Transmits a single character in front of any pending characters in the
1325 * output buffer. Usually used to send an interrupt character to a host.
1327 * PARAMS
1328 * hComm [in] The communication device in need of a command character
1329 * chTransmit [in] The character to transmit
1331 * RETURNS
1333 * True if the call succeeded, false if the previous command character to the
1334 * same device has not been sent yet the handle is bad etc.
1337 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
1339 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
1340 &chTransmit, sizeof(chTransmit), NULL, 0, NULL, NULL);
1344 /*****************************************************************************
1345 * GetCommTimeouts (KERNEL32.@)
1347 * Obtains the request timeout values for the communications device.
1349 * RETURNS
1351 * True on success, false if communications device handle is bad
1352 * or the target structure is null.
1354 BOOL WINAPI GetCommTimeouts(
1355 HANDLE hComm, /* [in] The communications device. */
1356 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1358 BOOL ret;
1360 TRACE("(%p,%p)\n",hComm,lptimeouts);
1362 if(!lptimeouts)
1364 SetLastError(ERROR_INVALID_PARAMETER);
1365 return FALSE;
1368 SERVER_START_REQ( get_serial_info )
1370 req->handle = hComm;
1371 if ((ret = !wine_server_call_err( req )))
1373 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1374 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1375 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1376 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1377 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1380 SERVER_END_REQ;
1381 return ret;
1384 /*****************************************************************************
1385 * SetCommTimeouts (KERNEL32.@)
1387 * Sets the timeouts used when reading and writing data to/from COMM ports.
1389 * ReadIntervalTimeout
1390 * - converted and passes to linux kernel as c_cc[VTIME]
1391 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1392 * - used in ReadFile to calculate GetOverlappedResult's timeout
1393 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1394 * - used in WriteFile to calculate GetOverlappedResult's timeout
1396 * RETURNS
1398 * True if the timeouts were set, false otherwise.
1400 BOOL WINAPI SetCommTimeouts(
1401 HANDLE hComm, /* [in] handle of COMM device */
1402 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1404 BOOL ret;
1405 int fd;
1406 struct termios tios;
1408 TRACE("(%p,%p)\n",hComm,lptimeouts);
1410 if(!lptimeouts)
1412 SetLastError(ERROR_INVALID_PARAMETER);
1413 return FALSE;
1416 SERVER_START_REQ( set_serial_info )
1418 req->handle = hComm;
1419 req->flags = SERIALINFO_SET_TIMEOUTS;
1420 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1421 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1422 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1423 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1424 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1425 ret = !wine_server_call_err( req );
1427 SERVER_END_REQ;
1428 if (!ret) return FALSE;
1430 /* FIXME: move this stuff to the server */
1431 fd = get_comm_fd( hComm, FILE_READ_DATA );
1432 if (fd < 0) return FALSE;
1434 if (-1==tcgetattr(fd,&tios)) {
1435 FIXME("tcgetattr on fd %d failed!\n",fd);
1436 release_comm_fd( hComm, fd );
1437 return FALSE;
1440 /* VTIME is in 1/10 seconds */
1442 unsigned int ux_timeout;
1444 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1446 ux_timeout = 0;
1448 else
1450 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1451 if(ux_timeout == 0)
1453 ux_timeout = 1; /* must be at least some timeout */
1456 tios.c_cc[VTIME] = ux_timeout;
1459 if (-1==tcsetattr(fd,0,&tios)) {
1460 FIXME("tcsetattr on fd %d failed!\n",fd);
1461 release_comm_fd( hComm, fd );
1462 return FALSE;
1464 release_comm_fd( hComm, fd );
1465 return TRUE;
1468 /***********************************************************************
1469 * GetCommModemStatus (KERNEL32.@)
1471 * Obtains the four control register bits if supported by the hardware.
1473 * PARAMS
1475 * hFile [in] The communications device
1476 * lpModemStat [out] The control register bits
1478 * RETURNS
1480 * True if the communications handle was good and for hardware that
1481 * control register access, false otherwise.
1483 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1485 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1486 NULL, 0, lpModemStat, sizeof(DWORD), NULL, NULL);
1489 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1491 DWORD ret = 0, queue;
1493 TRACE("mask 0x%08lx\n", mask);
1494 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old->rx, new->rx);
1495 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old->tx, new->tx);
1496 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old->frame, new->frame);
1497 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old->overrun, new->overrun);
1498 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old->parity, new->parity);
1499 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old->brk, new->brk);
1500 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1502 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1503 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1504 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1505 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1506 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1507 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1508 || (old->parity != new->parity)) )?EV_ERR :0;
1509 if (mask & EV_RXCHAR)
1511 queue = 0;
1512 #ifdef TIOCINQ
1513 if(ioctl(fd, TIOCINQ, &queue))
1514 WARN("TIOCINQ returned error\n");
1515 #endif
1516 if (queue)
1517 ret |= EV_RXCHAR;
1519 if (mask & EV_TXEMPTY)
1521 queue = 0;
1522 /* We really want to know when all characters have gone out of the transmitter */
1523 #if defined(TIOCSERGETLSR)
1524 if(ioctl(fd, TIOCSERGETLSR, &queue))
1525 WARN("TIOCSERGETLSR returned error\n");
1526 if (queue)
1527 /* TIOCINQ only checks for an empty buffer */
1528 #elif defined(TIOCINQ)
1529 if(ioctl(fd, TIOCOUTQ, &queue))
1530 WARN("TIOCOUTQ returned error\n");
1531 if (!queue)
1532 #endif
1533 ret |= EV_TXEMPTY;
1535 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1536 return ret;
1540 /***********************************************************************
1541 * COMM_WaitCommEventService (INTERNAL)
1543 * We need to poll for what is interesting
1544 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1547 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1549 async_commio *commio = (async_commio*) arg;
1550 int waitmask = 0;
1551 int rc, fd, abort;
1552 serial_irq_info new_irq_info;
1553 DWORD new_mstat, new_evtmask;
1555 fd=get_comm_fd( commio->handle, FILE_READ_DATA );
1557 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1558 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1562 * TIOCMIWAIT is not adequate
1564 * FIXME:
1565 * We don't handle the EV_RXFLAG (the eventchar)
1567 Sleep(1);
1568 rc= COMM_GetEInfo(fd,&new_irq_info);
1569 if (rc)
1570 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1571 rc = GetCommModemStatus(commio->handle, &new_mstat);
1572 if (!rc)
1573 TRACE("GetCommModemStatus failed\n");
1574 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1575 GetCommMask(commio->handle, &new_evtmask);
1576 abort = (commio->evtmask != new_evtmask);
1577 TRACE("resulting Eventmask 0x%08x\n", rc);
1578 } while (!rc && ! abort);
1579 if (abort) rc = 0;
1580 release_comm_fd( commio->handle, fd );
1581 *commio->buffer = rc;
1582 if (commio->hEvent != INVALID_HANDLE_VALUE )
1583 NtSetEvent( commio->hEvent, NULL );
1584 HeapFree(GetProcessHeap(), 0, commio );
1585 return 0;
1589 /***********************************************************************
1590 * COMM_WaitCommEvent (INTERNAL)
1592 * This function must have an lpOverlapped.
1594 static BOOL COMM_WaitCommEvent(
1595 HANDLE hFile, /* [in] handle of comm port to wait for */
1596 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1597 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1599 int fd;
1600 async_commio* commio;
1601 DWORD result_mask;
1602 BOOL res;
1604 if (!lpOverlapped)
1606 SetLastError(ERROR_INVALID_PARAMETER);
1607 return FALSE;
1610 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1611 return FALSE;
1613 fd = get_comm_fd( hFile, FILE_WRITE_DATA );
1614 if (fd < 0) return FALSE;
1616 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1617 if (!commio)
1619 release_comm_fd( hFile, fd );
1620 return FALSE;
1623 commio->handle = hFile;
1624 commio->buffer = (char *)lpdwEvents;
1625 commio->hEvent = lpOverlapped->hEvent;
1626 GetCommMask(hFile, &commio->evtmask);
1628 /* We may never return, if some capabilities miss
1629 * Return error in that case
1631 #if !defined(TIOCINQ)
1632 if(commio->evtmask & EV_RXCHAR)
1633 goto error;
1634 #endif
1635 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1636 if(commio->evtmask & EV_TXEMPTY)
1637 goto error;
1638 #endif
1639 #if !defined(TIOCMGET)
1640 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
1641 goto error;
1642 #endif
1643 #if !defined(TIOCM_CTS)
1644 if(commio->evtmask & EV_CTS)
1645 goto error;
1646 #endif
1647 #if !defined(TIOCM_DSR)
1648 if(commio->evtmask & EV_DSR)
1649 goto error;
1650 #endif
1651 #if !defined(TIOCM_RNG)
1652 if(commio->evtmask & EV_RING)
1653 goto error;
1654 #endif
1655 #if !defined(TIOCM_CAR)
1656 if(commio->evtmask & EV_RLSD)
1657 goto error;
1658 #endif
1659 if(commio->evtmask & EV_RXFLAG)
1660 FIXME("EV_RXFLAG not handled\n");
1661 COMM_GetEInfo(fd,&commio->irq_info);
1662 GetCommModemStatus(hFile, &commio->mstat);
1663 /* We might have received something or the TX bufffer is delivered*/
1664 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
1665 if (result_mask)
1667 TRACE("Event already met\n");
1668 *lpdwEvents = result_mask;
1669 HeapFree(GetProcessHeap(), 0, commio );
1670 res = TRUE;
1672 else
1674 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
1675 SetLastError(ERROR_IO_PENDING);
1676 res = FALSE;
1678 release_comm_fd( hFile, fd );
1679 return res;
1680 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
1681 error:
1682 FIXME("Returning error because of missing capabilities\n");
1683 release_comm_fd( hFile, fd );
1684 HeapFree(GetProcessHeap(), 0, commio );
1685 SetLastError(ERROR_INVALID_PARAMETER);
1686 return FALSE;
1687 #endif
1689 /***********************************************************************
1690 * WaitCommEvent (KERNEL32.@)
1692 * Wait until something interesting happens on a COMM port.
1693 * Interesting things (events) are set by calling SetCommMask before
1694 * this function is called.
1696 * RETURNS
1697 * TRUE if successful
1698 * FALSE if failure
1700 * The set of detected events will be written to *lpdwEventMask
1701 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1703 * BUGS:
1704 * Only supports EV_RXCHAR and EV_TXEMPTY
1706 BOOL WINAPI WaitCommEvent(
1707 HANDLE hFile, /* [in] handle of comm port to wait for */
1708 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1709 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1711 OVERLAPPED ov;
1712 int ret = 0;
1713 DWORD res, err;
1715 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1717 if(lpOverlapped)
1718 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1720 /* if there is no overlapped structure, create our own */
1721 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
1723 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1724 err = GetLastError();
1725 if (!res)
1727 if (err == ERROR_IO_PENDING)
1731 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
1732 } while (res != WAIT_OBJECT_0);
1733 TRACE("Event met\n:");
1734 ret = TRUE;
1736 else
1738 FIXME("Unknown error 0x%08lx\n", err);
1739 ret = FALSE;
1742 else
1743 ret = TRUE;
1744 CloseHandle(ov.hEvent);
1746 return ret;
1749 /***********************************************************************
1750 * GetCommProperties (KERNEL32.@)
1752 * This function fills in a structure with the capabilities of the
1753 * communications port driver.
1755 * RETURNS
1757 * TRUE on success, FALSE on failure
1758 * If successful, the lpCommProp structure be filled in with
1759 * properties of the comm port.
1761 BOOL WINAPI GetCommProperties(
1762 HANDLE hFile, /* [in] handle of the comm port */
1763 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1765 FIXME("(%p %p )\n",hFile,lpCommProp);
1766 if(!lpCommProp)
1767 return FALSE;
1770 * These values should be valid for LINUX's serial driver
1771 * FIXME: Perhaps they deserve an #ifdef LINUX
1773 memset(lpCommProp,0,sizeof(COMMPROP));
1774 lpCommProp->wPacketLength = 1;
1775 lpCommProp->wPacketVersion = 1;
1776 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1777 lpCommProp->dwReserved1 = 0;
1778 lpCommProp->dwMaxTxQueue = 4096;
1779 lpCommProp->dwMaxRxQueue = 4096;
1780 lpCommProp->dwMaxBaud = BAUD_115200;
1781 lpCommProp->dwProvSubType = PST_RS232;
1782 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1783 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1784 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1785 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1786 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1787 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1788 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1789 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1790 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1791 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1792 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1794 return TRUE;
1797 /***********************************************************************
1798 * FIXME:
1799 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1800 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1801 * This is dependent on the type of COMM port, but since it is doubtful
1802 * anybody will get around to implementing support for fancy serial
1803 * ports in WINE, this is hardcoded for the time being. The name of
1804 * this DLL should be stored in and read from the system registry in
1805 * the hive HKEY_LOCAL_MACHINE, key
1806 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1807 * where ???? is the port number... that is determined by PNP
1808 * The DLL should be loaded when the COMM port is opened, and closed
1809 * when the COMM port is closed. - MJM 20 June 2000
1810 ***********************************************************************/
1811 static const WCHAR lpszSerialUI[] = {
1812 's','e','r','i','a','l','u','i','.','d','l','l',0 };
1815 /***********************************************************************
1816 * CommConfigDialogA (KERNEL32.@)
1818 * Raises a dialog that allows the user to configure a comm port.
1819 * Fills the COMMCONFIG struct with information specified by the user.
1820 * This function should call a similar routine in the COMM driver...
1822 * RETURNS
1824 * TRUE on success, FALSE on failure
1825 * If successful, the lpCommConfig structure will contain a new
1826 * configuration for the comm port, as specified by the user.
1828 * BUGS
1829 * The library with the CommConfigDialog code is never unloaded.
1830 * Perhaps this should be done when the comm port is closed?
1832 BOOL WINAPI CommConfigDialogA(
1833 LPCSTR lpszDevice, /* [in] name of communications device */
1834 HWND hWnd, /* [in] parent window for the dialog */
1835 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1837 FARPROC lpfnCommDialog;
1838 HMODULE hConfigModule;
1839 BOOL r = FALSE;
1841 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1843 hConfigModule = LoadLibraryW(lpszSerialUI);
1844 if(!hConfigModule)
1845 return FALSE;
1847 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
1849 if(lpfnCommDialog)
1850 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1852 FreeLibrary(hConfigModule);
1854 return r;
1857 /***********************************************************************
1858 * CommConfigDialogW (KERNEL32.@)
1860 * See CommConfigDialogA.
1862 BOOL WINAPI CommConfigDialogW(
1863 LPCWSTR lpszDevice, /* [in] name of communications device */
1864 HWND hWnd, /* [in] parent window for the dialog */
1865 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1867 FARPROC lpfnCommDialog;
1868 HMODULE hConfigModule;
1869 BOOL r = FALSE;
1871 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1873 hConfigModule = LoadLibraryW(lpszSerialUI);
1874 if(!hConfigModule)
1875 return FALSE;
1877 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
1879 if(lpfnCommDialog)
1880 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1882 FreeLibrary(hConfigModule);
1884 return r;
1887 /***********************************************************************
1888 * GetCommConfig (KERNEL32.@)
1890 * Fill in the COMMCONFIG structure for the comm port hFile
1892 * RETURNS
1894 * TRUE on success, FALSE on failure
1895 * If successful, lpCommConfig contains the comm port configuration.
1897 * BUGS
1900 BOOL WINAPI GetCommConfig(
1901 HANDLE hFile, /* [in] The communications device. */
1902 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1903 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1904 afterwards the number of bytes copied to the buffer or
1905 the needed size of the buffer. */
1907 BOOL r;
1909 TRACE("(%p %p)\n",hFile,lpCommConfig);
1911 if(lpCommConfig == NULL)
1912 return FALSE;
1913 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
1914 *lpdwSize = sizeof(COMMCONFIG);
1915 if(r)
1916 return FALSE;
1918 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1919 lpCommConfig->wVersion = 1;
1920 lpCommConfig->wReserved = 0;
1921 r = GetCommState(hFile,&lpCommConfig->dcb);
1922 lpCommConfig->dwProviderSubType = PST_RS232;
1923 lpCommConfig->dwProviderOffset = 0;
1924 lpCommConfig->dwProviderSize = 0;
1926 return r;
1929 /***********************************************************************
1930 * SetCommConfig (KERNEL32.@)
1932 * Sets the configuration of the communications device.
1934 * RETURNS
1936 * True on success, false if the handle was bad is not a communications device.
1938 BOOL WINAPI SetCommConfig(
1939 HANDLE hFile, /* [in] The communications device. */
1940 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1941 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1943 TRACE("(%p %p)\n",hFile,lpCommConfig);
1944 return SetCommState(hFile,&lpCommConfig->dcb);
1947 /***********************************************************************
1948 * SetDefaultCommConfigA (KERNEL32.@)
1950 * Initializes the default configuration for the specified communication
1951 * device. (ascii)
1953 * RETURNS
1955 * True if the device was found and the defaults set, false otherwise
1957 BOOL WINAPI SetDefaultCommConfigW(
1958 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1959 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1960 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1962 FARPROC lpfnSetDefaultCommConfig;
1963 HMODULE hConfigModule;
1964 BOOL r = FALSE;
1966 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1968 hConfigModule = LoadLibraryW(lpszSerialUI);
1969 if(!hConfigModule)
1970 return r;
1972 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
1973 if (lpfnSetDefaultCommConfig)
1974 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1976 FreeLibrary(hConfigModule);
1978 return r;
1982 /***********************************************************************
1983 * SetDefaultCommConfigW (KERNEL32.@)
1985 * Initializes the default configuration for the specified
1986 * communication device. (unicode)
1988 * RETURNS
1991 BOOL WINAPI SetDefaultCommConfigA(
1992 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
1993 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1994 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1996 BOOL r;
1997 LPWSTR lpDeviceW = NULL;
1998 DWORD len;
2000 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2002 if (lpszDevice)
2004 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2005 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2006 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2008 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2009 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2010 return r;
2014 /***********************************************************************
2015 * GetDefaultCommConfigW (KERNEL32.@)
2017 * Acquires the default configuration of the specified communication device. (unicode)
2019 * RETURNS
2021 * True on successful reading of the default configuration,
2022 * if the device is not found or the buffer is too small.
2024 BOOL WINAPI GetDefaultCommConfigW(
2025 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2026 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2027 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2028 afterwards the number of bytes copied to the buffer or
2029 the needed size of the buffer. */
2031 LPDCB lpdcb = &(lpCC->dcb);
2032 WCHAR temp[40];
2033 static const WCHAR comW[] = {'C','O','M',0};
2034 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2036 if (strncmpiW(lpszName,comW,3)) {
2037 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2038 return FALSE;
2041 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2042 if (*lpdwSize < sizeof(COMMCONFIG)) {
2043 *lpdwSize = sizeof(COMMCONFIG);
2044 return FALSE;
2047 *lpdwSize = sizeof(COMMCONFIG);
2049 lpCC->dwSize = sizeof(COMMCONFIG);
2050 lpCC->wVersion = 1;
2051 lpCC->dwProviderSubType = PST_RS232;
2052 lpCC->dwProviderOffset = 0L;
2053 lpCC->dwProviderSize = 0L;
2055 sprintfW( temp, formatW, lpszName[3]);
2056 FIXME("setting %s as default\n", debugstr_w(temp));
2058 return BuildCommDCBW( temp, lpdcb);
2061 /**************************************************************************
2062 * GetDefaultCommConfigA (KERNEL32.@)
2064 * Acquires the default configuration of the specified communication device. (ascii)
2066 * RETURNS
2068 * True on successful reading of the default configuration,
2069 * if the device is not found or the buffer is too small.
2071 BOOL WINAPI GetDefaultCommConfigA(
2072 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2073 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2074 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2075 afterwards the number of bytes copied to the buffer or
2076 the needed size of the buffer. */
2078 BOOL ret = FALSE;
2079 UNICODE_STRING lpszNameW;
2081 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2082 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2083 else lpszNameW.Buffer = NULL;
2085 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2087 RtlFreeUnicodeString(&lpszNameW);
2088 return ret;