📄 termiostty.c
字号:
xbuf[xbufsize++] = *buf; if ((xbufsize >= (WRITE_BUFSIZE-1)) || (input_bytes_read == *len) || (*buf == '\n')) { cyg_int32 size = xbufsize; res = cyg_io_write(chan, xbuf, &size); if (res != ENOERR) { *len = input_bytes_read - (xbufsize - size); return res; } xbufsize = 0; } buf++; } // Everything sent, so *len is correct. return ENOERR;}//==========================================================================static Cyg_ErrNo termios_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len){ cyg_devtab_entry_t *dt = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)dt->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; struct termios *t = &priv->termios; cyg_uint32 clen; cyg_uint32 size; Cyg_ErrNo res; cyg_uint8 c; cyg_uint8 *buf = (cyg_uint8 *)_buf; cyg_bool discardc; // should c be discarded (not read, not printed) cyg_bool returnnow = false; // return back to user after this char // if receiver off if (0 == (t->c_cflag & CREAD) ) { *len = 0; return -EINVAL; } size = 0; if ( 0 == (t->c_lflag & ICANON) ) { // 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 // guarantees we won't block cyg_serial_buf_info_t dev_buf_conf; 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!" ); 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; res = cyg_io_read(chan, &c, &clen); if (res != ENOERR) { *len = size; return res; } // lock to prevent termios getting corrupted while we read from it cyg_drv_mutex_lock( &priv->lock ); if ( t->c_iflag & ISTRIP ) c &= 0x7f; // canonical mode: erase, kill, and newline processing if ( t->c_lflag & ICANON ) { if ( t->c_cc[ VERASE ] == c ) { discardc = true; // erase on display? if ( (t->c_lflag & ECHO) && (t->c_lflag & ECHOE) ) { cyg_uint8 erasebuf[3]; erasebuf[0] = erasebuf[2] = t->c_cc[ VERASE ]; erasebuf[1] = ' '; clen = sizeof(erasebuf); // FIXME: what about error or non-blocking? cyg_io_write(chan, erasebuf, &clen); } if ( size ) size--; } // if else if ( t->c_cc[ VKILL ] == c ) { // kill line on display? if ( (t->c_lflag & ECHO) && (t->c_lflag & ECHOK) ) { // we could try and be more efficient here and // output a stream of erases, and then a stream // of spaces and then more erases. But this is poor // because on a slow terminal the user will see characters // delete from the middle forward in chunks! // But at least we try and chunk up sets of writes cyg_uint8 erasebuf[30]; cyg_uint8 erasechunks; cyg_uint8 i; erasechunks = size < (sizeof(erasebuf)/3) ? size : (sizeof(erasebuf)/3); for (i=0; i<erasechunks; i++) { erasebuf[i*3] = erasebuf[i*3+2] = t->c_cc[ VERASE ]; erasebuf[i*3+1] = ' '; } while( size ) { cyg_uint8 j; j = size < (sizeof(erasebuf)/3) ? size : (sizeof(erasebuf)/3); clen = (j*3); // FIXME: what about error or non-blocking? cyg_io_write( chan, erasebuf, &clen ); size -= j; } } else size = 0; discardc = true; } // else if // CR else if ( '\r' == c ) { if ( t->c_iflag & IGNCR ) discardc = true; else if ( t->c_iflag & ICRNL ) c = '\n'; } // newlines or similar. // Note: not an else if to catch CRNL conversion if ( (t->c_cc[ VEOF ] == c) || (t->c_cc[ VEOL ] == c) || ('\n' == c) ) { if ( t->c_cc[ VEOF ] == c ) discardc = true; if ( t->c_lflag & ECHONL ) { // don't check ECHO in this case clen = 1; // FIXME: what about error or non-blocking? // FIXME: what if INLCR is set? cyg_io_write( chan, "\n", &clen ); } if ( t->c_iflag & INLCR ) c = '\r'; returnnow = true; // FIXME: true even for INLCR? } // else if } // 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) ) size = 0; // raise could be a non-local jump - we should unlock mutex cyg_drv_mutex_unlock( &priv->lock ); // FIXME: what if raise returns != 0? raise( SIGINT ); cyg_drv_mutex_lock( &priv->lock ); } if ( (t->c_lflag & ISIG) && (t->c_cc[ VQUIT ] == c) ) { discardc = true; if ( 0 == (t->c_lflag & NOFLSH) ) size = 0; // raise could be a non-local jump - we should unlock mutex cyg_drv_mutex_unlock( &priv->lock ); // FIXME: what if raise returns != 0? raise( SIGQUIT ); cyg_drv_mutex_lock( &priv->lock ); } #endif if (!discardc) { buf[size++] = c; 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; return ENOERR;}//==========================================================================static cyg_booltermios_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info){ cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)t->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; // Just pass it on to next driver level return cyg_io_select( chan, which, info );}//==========================================================================static Cyg_ErrNo termios_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len){ cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)t->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; Cyg_ErrNo res = ENOERR; switch (key) { case CYG_IO_GET_CONFIG_TERMIOS: { if ( *len < sizeof(struct termios) ) { return -EINVAL; } cyg_drv_mutex_lock( &priv->lock ); *(struct termios *)buf = priv->termios; cyg_drv_mutex_unlock( &priv->lock ); *len = sizeof(struct termios); } break; default: // Assume this is a 'serial' driver control res = cyg_io_get_config(chan, key, buf, len); } // switch return res;}//==========================================================================static Cyg_ErrNo termios_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len){ cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)t->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; Cyg_ErrNo res = ENOERR; switch (key) { case CYG_IO_SET_CONFIG_TERMIOS: { setattr_struct *attr = (setattr_struct *)buf; int optact = attr->optact; if ( *len != sizeof( *attr ) ) { return -EINVAL; } CYG_ASSERT( (optact == TCSAFLUSH) || (optact == TCSADRAIN) || (optact == TCSANOW), "Invalid optact" ); cyg_drv_mutex_lock( &priv->lock ); if ( ( TCSAFLUSH == optact ) || ( TCSADRAIN == optact ) ) { res = cyg_io_get_config( chan, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, NULL, NULL ); CYG_ASSERT( ENOERR == res, "Drain request failed" ); } if ( TCSAFLUSH == optact ) { res = cyg_io_get_config( chan, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, NULL, NULL ); CYG_ASSERT( ENOERR == res, "Flush request failed" ); } res = set_attr( attr->termios_p, priv ); cyg_drv_mutex_unlock( &priv->lock ); return res; } default: // Pass on to serial driver res = cyg_io_set_config(chan, key, buf, len); } return res;}//==========================================================================#endif // ifdef CYGPKG_IO_SERIAL_TERMIOS// EOF termiostty.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -