📄 termiostty.c
字号:
default:
CYG_FAIL( "Unsupported word length" );
break;
}
switch ( dev_conf.stop ) {
case CYGNUM_SERIAL_STOP_1:
// Don't need to do anything
break;
case CYGNUM_SERIAL_STOP_2:
t->c_cflag |= CSTOPB;
break;
default:
CYG_FAIL( "Unsupported number of stop bits" );
break;
}
switch ( dev_conf.flags ) {
case CYGNUM_SERIAL_FLOW_RTSCTS_RX:
t->c_cflag |= CRTSCTS;
// drop through
case CYGNUM_SERIAL_FLOW_XONXOFF_RX:
t->c_iflag |= IXOFF;
break;
case CYGNUM_SERIAL_FLOW_RTSCTS_TX:
t->c_cflag |= CRTSCTS;
// drop through
case CYGNUM_SERIAL_FLOW_XONXOFF_TX:
t->c_iflag |= IXON;
break;
default:
// Ignore flags we don't grok
break;
}
return ENOERR;
} // real_termios_init()
//==========================================================================
// set_attr() actually enacts the termios config. We come in here with
// the mutex in priv locked
//
// Possible deviation from standard: POSIX says we should enact which ever
// bits we can and only return EINVAL when none of them can be performed
// Rather than tracking whether *none* of them worked, instead we just
// always claim success. At the very least, setting c_cc is never to
// fail so I'm not sure if this is really non-standard or not!
static Cyg_ErrNo
set_attr( struct termios *t, struct termios_private_info *priv )
{
Cyg_ErrNo res = ENOERR;
cyg_serial_info_t dev_conf, new_dev_conf;
cyg_uint32 len = sizeof( dev_conf );
cc_t *tempcc = &priv->termios.c_cc[0];
struct termios *ptermios = &priv->termios;
// Get info from driver
res = cyg_io_get_config( priv->dev_handle, CYG_IO_GET_CONFIG_SERIAL_INFO,
&dev_conf, &len );
if ( ENOERR != res )
return res;
// We need to set up each facet of config to change one by one because
// POSIX says we should try and change as much of the config as possible
// This is tedious and has to be done by steam :-(
if ( t->c_ospeed != ptermios->c_ospeed ) {
new_dev_conf = dev_conf;
new_dev_conf.baud = map_posixbaud_to_ecosbaud( t->c_ospeed );
if ( 0 != new_dev_conf.baud ) {
len = sizeof( new_dev_conf );
res = cyg_io_set_config( priv->dev_handle,
CYG_IO_SET_CONFIG_SERIAL_INFO,
&new_dev_conf, &len );
if ( ENOERR == res ) {
// It worked, so update dev_conf to reflect the new state
dev_conf.baud = new_dev_conf.baud;
// and termios
ptermios->c_ispeed = t->c_ospeed;
ptermios->c_ospeed = t->c_ospeed;
}
}
}
if ( (t->c_cflag & CSTOPB) != (ptermios->c_cflag & CSTOPB) ) {
new_dev_conf = dev_conf;
if ( t->c_cflag & CSTOPB )
new_dev_conf.stop = CYGNUM_SERIAL_STOP_2;
else
new_dev_conf.stop = CYGNUM_SERIAL_STOP_1;
len = sizeof( new_dev_conf );
res = cyg_io_set_config( priv->dev_handle,
CYG_IO_SET_CONFIG_SERIAL_INFO,
&new_dev_conf, &len );
if ( ENOERR == res ) {
// It worked, so update dev_conf to reflect the new state
dev_conf.stop = new_dev_conf.stop;
// and termios
ptermios->c_cflag &= ~CSTOPB;
ptermios->c_cflag |= t->c_cflag & CSTOPB;
}
}
if ( ((t->c_cflag & PARENB) != (ptermios->c_cflag & PARENB)) ||
((t->c_cflag & PARODD) != (ptermios->c_cflag & PARODD)) ) {
new_dev_conf = dev_conf;
if ( t->c_cflag & PARENB )
if ( t->c_cflag & PARODD )
new_dev_conf.parity = CYGNUM_SERIAL_PARITY_ODD;
else
new_dev_conf.parity = CYGNUM_SERIAL_PARITY_EVEN;
else
new_dev_conf.parity = CYGNUM_SERIAL_PARITY_NONE;
len = sizeof( new_dev_conf );
res = cyg_io_set_config( priv->dev_handle,
CYG_IO_SET_CONFIG_SERIAL_INFO,
&new_dev_conf, &len );
if ( ENOERR == res ) {
// It worked, so update dev_conf to reflect the new state
dev_conf.parity = new_dev_conf.parity;
// and termios
ptermios->c_cflag &= ~(PARENB|PARODD);
ptermios->c_cflag |= t->c_cflag & (PARENB|PARODD);
}
}
if ( (t->c_cflag & CSIZE) != (ptermios->c_cflag & CSIZE) ) {
new_dev_conf = dev_conf;
switch ( t->c_cflag & CSIZE ) {
case CS5:
new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_5;
break;
case CS6:
new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_6;
break;
case CS7:
new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_7;
break;
case CS8:
new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_8;
break;
}
len = sizeof( new_dev_conf );
res = cyg_io_set_config( priv->dev_handle,
CYG_IO_SET_CONFIG_SERIAL_INFO,
&new_dev_conf, &len );
if ( ENOERR == res ) {
// It worked, so update dev_conf to reflect the new state
dev_conf.word_length = new_dev_conf.word_length;
// and termios
ptermios->c_cflag &= ~CSIZE;
ptermios->c_cflag |= t->c_cflag & CSIZE;
}
}
if ( (t->c_cflag & IXOFF) != (ptermios->c_cflag & IXOFF) ) {
new_dev_conf = dev_conf;
new_dev_conf.flags &=
~(CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_RTSCTS_RX);
if ( t->c_cflag & IXOFF )
if ( t->c_cflag & CRTSCTS)
new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_RX;
else
new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_RX;
else
new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_NONE;
len = sizeof( new_dev_conf );
res = cyg_io_set_config( priv->dev_handle,
CYG_IO_SET_CONFIG_SERIAL_INFO,
&new_dev_conf, &len );
if ( ENOERR == res ) {
// It worked, so update dev_conf to reflect the new state
dev_conf.flags = new_dev_conf.flags;
// and termios
ptermios->c_cflag &= ~(IXOFF|CRTSCTS);
ptermios->c_cflag |= t->c_cflag & (IXOFF|CRTSCTS);
}
}
if ( (t->c_cflag & IXON) != (ptermios->c_cflag & IXON) ) {
new_dev_conf = dev_conf;
new_dev_conf.flags &=
~(CYGNUM_SERIAL_FLOW_XONXOFF_TX|CYGNUM_SERIAL_FLOW_RTSCTS_TX);
if ( t->c_cflag & IXON )
if ( t->c_cflag & CRTSCTS)
new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_TX;
else
new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_TX;
else
new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_NONE;
len = sizeof( new_dev_conf );
res = cyg_io_set_config( priv->dev_handle,
CYG_IO_SET_CONFIG_SERIAL_INFO,
&new_dev_conf, &len );
if ( ENOERR == res ) {
// It worked, so update dev_conf to reflect the new state
dev_conf.flags = new_dev_conf.flags;
// and termios
ptermios->c_cflag &= ~(IXON|CRTSCTS);
ptermios->c_cflag |= t->c_cflag & (IXON|CRTSCTS);
}
}
// Input/Output processing flags can just be set as we grok them all
// with few exceptions (see lflags below)
ptermios->c_iflag &= ~(BRKINT|ICRNL|IGNBRK|IGNCR|IGNPAR|INLCR|INPCK|
ISTRIP|PARMRK);
ptermios->c_iflag |= t->c_iflag & (
#ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS
BRKINT|
#endif
ICRNL|IGNBRK|IGNCR|IGNPAR|
INLCR|INPCK|ISTRIP|PARMRK );
ptermios->c_oflag &= ~(OPOST|ONLCR);
ptermios->c_oflag |= t->c_oflag & (OPOST|ONLCR);
ptermios->c_cflag &= ~(CLOCAL|CREAD|HUPCL);
ptermios->c_cflag |= t->c_cflag & (CLOCAL|CREAD|HUPCL);
ptermios->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|
IEXTEN|ISIG|NOFLSH|TOSTOP);
// Note we don't support IEXTEN nor TOSTOP so we don't set them
ptermios->c_lflag |= t->c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ICANON|
#ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS
ISIG|
#endif
NOFLSH);
// control characters. We don't support changing of VSTART, VSTOP,
// VTIME or VSUSP though
tempcc[VEOF] = t->c_cc[VEOF];
tempcc[VEOL] = t->c_cc[VEOL];
tempcc[VERASE] = t->c_cc[VERASE];
tempcc[VINTR] = t->c_cc[VINTR];
tempcc[VKILL] = t->c_cc[VKILL];
tempcc[VMIN] = t->c_cc[VMIN];
tempcc[VQUIT] = t->c_cc[VQUIT];
return res;
}
//==========================================================================
static bool
termios_init(struct cyg_devtab_entry *tab)
{
// can't initialize the termios structure because we can't
// query the serial driver yet. Wait until lookup time.
return true;
} // termios_init()
//==========================================================================
static Cyg_ErrNo
termios_lookup(struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
cyg_io_handle_t chan = (cyg_io_handle_t)sub_tab;
struct termios_private_info *priv =
(struct termios_private_info *)(*tab)->priv;
Cyg_ErrNo err = ENOERR;
if ( !priv->init ) {
cyg_drv_mutex_lock( &priv->lock );
if ( !priv->init ) { // retest as we may have been pre-empted
priv->dev_handle = chan;
err = real_termios_init( priv );
}
cyg_drv_mutex_unlock( &priv->lock );
}
return err;
}
//==========================================================================
#define WRITE_BUFSIZE 100 // FIXME: ->CDL
// #define MAX_CANON 64 FIXME: relevance?
static Cyg_ErrNo
termios_write(cyg_io_handle_t handle, 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_int32 xbufsize, input_bytes_read;
cyg_uint8 xbuf[WRITE_BUFSIZE];
cyg_uint8 *buf = (cyg_uint8 *)_buf;
Cyg_ErrNo res;
xbufsize = input_bytes_read = 0;
while (input_bytes_read++ < *len) {
if ( (*buf == '\n') && (priv->termios.c_oflag & (OPOST|ONLCR)) ) {
xbuf[xbufsize++] = '\r';
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -