From 8ad70ca231934d8c14708c022c157573ed15de7f Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Fri, 5 May 2023 08:19:09 +0800 Subject: [PATCH] [tty] change driver of tty to device and code cleanup. (#7444) --- components/drivers/tty/console.c | 84 ++++------ components/drivers/tty/include/tty.h | 193 +---------------------- components/drivers/tty/n_tty.c | 220 ++++++++++++++++++++++----- components/drivers/tty/pty.c | 182 +++++++++------------- components/drivers/tty/tty.c | 62 +++++--- components/drivers/tty/tty_ldisc.c | 44 +++--- src/kservice.c | 3 +- 7 files changed, 345 insertions(+), 443 deletions(-) diff --git a/components/drivers/tty/console.c b/components/drivers/tty/console.c index 12e1ad629b..f9eb5ca510 100644 --- a/components/drivers/tty/console.c +++ b/components/drivers/tty/console.c @@ -20,7 +20,7 @@ #endif /* RT_TTY_DEBUG */ #include -static struct tty_struct console_driver; +static struct tty_struct console_dev; static void console_rx_notify(struct rt_device *dev) { @@ -35,7 +35,7 @@ static void console_rx_notify(struct rt_device *dev) while (1) { - len = rt_device_read(console->driver, -1, &ch, 1); + len = rt_device_read(console->io_dev, -1, &ch, 1); if (len == 0) { break; @@ -56,7 +56,7 @@ static void console_rx_notify(struct rt_device *dev) struct tty_struct *console_tty_get(void) { - return &console_driver; + return &console_dev; } static void iodev_close(struct tty_struct *console) @@ -67,8 +67,8 @@ static void iodev_close(struct tty_struct *console) rx_notify.dev = RT_NULL; /* clear notify */ - rt_device_control(console->driver, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); - rt_device_close(console->driver); + rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); + rt_device_close(console->io_dev); } static rt_err_t iodev_open(struct tty_struct *console) @@ -77,9 +77,9 @@ static rt_err_t iodev_open(struct tty_struct *console) struct rt_device_notify rx_notify; rt_uint16_t oflags = 0; - rt_device_control(console->driver, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags); + rt_device_control(console->io_dev, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags); - ret = rt_device_open(console->driver, oflags); + ret = rt_device_open(console->io_dev, oflags); if (ret != RT_EOK) { return -RT_ERROR; @@ -87,7 +87,7 @@ static rt_err_t iodev_open(struct tty_struct *console) rx_notify.notify = console_rx_notify; rx_notify.dev = (struct rt_device *)console; - rt_device_control(console->driver, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); + rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); return RT_EOK; } @@ -97,8 +97,9 @@ struct rt_device *console_get_iodev(void) struct rt_device *iodev = RT_NULL; level = rt_hw_interrupt_disable(); - iodev = console_driver.driver; + iodev = console_dev.io_dev; rt_hw_interrupt_enable(level); + return iodev; } @@ -110,14 +111,13 @@ struct rt_device *console_set_iodev(struct rt_device *iodev) RT_ASSERT(iodev != RT_NULL); - console = &console_driver; + console = &console_dev; level = rt_hw_interrupt_disable(); RT_ASSERT(console->init_flag >= TTY_INIT_FLAG_REGED); - io_before = console->driver; - + io_before = console->io_dev; if (iodev == io_before) { goto exit; @@ -129,8 +129,7 @@ struct rt_device *console_set_iodev(struct rt_device *iodev) iodev_close(console); } - console->driver = iodev; - + console->io_dev = iodev; if (console->init_flag >= TTY_INIT_FLAG_INITED) { rt_err_t ret; @@ -218,7 +217,7 @@ static rt_ssize_t rt_console_write(struct rt_device *dev, RT_ASSERT(console != RT_NULL); RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED); - len = rt_device_write((struct rt_device *)console->driver, -1, buffer, size); + len = rt_device_write((struct rt_device *)console->io_dev, -1, buffer, size); return len; } @@ -232,7 +231,7 @@ static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args) RT_ASSERT(console != RT_NULL); RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED); - len = rt_device_control((struct rt_device *)console->driver, cmd, args); + len = rt_device_control((struct rt_device *)console->io_dev, cmd, args); return len; } @@ -248,23 +247,24 @@ const static struct rt_device_ops console_ops = rt_console_control, }; #endif + /* * console register */ - static struct dfs_file_ops con_fops; +static struct dfs_file_ops con_fops; rt_err_t console_register(const char *name, struct rt_device *iodev) { - rt_base_t level = 0; rt_err_t ret = RT_EOK; struct rt_device *device = RT_NULL; - struct tty_struct *console = &console_driver; + struct tty_struct *console = &console_dev; - level = rt_hw_interrupt_disable(); - RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE); RT_ASSERT(iodev != RT_NULL); + RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE); + + tty_init(console, TTY_DRIVER_TYPE_CONSOLE, SERIAL_TYPE_NORMAL, iodev); + console_ldata_init(console); device = &(console->parent); - device->type = RT_Device_Class_Char; #ifdef RT_USING_DEVICE_OPS @@ -278,48 +278,20 @@ rt_err_t console_register(const char *name, struct rt_device *iodev) device->control = rt_console_control; #endif - /* register a character device */ ret = rt_device_register(device, name, 0); if (ret != RT_EOK) { LOG_E("console driver register fail\n"); - goto exit; } - -#ifdef RT_USING_POSIX_DEVIO - /* set fops */ - console_set_fops(&con_fops); - device->fops = &con_fops; -#endif - console->type = TTY_DRIVER_TYPE_CONSOLE; - console->subtype = SERIAL_TYPE_NORMAL; - console->driver = iodev; - console->head = rt_calloc(1, sizeof(struct tty_node)); - if (!console->head) + else { - return -RT_ENOMEM; +#ifdef RT_USING_POSIX_DEVIO + /* set fops */ + memcpy(&con_fops, tty_get_fops(), sizeof(struct dfs_file_ops)); + device->fops = &con_fops; +#endif } - tty_initstack(console->head); - rt_mutex_init(&console->lock, "ttylock", RT_IPC_FLAG_PRIO); - console->pgrp = -1; - console->session = -1; - console->foreground = RT_NULL; - rt_wqueue_init(&console->wait_queue); - - tty_ldisc_init(console); - -extern struct termios tty_std_termios; - console->init_termios = tty_std_termios; - console->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL; /* is normally B9600 default... */ - console->init_termios.__c_ispeed = 9600; - console->init_termios.__c_ospeed = 9600; - - console_ldata_init(console); - console->init_flag = TTY_INIT_FLAG_REGED; -exit: - rt_hw_interrupt_enable(level); return ret; } diff --git a/components/drivers/tty/include/tty.h b/components/drivers/tty/include/tty.h index e82dfafbea..298b033373 100644 --- a/components/drivers/tty/include/tty.h +++ b/components/drivers/tty/include/tty.h @@ -160,7 +160,7 @@ struct tty_struct struct tty_ldisc *ldisc; void *disc_data; - struct rt_device *driver; + struct rt_device *io_dev; struct rt_wqueue wait_queue; @@ -208,28 +208,6 @@ enum #define TTY_PTY_LOCK 16 #define TTY_NO_WRITE_SPLIT 17 -/* - * These bits are used in the flags field of the tty structure. - * - * So that interrupts won't be able to mess up the queues, - * copy_to_cooked must be atomic with respect to itself, as must - * tty->write. Thus, you must use the inline functions set_bit() and - * clear_bit() to make things atomic. - */ -#define TTY_THROTTLED 0 -#define TTY_IO_ERROR 1 -#define TTY_OTHER_CLOSED 2 -#define TTY_EXCLUSIVE 3 -#define TTY_DEBUG 4 -#define TTY_DO_WRITE_WAKEUP 5 -#define TTY_PUSH 6 -#define TTY_CLOSING 7 -#define TTY_DONT_FLIP 8 -#define TTY_HW_COOK_OUT 14 -#define TTY_HW_COOK_IN 15 -#define TTY_PTY_LOCK 16 -#define TTY_NO_WRITE_SPLIT 17 - #define NR_LDISCS 30 /* line disciplines */ @@ -270,14 +248,6 @@ enum #define TIOCPKT_NOSTOP 16 #define TIOCPKT_DOSTOP 32 -/* tty driver types */ -#define TTY_DRIVER_TYPE_SYSTEM 0x0001 -#define TTY_DRIVER_TYPE_CONSOLE 0x0002 -#define TTY_DRIVER_TYPE_SERIAL 0x0003 -#define TTY_DRIVER_TYPE_PTY 0x0004 -#define TTY_DRIVER_TYPE_SCC 0x0005 /* scc driver */ -#define TTY_DRIVER_TYPE_SYSCONS 0x0006 - /* pty subtypes */ #define PTY_TYPE_MASTER 0x0001 #define PTY_TYPE_SLAVE 0x0002 @@ -295,8 +265,6 @@ enum typeof(b) _b = b;\ _a < _b ? _a : _b; }) -void tty_set_fops(struct dfs_file_ops *fops); -void console_set_fops(struct dfs_file_ops *fops); void mutex_lock(rt_mutex_t mutex); void mutex_unlock(rt_mutex_t mutex); int __tty_check_change(struct tty_struct *tty, int sig); @@ -324,167 +292,12 @@ rt_inline void tty_wakeup_check(struct tty_struct *tty) rt_wqueue_wakeup(wq, (void*)POLLIN); } -rt_inline int set_bit(int nr,int *addr) -{ - int mask, retval, level; +int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev); +const struct dfs_file_ops *tty_get_fops(void); - addr += nr >> 5; - mask = 1 << (nr & 0x1f); - level = rt_hw_interrupt_disable(); - retval = (mask & *addr) != 0; - *addr |= mask; - rt_hw_interrupt_enable(level); - return retval; -} - -rt_inline int clear_bit(int nr, int *addr) -{ - int mask, retval, level; - - addr += nr >> 5; - mask = 1 << (nr & 0x1f); - level = rt_hw_interrupt_disable(); - retval = (mask & *addr) != 0; - *addr &= ~mask; - rt_hw_interrupt_enable(level); - return retval; -} - -rt_inline int test_bit(int nr, int *addr) -{ - int mask; - - addr += nr >> 5; - mask = 1 << (nr & 0x1f); - return ((mask & *addr) != 0); -} - -rt_inline int test_and_clear_bit(int nr, volatile void *addr) -{ - int mask, retval, level; - volatile unsigned int *a = addr; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - level = rt_hw_interrupt_disable(); - retval = (mask & *a) != 0; - *a &= ~mask; - rt_hw_interrupt_enable(level); - - return retval; -} - -rt_inline unsigned long __ffs(unsigned long word) -{ - int num = 0; - -#if BITS_PER_LONG == 64 - if ((word & 0xffffffff) == 0) - { - num += 32; - word >>= 32; - } -#endif - if ((word & 0xffff) == 0) - { - num += 16; - word >>= 16; - } - if ((word & 0xff) == 0) - { - num += 8; - word >>= 8; - } - if ((word & 0xf) == 0) - { - num += 4; - word >>= 4; - } - if ((word & 0x3) == 0) - { - num += 2; - word >>= 2; - } - if ((word & 0x1) == 0) - { - num += 1; - } - - return num; -} -#define BITS_PER_LONG 32 -#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) - -/* - * Find the next set bit in a memory region. - */ -rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - { - return size; - } - - size -= result; - offset %= BITS_PER_LONG; - if (offset) - { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - { - goto found_first; - } - - if (tmp) - { - goto found_middle; - } - - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - - while (size & ~(BITS_PER_LONG-1)) - { - if ((tmp = *(p++))) - { - goto found_middle; - } - - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - - if (!size) - { - return result; - } - - tmp = *p; - -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - { - return result + size; /* Nope. */ - } - -found_middle: - return result + __ffs(tmp); -} - -/*create by tty_ioctl.c*/ int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *arg); -/*create by n_tty.c*/ void console_ldata_init(struct tty_struct *tty); int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count); -void n_tty_init(void); #endif /*__TTY_H__*/ diff --git a/components/drivers/tty/n_tty.c b/components/drivers/tty/n_tty.c index d0fd9f8f65..5ed7d6a6f8 100644 --- a/components/drivers/tty/n_tty.c +++ b/components/drivers/tty/n_tty.c @@ -50,19 +50,6 @@ #define ECHO_BLOCK 256 #define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32) -rt_inline void tty_sigaddset(lwp_sigset_t *set, int _sig) -{ - unsigned long sig = _sig - 1; - - if (_LWP_NSIG_WORDS == 1) - { - set->sig[0] |= 1UL << sig; - } - else - { - set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW); - } -} struct n_tty_data { @@ -99,27 +86,197 @@ struct n_tty_data rt_mutex_t output_lock; }; -static inline size_t read_cnt(struct n_tty_data *ldata) +rt_inline int set_bit(int nr,int *addr) +{ + int mask, retval, level; + + addr += nr >> 5; + mask = 1 << (nr & 0x1f); + level = rt_hw_interrupt_disable(); + retval = (mask & *addr) != 0; + *addr |= mask; + rt_hw_interrupt_enable(level); + return retval; +} + +rt_inline int clear_bit(int nr, int *addr) +{ + int mask, retval, level; + + addr += nr >> 5; + mask = 1 << (nr & 0x1f); + level = rt_hw_interrupt_disable(); + retval = (mask & *addr) != 0; + *addr &= ~mask; + rt_hw_interrupt_enable(level); + return retval; +} + +rt_inline int test_bit(int nr, int *addr) +{ + int mask; + + addr += nr >> 5; + mask = 1 << (nr & 0x1f); + return ((mask & *addr) != 0); +} + +rt_inline int test_and_clear_bit(int nr, volatile void *addr) +{ + int mask, retval, level; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + level = rt_hw_interrupt_disable(); + retval = (mask & *a) != 0; + *a &= ~mask; + rt_hw_interrupt_enable(level); + + return retval; +} + +rt_inline unsigned long __ffs(unsigned long word) +{ + int num = 0; + +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) + { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) + { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) + { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) + { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) + { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + { + num += 1; + } + + return num; +} + +#define BITS_PER_LONG 32 +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) + +/* + * Find the next set bit in a memory region. + */ +rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + { + return size; + } + + size -= result; + offset %= BITS_PER_LONG; + if (offset) + { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < BITS_PER_LONG) + { + goto found_first; + } + + if (tmp) + { + goto found_middle; + } + + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + + while (size & ~(BITS_PER_LONG-1)) + { + if ((tmp = *(p++))) + { + goto found_middle; + } + + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + + if (!size) + { + return result; + } + + tmp = *p; + +found_first: + tmp &= (~0UL >> (BITS_PER_LONG - size)); + if (tmp == 0UL) /* Are any bits set? */ + { + return result + size; /* Nope. */ + } + +found_middle: + return result + __ffs(tmp); +} + +rt_inline void tty_sigaddset(lwp_sigset_t *set, int _sig) +{ + unsigned long sig = _sig - 1; + + if (_LWP_NSIG_WORDS == 1) + { + set->sig[0] |= 1UL << sig; + } + else + { + set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW); + } +} + +rt_inline size_t read_cnt(struct n_tty_data *ldata) { return ldata->read_head - ldata->read_tail; } -static inline char read_buf(struct n_tty_data *ldata, size_t i) +rt_inline char read_buf(struct n_tty_data *ldata, size_t i) { return ldata->read_buf[i & (RT_TTY_BUF - 1)]; } -static inline char *read_buf_addr(struct n_tty_data *ldata, size_t i) +rt_inline char *read_buf_addr(struct n_tty_data *ldata, size_t i) { return &ldata->read_buf[i & (RT_TTY_BUF - 1)]; } -static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) +rt_inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) { return ldata->echo_buf[i & (RT_TTY_BUF - 1)]; } -static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) +rt_inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) { return &ldata->echo_buf[i & (RT_TTY_BUF - 1)]; } @@ -134,8 +291,7 @@ static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem */ - -static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) +rt_inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) { *read_buf_addr(ldata, ldata->read_head) = c; ldata->read_head++; @@ -173,7 +329,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) * Add a character or operation byte to the echo buffer. */ -static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) +rt_inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { *echo_buf_addr(ldata, ldata->echo_head++) = c; } @@ -298,7 +454,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty) * @ldata: n_tty data */ -static inline void finish_erasing(struct n_tty_data *ldata) +rt_inline void finish_erasing(struct n_tty_data *ldata) { if (ldata->erasing) { @@ -316,7 +472,7 @@ static inline void finish_erasing(struct n_tty_data *ldata) * of the character when printing */ -static inline int is_utf8_continuation(unsigned char c) +rt_inline int is_utf8_continuation(unsigned char c) { return (c & 0xc0) == 0x80; } @@ -329,7 +485,7 @@ static inline int is_utf8_continuation(unsigned char c) * character and the terminal is in unicode mode. */ -static inline int is_continuation(unsigned char c, struct tty_struct *tty) +rt_inline int is_continuation(unsigned char c, struct tty_struct *tty) { return I_IUTF8(tty) && is_utf8_continuation(c); } @@ -1148,7 +1304,7 @@ static int n_tty_open(struct dfs_file *fd) return ret; } -static inline int input_available_p(struct tty_struct *tty, int poll) +rt_inline int input_available_p(struct tty_struct *tty, int poll) { struct n_tty_data *ldata = tty->disc_data; int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1; @@ -1570,7 +1726,7 @@ handle_newline: return 0; } -static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) +rt_inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1695,7 +1851,7 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int cou } } -static inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) +rt_inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -2018,19 +2174,18 @@ static int n_tty_poll(struct dfs_file *fd, struct rt_pollreq *req) lwp = (struct rt_lwp *)(rt_thread_self()->lwp); wq = wait_queue_get(lwp, tty); rt_poll_add(wq, req); - level = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); if (input_available_p(tty, 1)) { mask |= POLLIN; } - rt_hw_interrupt_enable(level); return mask; } -static struct tty_ldisc_ops n_tty_ops = { +struct tty_ldisc_ops n_tty_ops = { "n_tty", 0, n_tty_open, @@ -2046,8 +2201,3 @@ static struct tty_ldisc_ops n_tty_ops = { n_tty_receive_buf, 0, }; - -void n_tty_init(void) -{ - tty_register_ldisc(N_TTY, &n_tty_ops); -} diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c index acb217ecbc..87ee37b020 100644 --- a/components/drivers/tty/pty.c +++ b/components/drivers/tty/pty.c @@ -20,21 +20,21 @@ #include #define PTY_PTS_SIZE 10 -static struct tty_struct ptm_driver; -static struct tty_struct pts_drivers[PTY_PTS_SIZE]; +static struct tty_struct ptm_dev; +static struct tty_struct pts_devs[PTY_PTS_SIZE]; static int pts_index = 0; -static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, int pts_index); +static int pts_register(struct tty_struct *ptmx, struct tty_struct *pts, int pts_index); /* check free pts device */ static struct tty_struct *find_freepts(void) { for(int i = 0; i < PTY_PTS_SIZE; i++) { - if (pts_drivers[i].init_flag == TTY_INIT_FLAG_NONE) + if (pts_devs[i].init_flag == TTY_INIT_FLAG_NONE) { - pts_drivers[i].init_flag = TTY_INIT_FLAG_ALLOCED; - return &pts_drivers[i]; + pts_devs[i].init_flag = TTY_INIT_FLAG_ALLOCED; + return &pts_devs[i]; } } return RT_NULL; @@ -73,16 +73,18 @@ static int pty_get_index(struct tty_struct *tty, int *arg) */ static rt_err_t pty_device_init(struct rt_device *dev) { + rt_ubase_t level = 0; rt_err_t result = RT_EOK; - int level = 0; struct tty_struct *tty = RT_NULL; - RT_ASSERT(dev != RT_NULL); + RT_ASSERT(dev != RT_NULL); tty = (struct tty_struct *)dev; + level = rt_hw_interrupt_disable(); RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_REGED); tty->init_flag = TTY_INIT_FLAG_INITED; rt_hw_interrupt_enable(level); + return result; } @@ -138,8 +140,8 @@ static rt_ssize_t pty_device_write(struct rt_device *dev, const void *buffer, rt_size_t size) { - rt_base_t level = 0; rt_size_t len = 0; + rt_base_t level = 0; struct tty_struct *tty = RT_NULL; struct tty_struct *to = RT_NULL; @@ -147,8 +149,8 @@ static rt_ssize_t pty_device_write(struct rt_device *dev, RT_ASSERT(tty != RT_NULL); RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED); to = tty->other_struct; - level = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); if (to->ldisc->ops->receive_buf) { len = to->ldisc->ops->receive_buf(to, (char *)buffer, size); @@ -179,7 +181,7 @@ static int ptmx_open(struct dfs_file *fd) { int ret = 0; struct tty_struct *tty = RT_NULL; - struct tty_struct *pts_drv = RT_NULL; + struct tty_struct *pts = RT_NULL; struct tty_ldisc *ld = RT_NULL; struct rt_lwp *lwp = RT_NULL; struct rt_wqueue *wq = RT_NULL; @@ -187,24 +189,25 @@ static int ptmx_open(struct dfs_file *fd) tty = (struct tty_struct *)fd->vnode->data; RT_ASSERT(tty != RT_NULL); - pts_drv = find_freepts(); - if (pts_drv == RT_NULL) + pts = find_freepts(); + if (pts == RT_NULL) { - LOG_E("free pts driver find fail\n"); + LOG_E("No free PTS device found.\n"); return -1; } - ret = pts_register(tty, pts_drv, pts_index); + ret = pts_register(tty, pts, pts_index); if (ret < 0) { LOG_E("pts register fail\n"); - rt_free(pts_drv); + rt_free(pts); return -1; } pts_index++; - lwp = (struct rt_lwp *)(rt_thread_self()->lwp); + lwp = lwp_self(); wq = wait_queue_get(lwp, tty); - pts_drv->wait_queue = *wq; - tty->other_struct = pts_drv; + pts->wait_queue = *wq; + tty->other_struct = pts; + ld = tty->ldisc; if (ld->ops->open) { @@ -230,94 +233,73 @@ const static struct rt_device_ops pty_device_ops = pty_device_control, }; #endif /* RT_USING_DEVICE_OPS */ + static struct dfs_file_ops pts_fops; static struct dfs_file_ops ptmx_fops; -static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, int pts_index) +static int pts_register(struct tty_struct *ptmx, struct tty_struct *pts, int pts_index) { - rt_err_t ret = RT_EOK; - rt_base_t level = 0; - struct rt_device *device = RT_NULL; char name[20]; + rt_err_t ret = RT_EOK; + struct rt_device *device = RT_NULL; - RT_ASSERT(ptm_drv!=RT_NULL); - level = rt_hw_interrupt_disable(); + RT_ASSERT(ptmx!=RT_NULL); - if (pts_drv->init_flag != TTY_INIT_FLAG_ALLOCED) + if (pts->init_flag != TTY_INIT_FLAG_ALLOCED) { LOG_E("pts%d has been registered\n", pts_index); ret = (-RT_EBUSY); - goto _exit; } + else + { + tty_init(pts, TTY_DRIVER_TYPE_PTY, PTY_TYPE_SLAVE, NULL); + pts->index = pts_index; + pts->pts_lock = 1; + pts->other_struct = ptmx; - device = &pts_drv->parent; - device->type = RT_Device_Class_Char; + device = &pts->parent; + device->type = RT_Device_Class_Char; #ifdef RT_USING_DEVICE_OPS - device->ops = &pty_device_ops; + device->ops = &pty_device_ops; #else - device->init = pty_device_init; - device->open = pty_device_open; - device->close = pty_device_close; - device->read = pty_device_read; - device->write = pty_device_write; - device->control = pty_device_control; + device->init = pty_device_init; + device->open = pty_device_open; + device->close = pty_device_close; + device->read = pty_device_read; + device->write = pty_device_write; + device->control = pty_device_control; #endif /* RT_USING_DEVICE_OPS */ - rt_snprintf(name, sizeof(name), "pts%d", pts_index); - ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); - if (ret != RT_EOK) - { - LOG_E("pts%d register failed\n", pts_index); - ret = -RT_EIO; - goto _exit; - } - + rt_snprintf(name, sizeof(name), "pts%d", pts_index); + ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); + if (ret != RT_EOK) + { + LOG_E("pts%d register failed\n", pts_index); + ret = -RT_EIO; + } + else + { #ifdef RT_USING_POSIX_DEVIO - /* set fops */ - tty_set_fops(&pts_fops); - device->fops = &pts_fops; + /* set fops */ + memcpy(&pts_fops, tty_get_fops(), sizeof(struct dfs_file_ops)); + device->fops = &pts_fops; #endif - - pts_drv->type = TTY_DRIVER_TYPE_PTY; - pts_drv->subtype = PTY_TYPE_SLAVE; - - pts_drv->pgrp = -1; - pts_drv->session = -1; - pts_drv->foreground = RT_NULL; - pts_drv->index = pts_index; - pts_drv->pts_lock = 1; - rt_wqueue_init(&pts_drv->wait_queue); - - tty_ldisc_init(pts_drv); - -extern struct termios tty_std_termios; - pts_drv->init_termios = tty_std_termios; - pts_drv->init_termios.c_cflag = B38400 | CS8 | CREAD; - pts_drv->init_termios.c_lflag |= ECHO | ICANON; - pts_drv->init_termios.c_oflag |= ONLCR; - pts_drv->init_termios.__c_ispeed = 38400; - pts_drv->init_termios.__c_ospeed = 38400; - - pts_drv->other_struct = ptm_drv; - - pts_drv->init_flag = TTY_INIT_FLAG_REGED; -_exit: - rt_hw_interrupt_enable(level); + } + } return ret; } static int ptmx_register(void) { - rt_base_t level = 0; rt_err_t ret = RT_EOK; struct rt_device *device = RT_NULL; - struct tty_struct *ptm_drv = &ptm_driver; + struct tty_struct *ptmx = &ptm_dev; - level = rt_hw_interrupt_disable(); - RT_ASSERT(ptm_drv->init_flag == TTY_INIT_FLAG_NONE); + RT_ASSERT(ptmx->init_flag == TTY_INIT_FLAG_NONE); - device = &(ptm_drv->parent); + tty_init(ptmx, TTY_DRIVER_TYPE_PTY, PTY_TYPE_MASTER, NULL); + device = &(ptmx->parent); device->type = RT_Device_Class_Char; #ifdef RT_USING_DEVICE_OPS @@ -336,44 +318,16 @@ static int ptmx_register(void) { LOG_E("ptmx register fail\n"); ret = -RT_EIO; - goto _exit; } - -#ifdef RT_USING_POSIX_DEVIO - /* set fops */ - tty_set_fops(&ptmx_fops); - ptmx_fops.open = ptmx_open; - device->fops = &ptmx_fops; -#endif - - ptm_drv->type = TTY_DRIVER_TYPE_PTY; - ptm_drv->subtype = PTY_TYPE_MASTER; - ptm_drv->head = rt_calloc(1, sizeof(struct tty_node)); - if (!ptm_drv->head) + else { - return -RT_ENOMEM; +#ifdef RT_USING_POSIX_DEVIO + /* set fops */ + memcpy(&ptmx_fops, tty_get_fops(), sizeof(struct dfs_file_ops)); + ptmx_fops.open = ptmx_open; + device->fops = &ptmx_fops; +#endif } - tty_initstack(ptm_drv->head); - - ptm_drv->pgrp = -1; - ptm_drv->session = -1; - ptm_drv->foreground = RT_NULL; - rt_wqueue_init(&ptm_drv->wait_queue); - - tty_ldisc_init(ptm_drv); - -extern struct termios tty_std_termios; - ptm_drv->init_termios.c_iflag = 0; - ptm_drv->init_termios.c_oflag = 0; - ptm_drv->init_termios.c_cflag = B38400 | CS8 | CREAD; - ptm_drv->init_termios.c_lflag = 0; - ptm_drv->init_termios.__c_ispeed = 38400; - ptm_drv->init_termios.__c_ospeed = 38400; - - ptm_drv->init_flag = TTY_INIT_FLAG_REGED; - -_exit: - rt_hw_interrupt_enable(level); return ret; } diff --git a/components/drivers/tty/tty.c b/components/drivers/tty/tty.c index 40e22ad153..29a0f8a601 100644 --- a/components/drivers/tty/tty.c +++ b/components/drivers/tty/tty.c @@ -27,7 +27,7 @@ #endif /* RT_TTY_DEBUG */ #include -struct termios tty_std_termios = { /* for the benefit of tty drivers */ +const struct termios tty_std_termios = { /* for the benefit of tty drivers */ .c_iflag = IMAXBEL | IUCLC | INLCR | ICRNL | IGNPAR, .c_oflag = OPOST, .c_cflag = B38400 | CS8 | CREAD | HUPCL, @@ -219,6 +219,7 @@ static int tty_open(struct dfs_file *fd) tty = (struct tty_struct *)fd->vnode->data; RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; if (ld->ops->open) { @@ -322,11 +323,13 @@ static int tty_ioctl(struct dfs_file *fd, int cmd, void *args) { real_tty = tty; } + switch (cmd) { case TIOCSCTTY: return tiocsctty(real_tty, 1); } + ld = tty->ldisc; if (ld->ops->ioctl) { @@ -343,8 +346,9 @@ static int tty_read(struct dfs_file *fd, void *buf, size_t count) tty = (struct tty_struct *)fd->vnode->data; RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; - if (ld->ops->read) + if (ld && ld->ops->read) { ret = ld->ops->read(fd, buf, count); } @@ -359,11 +363,13 @@ static int tty_write(struct dfs_file *fd, const void *buf, size_t count) tty = (struct tty_struct *)fd->vnode->data; RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; - if (ld->ops->write) + if (ld && ld->ops->write) { ret = ld->ops->write(fd, buf, count); } + return ret; } @@ -395,30 +401,40 @@ static const struct dfs_file_ops tty_fops = RT_NULL, /* getdents */ tty_poll, }; -static const struct dfs_file_ops console_fops = -{ - tty_open, - tty_close, - tty_ioctl, - tty_read, - tty_write, - RT_NULL, /* flush */ - RT_NULL, /* lseek */ - RT_NULL, /* getdents */ - tty_poll, -}; -void console_init() +const struct dfs_file_ops *tty_get_fops(void) { - n_tty_init(); + return &tty_fops; } -void tty_set_fops(struct dfs_file_ops *fops) +int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev) { - *fops = tty_fops; -} + if (tty) + { + struct tty_node *node = NULL; -void console_set_fops(struct dfs_file_ops *fops) -{ - *fops = console_fops; + node = rt_calloc(1, sizeof(struct tty_node)); + if (node) + { + tty->type = type; + tty->subtype = subtype; + tty->io_dev = iodev; + + tty->head = node; + tty_initstack(tty->head); + + tty->pgrp = -1; + tty->session = -1; + tty->foreground = RT_NULL; + + rt_mutex_init(&tty->lock, "ttyLock", RT_IPC_FLAG_PRIO); + rt_wqueue_init(&tty->wait_queue); + + tty_ldisc_init(tty); + tty->init_termios = tty_std_termios; + tty->init_flag = TTY_INIT_FLAG_REGED; + } + } + + return 0; } diff --git a/components/drivers/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c index 2f13c60d14..5fb05a923c 100644 --- a/components/drivers/tty/tty_ldisc.c +++ b/components/drivers/tty/tty_ldisc.c @@ -9,7 +9,10 @@ #endif /* RT_TTY_DEBUG */ #include -static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; +extern struct tty_ldisc_ops n_tty_ops; +static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS] = { + &n_tty_ops, /* N_TTY = 0 */ +}; static struct tty_ldisc_ops *get_ldops(int disc) { @@ -33,6 +36,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops) ldops->refcount--; rt_hw_interrupt_enable(level); } + static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { struct tty_ldisc *ld = RT_NULL; @@ -70,13 +74,11 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) */ static void tty_ldisc_put(struct tty_ldisc *ld) { - if (ld == RT_NULL) + if (ld) { - return; + put_ldops(ld->ops); + rt_free(ld); } - - put_ldops(ld->ops); - rt_free(ld); } /** @@ -87,10 +89,9 @@ static void tty_ldisc_put(struct tty_ldisc *ld) * A helper close method. Also a convenient debugging and check * point. */ - static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) { - if (ld->ops->close) + if (ld && ld->ops->close) { ld->ops->close(tty); } @@ -104,18 +105,16 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) */ void tty_ldisc_kill(struct tty_struct *tty) { - if (!tty->ldisc) + if (tty && tty->ldisc) { - return; + /* + * Now kill off the ldisc + */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; } - - /* - * Now kill off the ldisc - */ - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* Force an oops if we mess this up */ - tty->ldisc = NULL; } int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) @@ -154,7 +153,6 @@ void tty_ldisc_release(struct tty_struct *tty) * Shutdown this line discipline. As this is the final close, * it does not race with the set_ldisc code path. */ - level = rt_hw_interrupt_disable(); tty_ldisc_kill(tty); if (o_tty) @@ -162,7 +160,6 @@ void tty_ldisc_release(struct tty_struct *tty) tty_ldisc_kill(o_tty); } rt_hw_interrupt_enable(level); - } /** @@ -175,7 +172,8 @@ void tty_ldisc_release(struct tty_struct *tty) void tty_ldisc_init(struct tty_struct *tty) { - struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); - RT_ASSERT(ld != RT_NULL); - tty->ldisc = ld; + if (tty) + { + tty->ldisc = tty_ldisc_get(tty, N_TTY); + } } diff --git a/src/kservice.c b/src/kservice.c index 6638173f2d..4f44183707 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -1370,8 +1370,7 @@ rt_device_t rt_console_set_device(const char *name) { #ifdef RT_USING_SMART rt_device_t new_iodev = RT_NULL, old_iodev = RT_NULL; -extern void console_init(); - console_init(); /*add line discipline*/ + /* find new console device */ new_iodev = rt_device_find(name); if (new_iodev != RT_NULL)