DTR/RTS fixes in {G|S}etCommState: take 2

Rein Klazes rklazes at xs4all.nl
Mon Apr 12 03:03:35 CDT 2004


Hi,

Mike McCormack noted that it is better to change the control lines after
setting the comm attributes, so flow control does not interfere. 

Changelog:
	dlls/kernel	: comm.c
	Fix GetCommState and SetCommState, so that these functions
	can be used to set/clear/read the DTR and RTS lines

Rein.
-- 
Rein Klazes
rklazes at xs4all.nl
-------------- next part --------------
--- wine/dlls/kernel/comm.c	2004-01-16 03:21:01.000000000 +0100
+++ mywine/dlls/kernel/comm.c	2004-04-12 09:49:27.000000000 +0200
@@ -1084,6 +1084,7 @@
 {
      struct termios port;
      int fd, bytesize, stopbits;
+     BOOL ret;
 
      TRACE("handle %p, ptr %p\n", handle, lpdcb);
      TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
@@ -1092,6 +1093,11 @@
 	   (lpdcb->StopBits == TWOSTOPBITS)?2:0);
      TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
 	   (lpdcb->fOutX)?"IXOFF":"~IXOFF");
+     TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
+             lpdcb->fRtsControl);
+     TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
+             lpdcb->fDtrControl);
+             
 
      fd = get_comm_fd( handle, GENERIC_READ );
      if (fd < 0) return FALSE;
@@ -1385,11 +1391,6 @@
 	  }
 #endif
 
-	if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
-	  {
-             WARN("DSR/DTR flow control not supported\n");
-	  }
-
 	if (lpdcb->fInX)
 		port.c_iflag |= IXON;
 	else
@@ -1400,16 +1401,39 @@
 		port.c_iflag &= ~IXOFF;
 
 	if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
-	        int save_error=errno;
+                ERR("tcsetattr error '%s'\n", strerror(errno));
                 COMM_SetCommError(handle,CE_IOE);
-                release_comm_fd( handle, fd );
-                ERR("tcsetattr error '%s'\n", strerror(save_error));
-		return FALSE;
+		ret = FALSE;
 	} else {
                 COMM_SetCommError(handle,0);
-                release_comm_fd( handle, fd );
-		return TRUE;
+		ret = TRUE;
 	}
+
+        /* note: change DTR/RTS lines after setting the comm attributes,
+         * so flow control does not interfere. */
+#ifdef TIOCM_DTR
+	if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
+        {
+             WARN("DSR/DTR flow control not supported\n");
+	} else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
+            COMM_WhackModem(fd, ~TIOCM_DTR, 0);
+        else    
+            COMM_WhackModem(fd, 0, TIOCM_DTR);
+#endif
+#ifdef TIOCM_RTS
+	if(!lpdcb->fOutxCtsFlow )
+        {
+            if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
+                COMM_WhackModem(fd, ~TIOCM_RTS, 0);
+            else    
+                COMM_WhackModem(fd, 0, TIOCM_RTS);
+        }
+#endif
+        if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
+            FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
+        release_comm_fd( handle, fd );
+        return ret;
+
 }
 
 
@@ -1432,14 +1456,19 @@
 {
      struct termios port;
      int fd,speed;
+     int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
 
      TRACE("handle %p, ptr %p\n", handle, lpdcb);
 
      fd = get_comm_fd( handle, GENERIC_READ );
      if (fd < 0) return FALSE;
-     if (tcgetattr(fd, &port) == -1) {
+     if (tcgetattr(fd, &port) == -1
+#ifdef TIOCMGET
+             || ioctl(fd, TIOCMGET, &stat) == -1
+#endif
+             ) {
                 int save_error=errno;
-                ERR("tcgetattr error '%s'\n", strerror(save_error));
+                ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
                 COMM_SetCommError(handle,CE_IOE);
                 release_comm_fd( handle, fd );
 		return FALSE;
@@ -1562,7 +1591,11 @@
 
 	/* termios does not support DTR/DSR flow control */
 	lpdcb->fOutxDsrFlow = 0;
-	lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
+	lpdcb->fDtrControl =
+#ifdef TIOCM_DTR
+            !(stat & TIOCM_DTR) ?  DTR_CONTROL_DISABLE:
+#endif
+                DTR_CONTROL_ENABLE  ;
 
 #ifdef CRTSCTS
 
@@ -1572,7 +1605,11 @@
 	} else
 #endif
 	{
-		lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
+		lpdcb->fRtsControl = 
+#ifdef TIOCM_RTS
+                    !(stat & TIOCM_RTS) ?  RTS_CONTROL_DISABLE :
+#endif
+                    RTS_CONTROL_ENABLE ;
 		lpdcb->fOutxCtsFlow = 0;
 	}
 	if (port.c_iflag & IXON)
@@ -1601,6 +1638,10 @@
 	      (lpdcb->StopBits == TWOSTOPBITS)?2:0);
 	TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
 	      (lpdcb->fOutX)?"IXOFF":"~IXOFF");
+         TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
+                 lpdcb->fRtsControl);
+         TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
+                 lpdcb->fDtrControl);
 #ifdef CRTSCTS
 	if (	lpdcb->fOutxCtsFlow 			||
 		lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
@@ -1609,7 +1650,6 @@
         else
 
 	  TRACE("~CRTSCTS\n");
-
 #endif
 	return TRUE;
 }


More information about the wine-patches mailing list