Index: cdl/termios.cdl =================================================================== RCS file: /cvs/ecos/ecos/packages/io/serial/current/cdl/termios.cdl,v retrieving revision 1.1 diff -u -r1.1 termios.cdl --- termios.cdl 2000/08/25 17:33:28 1.1 +++ termios.cdl 2001/09/28 12:26:45 @@ -105,4 +105,13 @@ SIGHUP is sent on terminal close." } +cdl_option CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME { + display "Support non-canonical mode input processing" + flavor bool + requires CYGVAR_KERNEL_COUNTERS_CLOCK + default_value { CYGVAR_KERNEL_COUNTERS_CLOCK != 0 } + description "This option selects whether to fully support + non-canonical mode input processing." +} + # EOF termios.cdl Index: src/common/termiostty.c =================================================================== RCS file: /cvs/ecos/ecos/packages/io/serial/current/src/common/termiostty.c,v retrieving revision 1.1 diff -u -r1.1 termiostty.c --- termiostty.c 2000/08/25 17:33:28 1.1 +++ termiostty.c 2001/09/28 12:26:45 @@ -95,6 +95,12 @@ struct termios termios; cyg_io_handle_t dev_handle; cyg_drv_mutex_t lock; +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME + cyg_handle_t rtc_counter; + cyg_handle_t alarm_handle; + cyg_alarm alarm; + cyg_uint32 tickds; +#endif cyg_bool init; cyg_uint8 *errbuf; cyg_uint8 *errbufpos; @@ -171,7 +177,7 @@ // map eCos bitrates to POSIX bitrates. static speed_t ecosbaud2posixbaud[] = { - 0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B2400, B3600, + 0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B3600, B4800, B7200, B9600, B14400, B19200, B38400, B57600, B115200, B230400 }; // map POSIX bitrates to eCos bitrates. @@ -205,6 +211,16 @@ return posixbaud2ecosbaud[ pbaud ]; } +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME +static void +termios_abort(cyg_handle_t alarm, cyg_addrword_t data) +{ + struct termios_private_info *priv = (struct termios_private_info *)data; + cyg_io_get_config(priv->dev_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, + NULL, NULL); +} +#endif + //========================================================================== // real_termios_init is used to initialize the termios structure. This is // called at lookup time, and not from termios_init() because it needs @@ -228,6 +244,10 @@ cyg_serial_info_t dev_conf; cyg_serial_buf_info_t dev_buf_conf; cyg_uint32 len = sizeof( dev_conf ); +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME + cyg_handle_t rtc; + cyg_resolution_t resolution; +#endif CYG_REPORT_FUNCTYPE("returning %d"); CYG_REPORT_FUNCARG1XV( priv ); @@ -327,6 +347,15 @@ break; } +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME + rtc = cyg_real_time_clock(); + resolution = cyg_clock_get_resolution(rtc); + priv->tickds = 100000000 / (resolution.dividend / resolution.divisor); + cyg_clock_to_counter(rtc, &priv->rtc_counter); + cyg_alarm_create(priv->rtc_counter, termios_abort, (cyg_addrword_t)priv, + &priv->alarm_handle, &priv->alarm); +#endif + return ENOERR; } // real_termios_init() @@ -539,6 +568,7 @@ tempcc[VINTR] = t->c_cc[VINTR]; tempcc[VKILL] = t->c_cc[VKILL]; tempcc[VMIN] = t->c_cc[VMIN]; + tempcc[VTIME] = t->c_cc[VTIME]; tempcc[VQUIT] = t->c_cc[VQUIT]; return res; @@ -572,6 +602,7 @@ if ( !priv->init ) { // retest as we may have been pre-empted priv->dev_handle = chan; err = real_termios_init( priv ); + priv->init = true; } cyg_drv_mutex_unlock( &priv->lock ); } @@ -644,7 +675,7 @@ } size = 0; - if ( 0 == (t->c_lflag & ICANON) ) { + if ( 0 == (t->c_lflag & ICANON) && 0 == t->c_cc[ VMIN ] ) { // In non-canonical mode we return the min of *len and the // number of bytes available // So we query the driver for how many bytes are available - this @@ -655,7 +686,20 @@ 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; + clen = dev_buf_conf.rx_count; +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME + if (clen > 0 || t->c_cc[VTIME] == 0) { + if (clen < *len) + *len = clen; + } else { + cyg_alarm_initialize(priv->alarm_handle, + cyg_counter_current_value(priv->rtc_counter) + + t->c_cc[VTIME] * priv->tickds, 0); + } +#else + if (clen < *len) + *len = clen; +#endif } // if while (!returnnow && size < *len) { @@ -664,6 +708,10 @@ res = cyg_io_read(chan, &c, &clen); if (res != ENOERR) { *len = size; +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME + if (res == -EINTR) + res = ENOERR; +#endif return res; } @@ -751,6 +799,19 @@ } else { // non-canonical mode if ( size+1 >= t->c_cc[ VMIN ] ) returnnow = true; +#ifdef CYGSEM_IO_SERIAL_TERMIOS_SUPPORT_VTIME + if (t->c_cc[VTIME] > 0) { + if (returnnow) + cyg_alarm_disable(priv->alarm_handle); + else + cyg_alarm_initialize(priv->alarm_handle, + cyg_counter_current_value(priv->rtc_counter) + + t->c_cc[VTIME] * priv->tickds, 0); + } else if (t->c_cc[VMIN] == 0) { + // continue to read in all chars received + returnnow = false; + } +#endif } // else #ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS @@ -863,7 +924,7 @@ (optact == TCSANOW), "Invalid optact" ); cyg_drv_mutex_lock( &priv->lock ); - + if ( ( TCSAFLUSH == optact ) || ( TCSADRAIN == optact ) ) { res = cyg_io_get_config( chan, @@ -877,7 +938,7 @@ NULL, NULL ); CYG_ASSERT( ENOERR == res, "Flush request failed" ); } - + res = set_attr( attr->termios_p, priv ); cyg_drv_mutex_unlock( &priv->lock ); return res;