This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

termios - bad behaviour with VMIN


According to my Linux manual page (I know it's not the POSIX
gospel, but it's what I have):

       These symbolic subscript values are all different, except that VTIME, VMIN may have
       the same value as VEOL, VEOF, respectively.  (In  non-canonical  mode  the  special
       character  meaning  is  replaced by the timeout meaning. MIN represents the minimum
       number of characters that should be  received  to  satisfy  the  read.  TIME  is  a
       decisecond-valued  timer.  When  both  are set, a read will wait until at least one
       character has been received, and then return as soon as either MIN characters  have
       been  received  or  time  TIME has passed since the last character was received. If
       only MIN is set, the read will not return before MIN characters have been received.
       If  only TIME is set, the read will return as soon as either at least one character
       has been received, or the timer times out. If neither is set, the read will  return
       immediately, only giving the currently already available characters.)

which tells me that if I have a termios device in non-canonical
mode and I set VMIN, then a read to that device will not be
satisfied until at least VMIN characters arrive.  Currently,
this does not happen; it returns 0, with no error, if there
are no characters available.

This patch fixes it and gives what I think is proper behaviour:

Index: io/serial/current/src/common/termiostty.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/io/serial/current/src/common/termiostty.c,v
retrieving revision 1.4
diff -u -5 -p -r1.4 termiostty.c
--- io/serial/current/src/common/termiostty.c	14 Feb 2003 11:50:12 -0000	1.4
+++ io/serial/current/src/common/termiostty.c	9 Mar 2003 15:39:58 -0000
@@ -659,11 +659,18 @@ termios_read(cyg_io_handle_t handle, voi
         cyg_uint32 dbc_len = sizeof( dev_buf_conf );
         res = cyg_io_get_config( chan,
                                  CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO,
                                  &dev_buf_conf, &dbc_len );
         CYG_ASSERT( res == ENOERR, "Query buffer status failed!" );
-        *len = *len < dev_buf_conf.rx_count ? *len : dev_buf_conf.rx_count;
+        if (dev_buf_conf.rx_count > 0) {
+            // Adjust length to be max characters currently available
+            *len = *len < dev_buf_conf.rx_count ? *len : dev_buf_conf.rx_count;
+        } else if (t->c_cc[VMIN] == 0) {
+            // No chars available - don't block
+            *len = 0;
+            return ENOERR;
+        }
     } // if
 
     while (!returnnow && size < *len) {
         clen = 1;
         discardc = false;
@@ -752,14 +759,11 @@ termios_read(cyg_io_handle_t handle, voi
                 }
                 if ( t->c_iflag & INLCR )
                     c = '\r';
                 returnnow = true; // FIXME: true even for INLCR?
             } // else if
-        } else { // non-canonical mode
-            if ( t->c_cc[ VMIN ] && (size+1 >= t->c_cc[ VMIN ]) )
-                returnnow = true;
-        } // else
+        } // if 
 
 #ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS
         if ( (t->c_lflag & ISIG) && (t->c_cc[ VINTR ] == c) ) {
             discardc = true;
             if ( 0 == (t->c_lflag & NOFLSH) )
@@ -789,10 +793,16 @@ termios_read(cyg_io_handle_t handle, voi
             if ( t->c_lflag & ECHO ) {
                 clen = 1;
                 // FIXME: what about error or non-blocking?
                 termios_write( handle, &c, &clen );
             }
+        }
+
+        if ( (t->c_lflag & ICANON) == 0 ) {
+            // Check to see if read has been satisfied
+            if ( t->c_cc[ VMIN ] && (size >= t->c_cc[ VMIN ]) )
+                returnnow = true;
         }
         cyg_drv_mutex_unlock( &priv->lock );
     } // while
 
     *len = size;


Basically, I think the test for VMIN is in the wrong place and also a
little correct.  With this change in place, the code I'm working with 
(a nice, standard, portable program) behaves the same on Linux and 
eCos.  Comments?

-- 
------------------------------------------------------------
Gary Thomas                 |
MLB Associates              |  Consulting for the
+1 (970) 229-1963           |    Embedded world
http://www.mlbassoc.com/    |
email: <gary at mlbassoc dot com>  |
gpg: http://www.chez-thomas.org/gary/gpg_key.asc
------------------------------------------------------------


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