Eric Pouech : ntdll/kernel32: SetCommState & IOCTL_SET_CHARS
Alexandre Julliard
julliard at wine.codeweavers.com
Tue May 9 14:15:45 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: a05a3435fdf425c2bafe3559b5b9427801f7d7a2
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=a05a3435fdf425c2bafe3559b5b9427801f7d7a2
Author: Eric Pouech <eric.pouech at wanadoo.fr>
Date: Sun May 7 14:10:43 2006 +0200
ntdll/kernel32: SetCommState & IOCTL_SET_CHARS
- implemented ntdll's serial IOCTL SET_CHARS
- used this IOCTL in kernel32.SetCommState
---
dlls/kernel/comm.c | 55 +++++++++++++++------------------------------------
dlls/ntdll/serial.c | 34 ++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 39 deletions(-)
diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 58e1b13..c6ac9f7 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -983,13 +983,10 @@ static void dump_dcb(const DCB* lpdcb)
*/
BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
{
- struct termios port;
- int fd;
- BOOL ret;
-
SERIAL_BAUD_RATE sbr;
SERIAL_LINE_CONTROL slc;
SERIAL_HANDFLOW shf;
+ SERIAL_CHARS sc;
if (lpdcb == NULL)
{
@@ -1040,44 +1037,24 @@ BOOL WINAPI SetCommState( HANDLE handle,
shf.XonLimit = lpdcb->XonLim;
shf.XoffLimit = lpdcb->XoffLim;
+ sc.EofChar = lpdcb->EofChar;
+ sc.ErrorChar = lpdcb->ErrorChar;
+ sc.BreakChar = 0;
+ sc.EventChar = lpdcb->EvtChar;
+ sc.XonChar = lpdcb->XonChar;
+ sc.XoffChar = lpdcb->XoffChar;
+
/* note: change DTR/RTS lines after setting the comm attributes,
* so flow control does not interfere.
*/
- if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
- &sbr, sizeof(sbr), NULL, 0, NULL, NULL))
- return FALSE;
- if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
- &slc, sizeof(slc), NULL, 0, NULL, NULL))
- return FALSE;
-
- if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
- &shf, sizeof(shf), NULL, 0, NULL, NULL))
- return FALSE;
-
- fd = get_comm_fd( handle, FILE_READ_DATA );
- if (fd < 0) return FALSE;
-
- if ((tcgetattr(fd,&port)) == -1) {
- int save_error = errno;
- release_comm_fd( handle, fd );
- ERR("tcgetattr error '%s'\n", strerror(save_error));
- return FALSE;
- }
-
- port.c_cc[VMIN] = 0;
- port.c_cc[VTIME] = 1;
-
- if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
- ERR("tcsetattr error '%s'\n", strerror(errno));
- ret = FALSE;
- } else {
- ClearCommError(handle, NULL, NULL);
- ret = TRUE;
- }
-
- release_comm_fd( handle, fd );
- return ret;
-
+ return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
+ &sbr, sizeof(sbr), NULL, 0, NULL, NULL) &&
+ DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
+ &slc, sizeof(slc), NULL, 0, NULL, NULL) &&
+ DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
+ &shf, sizeof(shf), NULL, 0, NULL, NULL) &&
+ DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS,
+ &sc, sizeof(sc), NULL, 0, NULL, NULL));
}
diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index 0225ba8..351b7e4 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -540,6 +540,34 @@ #endif
return STATUS_SUCCESS;
}
+static NTSTATUS set_special_chars(int fd, const SERIAL_CHARS* sc)
+{
+ struct termios port;
+
+ if (tcgetattr(fd, &port) == -1)
+ {
+ ERR("tcgetattr error '%s'\n", strerror(errno));
+ return FILE_GetNtStatus();
+ }
+
+ port.c_cc[VMIN ] = 0;
+ port.c_cc[VTIME ] = 1;
+
+ port.c_cc[VEOF ] = sc->EofChar;
+ /* FIXME: sc->ErrorChar is not supported */
+ /* FIXME: sc->BreakChar is not supported */
+ /* FIXME: sc->EventChar is not supported */
+ port.c_cc[VSTART] = sc->XonChar;
+ port.c_cc[VSTOP ] = sc->XoffChar;
+
+ if (tcsetattr(fd, TCSANOW, &port) == -1)
+ {
+ ERR("tcsetattr error '%s'\n", strerror(errno));
+ return FILE_GetNtStatus();
+ }
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask)
{
NTSTATUS status;
@@ -658,6 +686,12 @@ #else
status = STATUS_NOT_SUPPORTED;
#endif
break;
+ case IOCTL_SERIAL_SET_CHARS:
+ if (lpInBuffer && nInBufferSize == sizeof(SERIAL_CHARS))
+ status = set_special_chars(fd, (const SERIAL_CHARS*)lpInBuffer);
+ else
+ status = STATUS_INVALID_PARAMETER;
+ break;
case IOCTL_SERIAL_SET_HANDFLOW:
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_HANDFLOW))
status = set_handflow(fd, (const SERIAL_HANDFLOW*)lpInBuffer);
More information about the wine-cvs
mailing list