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

📄 termiostty.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        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 + -