usp10: Update tests in test_ScriptItemIzeShapePlace to match Windows results.
[wine/multimedia.git] / dlls / kernel / comm.c
blob74b22648eba291bccfff4e28761154b69cc28d6d
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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;
150 /***********************************************************************
151 * COMM_Parse* (Internal)
153 * The following COMM_Parse* functions are used by the BuildCommDCB
154 * functions to help parse the various parts of the device control string.
156 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
158 static const WCHAR comW[] = {'C','O','M',0};
160 /* The device control string may optionally start with "COMx" followed
161 by an optional ':' and spaces. */
162 if(!strncmpiW(ptr, comW, 3))
164 ptr += 3;
166 /* Allow any com port above 0 as Win 9x does (NT only allows
167 values for com ports which are actually present) */
168 if(*ptr < '1' || *ptr > '9')
169 return NULL;
171 /* Advance pointer past port number */
172 while(*ptr >= '0' && *ptr <= '9') ptr++;
174 /* The com port number must be followed by a ':' or ' ' */
175 if(*ptr != ':' && *ptr != ' ')
176 return NULL;
178 /* Advance pointer to beginning of next parameter */
179 while(*ptr == ' ') ptr++;
180 if(*ptr == ':')
182 ptr++;
183 while(*ptr == ' ') ptr++;
186 /* The device control string must not start with a space. */
187 else if(*ptr == ' ')
188 return NULL;
190 return ptr;
193 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
195 if(*ptr < '0' || *ptr > '9') return NULL;
196 *lpnumber = strtoulW(ptr, NULL, 10);
197 while(*ptr >= '0' && *ptr <= '9') ptr++;
198 return ptr;
201 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
203 /* Contrary to what you might expect, Windows only sets the Parity
204 member of DCB and not fParity even when parity is specified in the
205 device control string */
207 switch(toupperW(*ptr++))
209 case 'E':
210 *lpparity = EVENPARITY;
211 break;
212 case 'M':
213 *lpparity = MARKPARITY;
214 break;
215 case 'N':
216 *lpparity = NOPARITY;
217 break;
218 case 'O':
219 *lpparity = ODDPARITY;
220 break;
221 case 'S':
222 *lpparity = SPACEPARITY;
223 break;
224 default:
225 return NULL;
228 return ptr;
231 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
233 DWORD temp;
235 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
236 return NULL;
238 if(temp >= 5 && temp <= 8)
240 *lpbytesize = temp;
241 return ptr;
243 else
244 return NULL;
247 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
249 DWORD temp;
250 static const WCHAR stopbits15W[] = {'1','.','5',0};
252 if(!strncmpW(stopbits15W, ptr, 3))
254 ptr += 3;
255 *lpstopbits = ONE5STOPBITS;
257 else
259 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
260 return NULL;
262 if(temp == 1)
263 *lpstopbits = ONESTOPBIT;
264 else if(temp == 2)
265 *lpstopbits = TWOSTOPBITS;
266 else
267 return NULL;
270 return ptr;
273 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
275 static const WCHAR onW[] = {'o','n',0};
276 static const WCHAR offW[] = {'o','f','f',0};
278 if(!strncmpiW(onW, ptr, 2))
280 ptr += 2;
281 *lponoff = 1;
283 else if(!strncmpiW(offW, ptr, 3))
285 ptr += 3;
286 *lponoff = 0;
288 else
289 return NULL;
291 return ptr;
294 /***********************************************************************
295 * COMM_BuildOldCommDCB (Internal)
297 * Build a DCB using the old style settings string eg: "96,n,8,1"
299 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
301 WCHAR last = 0;
303 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
304 return FALSE;
306 switch(lpdcb->BaudRate)
308 case 11:
309 case 30:
310 case 60:
311 lpdcb->BaudRate *= 10;
312 break;
313 case 12:
314 case 24:
315 case 48:
316 case 96:
317 lpdcb->BaudRate *= 100;
318 break;
319 case 19:
320 lpdcb->BaudRate = 19200;
321 break;
324 while(*device == ' ') device++;
325 if(*device++ != ',') return FALSE;
326 while(*device == ' ') device++;
328 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
329 return FALSE;
331 while(*device == ' ') device++;
332 if(*device++ != ',') return FALSE;
333 while(*device == ' ') device++;
335 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
336 return FALSE;
338 while(*device == ' ') device++;
339 if(*device++ != ',') return FALSE;
340 while(*device == ' ') device++;
342 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
343 return FALSE;
345 /* The last parameter for flow control is optional. */
346 while(*device == ' ') device++;
347 if(*device == ',')
349 device++;
350 while(*device == ' ') device++;
351 if(*device) last = toupperW(*device++);
352 while(*device == ' ') device++;
355 /* Win NT sets the flow control members based on (or lack of) the last
356 parameter. Win 9x does not set these members. */
357 switch(last)
359 case 0:
360 lpdcb->fInX = FALSE;
361 lpdcb->fOutX = FALSE;
362 lpdcb->fOutxCtsFlow = FALSE;
363 lpdcb->fOutxDsrFlow = FALSE;
364 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
365 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
366 break;
367 case 'X':
368 lpdcb->fInX = TRUE;
369 lpdcb->fOutX = TRUE;
370 lpdcb->fOutxCtsFlow = FALSE;
371 lpdcb->fOutxDsrFlow = FALSE;
372 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
373 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
374 break;
375 case 'P':
376 lpdcb->fInX = FALSE;
377 lpdcb->fOutX = FALSE;
378 lpdcb->fOutxCtsFlow = TRUE;
379 lpdcb->fOutxDsrFlow = TRUE;
380 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
381 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
382 break;
383 default:
384 return FALSE;
387 /* This should be the end of the string. */
388 if(*device) return FALSE;
390 return TRUE;
393 /***********************************************************************
394 * COMM_BuildNewCommDCB (Internal)
396 * Build a DCB using the new style settings string.
397 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
399 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
401 DWORD temp;
402 BOOL baud = FALSE, stop = FALSE;
403 static const WCHAR baudW[] = {'b','a','u','d','=',0};
404 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
405 static const WCHAR dataW[] = {'d','a','t','a','=',0};
406 static const WCHAR stopW[] = {'s','t','o','p','=',0};
407 static const WCHAR toW[] = {'t','o','=',0};
408 static const WCHAR xonW[] = {'x','o','n','=',0};
409 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
410 static const WCHAR octsW[] = {'o','c','t','s','=',0};
411 static const WCHAR dtrW[] = {'d','t','r','=',0};
412 static const WCHAR rtsW[] = {'r','t','s','=',0};
413 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
415 while(*device)
417 while(*device == ' ') device++;
419 if(!strncmpiW(baudW, device, 5))
421 baud = TRUE;
423 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
424 return FALSE;
426 else if(!strncmpiW(parityW, device, 7))
428 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
429 return FALSE;
431 else if(!strncmpiW(dataW, device, 5))
433 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
434 return FALSE;
436 else if(!strncmpiW(stopW, device, 5))
438 stop = TRUE;
440 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
441 return FALSE;
443 else if(!strncmpiW(toW, device, 3))
445 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
446 return FALSE;
448 lptimeouts->ReadIntervalTimeout = 0;
449 lptimeouts->ReadTotalTimeoutMultiplier = 0;
450 lptimeouts->ReadTotalTimeoutConstant = 0;
451 lptimeouts->WriteTotalTimeoutMultiplier = 0;
452 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
454 else if(!strncmpiW(xonW, device, 4))
456 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
457 return FALSE;
459 lpdcb->fOutX = temp;
460 lpdcb->fInX = temp;
462 else if(!strncmpiW(odsrW, device, 5))
464 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
465 return FALSE;
467 lpdcb->fOutxDsrFlow = temp;
469 else if(!strncmpiW(octsW, device, 5))
471 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
472 return FALSE;
474 lpdcb->fOutxCtsFlow = temp;
476 else if(!strncmpiW(dtrW, device, 4))
478 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
479 return FALSE;
481 lpdcb->fDtrControl = temp;
483 else if(!strncmpiW(rtsW, device, 4))
485 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
486 return FALSE;
488 lpdcb->fRtsControl = temp;
490 else if(!strncmpiW(idsrW, device, 5))
492 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
493 return FALSE;
495 /* Win NT sets the fDsrSensitivity member based on the
496 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
497 lpdcb->fDsrSensitivity = temp;
499 else
500 return FALSE;
502 /* After the above parsing, the next character (if not the end of
503 the string) should be a space */
504 if(*device && *device != ' ')
505 return FALSE;
508 /* If stop bits were not specified, a default is always supplied. */
509 if(!stop)
511 if(baud && lpdcb->BaudRate == 110)
512 lpdcb->StopBits = TWOSTOPBITS;
513 else
514 lpdcb->StopBits = ONESTOPBIT;
517 return TRUE;
520 /**************************************************************************
521 * BuildCommDCBA (KERNEL32.@)
523 * Updates a device control block data structure with values from an
524 * ascii device control string. The device control string has two forms
525 * normal and extended, it must be exclusively in one or the other form.
527 * RETURNS
529 * True on success, false on a malformed control string.
531 BOOL WINAPI BuildCommDCBA(
532 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
533 LPDCB lpdcb) /* [out] The device control block to be updated. */
535 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
538 /**************************************************************************
539 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
541 * Updates a device control block data structure with values from an
542 * ascii device control string. Taking timeout values from a timeouts
543 * struct if desired by the control string.
545 * RETURNS
547 * True on success, false bad handles etc.
549 BOOL WINAPI BuildCommDCBAndTimeoutsA(
550 LPCSTR device, /* [in] The ascii device control string. */
551 LPDCB lpdcb, /* [out] The device control block to be updated. */
552 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
554 BOOL ret = FALSE;
555 UNICODE_STRING deviceW;
557 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
558 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
559 else deviceW.Buffer = NULL;
561 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
563 RtlFreeUnicodeString(&deviceW);
564 return ret;
567 /**************************************************************************
568 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
570 * Updates a device control block data structure with values from a
571 * unicode device control string. Taking timeout values from a timeouts
572 * struct if desired by the control string.
574 * RETURNS
576 * True on success, false bad handles etc
578 BOOL WINAPI BuildCommDCBAndTimeoutsW(
579 LPCWSTR devid, /* [in] The unicode device control string. */
580 LPDCB lpdcb, /* [out] The device control block to be updated. */
581 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
583 DCB dcb;
584 COMMTIMEOUTS timeouts;
585 BOOL result;
586 LPCWSTR ptr = devid;
588 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
590 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
591 lpdcb->DCBlength = sizeof(DCB);
593 /* Make a copy of the original data structures to work with since if
594 if there is an error in the device control string the originals
595 should not be modified (except possibly DCBlength) */
596 memcpy(&dcb, lpdcb, sizeof(DCB));
597 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
599 ptr = COMM_ParseStart(ptr);
601 if(ptr == NULL)
602 result = FALSE;
603 else if(strchrW(ptr, ','))
604 result = COMM_BuildOldCommDCB(ptr, &dcb);
605 else
606 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
608 if(result)
610 memcpy(lpdcb, &dcb, sizeof(DCB));
611 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
612 return TRUE;
614 else
616 WARN("Invalid device control string: %s\n", debugstr_w(devid));
617 SetLastError(ERROR_INVALID_PARAMETER);
618 return FALSE;
622 /**************************************************************************
623 * BuildCommDCBW (KERNEL32.@)
625 * Updates a device control block structure with values from an
626 * unicode device control string. The device control string has two forms
627 * normal and extended, it must be exclusively in one or the other form.
629 * RETURNS
631 * True on success, false on a malformed control string.
633 BOOL WINAPI BuildCommDCBW(
634 LPCWSTR devid, /* [in] The unicode device control string. */
635 LPDCB lpdcb) /* [out] The device control block to be updated. */
637 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
640 /*****************************************************************************
641 * SetCommBreak (KERNEL32.@)
643 * Halts the transmission of characters to a communications device.
645 * PARAMS
646 * handle [in] The communications device to suspend
648 * RETURNS
650 * True on success, and false if the communications device could not be found,
651 * the control is not supported.
653 * BUGS
655 * Only TIOCSBRK and TIOCCBRK are supported.
657 BOOL WINAPI SetCommBreak(HANDLE handle)
659 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, NULL, NULL);
662 /*****************************************************************************
663 * ClearCommBreak (KERNEL32.@)
665 * Resumes character transmission from a communication device.
667 * PARAMS
669 * handle [in] The halted communication device whose character transmission is to be resumed
671 * RETURNS
673 * True on success and false if the communications device could not be found.
675 * BUGS
677 * Only TIOCSBRK and TIOCCBRK are supported.
679 BOOL WINAPI ClearCommBreak(HANDLE handle)
681 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, NULL, NULL);
684 /*****************************************************************************
685 * EscapeCommFunction (KERNEL32.@)
687 * Directs a communication device to perform an extended function.
689 * PARAMS
691 * handle [in] The communication device to perform the extended function
692 * nFunction [in] The extended function to be performed
694 * RETURNS
696 * True or requested data on successful completion of the command,
697 * false if the device is not present cannot execute the command
698 * or the command failed.
700 BOOL WINAPI EscapeCommFunction(HANDLE handle, UINT func)
702 DWORD ioc;
704 switch (func)
706 case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break;
707 case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break;
708 case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break;
709 case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break;
710 case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break;
711 case SETXON: ioc = IOCTL_SERIAL_SET_XON; break;
712 case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break;
713 case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break;
714 case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break;
715 default:
716 ERR("Unknown function code (%u)\n", func);
717 SetLastError(ERROR_INVALID_PARAMETER);
718 return FALSE;
720 return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, NULL, NULL);
723 /********************************************************************
724 * PurgeComm (KERNEL32.@)
726 * Terminates pending operations and/or discards buffers on a
727 * communication resource.
729 * PARAMS
731 * handle [in] The communication resource to be purged
732 * flags [in] Flags for clear pending/buffer on input/output
734 * RETURNS
736 * True on success and false if the communications handle is bad.
738 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
740 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
741 NULL, 0, NULL, NULL);
744 /*****************************************************************************
745 * ClearCommError (KERNEL32.@)
747 * Enables further I/O operations on a communications resource after
748 * supplying error and current status information.
750 * PARAMS
752 * handle [in] The communication resource with the error
753 * errors [out] Flags indicating error the resource experienced
754 * lpStat [out] The status of the communication resource
755 * RETURNS
757 * True on success, false if the communication resource handle is bad.
759 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
761 SERIAL_STATUS ss;
763 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
764 &ss, sizeof(ss), NULL, NULL))
765 return FALSE;
767 if (errors)
769 *errors = 0;
770 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK;
771 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME;
772 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN;
773 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER;
774 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY;
777 if (lpStat)
779 memset(lpStat, 0, sizeof(*lpStat));
781 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE;
782 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE;
783 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE;
784 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE;
785 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE;
786 if (ss.EofReceived) lpStat->fEof = TRUE;
787 if (ss.WaitForImmediate) lpStat->fTxim = TRUE;
788 lpStat->cbInQue = ss.AmountInInQueue;
789 lpStat->cbOutQue = ss.AmountInOutQueue;
791 return TRUE;
794 /*****************************************************************************
795 * SetupComm (KERNEL32.@)
797 * Called after CreateFile to hint to the communication resource to use
798 * specified sizes for input and output buffers rather than the default values.
800 * PARAMS
801 * handle [in] The just created communication resource handle
802 * insize [in] The suggested size of the communication resources input buffer in bytes
803 * outsize [in] The suggested size of the communication resources output buffer in bytes
805 * RETURNS
807 * True if successful, false if the communications resource handle is bad.
809 * BUGS
811 * Stub.
813 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
815 SERIAL_QUEUE_SIZE sqs;
817 sqs.InSize = insize;
818 sqs.OutSize = outsize;
819 return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE,
820 &sqs, sizeof(sqs), NULL, 0, NULL, NULL);
823 /*****************************************************************************
824 * GetCommMask (KERNEL32.@)
826 * Obtain the events associated with a communication device that will cause
827 * a call WaitCommEvent to return.
829 * PARAMS
831 * handle [in] The communications device
832 * evtmask [out] The events which cause WaitCommEvent to return
834 * RETURNS
836 * True on success, fail on bad device handle etc.
838 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
840 TRACE("handle %p, mask %p\n", handle, evtmask);
841 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
842 NULL, 0, evtmask, sizeof(*evtmask), NULL, NULL);
845 /*****************************************************************************
846 * SetCommMask (KERNEL32.@)
848 * There be some things we need to hear about yon there communications device.
849 * (Set which events associated with a communication device should cause
850 * a call WaitCommEvent to return.)
852 * PARAMS
854 * handle [in] The communications device
855 * evtmask [in] The events that are to be monitored
857 * RETURNS
859 * True on success, false on bad handle etc.
861 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
863 TRACE("handle %p, mask %lx\n", handle, evtmask);
864 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
865 &evtmask, sizeof(evtmask), NULL, 0, NULL, NULL);
868 static void dump_dcb(const DCB* lpdcb)
870 TRACE("bytesize=%d baudrate=%ld fParity=%d Parity=%d stopbits=%d\n",
871 lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity,
872 (lpdcb->StopBits == ONESTOPBIT) ? 1 :
873 (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0);
874 TRACE("%sIXON %sIXOFF\n", (lpdcb->fInX) ? "" : "~", (lpdcb->fOutX) ? "" : "~");
875 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl);
876 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl);
877 if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE)
878 TRACE("CRTSCTS\n");
879 else
880 TRACE("~CRTSCTS\n");
883 /*****************************************************************************
884 * SetCommState (KERNEL32.@)
886 * Re-initializes all hardware and control settings of a communications device,
887 * with values from a device control block without effecting the input and output
888 * queues.
890 * PARAMS
892 * handle [in] The communications device
893 * lpdcb [out] The device control block
895 * RETURNS
897 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
899 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
901 SERIAL_BAUD_RATE sbr;
902 SERIAL_LINE_CONTROL slc;
903 SERIAL_HANDFLOW shf;
904 SERIAL_CHARS sc;
906 if (lpdcb == NULL)
908 SetLastError(ERROR_INVALID_PARAMETER);
909 return FALSE;
911 dump_dcb(lpdcb);
913 sbr.BaudRate = lpdcb->BaudRate;
915 slc.StopBits = lpdcb->StopBits;
916 slc.Parity = lpdcb->Parity;
917 slc.WordLength = lpdcb->ByteSize;
919 shf.ControlHandShake = 0;
920 shf.FlowReplace = 0;
921 if (lpdcb->fOutxCtsFlow) shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
922 if (lpdcb->fOutxDsrFlow) shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
923 switch (lpdcb->fDtrControl)
925 case DTR_CONTROL_DISABLE: break;
926 case DTR_CONTROL_ENABLE: shf.ControlHandShake |= SERIAL_DTR_CONTROL; break;
927 case DTR_CONTROL_HANDSHAKE: shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break;
928 default:
929 SetLastError(ERROR_INVALID_PARAMETER);
930 return FALSE;
932 switch (lpdcb->fDtrControl)
934 case RTS_CONTROL_DISABLE: break;
935 case RTS_CONTROL_ENABLE: shf.FlowReplace |= SERIAL_RTS_CONTROL; break;
936 case RTS_CONTROL_HANDSHAKE: shf.FlowReplace |= SERIAL_RTS_HANDSHAKE; break;
937 case RTS_CONTROL_TOGGLE: shf.FlowReplace |= SERIAL_RTS_CONTROL |
938 SERIAL_RTS_HANDSHAKE; break;
939 default:
940 SetLastError(ERROR_INVALID_PARAMETER);
941 return FALSE;
943 if (lpdcb->fDsrSensitivity) shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
944 if (lpdcb->fAbortOnError) shf.ControlHandShake |= SERIAL_ERROR_ABORT;
946 if (lpdcb->fErrorChar) shf.FlowReplace |= SERIAL_ERROR_CHAR;
947 if (lpdcb->fNull) shf.FlowReplace |= SERIAL_NULL_STRIPPING;
948 if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE;
949 if (lpdcb->fOutX) shf.FlowReplace |= SERIAL_AUTO_TRANSMIT;
950 if (lpdcb->fInX) shf.FlowReplace |= SERIAL_AUTO_RECEIVE;
952 shf.XonLimit = lpdcb->XonLim;
953 shf.XoffLimit = lpdcb->XoffLim;
955 sc.EofChar = lpdcb->EofChar;
956 sc.ErrorChar = lpdcb->ErrorChar;
957 sc.BreakChar = 0;
958 sc.EventChar = lpdcb->EvtChar;
959 sc.XonChar = lpdcb->XonChar;
960 sc.XoffChar = lpdcb->XoffChar;
962 /* note: change DTR/RTS lines after setting the comm attributes,
963 * so flow control does not interfere.
965 return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
966 &sbr, sizeof(sbr), NULL, 0, NULL, NULL) &&
967 DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
968 &slc, sizeof(slc), NULL, 0, NULL, NULL) &&
969 DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
970 &shf, sizeof(shf), NULL, 0, NULL, NULL) &&
971 DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS,
972 &sc, sizeof(sc), NULL, 0, NULL, NULL));
976 /*****************************************************************************
977 * GetCommState (KERNEL32.@)
979 * Fills in a device control block with information from a communications device.
981 * PARAMS
982 * handle [in] The communications device
983 * lpdcb [out] The device control block
985 * RETURNS
987 * True on success, false if the communication device handle is bad etc
989 * BUGS
991 * XonChar and XoffChar are not set.
993 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
995 SERIAL_BAUD_RATE sbr;
996 SERIAL_LINE_CONTROL slc;
997 SERIAL_HANDFLOW shf;
998 SERIAL_CHARS sc;
1000 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1002 if (!lpdcb)
1004 SetLastError(ERROR_INVALID_PARAMETER);
1005 return FALSE;
1008 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
1009 NULL, 0, &sbr, sizeof(sbr), NULL, NULL) ||
1010 !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
1011 NULL, 0, &slc, sizeof(slc), NULL, NULL) ||
1012 !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW,
1013 NULL, 0, &shf, sizeof(shf), NULL, NULL) ||
1014 !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS,
1015 NULL, 0, &sc, sizeof(sc), NULL, NULL))
1016 return FALSE;
1018 memset(lpdcb, 0, sizeof(*lpdcb));
1019 lpdcb->DCBlength = sizeof(*lpdcb);
1021 /* yes, they seem no never be (re)set on NT */
1022 lpdcb->fBinary = 1;
1023 lpdcb->fParity = 0;
1025 lpdcb->BaudRate = sbr.BaudRate;
1027 lpdcb->StopBits = slc.StopBits;
1028 lpdcb->Parity = slc.Parity;
1029 lpdcb->ByteSize = slc.WordLength;
1031 if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1;
1032 if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1;
1033 switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
1035 case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
1036 case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
1037 case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
1039 switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
1041 case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
1042 case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
1043 case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
1044 case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
1045 lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
1047 if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1;
1048 if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1;
1049 if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1;
1050 if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1;
1051 if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1;
1052 lpdcb->XonLim = shf.XonLimit;
1053 lpdcb->XoffLim = shf.XoffLimit;
1055 if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
1056 if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
1058 lpdcb->EofChar = sc.EofChar;
1059 lpdcb->ErrorChar = sc.ErrorChar;
1060 lpdcb->EvtChar = sc.EventChar;
1061 lpdcb->XonChar = sc.XonChar;
1062 lpdcb->XoffChar = sc.XoffChar;
1064 TRACE("OK\n");
1065 dump_dcb(lpdcb);
1067 return TRUE;
1070 /*****************************************************************************
1071 * TransmitCommChar (KERNEL32.@)
1073 * Transmits a single character in front of any pending characters in the
1074 * output buffer. Usually used to send an interrupt character to a host.
1076 * PARAMS
1077 * hComm [in] The communication device in need of a command character
1078 * chTransmit [in] The character to transmit
1080 * RETURNS
1082 * True if the call succeeded, false if the previous command character to the
1083 * same device has not been sent yet the handle is bad etc.
1086 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
1088 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
1089 &chTransmit, sizeof(chTransmit), NULL, 0, NULL, NULL);
1093 /*****************************************************************************
1094 * GetCommTimeouts (KERNEL32.@)
1096 * Obtains the request timeout values for the communications device.
1098 * PARAMS
1099 * hComm [in] The communications device
1100 * lptimeouts [out] The struct of request timeouts
1102 * RETURNS
1104 * True on success, false if communications device handle is bad
1105 * or the target structure is null.
1107 BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1109 SERIAL_TIMEOUTS st;
1111 TRACE("(%p, %p)\n", hComm, lptimeouts);
1112 if (!lptimeouts)
1114 SetLastError(ERROR_INVALID_PARAMETER);
1115 return FALSE;
1117 if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
1118 NULL, 0, &st, sizeof(st), NULL, NULL))
1119 return FALSE;
1120 lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout;
1121 lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier;
1122 lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant;
1123 lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
1124 lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant;
1125 return TRUE;
1128 /*****************************************************************************
1129 * SetCommTimeouts (KERNEL32.@)
1131 * Sets the timeouts used when reading and writing data to/from COMM ports.
1133 * PARAMS
1134 * hComm [in] handle of COMM device
1135 * lptimeouts [in] pointer to COMMTIMEOUTS structure
1137 * ReadIntervalTimeout
1138 * - converted and passes to linux kernel as c_cc[VTIME]
1139 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1140 * - used in ReadFile to calculate GetOverlappedResult's timeout
1141 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1142 * - used in WriteFile to calculate GetOverlappedResult's timeout
1144 * RETURNS
1146 * True if the timeouts were set, false otherwise.
1148 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1150 SERIAL_TIMEOUTS st;
1152 TRACE("(%p, %p)\n", hComm, lptimeouts);
1154 if (lptimeouts == NULL)
1156 SetLastError(ERROR_INVALID_PARAMETER);
1157 return FALSE;
1159 st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout;
1160 st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier;
1161 st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant;
1162 st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
1163 st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant;
1165 return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
1166 &st, sizeof(st), NULL, 0, NULL, NULL);
1169 /***********************************************************************
1170 * GetCommModemStatus (KERNEL32.@)
1172 * Obtains the four control register bits if supported by the hardware.
1174 * PARAMS
1176 * hFile [in] The communications device
1177 * lpModemStat [out] The control register bits
1179 * RETURNS
1181 * True if the communications handle was good and for hardware that
1182 * control register access, false otherwise.
1184 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1186 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1187 NULL, 0, lpModemStat, sizeof(DWORD), NULL, NULL);
1190 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1192 DWORD ret = 0, queue;
1194 TRACE("mask 0x%08lx\n", mask);
1195 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old->rx, new->rx);
1196 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old->tx, new->tx);
1197 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old->frame, new->frame);
1198 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old->overrun, new->overrun);
1199 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old->parity, new->parity);
1200 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old->brk, new->brk);
1201 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1203 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1204 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1205 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1206 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1207 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1208 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1209 || (old->parity != new->parity)) )?EV_ERR :0;
1210 if (mask & EV_RXCHAR)
1212 queue = 0;
1213 #ifdef TIOCINQ
1214 if(ioctl(fd, TIOCINQ, &queue))
1215 WARN("TIOCINQ returned error\n");
1216 #endif
1217 if (queue)
1218 ret |= EV_RXCHAR;
1220 if (mask & EV_TXEMPTY)
1222 queue = 0;
1223 /* We really want to know when all characters have gone out of the transmitter */
1224 #if defined(TIOCSERGETLSR)
1225 if(ioctl(fd, TIOCSERGETLSR, &queue))
1226 WARN("TIOCSERGETLSR returned error\n");
1227 if (queue)
1228 /* TIOCINQ only checks for an empty buffer */
1229 #elif defined(TIOCINQ)
1230 if(ioctl(fd, TIOCOUTQ, &queue))
1231 WARN("TIOCOUTQ returned error\n");
1232 if (!queue)
1233 #endif
1234 ret |= EV_TXEMPTY;
1235 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1237 return ret;
1241 /***********************************************************************
1242 * COMM_WaitCommEventService (INTERNAL)
1244 * We need to poll for what is interesting
1245 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1248 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1250 async_commio *commio = (async_commio*) arg;
1251 int waitmask = 0;
1252 int rc, fd, abort;
1253 serial_irq_info new_irq_info;
1254 DWORD new_mstat, new_evtmask;
1256 fd=get_comm_fd( commio->handle, FILE_READ_DATA );
1258 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1259 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1263 * TIOCMIWAIT is not adequate
1265 * FIXME:
1266 * We don't handle the EV_RXFLAG (the eventchar)
1268 Sleep(1);
1269 rc= COMM_GetEInfo(fd,&new_irq_info);
1270 if (rc)
1271 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1272 rc = GetCommModemStatus(commio->handle, &new_mstat);
1273 if (!rc)
1274 TRACE("GetCommModemStatus failed\n");
1275 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1276 GetCommMask(commio->handle, &new_evtmask);
1277 abort = (commio->evtmask != new_evtmask);
1278 TRACE("resulting Eventmask 0x%08x\n", rc);
1279 } while (!rc && ! abort);
1280 if (abort) rc = 0;
1281 release_comm_fd( commio->handle, fd );
1282 *commio->buffer = rc;
1283 if (commio->hEvent != INVALID_HANDLE_VALUE )
1284 NtSetEvent( commio->hEvent, NULL );
1285 HeapFree(GetProcessHeap(), 0, commio );
1286 return 0;
1290 /***********************************************************************
1291 * COMM_WaitCommEvent (INTERNAL)
1293 * This function must have an lpOverlapped.
1295 static BOOL COMM_WaitCommEvent(
1296 HANDLE hFile, /* [in] handle of comm port to wait for */
1297 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1298 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1300 int fd;
1301 async_commio* commio;
1302 DWORD result_mask;
1303 BOOL res;
1305 if (!lpOverlapped)
1307 SetLastError(ERROR_INVALID_PARAMETER);
1308 return FALSE;
1311 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1312 return FALSE;
1314 fd = get_comm_fd( hFile, FILE_WRITE_DATA );
1315 if (fd < 0) return FALSE;
1317 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1318 if (!commio)
1320 release_comm_fd( hFile, fd );
1321 return FALSE;
1324 commio->handle = hFile;
1325 commio->buffer = (char *)lpdwEvents;
1326 commio->hEvent = lpOverlapped->hEvent;
1327 GetCommMask(hFile, &commio->evtmask);
1329 /* We may never return, if some capabilities miss
1330 * Return error in that case
1332 #if !defined(TIOCINQ)
1333 if(commio->evtmask & EV_RXCHAR)
1334 goto error;
1335 #endif
1336 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1337 if(commio->evtmask & EV_TXEMPTY)
1338 goto error;
1339 #endif
1340 #if !defined(TIOCMGET)
1341 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
1342 goto error;
1343 #endif
1344 #if !defined(TIOCM_CTS)
1345 if(commio->evtmask & EV_CTS)
1346 goto error;
1347 #endif
1348 #if !defined(TIOCM_DSR)
1349 if(commio->evtmask & EV_DSR)
1350 goto error;
1351 #endif
1352 #if !defined(TIOCM_RNG)
1353 if(commio->evtmask & EV_RING)
1354 goto error;
1355 #endif
1356 #if !defined(TIOCM_CAR)
1357 if(commio->evtmask & EV_RLSD)
1358 goto error;
1359 #endif
1360 if(commio->evtmask & EV_RXFLAG)
1361 FIXME("EV_RXFLAG not handled\n");
1362 COMM_GetEInfo(fd,&commio->irq_info);
1363 GetCommModemStatus(hFile, &commio->mstat);
1364 /* We might have received something or the TX bufffer is delivered*/
1365 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
1366 if (result_mask)
1368 TRACE("Event already met\n");
1369 *lpdwEvents = result_mask;
1370 HeapFree(GetProcessHeap(), 0, commio );
1371 res = TRUE;
1373 else
1375 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
1376 SetLastError(ERROR_IO_PENDING);
1377 res = FALSE;
1379 release_comm_fd( hFile, fd );
1380 return res;
1381 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
1382 error:
1383 FIXME("Returning error because of missing capabilities\n");
1384 release_comm_fd( hFile, fd );
1385 HeapFree(GetProcessHeap(), 0, commio );
1386 SetLastError(ERROR_INVALID_PARAMETER);
1387 return FALSE;
1388 #endif
1390 /***********************************************************************
1391 * WaitCommEvent (KERNEL32.@)
1393 * Wait until something interesting happens on a COMM port.
1394 * Interesting things (events) are set by calling SetCommMask before
1395 * this function is called.
1397 * RETURNS
1398 * TRUE if successful
1399 * FALSE if failure
1401 * The set of detected events will be written to *lpdwEventMask
1402 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1404 * BUGS:
1405 * Only supports EV_RXCHAR and EV_TXEMPTY
1407 BOOL WINAPI WaitCommEvent(
1408 HANDLE hFile, /* [in] handle of comm port to wait for */
1409 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1410 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1412 OVERLAPPED ov;
1413 int ret = 0;
1414 DWORD res, err;
1416 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1418 if(lpOverlapped)
1419 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1421 /* if there is no overlapped structure, create our own */
1422 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
1424 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1425 err = GetLastError();
1426 if (!res)
1428 if (err == ERROR_IO_PENDING)
1432 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
1433 } while (res != WAIT_OBJECT_0);
1434 TRACE("Event met\n:");
1435 ret = TRUE;
1437 else
1439 FIXME("Unknown error 0x%08lx\n", err);
1440 ret = FALSE;
1443 else
1444 ret = TRUE;
1445 CloseHandle(ov.hEvent);
1447 return ret;
1450 /***********************************************************************
1451 * GetCommProperties (KERNEL32.@)
1453 * This function fills in a structure with the capabilities of the
1454 * communications port driver.
1456 * RETURNS
1458 * TRUE on success, FALSE on failure
1459 * If successful, the lpCommProp structure be filled in with
1460 * properties of the comm port.
1462 BOOL WINAPI GetCommProperties(
1463 HANDLE hFile, /* [in] handle of the comm port */
1464 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1466 FIXME("(%p %p )\n",hFile,lpCommProp);
1467 if(!lpCommProp)
1468 return FALSE;
1471 * These values should be valid for LINUX's serial driver
1472 * FIXME: Perhaps they deserve an #ifdef LINUX
1474 memset(lpCommProp,0,sizeof(COMMPROP));
1475 lpCommProp->wPacketLength = 1;
1476 lpCommProp->wPacketVersion = 1;
1477 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1478 lpCommProp->dwReserved1 = 0;
1479 lpCommProp->dwMaxTxQueue = 4096;
1480 lpCommProp->dwMaxRxQueue = 4096;
1481 lpCommProp->dwMaxBaud = BAUD_115200;
1482 lpCommProp->dwProvSubType = PST_RS232;
1483 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1484 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1485 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1486 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1487 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1488 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1489 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1490 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1491 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1492 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1493 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1495 return TRUE;
1498 /***********************************************************************
1499 * FIXME:
1500 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1501 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1502 * This is dependent on the type of COMM port, but since it is doubtful
1503 * anybody will get around to implementing support for fancy serial
1504 * ports in WINE, this is hardcoded for the time being. The name of
1505 * this DLL should be stored in and read from the system registry in
1506 * the hive HKEY_LOCAL_MACHINE, key
1507 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1508 * where ???? is the port number... that is determined by PNP
1509 * The DLL should be loaded when the COMM port is opened, and closed
1510 * when the COMM port is closed. - MJM 20 June 2000
1511 ***********************************************************************/
1512 static const WCHAR lpszSerialUI[] = {
1513 's','e','r','i','a','l','u','i','.','d','l','l',0 };
1516 /***********************************************************************
1517 * CommConfigDialogA (KERNEL32.@)
1519 * Raises a dialog that allows the user to configure a comm port.
1520 * Fills the COMMCONFIG struct with information specified by the user.
1521 * This function should call a similar routine in the COMM driver...
1523 * RETURNS
1525 * TRUE on success, FALSE on failure
1526 * If successful, the lpCommConfig structure will contain a new
1527 * configuration for the comm port, as specified by the user.
1529 * BUGS
1530 * The library with the CommConfigDialog code is never unloaded.
1531 * Perhaps this should be done when the comm port is closed?
1533 BOOL WINAPI CommConfigDialogA(
1534 LPCSTR lpszDevice, /* [in] name of communications device */
1535 HWND hWnd, /* [in] parent window for the dialog */
1536 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1538 FARPROC lpfnCommDialog;
1539 HMODULE hConfigModule;
1540 BOOL r = FALSE;
1542 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1544 hConfigModule = LoadLibraryW(lpszSerialUI);
1545 if(!hConfigModule)
1546 return FALSE;
1548 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
1550 if(lpfnCommDialog)
1551 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1553 FreeLibrary(hConfigModule);
1555 return r;
1558 /***********************************************************************
1559 * CommConfigDialogW (KERNEL32.@)
1561 * See CommConfigDialogA.
1563 BOOL WINAPI CommConfigDialogW(
1564 LPCWSTR lpszDevice, /* [in] name of communications device */
1565 HWND hWnd, /* [in] parent window for the dialog */
1566 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1568 FARPROC lpfnCommDialog;
1569 HMODULE hConfigModule;
1570 BOOL r = FALSE;
1572 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1574 hConfigModule = LoadLibraryW(lpszSerialUI);
1575 if(!hConfigModule)
1576 return FALSE;
1578 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
1580 if(lpfnCommDialog)
1581 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1583 FreeLibrary(hConfigModule);
1585 return r;
1588 /***********************************************************************
1589 * GetCommConfig (KERNEL32.@)
1591 * Fill in the COMMCONFIG structure for the comm port hFile
1593 * RETURNS
1595 * TRUE on success, FALSE on failure
1596 * If successful, lpCommConfig contains the comm port configuration.
1598 * BUGS
1601 BOOL WINAPI GetCommConfig(
1602 HANDLE hFile, /* [in] The communications device. */
1603 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1604 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1605 afterwards the number of bytes copied to the buffer or
1606 the needed size of the buffer. */
1608 BOOL r;
1610 TRACE("(%p %p)\n",hFile,lpCommConfig);
1612 if(lpCommConfig == NULL)
1613 return FALSE;
1614 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
1615 *lpdwSize = sizeof(COMMCONFIG);
1616 if(r)
1617 return FALSE;
1619 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1620 lpCommConfig->wVersion = 1;
1621 lpCommConfig->wReserved = 0;
1622 r = GetCommState(hFile,&lpCommConfig->dcb);
1623 lpCommConfig->dwProviderSubType = PST_RS232;
1624 lpCommConfig->dwProviderOffset = 0;
1625 lpCommConfig->dwProviderSize = 0;
1627 return r;
1630 /***********************************************************************
1631 * SetCommConfig (KERNEL32.@)
1633 * Sets the configuration of the communications device.
1635 * RETURNS
1637 * True on success, false if the handle was bad is not a communications device.
1639 BOOL WINAPI SetCommConfig(
1640 HANDLE hFile, /* [in] The communications device. */
1641 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1642 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1644 TRACE("(%p %p)\n",hFile,lpCommConfig);
1645 return SetCommState(hFile,&lpCommConfig->dcb);
1648 /***********************************************************************
1649 * SetDefaultCommConfigA (KERNEL32.@)
1651 * Initializes the default configuration for the specified communication
1652 * device. (ascii)
1654 * RETURNS
1656 * True if the device was found and the defaults set, false otherwise
1658 BOOL WINAPI SetDefaultCommConfigW(
1659 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1660 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1661 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1663 FARPROC lpfnSetDefaultCommConfig;
1664 HMODULE hConfigModule;
1665 BOOL r = FALSE;
1667 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1669 hConfigModule = LoadLibraryW(lpszSerialUI);
1670 if(!hConfigModule)
1671 return r;
1673 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
1674 if (lpfnSetDefaultCommConfig)
1675 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1677 FreeLibrary(hConfigModule);
1679 return r;
1683 /***********************************************************************
1684 * SetDefaultCommConfigW (KERNEL32.@)
1686 * Initializes the default configuration for the specified
1687 * communication device. (unicode)
1689 * RETURNS
1692 BOOL WINAPI SetDefaultCommConfigA(
1693 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
1694 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1695 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1697 BOOL r;
1698 LPWSTR lpDeviceW = NULL;
1699 DWORD len;
1701 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
1703 if (lpszDevice)
1705 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
1706 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1707 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
1709 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
1710 HeapFree( GetProcessHeap(), 0, lpDeviceW );
1711 return r;
1715 /***********************************************************************
1716 * GetDefaultCommConfigW (KERNEL32.@)
1718 * Acquires the default configuration of the specified communication device. (unicode)
1720 * RETURNS
1722 * True on successful reading of the default configuration,
1723 * if the device is not found or the buffer is too small.
1725 BOOL WINAPI GetDefaultCommConfigW(
1726 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
1727 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1728 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1729 afterwards the number of bytes copied to the buffer or
1730 the needed size of the buffer. */
1732 LPDCB lpdcb = &(lpCC->dcb);
1733 WCHAR temp[40];
1734 static const WCHAR comW[] = {'C','O','M',0};
1735 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
1737 if (strncmpiW(lpszName,comW,3)) {
1738 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
1739 return FALSE;
1742 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
1743 if (*lpdwSize < sizeof(COMMCONFIG)) {
1744 *lpdwSize = sizeof(COMMCONFIG);
1745 return FALSE;
1748 *lpdwSize = sizeof(COMMCONFIG);
1750 lpCC->dwSize = sizeof(COMMCONFIG);
1751 lpCC->wVersion = 1;
1752 lpCC->dwProviderSubType = PST_RS232;
1753 lpCC->dwProviderOffset = 0L;
1754 lpCC->dwProviderSize = 0L;
1756 sprintfW( temp, formatW, lpszName[3]);
1757 FIXME("setting %s as default\n", debugstr_w(temp));
1759 return BuildCommDCBW( temp, lpdcb);
1762 /**************************************************************************
1763 * GetDefaultCommConfigA (KERNEL32.@)
1765 * Acquires the default configuration of the specified communication device. (ascii)
1767 * RETURNS
1769 * True on successful reading of the default configuration,
1770 * if the device is not found or the buffer is too small.
1772 BOOL WINAPI GetDefaultCommConfigA(
1773 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
1774 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1775 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1776 afterwards the number of bytes copied to the buffer or
1777 the needed size of the buffer. */
1779 BOOL ret = FALSE;
1780 UNICODE_STRING lpszNameW;
1782 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
1783 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
1784 else lpszNameW.Buffer = NULL;
1786 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
1788 RtlFreeUnicodeString(&lpszNameW);
1789 return ret;