Eric Pouech : ntdll/kernel32: GetCommState & IOCTL_SERIAL_GET_HANDFLOW

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 9 14:15:48 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: 48646ea82b2aa27b16c3b900a677b8c0581cf7c3
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=48646ea82b2aa27b16c3b900a677b8c0581cf7c3

Author: Eric Pouech <eric.pouech at wanadoo.fr>
Date:   Sun May  7 14:10:52 2006 +0200

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 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 @@ #endif
     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-cvs mailing list