2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
49 #ifdef HAVE_SYS_POLL_H
50 # include <sys/poll.h>
52 #ifdef HAVE_SYS_MODEM_H
53 # include <sys/modem.h>
55 #ifdef HAVE_SYS_STRTIO_H
56 # include <sys/strtio.h>
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
66 #include "wine/server.h"
67 #include "wine/unicode.h"
69 #include "wine/debug.h"
71 #ifdef HAVE_LINUX_SERIAL_H
72 #include <linux/serial.h>
75 WINE_DEFAULT_DEBUG_CHANNEL(comm
);
77 /* retrieve the Unix handle corresponding to a comm handle */
78 static int get_comm_fd( HANDLE handle
, DWORD access
)
82 ret
= wine_server_handle_to_fd( handle
, access
, &fd
, NULL
);
83 if (ret
) SetLastError( RtlNtStatusToDosError(ret
) );
87 /* release the Unix handle returned by get_comm_fd */
88 static inline void release_comm_fd( HANDLE handle
, int fd
)
90 wine_server_release_fd( handle
, fd
);
94 * local structure holding the irq values we need for WaitCommEvent()
96 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
97 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
98 * no need to carry them in the internal structure
101 typedef struct serial_irq_info
103 int rx
, tx
, frame
, overrun
, parity
, brk
, buf_overrun
;
106 /***********************************************************************
107 * Data needed by the thread polling for the changing CommEvent
109 typedef struct async_commio
116 serial_irq_info irq_info
;
119 /***********************************************************************/
121 #if !defined(TIOCINQ) && defined(FIONREAD)
122 #define TIOCINQ FIONREAD
125 /***********************************************************************
126 * Get extended interrupt count info, needed for WaitCommEvent
128 static int COMM_GetEInfo(int fd
, serial_irq_info
*irq_info
)
131 struct serial_icounter_struct einfo
;
132 if (!ioctl(fd
,TIOCGICOUNT
, &einfo
))
134 irq_info
->rx
= einfo
.rx
;
135 irq_info
->tx
= einfo
.tx
;
136 irq_info
->frame
= einfo
.frame
;
137 irq_info
->overrun
= einfo
.overrun
;
138 irq_info
->parity
= einfo
.parity
;
139 irq_info
->brk
= einfo
.brk
;
140 irq_info
->buf_overrun
= einfo
.buf_overrun
;
144 memset(irq_info
,0, sizeof(serial_irq_info
));
148 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
151 unsigned int mstat
, okay
;
152 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
153 if (okay
) return okay
;
154 if (andy
) mstat
&= andy
;
156 return ioctl(fd
, TIOCMSET
, &mstat
);
162 /***********************************************************************
163 * COMM_Parse* (Internal)
165 * The following COMM_Parse* functions are used by the BuildCommDCB
166 * functions to help parse the various parts of the device control string.
168 static LPCWSTR
COMM_ParseStart(LPCWSTR ptr
)
170 static const WCHAR comW
[] = {'C','O','M',0};
172 /* The device control string may optionally start with "COMx" followed
173 by an optional ':' and spaces. */
174 if(!strncmpiW(ptr
, comW
, 3))
178 /* Allow any com port above 0 as Win 9x does (NT only allows
179 values for com ports which are actually present) */
180 if(*ptr
< '1' || *ptr
> '9')
183 /* Advance pointer past port number */
184 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
186 /* The com port number must be followed by a ':' or ' ' */
187 if(*ptr
!= ':' && *ptr
!= ' ')
190 /* Advance pointer to beginning of next parameter */
191 while(*ptr
== ' ') ptr
++;
195 while(*ptr
== ' ') ptr
++;
198 /* The device control string must not start with a space. */
205 static LPCWSTR
COMM_ParseNumber(LPCWSTR ptr
, LPDWORD lpnumber
)
207 if(*ptr
< '0' || *ptr
> '9') return NULL
;
208 *lpnumber
= strtoulW(ptr
, NULL
, 10);
209 while(*ptr
>= '0' && *ptr
<= '9') ptr
++;
213 static LPCWSTR
COMM_ParseParity(LPCWSTR ptr
, LPBYTE lpparity
)
215 /* Contrary to what you might expect, Windows only sets the Parity
216 member of DCB and not fParity even when parity is specified in the
217 device control string */
219 switch(toupperW(*ptr
++))
222 *lpparity
= EVENPARITY
;
225 *lpparity
= MARKPARITY
;
228 *lpparity
= NOPARITY
;
231 *lpparity
= ODDPARITY
;
234 *lpparity
= SPACEPARITY
;
243 static LPCWSTR
COMM_ParseByteSize(LPCWSTR ptr
, LPBYTE lpbytesize
)
247 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
250 if(temp
>= 5 && temp
<= 8)
259 static LPCWSTR
COMM_ParseStopBits(LPCWSTR ptr
, LPBYTE lpstopbits
)
262 static const WCHAR stopbits15W
[] = {'1','.','5',0};
264 if(!strncmpW(stopbits15W
, ptr
, 3))
267 *lpstopbits
= ONE5STOPBITS
;
271 if(!(ptr
= COMM_ParseNumber(ptr
, &temp
)))
275 *lpstopbits
= ONESTOPBIT
;
277 *lpstopbits
= TWOSTOPBITS
;
285 static LPCWSTR
COMM_ParseOnOff(LPCWSTR ptr
, LPDWORD lponoff
)
287 static const WCHAR onW
[] = {'o','n',0};
288 static const WCHAR offW
[] = {'o','f','f',0};
290 if(!strncmpiW(onW
, ptr
, 2))
295 else if(!strncmpiW(offW
, ptr
, 3))
306 /***********************************************************************
307 * COMM_BuildOldCommDCB (Internal)
309 * Build a DCB using the old style settings string eg: "96,n,8,1"
311 static BOOL
COMM_BuildOldCommDCB(LPCWSTR device
, LPDCB lpdcb
)
315 if(!(device
= COMM_ParseNumber(device
, &lpdcb
->BaudRate
)))
318 switch(lpdcb
->BaudRate
)
323 lpdcb
->BaudRate
*= 10;
329 lpdcb
->BaudRate
*= 100;
332 lpdcb
->BaudRate
= 19200;
336 while(*device
== ' ') device
++;
337 if(*device
++ != ',') return FALSE
;
338 while(*device
== ' ') device
++;
340 if(!(device
= COMM_ParseParity(device
, &lpdcb
->Parity
)))
343 while(*device
== ' ') device
++;
344 if(*device
++ != ',') return FALSE
;
345 while(*device
== ' ') device
++;
347 if(!(device
= COMM_ParseByteSize(device
, &lpdcb
->ByteSize
)))
350 while(*device
== ' ') device
++;
351 if(*device
++ != ',') return FALSE
;
352 while(*device
== ' ') device
++;
354 if(!(device
= COMM_ParseStopBits(device
, &lpdcb
->StopBits
)))
357 /* The last parameter for flow control is optional. */
358 while(*device
== ' ') device
++;
362 while(*device
== ' ') device
++;
363 if(*device
) last
= toupperW(*device
++);
364 while(*device
== ' ') device
++;
367 /* Win NT sets the flow control members based on (or lack of) the last
368 parameter. Win 9x does not set these members. */
373 lpdcb
->fOutX
= FALSE
;
374 lpdcb
->fOutxCtsFlow
= FALSE
;
375 lpdcb
->fOutxDsrFlow
= FALSE
;
376 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
377 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
382 lpdcb
->fOutxCtsFlow
= FALSE
;
383 lpdcb
->fOutxDsrFlow
= FALSE
;
384 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
385 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
389 lpdcb
->fOutX
= FALSE
;
390 lpdcb
->fOutxCtsFlow
= TRUE
;
391 lpdcb
->fOutxDsrFlow
= TRUE
;
392 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
393 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
399 /* This should be the end of the string. */
400 if(*device
) return FALSE
;
405 /***********************************************************************
406 * COMM_BuildNewCommDCB (Internal)
408 * Build a DCB using the new style settings string.
409 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
411 static BOOL
COMM_BuildNewCommDCB(LPCWSTR device
, LPDCB lpdcb
, LPCOMMTIMEOUTS lptimeouts
)
414 BOOL baud
= FALSE
, stop
= FALSE
;
415 static const WCHAR baudW
[] = {'b','a','u','d','=',0};
416 static const WCHAR parityW
[] = {'p','a','r','i','t','y','=',0};
417 static const WCHAR dataW
[] = {'d','a','t','a','=',0};
418 static const WCHAR stopW
[] = {'s','t','o','p','=',0};
419 static const WCHAR toW
[] = {'t','o','=',0};
420 static const WCHAR xonW
[] = {'x','o','n','=',0};
421 static const WCHAR odsrW
[] = {'o','d','s','r','=',0};
422 static const WCHAR octsW
[] = {'o','c','t','s','=',0};
423 static const WCHAR dtrW
[] = {'d','t','r','=',0};
424 static const WCHAR rtsW
[] = {'r','t','s','=',0};
425 static const WCHAR idsrW
[] = {'i','d','s','r','=',0};
429 while(*device
== ' ') device
++;
431 if(!strncmpiW(baudW
, device
, 5))
435 if(!(device
= COMM_ParseNumber(device
+ 5, &lpdcb
->BaudRate
)))
438 else if(!strncmpiW(parityW
, device
, 7))
440 if(!(device
= COMM_ParseParity(device
+ 7, &lpdcb
->Parity
)))
443 else if(!strncmpiW(dataW
, device
, 5))
445 if(!(device
= COMM_ParseByteSize(device
+ 5, &lpdcb
->ByteSize
)))
448 else if(!strncmpiW(stopW
, device
, 5))
452 if(!(device
= COMM_ParseStopBits(device
+ 5, &lpdcb
->StopBits
)))
455 else if(!strncmpiW(toW
, device
, 3))
457 if(!(device
= COMM_ParseOnOff(device
+ 3, &temp
)))
460 lptimeouts
->ReadIntervalTimeout
= 0;
461 lptimeouts
->ReadTotalTimeoutMultiplier
= 0;
462 lptimeouts
->ReadTotalTimeoutConstant
= 0;
463 lptimeouts
->WriteTotalTimeoutMultiplier
= 0;
464 lptimeouts
->WriteTotalTimeoutConstant
= temp
? 60000 : 0;
466 else if(!strncmpiW(xonW
, device
, 4))
468 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
474 else if(!strncmpiW(odsrW
, device
, 5))
476 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
479 lpdcb
->fOutxDsrFlow
= temp
;
481 else if(!strncmpiW(octsW
, device
, 5))
483 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
486 lpdcb
->fOutxCtsFlow
= temp
;
488 else if(!strncmpiW(dtrW
, device
, 4))
490 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
493 lpdcb
->fDtrControl
= temp
;
495 else if(!strncmpiW(rtsW
, device
, 4))
497 if(!(device
= COMM_ParseOnOff(device
+ 4, &temp
)))
500 lpdcb
->fRtsControl
= temp
;
502 else if(!strncmpiW(idsrW
, device
, 5))
504 if(!(device
= COMM_ParseOnOff(device
+ 5, &temp
)))
507 /* Win NT sets the fDsrSensitivity member based on the
508 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
509 lpdcb
->fDsrSensitivity
= temp
;
514 /* After the above parsing, the next character (if not the end of
515 the string) should be a space */
516 if(*device
&& *device
!= ' ')
520 /* If stop bits were not specified, a default is always supplied. */
523 if(baud
&& lpdcb
->BaudRate
== 110)
524 lpdcb
->StopBits
= TWOSTOPBITS
;
526 lpdcb
->StopBits
= ONESTOPBIT
;
532 /**************************************************************************
533 * BuildCommDCBA (KERNEL32.@)
535 * Updates a device control block data structure with values from an
536 * ascii device control string. The device control string has two forms
537 * normal and extended, it must be exclusively in one or the other form.
541 * True on success, false on a malformed control string.
543 BOOL WINAPI
BuildCommDCBA(
544 LPCSTR device
, /* [in] The ascii device control string used to update the DCB. */
545 LPDCB lpdcb
) /* [out] The device control block to be updated. */
547 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
550 /**************************************************************************
551 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
553 * Updates a device control block data structure with values from an
554 * ascii device control string. Taking timeout values from a timeouts
555 * struct if desired by the control string.
559 * True on success, false bad handles etc.
561 BOOL WINAPI
BuildCommDCBAndTimeoutsA(
562 LPCSTR device
, /* [in] The ascii device control string. */
563 LPDCB lpdcb
, /* [out] The device control block to be updated. */
564 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
567 UNICODE_STRING deviceW
;
569 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
570 if(device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
,device
);
571 else deviceW
.Buffer
= NULL
;
573 if(deviceW
.Buffer
) ret
= BuildCommDCBAndTimeoutsW(deviceW
.Buffer
,lpdcb
,lptimeouts
);
575 RtlFreeUnicodeString(&deviceW
);
579 /**************************************************************************
580 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
582 * Updates a device control block data structure with values from a
583 * unicode device control string. Taking timeout values from a timeouts
584 * struct if desired by the control string.
588 * True on success, false bad handles etc
590 BOOL WINAPI
BuildCommDCBAndTimeoutsW(
591 LPCWSTR devid
, /* [in] The unicode device control string. */
592 LPDCB lpdcb
, /* [out] The device control block to be updated. */
593 LPCOMMTIMEOUTS lptimeouts
) /* [in] The COMMTIMEOUTS structure to be updated. */
596 COMMTIMEOUTS timeouts
;
600 TRACE("(%s,%p,%p)\n",debugstr_w(devid
),lpdcb
,lptimeouts
);
602 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
603 lpdcb
->DCBlength
= sizeof(DCB
);
605 /* Make a copy of the original data structures to work with since if
606 if there is an error in the device control string the originals
607 should not be modified (except possibly DCBlength) */
608 memcpy(&dcb
, lpdcb
, sizeof(DCB
));
609 if(lptimeouts
) memcpy(&timeouts
, lptimeouts
, sizeof(COMMTIMEOUTS
));
611 ptr
= COMM_ParseStart(ptr
);
615 else if(strchrW(ptr
, ','))
616 result
= COMM_BuildOldCommDCB(ptr
, &dcb
);
618 result
= COMM_BuildNewCommDCB(ptr
, &dcb
, &timeouts
);
622 memcpy(lpdcb
, &dcb
, sizeof(DCB
));
623 if(lptimeouts
) memcpy(lptimeouts
, &timeouts
, sizeof(COMMTIMEOUTS
));
628 WARN("Invalid device control string: %s\n", debugstr_w(devid
));
629 SetLastError(ERROR_INVALID_PARAMETER
);
634 /**************************************************************************
635 * BuildCommDCBW (KERNEL32.@)
637 * Updates a device control block structure with values from an
638 * unicode device control string. The device control string has two forms
639 * normal and extended, it must be exclusively in one or the other form.
643 * True on success, false on a malformed control string.
645 BOOL WINAPI
BuildCommDCBW(
646 LPCWSTR devid
, /* [in] The unicode device control string. */
647 LPDCB lpdcb
) /* [out] The device control block to be updated. */
649 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
652 static BOOL
COMM_SetCommError(HANDLE handle
, DWORD error
)
656 SERVER_START_REQ( set_serial_info
)
658 req
->handle
= handle
;
659 req
->flags
= SERIALINFO_SET_ERROR
;
660 req
->commerror
= error
;
661 ret
= !wine_server_call_err( req
);
667 static BOOL
COMM_GetCommError(HANDLE handle
, LPDWORD lperror
)
674 SERVER_START_REQ( get_serial_info
)
676 req
->handle
= handle
;
677 ret
= !wine_server_call_err( req
);
678 *lperror
= reply
->commerror
;
685 /*****************************************************************************
686 * SetCommBreak (KERNEL32.@)
688 * Halts the transmission of characters to a communications device.
692 * True on success, and false if the communications device could not be found,
693 * the control is not supported.
697 * Only TIOCSBRK and TIOCCBRK are supported.
699 BOOL WINAPI
SetCommBreak(
700 HANDLE handle
) /* [in] The communications device to suspend. */
702 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
705 fd
= get_comm_fd( handle
, GENERIC_READ
);
706 if(fd
<0) return FALSE
;
707 result
= ioctl(fd
,TIOCSBRK
,0);
708 release_comm_fd( handle
, fd
);
711 TRACE("ioctl failed\n");
712 SetLastError(ERROR_NOT_SUPPORTED
);
717 FIXME("ioctl not available\n");
718 SetLastError(ERROR_NOT_SUPPORTED
);
723 /*****************************************************************************
724 * ClearCommBreak (KERNEL32.@)
726 * Resumes character transmission from a communication device.
730 * True on success and false if the communications device could not be found.
734 * Only TIOCSBRK and TIOCCBRK are supported.
736 BOOL WINAPI
ClearCommBreak(
737 HANDLE handle
) /* [in] The halted communication device whose character transmission is to be resumed. */
739 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
742 fd
= get_comm_fd( handle
, GENERIC_READ
);
743 if(fd
<0) return FALSE
;
744 result
= ioctl(fd
,TIOCCBRK
,0);
745 release_comm_fd( handle
, fd
);
748 TRACE("ioctl failed\n");
749 SetLastError(ERROR_NOT_SUPPORTED
);
754 FIXME("ioctl not available\n");
755 SetLastError(ERROR_NOT_SUPPORTED
);
760 /*****************************************************************************
761 * EscapeCommFunction (KERNEL32.@)
763 * Directs a communication device to perform an extended function.
767 * True or requested data on successful completion of the command,
768 * false if the device is not present cannot execute the command
769 * or the command failed.
771 BOOL WINAPI
EscapeCommFunction(
772 HANDLE handle
, /* [in] The communication device to perform the extended function. */
773 UINT nFunction
) /* [in] The extended function to be performed. */
775 int fd
,direct
=FALSE
,result
=FALSE
;
778 TRACE("handle %p, function=%d\n", handle
, nFunction
);
779 fd
= get_comm_fd( handle
, GENERIC_READ
);
780 if(fd
<0) return FALSE
;
782 if (tcgetattr(fd
,&port
) == -1) {
783 COMM_SetCommError(handle
,CE_IOE
);
784 release_comm_fd( handle
, fd
);
797 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
805 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
813 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
821 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
827 port
.c_iflag
|= IXOFF
;
832 port
.c_iflag
|= IXON
;
838 result
= ioctl(fd
,TIOCSBRK
,0);
845 result
= ioctl(fd
,TIOCCBRK
,0);
849 WARN("(handle=%p,nFunction=%d): Unknown function\n",
855 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
856 release_comm_fd( handle
, fd
);
857 COMM_SetCommError(handle
,CE_IOE
);
866 COMM_SetCommError(handle
,CE_IOE
);
871 release_comm_fd( handle
, fd
);
875 /********************************************************************
876 * PurgeComm (KERNEL32.@)
878 * Terminates pending operations and/or discards buffers on a
879 * communication resource.
883 * True on success and false if the communications handle is bad.
885 BOOL WINAPI
PurgeComm(
886 HANDLE handle
, /* [in] The communication resource to be purged. */
887 DWORD flags
) /* [in] Flags for clear pending/buffer on input/output. */
891 TRACE("handle %p, flags %lx\n", handle
, flags
);
893 fd
= get_comm_fd( handle
, GENERIC_READ
);
894 if(fd
<0) return FALSE
;
897 ** not exactly sure how these are different
898 ** Perhaps if we had our own internal queues, one flushes them
899 ** and the other flushes the kernel's buffers.
901 if(flags
&PURGE_TXABORT
)
902 tcflush(fd
,TCOFLUSH
);
903 if(flags
&PURGE_RXABORT
)
904 tcflush(fd
,TCIFLUSH
);
905 if(flags
&PURGE_TXCLEAR
)
906 tcflush(fd
,TCOFLUSH
);
907 if(flags
&PURGE_RXCLEAR
)
908 tcflush(fd
,TCIFLUSH
);
909 release_comm_fd( handle
, fd
);
914 /*****************************************************************************
915 * ClearCommError (KERNEL32.@)
917 * Enables further I/O operations on a communications resource after
918 * supplying error and current status information.
922 * True on success, false if the communication resource handle is bad.
924 BOOL WINAPI
ClearCommError(
925 HANDLE handle
, /* [in] The communication resource with the error. */
926 LPDWORD errors
, /* [out] Flags indicating error the resource experienced. */
927 LPCOMSTAT lpStat
) /* [out] The status of the communication resource. */
931 fd
=get_comm_fd( handle
, GENERIC_READ
);
932 if(0>fd
) return FALSE
;
936 lpStat
->fCtsHold
= 0;
937 lpStat
->fDsrHold
= 0;
938 lpStat
->fRlsdHold
= 0;
939 lpStat
->fXoffHold
= 0;
940 lpStat
->fXoffSent
= 0;
943 lpStat
->fReserved
= 0;
946 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
947 WARN("ioctl returned error\n");
949 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
953 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
954 WARN("ioctl returned error\n");
957 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
958 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
961 release_comm_fd( handle
, fd
);
963 COMM_GetCommError(handle
, errors
);
964 COMM_SetCommError(handle
, 0);
969 /*****************************************************************************
970 * SetupComm (KERNEL32.@)
972 * Called after CreateFile to hint to the communication resource to use
973 * specified sizes for input and output buffers rather than the default values.
977 * True if successful, false if the communications resource handle is bad.
983 BOOL WINAPI
SetupComm(
984 HANDLE handle
, /* [in] The just created communication resource handle. */
985 DWORD insize
, /* [in] The suggested size of the communication resources input buffer in bytes. */
986 DWORD outsize
) /* [in] The suggested size of the communication resources output buffer in bytes. */
990 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
991 fd
=get_comm_fd( handle
, GENERIC_READ
);
992 if(0>fd
) return FALSE
;
993 release_comm_fd( handle
, fd
);
997 /*****************************************************************************
998 * GetCommMask (KERNEL32.@)
1000 * Obtain the events associated with a communication device that will cause
1001 * a call WaitCommEvent to return.
1005 * True on success, fail on bad device handle etc.
1007 BOOL WINAPI
GetCommMask(
1008 HANDLE handle
, /* [in] The communications device. */
1009 LPDWORD evtmask
) /* [out] The events which cause WaitCommEvent to return. */
1013 TRACE("handle %p, mask %p\n", handle
, evtmask
);
1015 SERVER_START_REQ( get_serial_info
)
1017 req
->handle
= handle
;
1018 if ((ret
= !wine_server_call_err( req
)))
1020 if (evtmask
) *evtmask
= reply
->eventmask
;
1027 /*****************************************************************************
1028 * SetCommMask (KERNEL32.@)
1030 * There be some things we need to hear about yon there communications device.
1031 * (Set which events associated with a communication device should cause
1032 * a call WaitCommEvent to return.)
1036 * True on success, false on bad handle etc.
1038 BOOL WINAPI
SetCommMask(
1039 HANDLE handle
, /* [in] The communications device. */
1040 DWORD evtmask
) /* [in] The events that are to be monitored. */
1044 TRACE("handle %p, mask %lx\n", handle
, evtmask
);
1046 SERVER_START_REQ( set_serial_info
)
1048 req
->handle
= handle
;
1049 req
->flags
= SERIALINFO_SET_MASK
;
1050 req
->eventmask
= evtmask
;
1051 ret
= !wine_server_call_err( req
);
1057 /*****************************************************************************
1058 * SetCommState (KERNEL32.@)
1060 * Re-initializes all hardware and control settings of a communications device,
1061 * with values from a device control block without effecting the input and output
1066 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1068 BOOL WINAPI
SetCommState(
1069 HANDLE handle
, /* [in] The communications device. */
1070 LPDCB lpdcb
) /* [out] The device control block. */
1072 struct termios port
;
1073 int fd
, bytesize
, stopbits
;
1076 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1077 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1078 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1079 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1080 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1081 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1082 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1083 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1084 lpdcb
->fRtsControl
);
1085 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1086 lpdcb
->fDtrControl
);
1089 fd
= get_comm_fd( handle
, GENERIC_READ
);
1090 if (fd
< 0) return FALSE
;
1092 if ((tcgetattr(fd
,&port
)) == -1) {
1093 int save_error
= errno
;
1094 COMM_SetCommError(handle
,CE_IOE
);
1095 release_comm_fd( handle
, fd
);
1096 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1100 port
.c_cc
[VMIN
] = 0;
1101 port
.c_cc
[VTIME
] = 1;
1104 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1106 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1108 port
.c_iflag
|= (IGNBRK
);
1110 port
.c_oflag
&= ~(OPOST
);
1112 port
.c_cflag
&= ~(HUPCL
);
1113 port
.c_cflag
|= CLOCAL
| CREAD
;
1115 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1116 port
.c_lflag
|= NOFLSH
;
1119 port
.c_cflag
&= ~CBAUD
;
1120 switch (lpdcb
->BaudRate
) {
1125 port
.c_cflag
|= B50
;
1128 port
.c_cflag
|= B75
;
1132 port
.c_cflag
|= B110
;
1135 port
.c_cflag
|= B134
;
1138 port
.c_cflag
|= B150
;
1141 port
.c_cflag
|= B200
;
1145 port
.c_cflag
|= B300
;
1149 port
.c_cflag
|= B600
;
1153 port
.c_cflag
|= B1200
;
1156 port
.c_cflag
|= B1800
;
1160 port
.c_cflag
|= B2400
;
1164 port
.c_cflag
|= B4800
;
1168 port
.c_cflag
|= B9600
;
1172 port
.c_cflag
|= B19200
;
1176 port
.c_cflag
|= B38400
;
1180 port
.c_cflag
|= B57600
;
1185 port
.c_cflag
|= B115200
;
1190 port
.c_cflag
|= B230400
;
1195 port
.c_cflag
|= B460800
;
1199 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1200 { struct serial_struct nuts
;
1202 ioctl(fd
, TIOCGSERIAL
, &nuts
);
1203 nuts
.custom_divisor
= nuts
.baud_base
/ lpdcb
->BaudRate
;
1204 if (!(nuts
.custom_divisor
)) nuts
.custom_divisor
= 1;
1205 arby
= nuts
.baud_base
/ nuts
.custom_divisor
;
1206 nuts
.flags
&= ~ASYNC_SPD_MASK
;
1207 nuts
.flags
|= ASYNC_SPD_CUST
;
1208 WARN("You (or a program acting at your behest) have specified\n"
1209 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1210 "which is as close as we can get by our present understanding of your\n"
1211 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1212 "has caused to your linux system can be undone with setserial \n"
1213 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1214 "reset it and it will probably recover.\n", lpdcb
->BaudRate
, arby
);
1215 ioctl(fd
, TIOCSSERIAL
, &nuts
);
1216 port
.c_cflag
|= B38400
;
1219 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1222 COMM_SetCommError(handle
,IE_BAUDRATE
);
1223 release_comm_fd( handle
, fd
);
1224 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1227 #elif !defined(__EMX__)
1228 switch (lpdcb
->BaudRate
) {
1233 port
.c_ospeed
= B50
;
1236 port
.c_ospeed
= B75
;
1240 port
.c_ospeed
= B110
;
1243 port
.c_ospeed
= B134
;
1246 port
.c_ospeed
= B150
;
1249 port
.c_ospeed
= B200
;
1253 port
.c_ospeed
= B300
;
1257 port
.c_ospeed
= B600
;
1261 port
.c_ospeed
= B1200
;
1264 port
.c_ospeed
= B1800
;
1268 port
.c_ospeed
= B2400
;
1272 port
.c_ospeed
= B4800
;
1276 port
.c_ospeed
= B9600
;
1280 port
.c_ospeed
= B19200
;
1284 port
.c_ospeed
= B38400
;
1289 port
.c_cflag
|= B57600
;
1295 port
.c_cflag
|= B115200
;
1300 port
.c_cflag
|= B230400
;
1305 port
.c_cflag
|= B460800
;
1309 COMM_SetCommError(handle
,IE_BAUDRATE
);
1310 release_comm_fd( handle
, fd
);
1311 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1314 port
.c_ispeed
= port
.c_ospeed
;
1316 bytesize
=lpdcb
->ByteSize
;
1317 stopbits
=lpdcb
->StopBits
;
1320 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
1322 port
.c_cflag
&= ~(PARENB
| PARODD
);
1325 port
.c_iflag
|= INPCK
;
1327 port
.c_iflag
&= ~INPCK
;
1328 switch (lpdcb
->Parity
) {
1332 port
.c_cflag
|= (PARENB
| PARODD
);
1335 port
.c_cflag
|= PARENB
;
1338 /* Linux defines mark/space (stick) parity */
1340 port
.c_cflag
|= (PARENB
| CMSPAR
);
1343 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1346 /* try the POSIX way */
1348 if( stopbits
== ONESTOPBIT
) {
1349 stopbits
= TWOSTOPBITS
;
1350 port
.c_iflag
&= ~INPCK
;
1352 COMM_SetCommError(handle
,IE_BYTESIZE
);
1353 release_comm_fd( handle
, fd
);
1354 ERR("Cannot set MARK Parity\n");
1361 port
.c_iflag
&= ~INPCK
;
1363 COMM_SetCommError(handle
,IE_BYTESIZE
);
1364 release_comm_fd( handle
, fd
);
1365 ERR("Cannot set SPACE Parity\n");
1371 COMM_SetCommError(handle
,IE_BYTESIZE
);
1372 release_comm_fd( handle
, fd
);
1378 port
.c_cflag
&= ~CSIZE
;
1381 port
.c_cflag
|= CS5
;
1384 port
.c_cflag
|= CS6
;
1387 port
.c_cflag
|= CS7
;
1390 port
.c_cflag
|= CS8
;
1393 COMM_SetCommError(handle
,IE_BYTESIZE
);
1394 release_comm_fd( handle
, fd
);
1401 port
.c_cflag
&= ~CSTOPB
;
1403 case ONE5STOPBITS
: /* will be selected if bytesize is 5 */
1405 port
.c_cflag
|= CSTOPB
;
1408 COMM_SetCommError(handle
,IE_BYTESIZE
);
1409 release_comm_fd( handle
, fd
);
1414 if ( lpdcb
->fOutxCtsFlow
||
1415 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1418 port
.c_cflag
|= CRTSCTS
;
1424 port
.c_iflag
|= IXON
;
1426 port
.c_iflag
&= ~IXON
;
1428 port
.c_iflag
|= IXOFF
;
1430 port
.c_iflag
&= ~IXOFF
;
1432 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
1433 ERR("tcsetattr error '%s'\n", strerror(errno
));
1434 COMM_SetCommError(handle
,CE_IOE
);
1437 COMM_SetCommError(handle
,0);
1441 /* note: change DTR/RTS lines after setting the comm attributes,
1442 * so flow control does not interfere. */
1444 if (lpdcb
->fDtrControl
== DTR_CONTROL_HANDSHAKE
)
1446 WARN("DSR/DTR flow control not supported\n");
1447 } else if(lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
1448 COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1450 COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1453 if(!lpdcb
->fOutxCtsFlow
)
1455 if(lpdcb
->fRtsControl
== RTS_CONTROL_DISABLE
)
1456 COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1458 COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1461 if(lpdcb
->fRtsControl
== RTS_CONTROL_TOGGLE
)
1462 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1463 release_comm_fd( handle
, fd
);
1469 /*****************************************************************************
1470 * GetCommState (KERNEL32.@)
1472 * Fills in a device control block with information from a communications device.
1476 * True on success, false if the communication device handle is bad etc
1480 * XonChar and XoffChar are not set.
1482 BOOL WINAPI
GetCommState(
1483 HANDLE handle
, /* [in] The communications device. */
1484 LPDCB lpdcb
) /* [out] The device control block. */
1486 struct termios port
;
1488 int stat
= DTR_CONTROL_ENABLE
| RTS_CONTROL_ENABLE
;
1490 TRACE("handle %p, ptr %p\n", handle
, lpdcb
);
1492 fd
= get_comm_fd( handle
, GENERIC_READ
);
1493 if (fd
< 0) return FALSE
;
1494 if (tcgetattr(fd
, &port
) == -1) {
1495 int save_error
=errno
;
1496 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1497 COMM_SetCommError(handle
,CE_IOE
);
1498 release_comm_fd( handle
, fd
);
1503 if (ioctl(fd
, TIOCMGET
, &stat
) == -1)
1505 int save_error
=errno
;
1506 WARN("ioctl error '%s'\n", strerror(save_error
));
1507 stat
= DTR_CONTROL_ENABLE
| RTS_CONTROL_ENABLE
;
1510 release_comm_fd( handle
, fd
);
1513 speed
= (port
.c_cflag
& CBAUD
);
1515 speed
= (cfgetospeed(&port
));
1519 lpdcb
->BaudRate
= 0;
1522 lpdcb
->BaudRate
= 50;
1525 lpdcb
->BaudRate
= 75;
1528 lpdcb
->BaudRate
= 110;
1531 lpdcb
->BaudRate
= 134;
1534 lpdcb
->BaudRate
= 150;
1537 lpdcb
->BaudRate
= 200;
1540 lpdcb
->BaudRate
= 300;
1543 lpdcb
->BaudRate
= 600;
1546 lpdcb
->BaudRate
= 1200;
1549 lpdcb
->BaudRate
= 1800;
1552 lpdcb
->BaudRate
= 2400;
1555 lpdcb
->BaudRate
= 4800;
1558 lpdcb
->BaudRate
= 9600;
1561 lpdcb
->BaudRate
= 19200;
1564 lpdcb
->BaudRate
= 38400;
1568 lpdcb
->BaudRate
= 57600;
1573 lpdcb
->BaudRate
= 115200;
1578 lpdcb
->BaudRate
= 230400;
1583 lpdcb
->BaudRate
= 460800;
1587 ERR("unknown speed %x \n",speed
);
1590 switch (port
.c_cflag
& CSIZE
) {
1592 lpdcb
->ByteSize
= 5;
1595 lpdcb
->ByteSize
= 6;
1598 lpdcb
->ByteSize
= 7;
1601 lpdcb
->ByteSize
= 8;
1604 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
1607 if(port
.c_iflag
& INPCK
)
1608 lpdcb
->fParity
= TRUE
;
1610 lpdcb
->fParity
= FALSE
;
1612 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
))
1614 switch (port
.c_cflag
& (PARENB
| PARODD
))
1618 lpdcb
->Parity
= NOPARITY
;
1621 lpdcb
->Parity
= EVENPARITY
;
1623 case (PARENB
| PARODD
):
1624 lpdcb
->Parity
= ODDPARITY
;
1627 case (PARENB
| CMSPAR
):
1628 lpdcb
->Parity
= MARKPARITY
;
1630 case (PARENB
| PARODD
| CMSPAR
):
1631 lpdcb
->Parity
= SPACEPARITY
;
1636 if (port
.c_cflag
& CSTOPB
)
1637 if(lpdcb
->ByteSize
== 5)
1638 lpdcb
->StopBits
= ONE5STOPBITS
;
1640 lpdcb
->StopBits
= TWOSTOPBITS
;
1642 lpdcb
->StopBits
= ONESTOPBIT
;
1647 /* termios does not support DTR/DSR flow control */
1648 lpdcb
->fOutxDsrFlow
= 0;
1649 lpdcb
->fDtrControl
=
1651 !(stat
& TIOCM_DTR
) ? DTR_CONTROL_DISABLE
:
1653 DTR_CONTROL_ENABLE
;
1657 if (port
.c_cflag
& CRTSCTS
) {
1658 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1659 lpdcb
->fOutxCtsFlow
= 1;
1663 lpdcb
->fRtsControl
=
1665 !(stat
& TIOCM_RTS
) ? RTS_CONTROL_DISABLE
:
1667 RTS_CONTROL_ENABLE
;
1668 lpdcb
->fOutxCtsFlow
= 0;
1670 if (port
.c_iflag
& IXON
)
1675 if (port
.c_iflag
& IXOFF
)
1684 lpdcb
->XoffLim
= 10;
1686 COMM_SetCommError(handle
,0);
1690 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1691 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1692 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1693 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1694 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1695 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1696 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb
->fOutxCtsFlow
,
1697 lpdcb
->fRtsControl
);
1698 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb
->fOutxDsrFlow
,
1699 lpdcb
->fDtrControl
);
1701 if ( lpdcb
->fOutxCtsFlow
||
1702 lpdcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
1707 TRACE("~CRTSCTS\n");
1712 /*****************************************************************************
1713 * TransmitCommChar (KERNEL32.@)
1715 * Transmits a single character in front of any pending characters in the
1716 * output buffer. Usually used to send an interrupt character to a host.
1720 * True if the call succeeded, false if the previous command character to the
1721 * same device has not been sent yet the handle is bad etc.
1727 BOOL WINAPI
TransmitCommChar(
1728 HANDLE hComm
, /* [in] The communication device in need of a command character. */
1729 CHAR chTransmit
) /* [in] The character to transmit. */
1732 WARN("(%p,'%c') not perfect!\n",hComm
,chTransmit
);
1734 return WriteFile( hComm
, &chTransmit
, 1, &w
, NULL
);
1738 /*****************************************************************************
1739 * GetCommTimeouts (KERNEL32.@)
1741 * Obtains the request timeout values for the communications device.
1745 * True on success, false if communications device handle is bad
1746 * or the target structure is null.
1748 BOOL WINAPI
GetCommTimeouts(
1749 HANDLE hComm
, /* [in] The communications device. */
1750 LPCOMMTIMEOUTS lptimeouts
) /* [out] The struct of request timeouts. */
1754 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1758 SetLastError(ERROR_INVALID_PARAMETER
);
1762 SERVER_START_REQ( get_serial_info
)
1764 req
->handle
= hComm
;
1765 if ((ret
= !wine_server_call_err( req
)))
1767 lptimeouts
->ReadIntervalTimeout
= reply
->readinterval
;
1768 lptimeouts
->ReadTotalTimeoutMultiplier
= reply
->readmult
;
1769 lptimeouts
->ReadTotalTimeoutConstant
= reply
->readconst
;
1770 lptimeouts
->WriteTotalTimeoutMultiplier
= reply
->writemult
;
1771 lptimeouts
->WriteTotalTimeoutConstant
= reply
->writeconst
;
1778 /*****************************************************************************
1779 * SetCommTimeouts (KERNEL32.@)
1781 * Sets the timeouts used when reading and writing data to/from COMM ports.
1783 * ReadIntervalTimeout
1784 * - converted and passes to linux kernel as c_cc[VTIME]
1785 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1786 * - used in ReadFile to calculate GetOverlappedResult's timeout
1787 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1788 * - used in WriteFile to calculate GetOverlappedResult's timeout
1792 * True if the timeouts were set, false otherwise.
1794 BOOL WINAPI
SetCommTimeouts(
1795 HANDLE hComm
, /* [in] handle of COMM device */
1796 LPCOMMTIMEOUTS lptimeouts
) /* [in] pointer to COMMTIMEOUTS structure */
1800 struct termios tios
;
1802 TRACE("(%p,%p)\n",hComm
,lptimeouts
);
1806 SetLastError(ERROR_INVALID_PARAMETER
);
1810 SERVER_START_REQ( set_serial_info
)
1812 req
->handle
= hComm
;
1813 req
->flags
= SERIALINFO_SET_TIMEOUTS
;
1814 req
->readinterval
= lptimeouts
->ReadIntervalTimeout
;
1815 req
->readmult
= lptimeouts
->ReadTotalTimeoutMultiplier
;
1816 req
->readconst
= lptimeouts
->ReadTotalTimeoutConstant
;
1817 req
->writemult
= lptimeouts
->WriteTotalTimeoutMultiplier
;
1818 req
->writeconst
= lptimeouts
->WriteTotalTimeoutConstant
;
1819 ret
= !wine_server_call_err( req
);
1822 if (!ret
) return FALSE
;
1824 /* FIXME: move this stuff to the server */
1825 fd
= get_comm_fd( hComm
, GENERIC_READ
);
1826 if (fd
< 0) return FALSE
;
1828 if (-1==tcgetattr(fd
,&tios
)) {
1829 FIXME("tcgetattr on fd %d failed!\n",fd
);
1830 release_comm_fd( hComm
, fd
);
1834 /* VTIME is in 1/10 seconds */
1836 unsigned int ux_timeout
;
1838 if(lptimeouts
->ReadIntervalTimeout
== 0) /* 0 means no timeout */
1844 ux_timeout
= (lptimeouts
->ReadIntervalTimeout
+99)/100;
1847 ux_timeout
= 1; /* must be at least some timeout */
1850 tios
.c_cc
[VTIME
] = ux_timeout
;
1853 if (-1==tcsetattr(fd
,0,&tios
)) {
1854 FIXME("tcsetattr on fd %d failed!\n",fd
);
1855 release_comm_fd( hComm
, fd
);
1858 release_comm_fd( hComm
, fd
);
1862 /***********************************************************************
1863 * GetCommModemStatus (KERNEL32.@)
1865 * Obtains the four control register bits if supported by the hardware.
1869 * True if the communications handle was good and for hardware that
1870 * control register access, false otherwise.
1872 BOOL WINAPI
GetCommModemStatus(
1873 HANDLE hFile
, /* [in] The communications device. */
1874 LPDWORD lpModemStat
) /* [out] The control register bits. */
1876 int fd
,mstat
, result
=FALSE
;
1880 fd
= get_comm_fd( hFile
, GENERIC_READ
);
1883 result
= ioctl(fd
, TIOCMGET
, &mstat
);
1884 release_comm_fd( hFile
, fd
);
1887 WARN("ioctl failed\n");
1891 if (mstat
& TIOCM_CTS
)
1892 *lpModemStat
|= MS_CTS_ON
;
1895 if (mstat
& TIOCM_DSR
)
1896 *lpModemStat
|= MS_DSR_ON
;
1899 if (mstat
& TIOCM_RNG
)
1900 *lpModemStat
|= MS_RING_ON
;
1903 /*FIXME: Not really sure about RLSD UB 990810*/
1904 if (mstat
& TIOCM_CAR
)
1905 *lpModemStat
|= MS_RLSD_ON
;
1907 TRACE("%04x -> %s%s%s%s\n", mstat
,
1908 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
1909 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
1910 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
1911 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
1918 static DWORD WINAPI
Comm_CheckEvents(int fd
, DWORD mask
, serial_irq_info
*new, serial_irq_info
*old
, DWORD new_mstat
, DWORD old_mstat
)
1920 DWORD ret
= 0, queue
;
1922 TRACE("mask 0x%08lx\n", mask
);
1923 TRACE("old->rx 0x%08x vs. new->rx 0x%08x \n", old
->rx
, new->rx
);
1924 TRACE("old->tx 0x%08x vs. new->tx 0x%08x \n", old
->tx
, new->tx
);
1925 TRACE("old->frame 0x%08x vs. new->frame 0x%08x \n", old
->frame
, new->frame
);
1926 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x \n", old
->overrun
, new->overrun
);
1927 TRACE("old->parity 0x%08x vs. new->parity 0x%08x \n", old
->parity
, new->parity
);
1928 TRACE("old->brk 0x%08x vs. new->brk 0x%08x \n", old
->brk
, new->brk
);
1929 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x \n", old
->buf_overrun
, new->buf_overrun
);
1931 ret
|= ((mask
& EV_BREAK
) && ( old
->brk
!= new->brk
))?EV_BREAK
:0;
1932 ret
|= ((mask
& EV_CTS
) && ((old_mstat
&MS_CTS_ON
)!=(new_mstat
&MS_CTS_ON
)))?EV_CTS
:0;
1933 ret
|= ((mask
& EV_DSR
) && ((old_mstat
&MS_DSR_ON
)!=(new_mstat
&MS_DSR_ON
)))?EV_DSR
:0;
1934 ret
|= ((mask
& EV_RING
) && ((old_mstat
&MS_RING_ON
)!=(new_mstat
&MS_RING_ON
)))?EV_RING
:0;
1935 ret
|= ((mask
& EV_RLSD
) && ((old_mstat
&MS_RLSD_ON
)!=(new_mstat
&MS_RLSD_ON
)))?EV_RLSD
:0;
1936 ret
|= ((mask
& EV_ERR
) && (( old
->frame
!= new->frame
) ||(old
->overrun
!= new->overrun
)
1937 || (old
->parity
!= new->parity
)) )?EV_ERR
:0;
1938 if (mask
& EV_RXCHAR
)
1942 if(ioctl(fd
, TIOCINQ
, &queue
))
1943 WARN("TIOCINQ returned error\n");
1948 if (mask
& EV_TXEMPTY
)
1951 /* We really want to know when all characters have gone out of the transmitter */
1952 #if defined(TIOCSERGETLSR)
1953 if(ioctl(fd
, TIOCSERGETLSR
, &queue
))
1954 WARN("TIOCSERGETLSR returned error\n");
1956 /* TIOCINQ only checks for an empty buffer */
1957 #elif defined(TIOCINQ)
1958 if(ioctl(fd
, TIOCOUTQ
, &queue
))
1959 WARN("TIOCOUTQ returned error\n");
1964 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue
, (ret
& EV_TXEMPTY
)?"":"not ");
1969 /***********************************************************************
1970 * COMM_WaitCommEventService (INTERNAL)
1972 * We need to poll for what is interesting
1973 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1976 static DWORD WINAPI
COMM_WaitCommEventService(LPVOID arg
)
1978 async_commio
*commio
= (async_commio
*) arg
;
1981 serial_irq_info new_irq_info
;
1982 DWORD new_mstat
, new_evtmask
;
1984 fd
=get_comm_fd( commio
->handle
, GENERIC_READ
);
1986 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1987 commio
->handle
, fd
, commio
->evtmask
, commio
->buffer
, commio
->hEvent
, &commio
->irq_info
, waitmask
);
1991 * TIOCMIWAIT is not adequate
1994 * We don't handle the EV_RXFLAG (the eventchar)
1997 rc
= COMM_GetEInfo(fd
,&new_irq_info
);
1999 TRACE("TIOCGICOUNT err %s\n", strerror(errno
));
2000 rc
= GetCommModemStatus(commio
->handle
, &new_mstat
);
2002 TRACE("GetCommModemStatus failed\n");
2003 rc
= Comm_CheckEvents(fd
, commio
->evtmask
,&new_irq_info
,&commio
->irq_info
, new_mstat
, commio
->mstat
);
2004 GetCommMask(commio
->handle
, &new_evtmask
);
2005 abort
= (commio
->evtmask
!= new_evtmask
);
2006 TRACE("resulting Eventmask 0x%08x\n", rc
);
2007 } while (!rc
&& ! abort
);
2009 release_comm_fd( commio
->handle
, fd
);
2010 *commio
->buffer
= rc
;
2011 if (commio
->hEvent
!= INVALID_HANDLE_VALUE
)
2012 NtSetEvent( commio
->hEvent
, NULL
);
2013 HeapFree(GetProcessHeap(), 0, commio
);
2018 /***********************************************************************
2019 * COMM_WaitCommEvent (INTERNAL)
2021 * This function must have an lpOverlapped.
2023 static BOOL
COMM_WaitCommEvent(
2024 HANDLE hFile
, /* [in] handle of comm port to wait for */
2025 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2026 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2029 async_commio
* commio
;
2035 SetLastError(ERROR_INVALID_PARAMETER
);
2039 if (NtResetEvent(lpOverlapped
->hEvent
,NULL
))
2042 fd
= get_comm_fd( hFile
, GENERIC_WRITE
);
2043 if (fd
< 0) return FALSE
;
2045 commio
= HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio
));
2048 release_comm_fd( hFile
, fd
);
2052 commio
->handle
= hFile
;
2053 commio
->buffer
= (char *)lpdwEvents
;
2054 commio
->hEvent
= lpOverlapped
->hEvent
;
2055 GetCommMask(hFile
, &commio
->evtmask
);
2057 /* We may never return, if some capabilities miss
2058 * Return error in that case
2060 #if !defined(TIOCINQ)
2061 if(commio
->evtmask
& EV_RXCHAR
)
2064 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
2065 if(commio
->evtmask
& EV_TXEMPTY
)
2068 #if !defined(TIOCMGET)
2069 if(commio
->evtmask
& (EV_CTS
| EV_DSR
| EV_RING
| EV_RLSD
))
2072 #if !defined(TIOCM_CTS)
2073 if(commio
->evtmask
& EV_CTS
)
2076 #if !defined(TIOCM_DSR)
2077 if(commio
->evtmask
& EV_DSR
)
2080 #if !defined(TIOCM_RNG)
2081 if(commio
->evtmask
& EV_RING
)
2084 #if !defined(TIOCM_CAR)
2085 if(commio
->evtmask
& EV_RLSD
)
2088 if(commio
->evtmask
& EV_RXFLAG
)
2089 FIXME("EV_RXFLAG not handled\n");
2090 COMM_GetEInfo(fd
,&commio
->irq_info
);
2091 GetCommModemStatus(hFile
, &commio
->mstat
);
2092 /* We might have received something or the TX bufffer is delivered*/
2093 result_mask
= Comm_CheckEvents( fd
, commio
->evtmask
, &commio
->irq_info
, &commio
->irq_info
,commio
->mstat
,commio
->mstat
);
2096 TRACE("Event already met\n");
2097 *lpdwEvents
= result_mask
;
2098 release_comm_fd( commio
->handle
, fd
);
2099 HeapFree(GetProcessHeap(), 0, commio
);
2104 CreateThread(NULL
, 0, COMM_WaitCommEventService
, (LPVOID
)commio
, 0, NULL
);
2105 SetLastError(ERROR_IO_PENDING
);
2109 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2111 FIXME("Returning error because of missing capabilities\n");
2112 HeapFree(GetProcessHeap(), 0, commio
);
2113 SetLastError(ERROR_INVALID_PARAMETER
);
2117 /***********************************************************************
2118 * WaitCommEvent (KERNEL32.@)
2120 * Wait until something interesting happens on a COMM port.
2121 * Interesting things (events) are set by calling SetCommMask before
2122 * this function is called.
2125 * TRUE if successful
2128 * The set of detected events will be written to *lpdwEventMask
2129 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2132 * Only supports EV_RXCHAR and EV_TXEMPTY
2134 BOOL WINAPI
WaitCommEvent(
2135 HANDLE hFile
, /* [in] handle of comm port to wait for */
2136 LPDWORD lpdwEvents
, /* [out] event(s) that were detected */
2137 LPOVERLAPPED lpOverlapped
) /* [in/out] for Asynchronous waiting */
2143 TRACE("(%p %p %p )\n",hFile
, lpdwEvents
,lpOverlapped
);
2146 return COMM_WaitCommEvent(hFile
, lpdwEvents
, lpOverlapped
);
2148 /* if there is no overlapped structure, create our own */
2149 ov
.hEvent
= CreateEventW(NULL
,FALSE
,FALSE
,NULL
);
2151 res
= COMM_WaitCommEvent(hFile
, lpdwEvents
, &ov
);
2152 err
= GetLastError();
2155 if (err
== ERROR_IO_PENDING
)
2159 res
= WaitForSingleObjectEx(ov
.hEvent
, INFINITE
, FALSE
);
2160 } while (res
!= WAIT_OBJECT_0
);
2161 TRACE("Event met\n:");
2166 FIXME("Unknown error 0x%08lx\n", err
);
2172 CloseHandle(ov
.hEvent
);
2177 /***********************************************************************
2178 * GetCommProperties (KERNEL32.@)
2180 * This function fills in a structure with the capabilities of the
2181 * communications port driver.
2185 * TRUE on success, FALSE on failure
2186 * If successful, the lpCommProp structure be filled in with
2187 * properties of the comm port.
2189 BOOL WINAPI
GetCommProperties(
2190 HANDLE hFile
, /* [in] handle of the comm port */
2191 LPCOMMPROP lpCommProp
) /* [out] pointer to struct to be filled */
2193 FIXME("(%p %p )\n",hFile
,lpCommProp
);
2198 * These values should be valid for LINUX's serial driver
2199 * FIXME: Perhaps they deserve an #ifdef LINUX
2201 memset(lpCommProp
,0,sizeof(COMMPROP
));
2202 lpCommProp
->wPacketLength
= 1;
2203 lpCommProp
->wPacketVersion
= 1;
2204 lpCommProp
->dwServiceMask
= SP_SERIALCOMM
;
2205 lpCommProp
->dwReserved1
= 0;
2206 lpCommProp
->dwMaxTxQueue
= 4096;
2207 lpCommProp
->dwMaxRxQueue
= 4096;
2208 lpCommProp
->dwMaxBaud
= BAUD_115200
;
2209 lpCommProp
->dwProvSubType
= PST_RS232
;
2210 lpCommProp
->dwProvCapabilities
= PCF_DTRDSR
| PCF_PARITY_CHECK
| PCF_RTSCTS
| PCF_TOTALTIMEOUTS
;
2211 lpCommProp
->dwSettableParams
= SP_BAUD
| SP_DATABITS
| SP_HANDSHAKING
|
2212 SP_PARITY
| SP_PARITY_CHECK
| SP_STOPBITS
;
2213 lpCommProp
->dwSettableBaud
= BAUD_075
| BAUD_110
| BAUD_134_5
| BAUD_150
|
2214 BAUD_300
| BAUD_600
| BAUD_1200
| BAUD_1800
| BAUD_2400
| BAUD_4800
|
2215 BAUD_9600
| BAUD_19200
| BAUD_38400
| BAUD_57600
| BAUD_115200
;
2216 lpCommProp
->wSettableData
= DATABITS_5
| DATABITS_6
| DATABITS_7
| DATABITS_8
;
2217 lpCommProp
->wSettableStopParity
= STOPBITS_10
| STOPBITS_15
| STOPBITS_20
|
2218 PARITY_NONE
| PARITY_ODD
|PARITY_EVEN
| PARITY_MARK
| PARITY_SPACE
;
2219 lpCommProp
->dwCurrentTxQueue
= lpCommProp
->dwMaxTxQueue
;
2220 lpCommProp
->dwCurrentRxQueue
= lpCommProp
->dwMaxRxQueue
;
2225 /***********************************************************************
2227 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2228 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2229 * This is dependent on the type of COMM port, but since it is doubtful
2230 * anybody will get around to implementing support for fancy serial
2231 * ports in WINE, this is hardcoded for the time being. The name of
2232 * this DLL should be stored in and read from the system registry in
2233 * the hive HKEY_LOCAL_MACHINE, key
2234 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2235 * where ???? is the port number... that is determined by PNP
2236 * The DLL should be loaded when the COMM port is opened, and closed
2237 * when the COMM port is closed. - MJM 20 June 2000
2238 ***********************************************************************/
2239 static WCHAR lpszSerialUI
[] = {
2240 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2243 /***********************************************************************
2244 * CommConfigDialogA (KERNEL32.@)
2246 * Raises a dialog that allows the user to configure a comm port.
2247 * Fills the COMMCONFIG struct with information specified by the user.
2248 * This function should call a similar routine in the COMM driver...
2252 * TRUE on success, FALSE on failure
2253 * If successful, the lpCommConfig structure will contain a new
2254 * configuration for the comm port, as specified by the user.
2257 * The library with the CommConfigDialog code is never unloaded.
2258 * Perhaps this should be done when the comm port is closed?
2260 BOOL WINAPI
CommConfigDialogA(
2261 LPCSTR lpszDevice
, /* [in] name of communications device */
2262 HWND hWnd
, /* [in] parent window for the dialog */
2263 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2265 FARPROC lpfnCommDialog
;
2266 HMODULE hConfigModule
;
2269 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2271 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2275 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogA");
2278 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2280 FreeLibrary(hConfigModule
);
2285 /***********************************************************************
2286 * CommConfigDialogW (KERNEL32.@)
2288 * see CommConfigDialogA for more info
2290 BOOL WINAPI
CommConfigDialogW(
2291 LPCWSTR lpszDevice
, /* [in] name of communications device */
2292 HWND hWnd
, /* [in] parent window for the dialog */
2293 LPCOMMCONFIG lpCommConfig
) /* [out] pointer to struct to fill */
2295 FARPROC lpfnCommDialog
;
2296 HMODULE hConfigModule
;
2299 TRACE("(%p %p %p)\n",lpszDevice
, hWnd
, lpCommConfig
);
2301 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2305 lpfnCommDialog
= GetProcAddress(hConfigModule
, "drvCommConfigDialogW");
2308 r
= lpfnCommDialog(lpszDevice
,hWnd
,lpCommConfig
);
2310 FreeLibrary(hConfigModule
);
2315 /***********************************************************************
2316 * GetCommConfig (KERNEL32.@)
2318 * Fill in the COMMCONFIG structure for the comm port hFile
2322 * TRUE on success, FALSE on failure
2323 * If successful, lpCommConfig contains the comm port configuration.
2328 BOOL WINAPI
GetCommConfig(
2329 HANDLE hFile
, /* [in] The communications device. */
2330 LPCOMMCONFIG lpCommConfig
, /* [out] The communications configuration of the device (if it fits). */
2331 LPDWORD lpdwSize
) /* [in/out] Initially the size of the configuration buffer/structure,
2332 afterwards the number of bytes copied to the buffer or
2333 the needed size of the buffer. */
2337 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2339 if(lpCommConfig
== NULL
)
2341 r
= *lpdwSize
< sizeof(COMMCONFIG
); /* TRUE if not enough space */
2342 *lpdwSize
= sizeof(COMMCONFIG
);
2346 lpCommConfig
->dwSize
= sizeof(COMMCONFIG
);
2347 lpCommConfig
->wVersion
= 1;
2348 lpCommConfig
->wReserved
= 0;
2349 r
= GetCommState(hFile
,&lpCommConfig
->dcb
);
2350 lpCommConfig
->dwProviderSubType
= PST_RS232
;
2351 lpCommConfig
->dwProviderOffset
= 0;
2352 lpCommConfig
->dwProviderSize
= 0;
2357 /***********************************************************************
2358 * SetCommConfig (KERNEL32.@)
2360 * Sets the configuration of the communications device.
2364 * True on success, false if the handle was bad is not a communications device.
2366 BOOL WINAPI
SetCommConfig(
2367 HANDLE hFile
, /* [in] The communications device. */
2368 LPCOMMCONFIG lpCommConfig
, /* [in] The desired configuration. */
2369 DWORD dwSize
) /* [in] size of the lpCommConfig struct */
2371 TRACE("(%p %p)\n",hFile
,lpCommConfig
);
2372 return SetCommState(hFile
,&lpCommConfig
->dcb
);
2375 /***********************************************************************
2376 * SetDefaultCommConfigA (KERNEL32.@)
2378 * Initializes the default configuration for the specified communication
2383 * True if the device was found and the defaults set, false otherwise
2385 BOOL WINAPI
SetDefaultCommConfigW(
2386 LPCWSTR lpszDevice
, /* [in] The ascii name of the device targeted for configuration. */
2387 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2388 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2390 FARPROC lpfnSetDefaultCommConfig
;
2391 HMODULE hConfigModule
;
2394 TRACE("(%p %p %lx)\n",lpszDevice
, lpCommConfig
, dwSize
);
2396 hConfigModule
= LoadLibraryW(lpszSerialUI
);
2400 lpfnSetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvSetDefaultCommConfigW");
2401 if (lpfnSetDefaultCommConfig
)
2402 r
= lpfnSetDefaultCommConfig(lpszDevice
, lpCommConfig
, dwSize
);
2404 FreeLibrary(hConfigModule
);
2410 /***********************************************************************
2411 * SetDefaultCommConfigW (KERNEL32.@)
2413 * Initializes the default configuration for the specified
2414 * communication device. (unicode)
2419 BOOL WINAPI
SetDefaultCommConfigA(
2420 LPCSTR lpszDevice
, /* [in] The unicode name of the device targeted for configuration. */
2421 LPCOMMCONFIG lpCommConfig
, /* [in] The default configuration for the device. */
2422 DWORD dwSize
) /* [in] The number of bytes in the configuration structure. */
2425 LPWSTR lpDeviceW
= NULL
;
2428 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice
),lpCommConfig
,dwSize
);
2432 len
= MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, NULL
, 0 );
2433 lpDeviceW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
2434 MultiByteToWideChar( CP_ACP
, 0, lpszDevice
, -1, lpDeviceW
, len
);
2436 r
= SetDefaultCommConfigW(lpDeviceW
,lpCommConfig
,dwSize
);
2437 HeapFree( GetProcessHeap(), 0, lpDeviceW
);
2442 /***********************************************************************
2443 * GetDefaultCommConfigW (KERNEL32.@)
2445 * Acquires the default configuration of the specified communication device. (unicode)
2449 * True on successful reading of the default configuration,
2450 * if the device is not found or the buffer is too small.
2452 BOOL WINAPI
GetDefaultCommConfigW(
2453 LPCWSTR lpszName
, /* [in] The unicode name of the device targeted for configuration. */
2454 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2455 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2456 afterwards the number of bytes copied to the buffer or
2457 the needed size of the buffer. */
2459 LPDCB lpdcb
= &(lpCC
->dcb
);
2461 static const WCHAR comW
[] = {'C','O','M',0};
2462 static const WCHAR formatW
[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2464 if (strncmpiW(lpszName
,comW
,3)) {
2465 ERR("not implemented for <%s>\n", debugstr_w(lpszName
));
2469 TRACE("(%s %p %ld)\n", debugstr_w(lpszName
), lpCC
, *lpdwSize
);
2470 if (*lpdwSize
< sizeof(COMMCONFIG
)) {
2471 *lpdwSize
= sizeof(COMMCONFIG
);
2475 *lpdwSize
= sizeof(COMMCONFIG
);
2477 lpCC
->dwSize
= sizeof(COMMCONFIG
);
2479 lpCC
->dwProviderSubType
= PST_RS232
;
2480 lpCC
->dwProviderOffset
= 0L;
2481 lpCC
->dwProviderSize
= 0L;
2483 sprintfW( temp
, formatW
, lpszName
[3]);
2484 FIXME("setting %s as default\n", debugstr_w(temp
));
2486 return BuildCommDCBW( temp
, lpdcb
);
2489 /**************************************************************************
2490 * GetDefaultCommConfigA (KERNEL32.@)
2492 * Acquires the default configuration of the specified communication device. (ascii)
2496 * True on successful reading of the default configuration,
2497 * if the device is not found or the buffer is too small.
2499 BOOL WINAPI
GetDefaultCommConfigA(
2500 LPCSTR lpszName
, /* [in] The ascii name of the device targeted for configuration. */
2501 LPCOMMCONFIG lpCC
, /* [out] The default configuration for the device. */
2502 LPDWORD lpdwSize
) /* [in/out] Initially the size of the default configuration buffer,
2503 afterwards the number of bytes copied to the buffer or
2504 the needed size of the buffer. */
2507 UNICODE_STRING lpszNameW
;
2509 TRACE("(%s,%p,%ld)\n",lpszName
,lpCC
,*lpdwSize
);
2510 if(lpszName
) RtlCreateUnicodeStringFromAsciiz(&lpszNameW
,lpszName
);
2511 else lpszNameW
.Buffer
= NULL
;
2513 if(lpszNameW
.Buffer
) ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
2515 RtlFreeUnicodeString(&lpszNameW
);