⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 termiostty.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -