2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
49 #ifdef HAVE_SYS_POLL_H
50 # include <sys/poll.h>
52 #ifdef HAVE_SYS_MODEM_H
53 # include <sys/modem.h>
55 #ifdef HAVE_SYS_STRTIO_H
56 # include <sys/strtio.h>
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
65 #include "ddk/ntddser.h"
67 #include "wine/server.h"
68 #include "wine/unicode.h"
70 #include "wine/debug.h"
72 #ifdef HAVE_LINUX_SERIAL_H
73 #include <linux/serial.h>
76 WINE_DEFAULT_DEBUG_CHANNEL(comm
);
78 /* retrieve the Unix handle corresponding to a comm handle */
79 static int get_comm_fd( HANDLE handle
, DWORD access
)
83 ret
= wine_server_handle_to_fd( handle
, access
, &fd
, NULL
);
84 if (ret
) SetLastError( RtlNtStatusToDosError(ret
) );
88 /* release the Unix handle returned by get_comm_fd */
89 static inline void release_comm_fd( HANDLE handle
, int fd
)
91 wine_server_release_fd( handle
, fd
);
95 * local structure holding the irq values we need for WaitCommEvent()
97 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
98 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
99 * no need to carry them in the internal structure
102 typedef struct serial_irq_info
104 int rx
, tx
, frame
, overrun
, parity
, brk
, buf_overrun
;
107 /***********************************************************************
108 * Data needed by the thread polling for the changing CommEvent
110 typedef struct async_commio
117 serial_irq_info irq_info
;
120 /***********************************************************************/
122 #if !defined(TIOCINQ) && defined(FIONREAD)
123 #define TIOCINQ FIONREAD
126 /***********************************************************************
127 * Get extended interrupt count info, needed for WaitCommEvent
129 static int COMM_GetEInfo(int fd
, serial_irq_info
*irq_info
)
132 struct serial_icounter_struct einfo
;
133 if (!ioctl(fd
,TIOCGICOUNT
, &einfo
))
135 irq_info
->rx
= einfo
.rx
;
136 irq_info
->tx
= einfo
.tx
;
137 irq_info
->frame
= einfo
.frame
;
138 irq_info
->overrun
= einfo
.overrun
;
139 irq_info
->parity
= einfo
.parity
;
140 irq_info
->brk
= einfo
.brk
;
141 irq_info
->buf_overrun
= einfo
.buf_overrun
;
145 memset(irq_info
,0, sizeof(serial_irq_info
));
149 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
152 unsigned int mstat
, okay
;
153 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
154 if (okay
) return okay
;
155 if (andy
) mstat
&= andy
;
157 return ioctl(fd
, TIOCMSET
, &mstat
);
163 /***********************************************************************
164 * COMM_Parse* (Internal)
166 * The following COMM_Parse* functions are used by the BuildCommDCB
167 * functions to help parse the various parts of the device control string.
169 static LPCWSTR
COMM_ParseStart(LPCWSTR ptr
)
171 static const WCHAR comW
[] = {'C','O','M',0};
173 /* The device control string may optionally start with "COMx" followed
174 by an optional ':' and spaces. */
175 if(!strncmpiW(ptr
, comW
, 3))
179 /* Allow any com port above 0 as Win 9x does (NT only allows
180 values for com ports which are actually present) */
181 if(*ptr
< '1' || *ptr
> '9')
184 /* Advance pointer past port number */
185 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
187 /* The com port number must be followed by a ':' or ' ' */
188 if(*ptr
!= ':' && *ptr
!= ' ')
191 /* Advance pointer to beginning of next parameter */
192 while(*ptr
== ' ') ptr
++;
196 while(*ptr
== ' ') ptr
++;
199 /* The device control string must not start with a space. */
206 static LPCWSTR
COMM_ParseNumber(LPCWSTR ptr
, LPDWORD lpnumber
)
208 if(*ptr
< '0' || *ptr
> '9') return NULL
;
209 *lpnumber
= strtoulW(ptr
, NULL
, 10);
210 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
214 static LPCWSTR
COMM_ParseParity(LPCWSTR ptr
, LPBYTE lpparity
)
216 /* Contrary to what you might expect, Windows only sets the Parity
217 member of DCB and not fParity even when parity is specified in the
218 device control string */
220 switch(toupperW(*ptr
++))
223 *lpparity
= EVENPARITY
;
226 *lpparity
= MARKPARITY
;
229 *lpparity
= NOPARITY
;
232 *lpparity
= ODDPARITY
;
235 *lpparity
= SPACEPARITY
;
244 static LPCWSTR
COMM_ParseByteSize(LPCWSTR ptr
, LPBYTE lpbytesize
)
248 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
251 if(temp
>= 5 && temp
<= 8)
260 static LPCWSTR
COMM_ParseStopBits(LPCWSTR ptr
, LPBYTE lpstopbits
)
263 static const WCHAR stopbits15W
[] = {'1','.','5',0};
265 if(!strncmpW(stopbits15W
, ptr
, 3))
268 *lpstopbits
= ONE5STOPBITS
;
272 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
276 *lpstopbits
= ONESTOPBIT
;
278 *lpstopbits
= TWOSTOPBITS
;
286 static LPCWSTR
COMM_ParseOnOff(LPCWSTR ptr
, LPDWORD lponoff
)
288 static const WCHAR onW
[] = {'o','n',0};
289 static const WCHAR offW
[] = {'o','f','f',0};
291 if(!strncmpiW(onW
, ptr
, 2))
296 else if(!strncmpiW(offW
, ptr
, 3))
307 /***********************************************************************
308 * COMM_BuildOldCommDCB (Internal)
310 * Build a DCB using the old style settings string eg: "96,n,8,1"
312 static BOOL
COMM_BuildOldCommDCB(LPCWSTR device
, LPDCB lpdcb
)
316 if(!(device
= COMM_ParseNumber(device
, &lpdcb
->BaudRate
)))
319 switch(lpdcb
->BaudRate
)
324 lpdcb
->BaudRate
*= 10;
330 lpdcb
->BaudRate
*= 100;
333 lpdcb
->BaudRate
= 19200;
337 while(*device
== ' ') device
++;
338 if(*device
++ != ',') return FALSE
;
339 while(*device
== ' ') device
++;
341 if(!(device
= COMM_ParseParity(device
, &lpdcb
->Parity
)))
344 while(*device
== ' ') device
++;
345 if(*device
++ != ',') return FALSE
;
346 while(*device
== ' ') device
++;
348 if(!(device
= COMM_ParseByteSize(device
, &lpdcb
->ByteSize
)))
351 while(*device
== ' ') device
++;
352 if(*device
++ != ',') return FALSE
;
353 while(*device
== ' ') device
++;
355 if(!(device
= COMM_ParseStopBits(device
, &lpdcb
->StopBits
)))
358 /* The last parameter for flow control is optional. */
359 while(*device
== ' ') device
++;
363 while(*device
== ' ') device
++;
364 if(*device
) last
= toupperW(*device
++);
365 while(*device
== ' ') device
++;
368 /* Win NT sets the flow control members based on (or lack of) the last
369 parameter. Win 9x does not set these members. */
374 lpdcb
->fOutX
= FALSE
;
375 lpdcb
->fOutxCtsFlow
= FALSE
;
376 lpdcb
->fOutxDsrFlow
= FALSE
;
377 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
378 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
383 lpdcb
->fOutxCtsFlow
= FALSE
;
384 lpdcb
->fOutxDsrFlow
= FALSE
;
385 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
386 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
390 lpdcb
->fOutX
= FALSE
;
391 lpdcb
->fOutxCtsFlow
= TRUE
;
392 lpdcb
->fOutxDsrFlow
= TRUE
;
393 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
394 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
400 /* This should be the end of the string. */
401 if(*device
) return FALSE
;
406 /***********************************************************************
407 * COMM_BuildNewCommDCB (Internal)
409 * Build a DCB using the new style settings string.
410 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
412 static BOOL
COMM_BuildNewCommDCB(LPCWSTR device
, LPDCB lpdcb
, LPCOMMTIMEOUTS lptimeouts
)
415 BOOL baud
= FALSE
, stop
= FALSE
;
416 static const WCHAR baudW
[] = {'b','a','u','d','=',0};
417 static const WCHAR parityW
[] = {'p','a','r','i','t','y','=',0};
418 static const WCHAR dataW
[] = {'d','a','t','a','=',0};
419 static const WCHAR stopW
[] = {'s','t','o','p','=',0};
420 static const WCHAR toW
[] = {'t','o','=',0};
421 static const WCHAR xonW
[] = {'x','o','n','=',0};
422 static const WCHAR odsrW
[] = {'o','d','s','r','=',0};
423 static const WCHAR octsW
[] = {'o','c','t','s','=',0};
424 static const WCHAR dtrW
[] = {'d','t','r','=',0};
425 static const WCHAR rtsW
[] = {'r','t','s','=',0};
426 static const WCHAR idsrW
[] = {'i','d','s','r','=',0};
430 while(*device
== ' ') device
++;
432 if(!strncmpiW(baudW
, device
, 5))
436 if(!(device
= COMM_ParseNumber(device
+ 5, &lpdcb
->BaudRate
)))
439 else if(!strncmpiW(parityW
, device
, 7))
441 if(!(device
= COMM_ParseParity(device
+ 7, &lpdcb
->Parity
)))
444 else if(!strncmpiW(dataW
, device
, 5))
446 if(!(device
= COMM_ParseByteSize(device
+ 5, &lpdcb
->ByteSize
)))
449 else if(!strncmpiW(stopW
, device
, 5))
453 if(!(device
= COMM_ParseStopBits(device
+ 5, &lpdcb
->StopBits
)))
456 else if(!strncmpiW(toW
, device
, 3))
458 if(!(device
= COMM_ParseOnOff(device
+ 3, &temp
)))
461 lptimeouts
->ReadIntervalTimeout
= 0;
462 lptimeouts
->ReadTotalTimeoutMultiplier
= 0;
463 lptimeouts
->ReadTotalTimeoutConstant
= 0;
464 lptimeouts
->WriteTotalTimeoutMultiplier
= 0;
465 lptimeouts
->WriteTotalTimeoutConstant
= temp
? 60000 : 0;
467 else if(!strncmpiW(xonW
, device
, 4))
469 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
475 else if(!strncmpiW(odsrW
, device
, 5))
477 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
480 lpdcb
->fOutxDsrFlow
= temp
;
482 else if(!strncmpiW(octsW
, device
, 5))
484 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
487 lpdcb
->fOutxCtsFlow
= temp
;
489 else if(!strncmpiW(dtrW
, device
, 4))
491 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
494 lpdcb
->fDtrControl
= temp
;
496 else if(!strncmpiW(rtsW
, device
, 4))
498 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
501 lpdcb
->fRtsControl
= temp
;
503 else if(!strncmpiW(idsrW
, device
, 5))
505 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
508 /* Win NT sets the fDsrSensitivity member based on the
509 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
510 lpdcb
->fDsrSensitivity
= temp
;
515 /* After the above parsing, the next character (if not the end of
516 the string) should be a space */
517 if(*device
&& *device
!= ' ')
521 /* If stop bits were not specified, a default is always supplied. */
524 if(baud
&& lpdcb
->BaudRate
== 110)
525 lpdcb
->StopBits
= TWOSTOPBITS
;
527 lpdcb
->StopBits
= ONESTOPBIT
;
533 /**************************************************************************
534 * BuildCommDCBA (KERNEL32.@)
536 * Updates a device control block data structure with values from an
537 * ascii device control string. The device control string has two forms
538 * normal and extended, it must be exclusively in one or the other form.
542 * True on success, false on a malformed control string.
544 BOOL WINAPI
BuildCommDCBA(
545 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
546 LPDCB lpdcb
) /* [out] The device control block to be updated. */
548 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
551 /**************************************************************************
552 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
554 * Updates a device control block data structure with values from an
555 * ascii device control string. Taking timeout values from a timeouts
556 * struct if desired by the control string.
560 * True on success, false bad handles etc.
562 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
563 LPCSTR device
, /* [in] The ascii device control string. */
564 LPDCB lpdcb
, /* [out] The device control block to be updated. */
565 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
568 UNICODE_STRING deviceW
;
570 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
571 if(device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
,device
);
572 else deviceW
.Buffer
= NULL
;
574 if(deviceW
.Buffer
) ret
= BuildCommDCBAndTimeoutsW(deviceW
.Buffer
,lpdcb
,lptimeouts
);
576 RtlFreeUnicodeString(&deviceW
);
580 /**************************************************************************
581 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
583 * Updates a device control block data structure with values from a
584 * unicode device control string. Taking timeout values from a timeouts
585 * struct if desired by the control string.
589 * True on success, false bad handles etc
591 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
592 LPCWSTR devid
, /* [in] The unicode device control string. */
593 LPDCB lpdcb
, /* [out] The device control block to be updated. */
594 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
597 COMMTIMEOUTS timeouts
;
601 TRACE("(%s,%p,%p)\n",debugstr_w(devid
),lpdcb
,lptimeouts
);
603 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
604 lpdcb
->DCBlength
= sizeof(DCB
);
606 /* Make a copy of the original data structures to work with since if
607 if there is an error in the device control string the originals
608 should not be modified (except possibly DCBlength) */
609 memcpy(&dcb
, lpdcb
, sizeof(DCB
));
610 if(lptimeouts
) memcpy(&timeouts
, lptimeouts
, sizeof(COMMTIMEOUTS
));
612 ptr
= COMM_ParseStart(ptr
);
616 else if(strchrW(ptr
, ','))
617 result
= COMM_BuildOldCommDCB(ptr
, &dcb
);
619 result
= COMM_BuildNewCommDCB(ptr
, &dcb
, &timeouts
);
623 memcpy(lpdcb
, &dcb
, sizeof(DCB
));
624 if(lptimeouts
) memcpy(lptimeouts
, &timeouts
, sizeof(COMMTIMEOUTS
));
629 WARN("Invalid device control string: %s\n", debugstr_w(devid
));
630 SetLastError(ERROR_INVALID_PARAMETER
);
635 /**************************************************************************
636 * BuildCommDCBW (KERNEL32.@)
638 * Updates a device control block structure with values from an
639 * unicode device control string. The device control string has two forms
640 * normal and extended, it must be exclusively in one or the other form.
644 * True on success, false on a malformed control string.
646 BOOL WINAPI
BuildCommDCBW(
647 LPCWSTR devid
, /* [in] The unicode device control string. */
648 LPDCB lpdcb
) /* [out] The device control block to be updated. */
650 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
653 /*****************************************************************************
654 * SetCommBreak (KERNEL32.@)
656 * Halts the transmission of characters to a communications device.
659 * handle [in] The communications device to suspend
663 * True on success, and false if the communications device could not be found,
664 * the control is not supported.
668 * Only TIOCSBRK and TIOCCBRK are supported.
670 BOOL WINAPI
SetCommBreak(HANDLE handle
)
672 return DeviceIoControl(handle
, IOCTL_SERIAL_SET_BREAK_ON
, NULL
, 0, NULL
, 0, NULL
, NULL
);
675 /*****************************************************************************
676 * ClearCommBreak (KERNEL32.@)
678 * Resumes character transmission from a communication device.
682 * handle [in] The halted communication device whose character transmission is to be resumed
686 * True on success and false if the communications device could not be found.
690 * Only TIOCSBRK and TIOCCBRK are supported.
692 BOOL WINAPI
ClearCommBreak(HANDLE handle
)
694 return DeviceIoControl(handle
, IOCTL_SERIAL_SET_BREAK_OFF
, NULL
, 0, NULL
, 0, NULL
, NULL
);
697 /*****************************************************************************
698 * EscapeCommFunction (KERNEL32.@)
700 * Directs a communication device to perform an extended function.
704 * True or requested data on successful completion of the command,
705 * false if the device is not present cannot execute the command
706 * or the command failed.
708 BOOL WINAPI
EscapeCommFunction(
709 HANDLE handle
, /* [in] The communication device to perform the extended function. */
710 UINT nFunction
) /* [in] The extended function to be performed. */
712 int fd
,direct
=FALSE
,result
=FALSE
;
715 TRACE("handle %p, function=%d\n", handle
, nFunction
);
716 fd
= get_comm_fd( handle
, FILE_READ_DATA
);
717 if(fd
<0) return FALSE
;
719 if (tcgetattr(fd
,&port
) == -1) {
720 release_comm_fd( handle
, fd
);
733 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
741 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
749 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
757 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
763 port
.c_iflag
|= IXOFF
;
768 port
.c_iflag
|= IXON
;
774 result
= ioctl(fd
,TIOCSBRK
,0);
781 result
= ioctl(fd
,TIOCCBRK
,0);
785 WARN("(handle=%p,nFunction=%d): Unknown function\n",
791 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
792 release_comm_fd( handle
, fd
);
805 release_comm_fd( handle
, fd
);
809 /********************************************************************
810 * PurgeComm (KERNEL32.@)
812 * Terminates pending operations and/or discards buffers on a
813 * communication resource.
817 * handle [in] The communication resource to be purged
818 * flags [in] Flags for clear pending/buffer on input/output
822 * True on success and false if the communications handle is bad.
824 BOOL WINAPI
PurgeComm(HANDLE handle
, DWORD flags
)
826 return DeviceIoControl(handle
, IOCTL_SERIAL_PURGE
, &flags
, sizeof(flags
),
827 NULL
, 0, NULL
, NULL
);
830 /*****************************************************************************
831 * ClearCommError (KERNEL32.@)
833 * Enables further I/O operations on a communications resource after
834 * supplying error and current status information.
838 * handle [in] The communication resource with the error
839 * errors [out] Flags indicating error the resource experienced
840 * lpStat [out] The status of the communication resource
843 * True on success, false if the communication resource handle is bad.
845 BOOL WINAPI
ClearCommError(HANDLE handle
, LPDWORD errors
, LPCOMSTAT lpStat
)
849 if (!DeviceIoControl(handle
, IOCTL_SERIAL_GET_COMMSTATUS
, NULL
, 0,
850 &ss
, sizeof(ss
), NULL
, NULL
))
856 if (ss
.Errors
& SERIAL_ERROR_BREAK
) *errors
|= CE_BREAK
;
857 if (ss
.Errors
& SERIAL_ERROR_FRAMING
) *errors
|= CE_FRAME
;
858 if (ss
.Errors
& SERIAL_ERROR_OVERRUN
) *errors
|= CE_OVERRUN
;
859 if (ss
.Errors
& SERIAL_ERROR_QUEUEOVERRUN
) *errors
|= CE_RXOVER
;
860 if (ss
.Errors
& SERIAL_ERROR_PARITY
) *errors
|= CE_RXPARITY
;
865 memset(lpStat
, 0, sizeof(*lpStat
));
867 if (ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_CTS
) lpStat
->fCtsHold
= TRUE
;
868 if (ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_DSR
) lpStat
->fDsrHold
= TRUE
;
869 if (ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_DCD
) lpStat
->fRlsdHold
= TRUE
;
870 if (ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_XON
) lpStat
->fXoffHold
= TRUE
;
871 if (ss
.HoldReasons
& SERIAL_TX_WAITING_XOFF_SENT
) lpStat
->fXoffSent
= TRUE
;
872 if (ss
.EofReceived
) lpStat
->fEof
= TRUE
;
873 if (ss
.WaitForImmediate
) lpStat
->fTxim
= TRUE
;
874 lpStat
->cbInQue
= ss
.AmountInInQueue
;
875 lpStat
->cbOutQue
= ss
.AmountInOutQueue
;
880 /*****************************************************************************
881 * SetupComm (KERNEL32.@)
883 * Called after CreateFile to hint to the communication resource to use
884 * specified sizes for input and output buffers rather than the default values.
888 * True if successful, false if the communications resource handle is bad.
894 BOOL WINAPI
SetupComm(
895 HANDLE handle
, /* [in] The just created communication resource handle. */
896 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
897 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
901 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
902 fd
=get_comm_fd( handle
, FILE_READ_DATA
);
903 if(0>fd
) return FALSE
;
904 release_comm_fd( handle
, fd
);
908 /*****************************************************************************
909 * GetCommMask (KERNEL32.@)
911 * Obtain the events associated with a communication device that will cause
912 * a call WaitCommEvent to return.
916 * handle [in] The communications device
917 * evtmask [out] The events which cause WaitCommEvent to return
921 * True on success, fail on bad device handle etc.
923 BOOL WINAPI
GetCommMask(HANDLE handle
, LPDWORD evtmask
)
925 TRACE("handle %p, mask %p\n", handle
, evtmask
);
926 return DeviceIoControl(handle
, IOCTL_SERIAL_GET_WAIT_MASK
,
927 NULL
, 0, evtmask
, sizeof(*evtmask
), NULL
, NULL
);
930 /*****************************************************************************
931 * SetCommMask (KERNEL32.@)
933 * There be some things we need to hear about yon there communications device.
934 * (Set which events associated with a communication device should cause
935 * a call WaitCommEvent to return.)
939 * handle [in] The communications device
940 * evtmask [in] The events that are to be monitored
944 * True on success, false on bad handle etc.
946 BOOL WINAPI
SetCommMask(HANDLE handle
, DWORD evtmask
)
948 TRACE("handle %p, mask %lx\n", handle
, evtmask
);
949 return DeviceIoControl(handle
, IOCTL_SERIAL_SET_WAIT_MASK
,
950 &evtmask
, sizeof(evtmask
), NULL
, 0, NULL
, NULL
);
953 static void dump_dcb(const DCB
* lpdcb
)
955 TRACE("bytesize=%d baudrate=%ld fParity=%d Parity=%d stopbits=%d\n",
956 lpdcb
->ByteSize
, lpdcb
->BaudRate
, lpdcb
->fParity
, lpdcb
->Parity
,
957 (lpdcb
->StopBits
== ONESTOPBIT
) ? 1 :
958 (lpdcb
->StopBits
== TWOSTOPBITS
) ? 2 : 0);
959 TRACE("%sIXON %sIXOFF\n", (lpdcb
->fInX
) ? "" : "~", (lpdcb
->fOutX
) ? "" : "~");
960 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb
->fOutxCtsFlow
, lpdcb
->fRtsControl
);
961 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb
->fOutxDsrFlow
, lpdcb
->fDtrControl
);
962 if (lpdcb
->fOutxCtsFlow
|| lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
)
968 /*****************************************************************************
969 * SetCommState (KERNEL32.@)
971 * Re-initializes all hardware and control settings of a communications device,
972 * with values from a device control block without effecting the input and output
977 * handle [in] The communications device
978 * lpdcb [out] The device control block
982 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
984 BOOL WINAPI
SetCommState( HANDLE handle
, LPDCB lpdcb
)
986 SERIAL_BAUD_RATE sbr
;
987 SERIAL_LINE_CONTROL slc
;
993 SetLastError(ERROR_INVALID_PARAMETER
);
998 sbr
.BaudRate
= lpdcb
->BaudRate
;
1000 slc
.StopBits
= lpdcb
->StopBits
;
1001 slc
.Parity
= lpdcb
->Parity
;
1002 slc
.WordLength
= lpdcb
->ByteSize
;
1004 shf
.ControlHandShake
= 0;
1005 shf
.FlowReplace
= 0;
1006 if (lpdcb
->fOutxCtsFlow
) shf
.ControlHandShake
|= SERIAL_CTS_HANDSHAKE
;
1007 if (lpdcb
->fOutxDsrFlow
) shf
.ControlHandShake
|= SERIAL_DSR_HANDSHAKE
;
1008 switch (lpdcb
->fDtrControl
)
1010 case DTR_CONTROL_DISABLE
: break;
1011 case DTR_CONTROL_ENABLE
: shf
.ControlHandShake
|= SERIAL_DTR_CONTROL
; break;
1012 case DTR_CONTROL_HANDSHAKE
: shf
.ControlHandShake
|= SERIAL_DTR_HANDSHAKE
;break;
1014 SetLastError(ERROR_INVALID_PARAMETER
);
1017 switch (lpdcb
->fDtrControl
)
1019 case RTS_CONTROL_DISABLE
: break;
1020 case RTS_CONTROL_ENABLE
: shf
.FlowReplace
|= SERIAL_RTS_CONTROL
; break;
1021 case RTS_CONTROL_HANDSHAKE
: shf
.FlowReplace
|= SERIAL_RTS_HANDSHAKE
; break;
1022 case RTS_CONTROL_TOGGLE
: shf
.FlowReplace
|= SERIAL_RTS_CONTROL
|
1023 SERIAL_RTS_HANDSHAKE
; break;
1025 SetLastError(ERROR_INVALID_PARAMETER
);
1028 if (lpdcb
->fDsrSensitivity
) shf
.ControlHandShake
|= SERIAL_DSR_SENSITIVITY
;
1029 if (lpdcb
->fAbortOnError
) shf
.ControlHandShake
|= SERIAL_ERROR_ABORT
;
1031 if (lpdcb
->fErrorChar
) shf
.FlowReplace
|= SERIAL_ERROR_CHAR
;
1032 if (lpdcb
->fNull
) shf
.FlowReplace
|= SERIAL_NULL_STRIPPING
;
1033 if (lpdcb
->fTXContinueOnXoff
) shf
.FlowReplace
|= SERIAL_XOFF_CONTINUE
;
1034 if (lpdcb
->fOutX
) shf
.FlowReplace
|= SERIAL_AUTO_TRANSMIT
;
1035 if (lpdcb
->fInX
) shf
.FlowReplace
|= SERIAL_AUTO_RECEIVE
;
1037 shf
.XonLimit
= lpdcb
->XonLim
;
1038 shf
.XoffLimit
= lpdcb
->XoffLim
;
1040 sc
.EofChar
= lpdcb
->EofChar
;
1041 sc
.ErrorChar
= lpdcb
->ErrorChar
;
1043 sc
.EventChar
= lpdcb
->EvtChar
;
1044 sc
.XonChar
= lpdcb
->XonChar
;
1045 sc
.XoffChar
= lpdcb
->XoffChar
;
1047 /* note: change DTR/RTS lines after setting the comm attributes,
1048 * so flow control does not interfere.
1050 return (DeviceIoControl(handle
, IOCTL_SERIAL_SET_BAUD_RATE
,
1051 &sbr
, sizeof(sbr
), NULL
, 0, NULL
, NULL
) &&
1052 DeviceIoControl(handle
, IOCTL_SERIAL_SET_LINE_CONTROL
,
1053 &slc
, sizeof(slc
), NULL
, 0, NULL
, NULL
) &&
1054 DeviceIoControl(handle
, IOCTL_SERIAL_SET_HANDFLOW
,
1055 &shf
, sizeof(shf
), NULL
, 0, NULL
, NULL
) &&
1056 DeviceIoControl(handle
, IOCTL_SERIAL_SET_CHARS
,
1057 &sc
, sizeof(sc
), NULL
, 0, NULL
, NULL
));
1061 /*****************************************************************************
1062 * GetCommState (KERNEL32.@)
1064 * Fills in a device control block with information from a communications device.
1067 * handle [in] The communications device
1068 * lpdcb [out] The device control block
1072 * True on success, false if the communication device handle is bad etc
1076 * XonChar and XoffChar are not set.
1078 BOOL WINAPI
GetCommState(HANDLE handle
, LPDCB lpdcb
)
1080 SERIAL_BAUD_RATE sbr
;
1081 SERIAL_LINE_CONTROL slc
;
1082 SERIAL_HANDFLOW shf
;
1084 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1088 SetLastError(ERROR_INVALID_PARAMETER
);
1092 if (!DeviceIoControl(handle
, IOCTL_SERIAL_GET_BAUD_RATE
,
1093 NULL
, 0, &sbr
, sizeof(sbr
), NULL
, NULL
) ||
1094 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_LINE_CONTROL
,
1095 NULL
, 0, &slc
, sizeof(slc
), NULL
, NULL
) ||
1096 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_HANDFLOW
,
1097 NULL
, 0, &shf
, sizeof(shf
), NULL
, NULL
))
1100 memset(lpdcb
, 0, sizeof(*lpdcb
));
1101 lpdcb
->DCBlength
= sizeof(*lpdcb
);
1103 /* yes, they seem no never be (re)set on NT */
1107 lpdcb
->BaudRate
= sbr
.BaudRate
;
1109 lpdcb
->StopBits
= slc
.StopBits
;
1110 lpdcb
->Parity
= slc
.Parity
;
1111 lpdcb
->ByteSize
= slc
.WordLength
;
1113 if (shf
.ControlHandShake
& SERIAL_CTS_HANDSHAKE
) lpdcb
->fOutxCtsFlow
= 1;
1114 if (shf
.ControlHandShake
& SERIAL_DSR_HANDSHAKE
) lpdcb
->fOutxDsrFlow
= 1;
1115 switch (shf
.ControlHandShake
& (SERIAL_DTR_CONTROL
| SERIAL_DTR_HANDSHAKE
))
1117 case 0: lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
; break;
1118 case SERIAL_DTR_CONTROL
: lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
; break;
1119 case SERIAL_DTR_HANDSHAKE
: lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
; break;
1121 switch (shf
.FlowReplace
& (SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
))
1123 case 0: lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
; break;
1124 case SERIAL_RTS_CONTROL
: lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
; break;
1125 case SERIAL_RTS_HANDSHAKE
: lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
; break;
1126 case SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
:
1127 lpdcb
->fRtsControl
= RTS_CONTROL_TOGGLE
; break;
1129 if (shf
.ControlHandShake
& SERIAL_DSR_SENSITIVITY
) lpdcb
->fDsrSensitivity
= 1;
1130 if (shf
.ControlHandShake
& SERIAL_ERROR_ABORT
) lpdcb
->fAbortOnError
= 1;
1131 if (shf
.FlowReplace
& SERIAL_ERROR_CHAR
) lpdcb
->fErrorChar
= 1;
1132 if (shf
.FlowReplace
& SERIAL_NULL_STRIPPING
) lpdcb
->fNull
= 1;
1133 if (shf
.FlowReplace
& SERIAL_XOFF_CONTINUE
) lpdcb
->fTXContinueOnXoff
= 1;
1134 lpdcb
->XonLim
= shf
.XonLimit
;
1135 lpdcb
->XoffLim
= shf
.XoffLimit
;
1137 if (shf
.FlowReplace
& SERIAL_AUTO_TRANSMIT
) lpdcb
->fOutX
= 1;
1138 if (shf
.FlowReplace
& SERIAL_AUTO_RECEIVE
) lpdcb
->fInX
= 1;
1151 /*****************************************************************************
1152 * TransmitCommChar (KERNEL32.@)
1154 * Transmits a single character in front of any pending characters in the
1155 * output buffer. Usually used to send an interrupt character to a host.
1158 * hComm [in] The communication device in need of a command character
1159 * chTransmit [in] The character to transmit
1163 * True if the call succeeded, false if the previous command character to the
1164 * same device has not been sent yet the handle is bad etc.
1167 BOOL WINAPI
TransmitCommChar(HANDLE hComm
, CHAR chTransmit
)
1169 return DeviceIoControl(hComm
, IOCTL_SERIAL_IMMEDIATE_CHAR
,
1170 &chTransmit
, sizeof(chTransmit
), NULL
, 0, NULL
, NULL
);
1174 /*****************************************************************************
1175 * GetCommTimeouts (KERNEL32.@)
1177 * Obtains the request timeout values for the communications device.
1181 * True on success, false if communications device handle is bad
1182 * or the target structure is null.
1184 BOOL WINAPI
GetCommTimeouts(
1185 HANDLE hComm
, /* [in] The communications device. */
1186 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request timeouts. */
1190 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1194 SetLastError(ERROR_INVALID_PARAMETER
);
1198 SERVER_START_REQ( get_serial_info
)
1200 req
->handle
= hComm
;
1201 if ((ret
= !wine_server_call_err( req
)))
1203 lptimeouts
->ReadIntervalTimeout
= reply
->readinterval
;
1204 lptimeouts
->ReadTotalTimeoutMultiplier
= reply
->readmult
;
1205 lptimeouts
->ReadTotalTimeoutConstant
= reply
->readconst
;
1206 lptimeouts
->WriteTotalTimeoutMultiplier
= reply
->writemult
;
1207 lptimeouts
->WriteTotalTimeoutConstant
= reply
->writeconst
;
1214 /*****************************************************************************
1215 * SetCommTimeouts (KERNEL32.@)
1217 * Sets the timeouts used when reading and writing data to/from COMM ports.
1219 * ReadIntervalTimeout
1220 * - converted and passes to linux kernel as c_cc[VTIME]
1221 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1222 * - used in ReadFile to calculate GetOverlappedResult's timeout
1223 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1224 * - used in WriteFile to calculate GetOverlappedResult's timeout
1228 * True if the timeouts were set, false otherwise.
1230 BOOL WINAPI
SetCommTimeouts(
1231 HANDLE hComm
, /* [in] handle of COMM device */
1232 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
1236 struct termios tios
;
1238 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1242 SetLastError(ERROR_INVALID_PARAMETER
);
1246 SERVER_START_REQ( set_serial_info
)
1248 req
->handle
= hComm
;
1249 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
1250 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
1251 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
1252 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
1253 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
1254 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
1255 ret
= !wine_server_call_err( req
);
1258 if (!ret
) return FALSE
;
1260 /* FIXME: move this stuff to the server */
1261 fd
= get_comm_fd( hComm
, FILE_READ_DATA
);
1262 if (fd
< 0) return FALSE
;
1264 if (-1==tcgetattr(fd
,&tios
)) {
1265 FIXME("tcgetattr on fd %d failed!\n",fd
);
1266 release_comm_fd( hComm
, fd
);
1270 /* VTIME is in 1/10 seconds */
1272 unsigned int ux_timeout
;
1274 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
1280 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
1283 ux_timeout
= 1; /* must be at least some timeout */
1286 tios
.c_cc
[VTIME
] = ux_timeout
;
1289 if (-1==tcsetattr(fd
,0,&tios
)) {
1290 FIXME("tcsetattr on fd %d failed!\n",fd
);
1291 release_comm_fd( hComm
, fd
);
1294 release_comm_fd( hComm
, fd
);
1298 /***********************************************************************
1299 * GetCommModemStatus (KERNEL32.@)
1301 * Obtains the four control register bits if supported by the hardware.
1305 * hFile [in] The communications device
1306 * lpModemStat [out] The control register bits
1310 * True if the communications handle was good and for hardware that
1311 * control register access, false otherwise.
1313 BOOL WINAPI
GetCommModemStatus(HANDLE hFile
, LPDWORD lpModemStat
)
1315 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_MODEMSTATUS
,
1316 NULL
, 0, lpModemStat
, sizeof(DWORD
), NULL
, NULL
);
1319 static DWORD WINAPI
Comm_CheckEvents(int fd
, DWORD mask
, serial_irq_info
*new, serial_irq_info
*old
, DWORD new_mstat
, DWORD old_mstat
)
1321 DWORD ret
= 0, queue
;
1323 TRACE("mask 0x%08lx\n", mask
);
1324 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old
->rx
, new->rx
);
1325 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old
->tx
, new->tx
);
1326 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old
->frame
, new->frame
);
1327 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old
->overrun
, new->overrun
);
1328 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old
->parity
, new->parity
);
1329 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old
->brk
, new->brk
);
1330 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old
->buf_overrun
, new->buf_overrun
);
1332 ret
|= ((mask
& EV_BREAK
) && ( old
->brk
!= new->brk
))?EV_BREAK
:0;
1333 ret
|= ((mask
& EV_CTS
) && ((old_mstat
&MS_CTS_ON
)!=(new_mstat
&MS_CTS_ON
)))?EV_CTS
:0;
1334 ret
|= ((mask
& EV_DSR
) && ((old_mstat
&MS_DSR_ON
)!=(new_mstat
&MS_DSR_ON
)))?EV_DSR
:0;
1335 ret
|= ((mask
& EV_RING
) && ((old_mstat
&MS_RING_ON
)!=(new_mstat
&MS_RING_ON
)))?EV_RING
:0;
1336 ret
|= ((mask
& EV_RLSD
) && ((old_mstat
&MS_RLSD_ON
)!=(new_mstat
&MS_RLSD_ON
)))?EV_RLSD
:0;
1337 ret
|= ((mask
& EV_ERR
) && (( old
->frame
!= new->frame
) ||(old
->overrun
!= new->overrun
)
1338 || (old
->parity
!= new->parity
)) )?EV_ERR
:0;
1339 if (mask
& EV_RXCHAR
)
1343 if(ioctl(fd
, TIOCINQ
, &queue
))
1344 WARN("TIOCINQ returned error\n");
1349 if (mask
& EV_TXEMPTY
)
1352 /* We really want to know when all characters have gone out of the transmitter */
1353 #if defined(TIOCSERGETLSR)
1354 if(ioctl(fd
, TIOCSERGETLSR
, &queue
))
1355 WARN("TIOCSERGETLSR returned error\n");
1357 /* TIOCINQ only checks for an empty buffer */
1358 #elif defined(TIOCINQ)
1359 if(ioctl(fd
, TIOCOUTQ
, &queue
))
1360 WARN("TIOCOUTQ returned error\n");
1365 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue
, (ret
& EV_TXEMPTY
)?"":"not ");
1370 /***********************************************************************
1371 * COMM_WaitCommEventService (INTERNAL)
1373 * We need to poll for what is interesting
1374 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1377 static DWORD WINAPI
COMM_WaitCommEventService(LPVOID arg
)
1379 async_commio
*commio
= (async_commio
*) arg
;
1382 serial_irq_info new_irq_info
;
1383 DWORD new_mstat
, new_evtmask
;
1385 fd
=get_comm_fd( commio
->handle
, FILE_READ_DATA
);
1387 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1388 commio
->handle
, fd
, commio
->evtmask
, commio
->buffer
, commio
->hEvent
, &commio
->irq_info
, waitmask
);
1392 * TIOCMIWAIT is not adequate
1395 * We don't handle the EV_RXFLAG (the eventchar)
1398 rc
= COMM_GetEInfo(fd
,&new_irq_info
);
1400 TRACE("TIOCGICOUNT err %s\n", strerror(errno
));
1401 rc
= GetCommModemStatus(commio
->handle
, &new_mstat
);
1403 TRACE("GetCommModemStatus failed\n");
1404 rc
= Comm_CheckEvents(fd
, commio
->evtmask
,&new_irq_info
,&commio
->irq_info
, new_mstat
, commio
->mstat
);
1405 GetCommMask(commio
->handle
, &new_evtmask
);
1406 abort
= (commio
->evtmask
!= new_evtmask
);
1407 TRACE("resulting Eventmask 0x%08x\n", rc
);
1408 } while (!rc
&& ! abort
);
1410 release_comm_fd( commio
->handle
, fd
);
1411 *commio
->buffer
= rc
;
1412 if (commio
->hEvent
!= INVALID_HANDLE_VALUE
)
1413 NtSetEvent( commio
->hEvent
, NULL
);
1414 HeapFree(GetProcessHeap(), 0, commio
);
1419 /***********************************************************************
1420 * COMM_WaitCommEvent (INTERNAL)
1422 * This function must have an lpOverlapped.
1424 static BOOL
COMM_WaitCommEvent(
1425 HANDLE hFile
, /* [in] handle of comm port to wait for */
1426 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1427 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1430 async_commio
* commio
;
1436 SetLastError(ERROR_INVALID_PARAMETER
);
1440 if (NtResetEvent(lpOverlapped
->hEvent
,NULL
))
1443 fd
= get_comm_fd( hFile
, FILE_WRITE_DATA
);
1444 if (fd
< 0) return FALSE
;
1446 commio
= HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio
));
1449 release_comm_fd( hFile
, fd
);
1453 commio
->handle
= hFile
;
1454 commio
->buffer
= (char *)lpdwEvents
;
1455 commio
->hEvent
= lpOverlapped
->hEvent
;
1456 GetCommMask(hFile
, &commio
->evtmask
);
1458 /* We may never return, if some capabilities miss
1459 * Return error in that case
1461 #if !defined(TIOCINQ)
1462 if(commio
->evtmask
& EV_RXCHAR
)
1465 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1466 if(commio
->evtmask
& EV_TXEMPTY
)
1469 #if !defined(TIOCMGET)
1470 if(commio
->evtmask
& (EV_CTS
| EV_DSR
| EV_RING
| EV_RLSD
))
1473 #if !defined(TIOCM_CTS)
1474 if(commio
->evtmask
& EV_CTS
)
1477 #if !defined(TIOCM_DSR)
1478 if(commio
->evtmask
& EV_DSR
)
1481 #if !defined(TIOCM_RNG)
1482 if(commio
->evtmask
& EV_RING
)
1485 #if !defined(TIOCM_CAR)
1486 if(commio
->evtmask
& EV_RLSD
)
1489 if(commio
->evtmask
& EV_RXFLAG
)
1490 FIXME("EV_RXFLAG not handled\n");
1491 COMM_GetEInfo(fd
,&commio
->irq_info
);
1492 GetCommModemStatus(hFile
, &commio
->mstat
);
1493 /* We might have received something or the TX bufffer is delivered*/
1494 result_mask
= Comm_CheckEvents( fd
, commio
->evtmask
, &commio
->irq_info
, &commio
->irq_info
,commio
->mstat
,commio
->mstat
);
1497 TRACE("Event already met\n");
1498 *lpdwEvents
= result_mask
;
1499 HeapFree(GetProcessHeap(), 0, commio
);
1504 CreateThread(NULL
, 0, COMM_WaitCommEventService
, (LPVOID
)commio
, 0, NULL
);
1505 SetLastError(ERROR_IO_PENDING
);
1508 release_comm_fd( hFile
, fd
);
1510 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
1512 FIXME("Returning error because of missing capabilities\n");
1513 release_comm_fd( hFile
, fd
);
1514 HeapFree(GetProcessHeap(), 0, commio
);
1515 SetLastError(ERROR_INVALID_PARAMETER
);
1519 /***********************************************************************
1520 * WaitCommEvent (KERNEL32.@)
1522 * Wait until something interesting happens on a COMM port.
1523 * Interesting things (events) are set by calling SetCommMask before
1524 * this function is called.
1527 * TRUE if successful
1530 * The set of detected events will be written to *lpdwEventMask
1531 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1534 * Only supports EV_RXCHAR and EV_TXEMPTY
1536 BOOL WINAPI
WaitCommEvent(
1537 HANDLE hFile
, /* [in] handle of comm port to wait for */
1538 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
1539 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
1545 TRACE("(%p %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
1548 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
1550 /* if there is no overlapped structure, create our own */
1551 ov
.hEvent
= CreateEventW(NULL
,FALSE
,FALSE
,NULL
);
1553 res
= COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
1554 err
= GetLastError();
1557 if (err
== ERROR_IO_PENDING
)
1561 res
= WaitForSingleObjectEx(ov
.hEvent
, INFINITE
, FALSE
);
1562 } while (res
!= WAIT_OBJECT_0
);
1563 TRACE("Event met\n:");
1568 FIXME("Unknown error 0x%08lx\n", err
);
1574 CloseHandle(ov
.hEvent
);
1579 /***********************************************************************
1580 * GetCommProperties (KERNEL32.@)
1582 * This function fills in a structure with the capabilities of the
1583 * communications port driver.
1587 * TRUE on success, FALSE on failure
1588 * If successful, the lpCommProp structure be filled in with
1589 * properties of the comm port.
1591 BOOL WINAPI
GetCommProperties(
1592 HANDLE hFile
, /* [in] handle of the comm port */
1593 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
1595 FIXME("(%p %p )\n",hFile
,lpCommProp
);
1600 * These values should be valid for LINUX's serial driver
1601 * FIXME: Perhaps they deserve an #ifdef LINUX
1603 memset(lpCommProp
,0,sizeof(COMMPROP
));
1604 lpCommProp
->wPacketLength
= 1;
1605 lpCommProp
->wPacketVersion
= 1;
1606 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
1607 lpCommProp
->dwReserved1
= 0;
1608 lpCommProp
->dwMaxTxQueue
= 4096;
1609 lpCommProp
->dwMaxRxQueue
= 4096;
1610 lpCommProp
->dwMaxBaud
= BAUD_115200
;
1611 lpCommProp
->dwProvSubType
= PST_RS232
;
1612 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
| PCF_TOTALTIMEOUTS
;
1613 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
1614 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
1615 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
1616 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
1617 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
1618 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
1619 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
1620 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
1621 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
1622 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
1627 /***********************************************************************
1629 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1630 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1631 * This is dependent on the type of COMM port, but since it is doubtful
1632 * anybody will get around to implementing support for fancy serial
1633 * ports in WINE, this is hardcoded for the time being. The name of
1634 * this DLL should be stored in and read from the system registry in
1635 * the hive HKEY_LOCAL_MACHINE, key
1636 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1637 * where ???? is the port number... that is determined by PNP
1638 * The DLL should be loaded when the COMM port is opened, and closed
1639 * when the COMM port is closed. - MJM 20 June 2000
1640 ***********************************************************************/
1641 static const WCHAR lpszSerialUI
[] = {
1642 's','e','r','i','a','l','u','i','.','d','l','l',0 };
1645 /***********************************************************************
1646 * CommConfigDialogA (KERNEL32.@)
1648 * Raises a dialog that allows the user to configure a comm port.
1649 * Fills the COMMCONFIG struct with information specified by the user.
1650 * This function should call a similar routine in the COMM driver...
1654 * TRUE on success, FALSE on failure
1655 * If successful, the lpCommConfig structure will contain a new
1656 * configuration for the comm port, as specified by the user.
1659 * The library with the CommConfigDialog code is never unloaded.
1660 * Perhaps this should be done when the comm port is closed?
1662 BOOL WINAPI
CommConfigDialogA(
1663 LPCSTR lpszDevice
, /* [in] name of communications device */
1664 HWND hWnd
, /* [in] parent window for the dialog */
1665 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
1667 FARPROC lpfnCommDialog
;
1668 HMODULE hConfigModule
;
1671 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
1673 hConfigModule
= LoadLibraryW(lpszSerialUI
);
1677 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogA");
1680 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
1682 FreeLibrary(hConfigModule
);
1687 /***********************************************************************
1688 * CommConfigDialogW (KERNEL32.@)
1690 * See CommConfigDialogA.
1692 BOOL WINAPI
CommConfigDialogW(
1693 LPCWSTR lpszDevice
, /* [in] name of communications device */
1694 HWND hWnd
, /* [in] parent window for the dialog */
1695 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
1697 FARPROC lpfnCommDialog
;
1698 HMODULE hConfigModule
;
1701 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
1703 hConfigModule
= LoadLibraryW(lpszSerialUI
);
1707 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogW");
1710 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
1712 FreeLibrary(hConfigModule
);
1717 /***********************************************************************
1718 * GetCommConfig (KERNEL32.@)
1720 * Fill in the COMMCONFIG structure for the comm port hFile
1724 * TRUE on success, FALSE on failure
1725 * If successful, lpCommConfig contains the comm port configuration.
1730 BOOL WINAPI
GetCommConfig(
1731 HANDLE hFile
, /* [in] The communications device. */
1732 LPCOMMCONFIG lpCommConfig
, /* [out] The communications configuration of the device (if it fits). */
1733 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
1734 afterwards the number of bytes copied to the buffer or
1735 the needed size of the buffer. */
1739 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
1741 if(lpCommConfig
== NULL
)
1743 r
= *lpdwSize
< sizeof(COMMCONFIG
); /* TRUE if not enough space */
1744 *lpdwSize
= sizeof(COMMCONFIG
);
1748 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
1749 lpCommConfig
->wVersion
= 1;
1750 lpCommConfig
->wReserved
= 0;
1751 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
1752 lpCommConfig
->dwProviderSubType
= PST_RS232
;
1753 lpCommConfig
->dwProviderOffset
= 0;
1754 lpCommConfig
->dwProviderSize
= 0;
1759 /***********************************************************************
1760 * SetCommConfig (KERNEL32.@)
1762 * Sets the configuration of the communications device.
1766 * True on success, false if the handle was bad is not a communications device.
1768 BOOL WINAPI
SetCommConfig(
1769 HANDLE hFile
, /* [in] The communications device. */
1770 LPCOMMCONFIG lpCommConfig
, /* [in] The desired configuration. */
1771 DWORD dwSize
) /* [in] size of the lpCommConfig struct */
1773 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
1774 return SetCommState(hFile
,&lpCommConfig
->dcb
);
1777 /***********************************************************************
1778 * SetDefaultCommConfigA (KERNEL32.@)
1780 * Initializes the default configuration for the specified communication
1785 * True if the device was found and the defaults set, false otherwise
1787 BOOL WINAPI
SetDefaultCommConfigW(
1788 LPCWSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
1789 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
1790 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
1792 FARPROC lpfnSetDefaultCommConfig
;
1793 HMODULE hConfigModule
;
1796 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
1798 hConfigModule
= LoadLibraryW(lpszSerialUI
);
1802 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvSetDefaultCommConfigW");
1803 if (lpfnSetDefaultCommConfig
)
1804 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
1806 FreeLibrary(hConfigModule
);
1812 /***********************************************************************
1813 * SetDefaultCommConfigW (KERNEL32.@)
1815 * Initializes the default configuration for the specified
1816 * communication device. (unicode)
1821 BOOL WINAPI
SetDefaultCommConfigA(
1822 LPCSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
1823 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
1824 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
1827 LPWSTR lpDeviceW
= NULL
;
1830 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice
),lpCommConfig
,dwSize
);
1834 len
= MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, NULL
, 0 );
1835 lpDeviceW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
1836 MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, lpDeviceW
, len
);
1838 r
= SetDefaultCommConfigW(lpDeviceW
,lpCommConfig
,dwSize
);
1839 HeapFree( GetProcessHeap(), 0, lpDeviceW
);
1844 /***********************************************************************
1845 * GetDefaultCommConfigW (KERNEL32.@)
1847 * Acquires the default configuration of the specified communication device. (unicode)
1851 * True on successful reading of the default configuration,
1852 * if the device is not found or the buffer is too small.
1854 BOOL WINAPI
GetDefaultCommConfigW(
1855 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
1856 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
1857 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
1858 afterwards the number of bytes copied to the buffer or
1859 the needed size of the buffer. */
1861 LPDCB lpdcb
= &(lpCC
->dcb
);
1863 static const WCHAR comW
[] = {'C','O','M',0};
1864 static const WCHAR formatW
[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
1866 if (strncmpiW(lpszName
,comW
,3)) {
1867 ERR("not implemented for <%s>\n", debugstr_w(lpszName
));
1871 TRACE("(%s %p %ld)\n", debugstr_w(lpszName
), lpCC
, *lpdwSize
);
1872 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
1873 *lpdwSize
= sizeof(COMMCONFIG
);
1877 *lpdwSize
= sizeof(COMMCONFIG
);
1879 lpCC
->dwSize
= sizeof(COMMCONFIG
);
1881 lpCC
->dwProviderSubType
= PST_RS232
;
1882 lpCC
->dwProviderOffset
= 0L;
1883 lpCC
->dwProviderSize
= 0L;
1885 sprintfW( temp
, formatW
, lpszName
[3]);
1886 FIXME("setting %s as default\n", debugstr_w(temp
));
1888 return BuildCommDCBW( temp
, lpdcb
);
1891 /**************************************************************************
1892 * GetDefaultCommConfigA (KERNEL32.@)
1894 * Acquires the default configuration of the specified communication device. (ascii)
1898 * True on successful reading of the default configuration,
1899 * if the device is not found or the buffer is too small.
1901 BOOL WINAPI
GetDefaultCommConfigA(
1902 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
1903 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
1904 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
1905 afterwards the number of bytes copied to the buffer or
1906 the needed size of the buffer. */
1909 UNICODE_STRING lpszNameW
;
1911 TRACE("(%s,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
1912 if(lpszName
) RtlCreateUnicodeStringFromAsciiz(&lpszNameW
,lpszName
);
1913 else lpszNameW
.Buffer
= NULL
;
1915 if(lpszNameW
.Buffer
) ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
1917 RtlFreeUnicodeString(&lpszNameW
);