[PATCH 07/11] [NtDll/Kernel32]: GetCommState &
IOCTL_SERIAL_GET_HANDFLOW
Eric Pouech
eric.pouech at wanadoo.fr
Sun May 7 07:10:52 CDT 2006
- implemented SERIAL_GET_HANDFLOW ioctl
- made use of it in kernel!GetCommState
A+
---
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 6fa5b89..de17f34 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -1077,12 +1077,9 @@ BOOL WINAPI SetCommState( HANDLE handle,
*/
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,
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->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;
-
- lpdcb->fNull = 0;
-
- /* 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 ;
+ 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;
-#ifdef CRTSCTS
+ if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
+ if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
- 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 0a6d8f1..65eafd2 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -185,6 +185,54 @@ static NTSTATUS get_baud_rate(int fd, SE
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 hDe
}
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))
{
More information about the wine-patches
mailing list