From 48646ea82b2aa27b16c3b900a677b8c0581cf7c3 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 7 May 2006 14:10:52 +0200 Subject: [PATCH] ntdll/kernel32: GetCommState & IOCTL_SERIAL_GET_HANDFLOW - implemented SERIAL_GET_HANDFLOW ioctl - made use of it in kernel.GetCommState --- dlls/kernel/comm.c | 95 +++++++++++++++------------------------------ dlls/ntdll/serial.c | 57 +++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 63 deletions(-) diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c index 6fa5b89d244..de17f34dfb0 100644 --- a/dlls/kernel/comm.c +++ b/dlls/kernel/comm.c @@ -1077,12 +1077,9 @@ BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb) */ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) { - struct termios port; - int fd; - int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE; - SERIAL_BAUD_RATE sbr; SERIAL_LINE_CONTROL slc; + SERIAL_HANDFLOW shf; TRACE("handle %p, ptr %p\n", handle, lpdcb); @@ -1091,14 +1088,18 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - lpdcb->DCBlength = sizeof(*lpdcb); if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE, NULL, 0, &sbr, sizeof(sbr), NULL, NULL) || !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL, - NULL, 0, &slc, sizeof(slc), NULL, NULL)) + NULL, 0, &slc, sizeof(slc), NULL, NULL) || + !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW, + NULL, 0, &shf, sizeof(shf), NULL, NULL)) return FALSE; + memset(lpdcb, 0, sizeof(*lpdcb)); + lpdcb->DCBlength = sizeof(*lpdcb); + /* yes, they seem no never be (re)set on NT */ lpdcb->fBinary = 1; lpdcb->fParity = 0; @@ -1109,69 +1110,37 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) lpdcb->Parity = slc.Parity; lpdcb->ByteSize = slc.WordLength; - fd = get_comm_fd( handle, FILE_READ_DATA ); - if (fd < 0) return FALSE; - if (tcgetattr(fd, &port) == -1) { - int save_error=errno; - ERR("tcgetattr error '%s'\n", strerror(save_error)); - release_comm_fd( handle, fd ); - return FALSE; - } - -#ifdef TIOCMGET - if (ioctl(fd, TIOCMGET, &stat) == -1) - { - int save_error=errno; - WARN("ioctl error '%s'\n", strerror(save_error)); - stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE; - } -#endif - release_comm_fd( handle, fd ); - if(port.c_iflag & INPCK) - lpdcb->fParity = TRUE; - else - lpdcb->fParity = FALSE; + if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1; + if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1; + switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE)) + { + case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break; + case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break; + case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break; + } + switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE)) + { + case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break; + case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break; + case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break; + case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE: + lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break; + } + if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1; + if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1; + if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1; + if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1; + if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1; + lpdcb->XonLim = shf.XonLimit; + lpdcb->XoffLim = shf.XoffLimit; - lpdcb->fNull = 0; + if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1; + if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1; - /* termios does not support DTR/DSR flow control */ - lpdcb->fOutxDsrFlow = 0; - lpdcb->fDtrControl = -#ifdef TIOCM_DTR - !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE: -#endif - DTR_CONTROL_ENABLE ; - -#ifdef CRTSCTS - - if (port.c_cflag & CRTSCTS) { - lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; - lpdcb->fOutxCtsFlow = 1; - } else -#endif - { - lpdcb->fRtsControl = -#ifdef TIOCM_RTS - !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE : -#endif - RTS_CONTROL_ENABLE ; - lpdcb->fOutxCtsFlow = 0; - } - if (port.c_iflag & IXON) - lpdcb->fInX = 1; - else - lpdcb->fInX = 0; - - if (port.c_iflag & IXOFF) - lpdcb->fOutX = 1; - else - lpdcb->fOutX = 0; /* lpdcb->XonChar = lpdcb->XoffChar = */ - lpdcb->XonLim = 10; - lpdcb->XoffLim = 10; TRACE("OK\n"); dump_dcb(lpdcb); diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c index 0a6d8f12db2..65eafd2dca9 100644 --- a/dlls/ntdll/serial.c +++ b/dlls/ntdll/serial.c @@ -185,6 +185,54 @@ static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr) return STATUS_SUCCESS; } +static NTSTATUS get_hand_flow(int fd, SERIAL_HANDFLOW* shf) +{ + int stat; + struct termios port; + + if (tcgetattr(fd, &port) == -1) + { + ERR("tcgetattr error '%s'\n", strerror(errno)); + return FILE_GetNtStatus(); + } +#ifdef TIOCMGET + if (ioctl(fd, TIOCMGET, &stat) == -1) + { + WARN("ioctl error '%s'\n", strerror(errno)); + stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE; + } +#endif + /* termios does not support DTR/DSR flow control */ + shf->ControlHandShake = 0; + shf->FlowReplace = 0; +#ifdef TIOCM_DTR + if (stat & TIOCM_DTR) +#endif + shf->ControlHandShake |= SERIAL_DTR_CONTROL; +#ifdef CRTSCTS + if (port.c_cflag & CRTSCTS) + { + shf->ControlHandShake |= SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE; + shf->ControlHandShake |= SERIAL_CTS_HANDSHAKE; + } + else +#endif + { +#ifdef TIOCM_RTS + if (stat & TIOCM_RTS) +#endif + shf->ControlHandShake |= SERIAL_RTS_CONTROL; + } + if (port.c_iflag & IXON) + shf->FlowReplace |= SERIAL_AUTO_RECEIVE; + if (port.c_iflag & IXOFF) + shf->FlowReplace |= SERIAL_AUTO_TRANSMIT; + + shf->XonLimit = 10; + shf->XoffLimit = 10; + return STATUS_SUCCESS; +} + static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc) { struct termios port; @@ -739,6 +787,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice, } else status = STATUS_INVALID_PARAMETER; break; + case IOCTL_SERIAL_GET_HANDFLOW: + if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_HANDFLOW)) + { + if (!(status = get_hand_flow(fd, (SERIAL_HANDFLOW*)lpOutBuffer))) + sz = sizeof(SERIAL_HANDFLOW); + } + else + status = STATUS_INVALID_PARAMETER; + break; case IOCTL_SERIAL_GET_LINE_CONTROL: if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL)) {