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
22 #include "wine/port.h"
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
49 #ifdef HAVE_SYS_POLL_H
50 # include <sys/poll.h>
52 #ifdef HAVE_SYS_MODEM_H
53 # include <sys/modem.h>
55 #ifdef HAVE_SYS_STRTIO_H
56 # include <sys/strtio.h>
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
65 #include "ddk/ntddser.h"
67 #include "wine/server.h"
68 #include "wine/unicode.h"
70 #include "wine/debug.h"
72 #ifdef HAVE_LINUX_SERIAL_H
73 #include <linux/serial.h>
76 WINE_DEFAULT_DEBUG_CHANNEL(comm);
78 /* retrieve the Unix handle corresponding to a comm handle */
79 static int get_comm_fd( HANDLE handle, DWORD access )
83 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
84 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
88 /* release the Unix handle returned by get_comm_fd */
89 static inline void release_comm_fd( HANDLE handle, int fd )
91 wine_server_release_fd( handle, fd );
95 * local structure holding the irq values we need for WaitCommEvent()
97 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
98 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
99 * no need to carry them in the internal structure
102 typedef struct serial_irq_info
104 int rx , tx, frame, overrun, parity, brk, buf_overrun;
107 /***********************************************************************
108 * Data needed by the thread polling for the changing CommEvent
110 typedef struct async_commio
117 serial_irq_info irq_info;
120 /***********************************************************************/
122 #if !defined(TIOCINQ) && defined(FIONREAD)
123 #define TIOCINQ FIONREAD
126 /***********************************************************************
127 * Get extended interrupt count info, needed for WaitCommEvent
129 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
132 struct serial_icounter_struct einfo;
133 if (!ioctl(fd,TIOCGICOUNT, &einfo))
135 irq_info->rx = einfo.rx;
136 irq_info->tx = einfo.tx;
137 irq_info->frame = einfo.frame;
138 irq_info->overrun = einfo.overrun;
139 irq_info->parity = einfo.parity;
140 irq_info->brk = einfo.brk;
141 irq_info->buf_overrun = einfo.buf_overrun;
145 memset(irq_info,0, sizeof(serial_irq_info));
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))
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')
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 != ' ')
178 /* Advance pointer to beginning of next parameter */
179 while(*ptr == ' ') ptr++;
183 while(*ptr == ' ') ptr++;
186 /* The device control string must not start with a space. */
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++;
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++))
210 *lpparity = EVENPARITY;
213 *lpparity = MARKPARITY;
216 *lpparity = NOPARITY;
219 *lpparity = ODDPARITY;
222 *lpparity = SPACEPARITY;
231 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
235 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
238 if(temp >= 5 && temp <= 8)
247 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
250 static const WCHAR stopbits15W[] = {'1','.','5',0};
252 if(!strncmpW(stopbits15W, ptr, 3))
255 *lpstopbits = ONE5STOPBITS;
259 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
263 *lpstopbits = ONESTOPBIT;
265 *lpstopbits = TWOSTOPBITS;
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))
283 else if(!strncmpiW(offW, ptr, 3))
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)
303 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
306 switch(lpdcb->BaudRate)
311 lpdcb->BaudRate *= 10;
317 lpdcb->BaudRate *= 100;
320 lpdcb->BaudRate = 19200;
324 while(*device == ' ') device++;
325 if(*device++ != ',') return FALSE;
326 while(*device == ' ') device++;
328 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
331 while(*device == ' ') device++;
332 if(*device++ != ',') return FALSE;
333 while(*device == ' ') device++;
335 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
338 while(*device == ' ') device++;
339 if(*device++ != ',') return FALSE;
340 while(*device == ' ') device++;
342 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
345 /* The last parameter for flow control is optional. */
346 while(*device == ' ') 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. */
361 lpdcb->fOutX = FALSE;
362 lpdcb->fOutxCtsFlow = FALSE;
363 lpdcb->fOutxDsrFlow = FALSE;
364 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
365 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
370 lpdcb->fOutxCtsFlow = FALSE;
371 lpdcb->fOutxDsrFlow = FALSE;
372 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
373 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
377 lpdcb->fOutX = FALSE;
378 lpdcb->fOutxCtsFlow = TRUE;
379 lpdcb->fOutxDsrFlow = TRUE;
380 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
381 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
387 /* This should be the end of the string. */
388 if(*device) return FALSE;
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)
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};
417 while(*device == ' ') device++;
419 if(!strncmpiW(baudW, device, 5))
423 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
426 else if(!strncmpiW(parityW, device, 7))
428 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
431 else if(!strncmpiW(dataW, device, 5))
433 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
436 else if(!strncmpiW(stopW, device, 5))
440 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
443 else if(!strncmpiW(toW, device, 3))
445 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
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)))
462 else if(!strncmpiW(odsrW, device, 5))
464 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
467 lpdcb->fOutxDsrFlow = temp;
469 else if(!strncmpiW(octsW, device, 5))
471 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
474 lpdcb->fOutxCtsFlow = temp;
476 else if(!strncmpiW(dtrW, device, 4))
478 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
481 lpdcb->fDtrControl = temp;
483 else if(!strncmpiW(rtsW, device, 4))
485 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
488 lpdcb->fRtsControl = temp;
490 else if(!strncmpiW(idsrW, device, 5))
492 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
495 /* Win NT sets the fDsrSensitivity member based on the
496 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
497 lpdcb->fDsrSensitivity = temp;
502 /* After the above parsing, the next character (if not the end of
503 the string) should be a space */
504 if(*device && *device != ' ')
508 /* If stop bits were not specified, a default is always supplied. */
511 if(baud && lpdcb->BaudRate == 110)
512 lpdcb->StopBits = TWOSTOPBITS;
514 lpdcb->StopBits = ONESTOPBIT;
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.
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.
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. */
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);
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.
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. */
584 COMMTIMEOUTS timeouts;
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);
603 else if(strchrW(ptr, ','))
604 result = COMM_BuildOldCommDCB(ptr, &dcb);
606 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
610 memcpy(lpdcb, &dcb, sizeof(DCB));
611 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
616 WARN("Invalid device control string: %s\n", debugstr_w(devid));
617 SetLastError(ERROR_INVALID_PARAMETER);
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.
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.
646 * handle [in] The communications device to suspend
650 * True on success, and false if the communications device could not be found,
651 * the control is not supported.
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.
669 * handle [in] The halted communication device whose character transmission is to be resumed
673 * True on success and false if the communications device could not be found.
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.
691 * handle [in] The communication device to perform the extended function
692 * nFunction [in] The extended function to be performed
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)
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;
716 ERR("Unknown function code (%u)\n", func);
717 SetLastError(ERROR_INVALID_PARAMETER);
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.
731 * handle [in] The communication resource to be purged
732 * flags [in] Flags for clear pending/buffer on input/output
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.
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
757 * True on success, false if the communication resource handle is bad.
759 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
763 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
764 &ss, sizeof(ss), NULL, NULL))
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;
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;
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.
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
807 * True if successful, false if the communications resource handle is bad.
813 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
815 SERIAL_QUEUE_SIZE sqs;
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.
831 * handle [in] The communications device
832 * evtmask [out] The events which cause WaitCommEvent to return
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.)
854 * handle [in] The communications device
855 * evtmask [in] The events that are to be monitored
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)
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
892 * handle [in] The communications device
893 * lpdcb [out] The device control block
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;
908 SetLastError(ERROR_INVALID_PARAMETER);
913 sbr.BaudRate = lpdcb->BaudRate;
915 slc.StopBits = lpdcb->StopBits;
916 slc.Parity = lpdcb->Parity;
917 slc.WordLength = lpdcb->ByteSize;
919 shf.ControlHandShake = 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;
929 SetLastError(ERROR_INVALID_PARAMETER);
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;
940 SetLastError(ERROR_INVALID_PARAMETER);
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;
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.
982 * handle [in] The communications device
983 * lpdcb [out] The device control block
987 * True on success, false if the communication device handle is bad etc
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;
1000 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1004 SetLastError(ERROR_INVALID_PARAMETER);
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))
1018 memset(lpdcb, 0, sizeof(*lpdcb));
1019 lpdcb->DCBlength = sizeof(*lpdcb);
1021 /* yes, they seem no never be (re)set on NT */
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;
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.
1077 * hComm [in] The communication device in need of a command character
1078 * chTransmit [in] The character to transmit
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.
1099 * hComm [in] The communications device
1100 * lptimeouts [out] The struct of request timeouts
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)
1111 TRACE("(%p, %p)\n", hComm, lptimeouts);
1114 SetLastError(ERROR_INVALID_PARAMETER);
1117 if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
1118 NULL, 0, &st, sizeof(st), NULL, NULL))
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;
1128 /*****************************************************************************
1129 * SetCommTimeouts (KERNEL32.@)
1131 * Sets the timeouts used when reading and writing data to/from COMM ports.
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
1146 * True if the timeouts were set, false otherwise.
1148 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1152 TRACE("(%p, %p)\n", hComm, lptimeouts);
1154 if (lptimeouts == NULL)
1156 SetLastError(ERROR_INVALID_PARAMETER);
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.
1176 * hFile [in] The communications device
1177 * lpModemStat [out] The control register bits
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)
1214 if(ioctl(fd, TIOCINQ, &queue))
1215 WARN("TIOCINQ returned error\n");
1220 if (mask & EV_TXEMPTY)
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");
1228 /* TIOCINQ only checks for an empty buffer */
1229 #elif defined(TIOCINQ)
1230 if(ioctl(fd, TIOCOUTQ, &queue))
1231 WARN("TIOCOUTQ returned error\n");
1235 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
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;
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
1266 * We don't handle the EV_RXFLAG (the eventchar)
1269 rc= COMM_GetEInfo(fd,&new_irq_info);
1271 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1272 rc = GetCommModemStatus(commio->handle, &new_mstat);
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);
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 );
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 */
1301 async_commio* commio;
1307 SetLastError(ERROR_INVALID_PARAMETER);
1311 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1314 fd = get_comm_fd( hFile, FILE_WRITE_DATA );
1315 if (fd < 0) return FALSE;
1317 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1320 release_comm_fd( hFile, fd );
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)
1336 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1337 if(commio->evtmask & EV_TXEMPTY)
1340 #if !defined(TIOCMGET)
1341 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
1344 #if !defined(TIOCM_CTS)
1345 if(commio->evtmask & EV_CTS)
1348 #if !defined(TIOCM_DSR)
1349 if(commio->evtmask & EV_DSR)
1352 #if !defined(TIOCM_RNG)
1353 if(commio->evtmask & EV_RING)
1356 #if !defined(TIOCM_CAR)
1357 if(commio->evtmask & EV_RLSD)
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);
1368 TRACE("Event already met\n");
1369 *lpdwEvents = result_mask;
1370 HeapFree(GetProcessHeap(), 0, commio );
1375 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
1376 SetLastError(ERROR_IO_PENDING);
1379 release_comm_fd( hFile, fd );
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)
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);
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.
1398 * TRUE if successful
1401 * The set of detected events will be written to *lpdwEventMask
1402 * ERROR_IO_PENDING will be returned the overlapped structure was passed
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 */
1416 TRACE("(%p %p %p )\n",hFile, lpdwEvents,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();
1428 if (err == ERROR_IO_PENDING)
1432 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
1433 } while (res != WAIT_OBJECT_0);
1434 TRACE("Event met\n:");
1439 FIXME("Unknown error 0x%08lx\n", err);
1445 CloseHandle(ov.hEvent);
1450 /***********************************************************************
1451 * GetCommProperties (KERNEL32.@)
1453 * This function fills in a structure with the capabilities of the
1454 * communications port driver.
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);
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;
1498 /***********************************************************************
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...
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.
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;
1542 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1544 hConfigModule = LoadLibraryW(lpszSerialUI);
1548 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
1551 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1553 FreeLibrary(hConfigModule);
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;
1572 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1574 hConfigModule = LoadLibraryW(lpszSerialUI);
1578 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
1581 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1583 FreeLibrary(hConfigModule);
1588 /***********************************************************************
1589 * GetCommConfig (KERNEL32.@)
1591 * Fill in the COMMCONFIG structure for the comm port hFile
1595 * TRUE on success, FALSE on failure
1596 * If successful, lpCommConfig contains the comm port configuration.
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. */
1610 TRACE("(%p %p)\n",hFile,lpCommConfig);
1612 if(lpCommConfig == NULL)
1614 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
1615 *lpdwSize = sizeof(COMMCONFIG);
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;
1630 /***********************************************************************
1631 * SetCommConfig (KERNEL32.@)
1633 * Sets the configuration of the communications device.
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
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;
1667 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1669 hConfigModule = LoadLibraryW(lpszSerialUI);
1673 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
1674 if (lpfnSetDefaultCommConfig)
1675 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1677 FreeLibrary(hConfigModule);
1683 /***********************************************************************
1684 * SetDefaultCommConfigW (KERNEL32.@)
1686 * Initializes the default configuration for the specified
1687 * communication device. (unicode)
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. */
1698 LPWSTR lpDeviceW = NULL;
1701 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
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 );
1715 /***********************************************************************
1716 * GetDefaultCommConfigW (KERNEL32.@)
1718 * Acquires the default configuration of the specified communication device. (unicode)
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);
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));
1742 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
1743 if (*lpdwSize < sizeof(COMMCONFIG)) {
1744 *lpdwSize = sizeof(COMMCONFIG);
1748 *lpdwSize = sizeof(COMMCONFIG);
1750 lpCC->dwSize = sizeof(COMMCONFIG);
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)
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. */
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);