This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Serial programming patch


Hi !,
Here is my patch to serial device. I implemented ioctl function which
makes possible
to get modem lines state (CTS,DSR,RI,CD) and set(get) modem control
lines (RTS and DTR)
It does not get(set) other signals from MCR register(there is no need).
It will be usefull for people (like me) who have to connect devices
requiring mentioned signals f.e. chip card readers.
I made changes in fhandler_serial.cc, fhandler.h and in termios.h where
I placed
proper constants taken directly from linux headers. I tested it in NT
and W2K environment
where there is nice way to get RTS and DTR state by DeviceIoControl
function. In
Windows 9x it is no possible and so far I do not know how to do it
without big gimnastics.
In consequence for 9x I keep mirror of this signals set by functions
which influence on state
of this signals (open, ioctl,tcsetattr) and in my ioctl simply return
it.
This patch was created on base of cygwin sources version 1.3.1-1
I have to send it as attachment because my post client is netscape and
inserted patch looks
horrible
Jacek
--- fhandler_serial.old.cc	Tue Apr 24 03:19:15 2001
+++ fhandler_serial.cc	Tue May 22 11:01:29 2001
@@ -32,6 +32,9 @@ fhandler_serial::fhandler_serial (const 
   vtime_ = 0;
   pgrp_ = myself->pgid;
   set_need_fork_fixup ();
+  osVersion=GetVersion();
+  dtr=0;
+  rts=0;
 }
 
 void
@@ -275,7 +278,8 @@ fhandler_serial::open (const char *name,
       if (!SetCommState (get_handle (), &state))
 	system_printf ("couldn't set initial state for %s, %E", get_name ());
     }
-
+  rts=TIOCM_RTS;
+  dtr=TIOCM_DTR;
   SetCommMask (get_handle (), EV_RXCHAR);
   set_open_status ();
   syscall_printf ("%p = fhandler_serial::open (%s, %p, %p)",
@@ -366,6 +370,93 @@ fhandler_serial::tcflow (int action)
   return 0;
 }
 
+
+/* ioctl: POSIX  */
+int
+fhandler_serial::ioctl (unsigned int cmd,void * buffer)
+{
+ 
+  DCB dcb;
+  DWORD ev;
+  COMSTAT st;
+  DWORD action;
+  DWORD modemLines;
+  DWORD mcr;
+  DWORD cbReturned;
+  bool  result;
+  int   modemStatus;
+  int request;
+
+  request=*(int*)buffer;
+  action=0;
+  modemStatus=0;
+  if (!ClearCommError (get_handle (), &ev, &st)) return -1;
+  switch (cmd)
+    {
+      case TIOCMGET:
+        if(GetCommModemStatus(get_handle(),&modemLines)==0) return -1;
+	if(modemLines&MS_CTS_ON) modemStatus|=TIOCM_CTS;
+	if(modemLines&MS_DSR_ON) modemStatus|=TIOCM_DSR;
+	if(modemLines&MS_RING_ON) modemStatus|=TIOCM_RNG | TIOCM_RI;
+	if(modemLines&MS_RLSD_ON) modemStatus|=TIOCM_CAR | TIOCM_CD;
+	if(!(osVersion&0x80000000))
+	{
+	// here is Windows NT or Windows 2000
+	  result=DeviceIoControl(
+	                          get_handle(),
+				  0x001B0078,
+				  NULL,
+				  0,
+				  &mcr,
+				  4,
+				  &cbReturned,
+				  0
+				  );
+	  if(!result) return -1;
+	  if(cbReturned!=4) return -1;
+	  if(mcr&2) modemStatus|=TIOCM_RTS;
+	  if(mcr&1) modemStatus|=TIOCM_DTR;
+	  
+	} else
+	{
+	
+	// here is Windows 9x
+	  modemStatus|=rts|dtr;
+	  
+	}
+	*(int*)buffer=modemStatus;
+	return 0;
+      case TIOCMSET:
+        //if(request & ~(TIOCM_RTS | TIOCM_DTR)) return -1;
+	if (request&TIOCM_RTS)
+	{
+	    if(EscapeCommFunction(get_handle(),SETRTS)==0) return -1; else
+	    rts=TIOCM_RTS;
+	} else
+	{
+	    if(EscapeCommFunction(get_handle(),CLRRTS)==0) return -1;else
+	    rts=0;
+	}
+	if (request&TIOCM_DTR)
+	{
+	    if(EscapeCommFunction(get_handle(),SETDTR)==0) return -1;else
+	    dtr=TIOCM_DTR;
+	} else
+	{
+	    if(EscapeCommFunction(get_handle(),CLRDTR)==0) return -1;else
+	    dtr=0;
+	}
+	return 0;
+      case TIOCINQ:
+        if(ev&CE_FRAME | ev&CE_IOE | ev&CE_OVERRUN | \
+	ev&CE_RXOVER | ev&CE_RXPARITY) return -1;
+	*(int*)buffer=st.cbInQue;
+	return 0;
+      default:
+	return -1;
+    }
+}
+
 /* tcflush: POSIX 7.2.2.1 */
 int
 fhandler_serial::tcflush (int queue)
@@ -373,7 +464,7 @@ fhandler_serial::tcflush (int queue)
   if (queue == TCOFLUSH || queue == TCIOFLUSH)
     PurgeComm (get_handle (), PURGE_TXABORT | PURGE_TXCLEAR);
 
-  if (queue == TCIFLUSH | queue == TCIOFLUSH)
+  if (queue == TCIFLUSH || queue == TCIOFLUSH)
     /* Input flushing by polling until nothing turns up
        (we stop after 1000 chars anyway) */
     for (int max = 1000; max > 0; max--)
@@ -404,6 +495,8 @@ fhandler_serial::tcsetattr (int action, 
   COMMTIMEOUTS to;
   DCB ostate, state;
   unsigned int ovtime = vtime_, ovmin = vmin_;
+  int tmpDtr,tmpRts;
+  tmpDtr=tmpRts=0;
 
   termios_printf ("action %d", action);
   if ((action == TCSADRAIN) || (action == TCSAFLUSH))
@@ -569,6 +662,7 @@ fhandler_serial::tcsetattr (int action, 
     {							/* disable */
       state.fRtsControl = RTS_CONTROL_ENABLE;
       state.fOutxCtsFlow = FALSE;
+      tmpRts=TIOCM_RTS;
     }
 
   if (t->c_cflag & CRTSXOFF)
@@ -601,7 +695,10 @@ fhandler_serial::tcsetattr (int action, 
   set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1);
 
   if (dropDTR == TRUE)
+  {
     EscapeCommFunction (get_handle (), CLRDTR);
+    tmpDtr=0;
+  }
   else
     {
       /* FIXME: Sometimes when CLRDTR is set, setting
@@ -610,7 +707,11 @@ fhandler_serial::tcsetattr (int action, 
       parameters while DTR is still down. */
 
       EscapeCommFunction (get_handle (), SETDTR);
+      tmpDtr=TIOCM_DTR;
     }
+    
+  rts=tmpRts;
+  dtr=tmpDtr;
 
   /*
   The following documentation on was taken from "Linux Serial Programming
--- fhandler.old.h	Tue Apr 24 03:19:14 2001
+++ fhandler.h	Tue May 22 10:34:58 2001
@@ -529,6 +529,9 @@ private:
   unsigned int vmin_;			/* from termios */
   unsigned int vtime_;			/* from termios */
   pid_t pgrp_;
+  unsigned int osVersion;
+  int	rts;
+  int	dtr;
 
 public:
   int overlapped_armed;
@@ -547,6 +550,7 @@ public:
   int tcsendbreak (int);
   int tcdrain ();
   int tcflow (int);
+  int ioctl (unsigned int cmd, void *);
   int tcsetattr (int a, const struct termios *t);
   int tcgetattr (struct termios *t);
   off_t lseek (off_t, int) { return 0; }
--- ./include/sys/termios.old.h	Sun Mar 25 21:09:52 2001
+++ ./include/sys/termios.h	Tue May 22 12:03:16 2001
@@ -13,6 +13,22 @@ details. */
 #ifndef	_SYS_TERMIOS_H
 #define _SYS_TERMIOS_H
 
+
+#define	TIOCMGET	0x5415
+#define TIOCMSET	0x5418
+#define TIOCINQ		0x541B
+
+#define	TIOCM_LE	0x001
+#define	TIOCM_DTR	0x002
+#define	TIOCM_RTS	0x004
+#define	TIOCM_CTS	0x020
+#define	TIOCM_CAR	0x040
+#define	TIOCM_RNG	0x080
+#define	TIOCM_DSR	0x100
+#define	TIOCM_CD	TIOCM_CAR
+#define	TIOCM_RI	TIOCM_RNG
+
+
 #define TCOOFF		0
 #define TCOON		1
 #define TCIOFF		2

--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]