From 83e95bdff4c48c661b50e1eec56d5fd293b28fbb Mon Sep 17 00:00:00 2001 From: Shell Date: Thu, 28 Mar 2024 23:42:56 +0800 Subject: sync smart & dfs (#8672) Signed-off-by: xqyjlj Signed-off-by: Shell Co-authored-by: xqyjlj --- components/drivers/tty/SConscript | 10 - components/drivers/tty/console.c | 346 ----- components/drivers/tty/include/console.h | 19 - components/drivers/tty/include/tty.h | 304 ---- components/drivers/tty/include/tty_ldisc.h | 56 - components/drivers/tty/n_tty.c | 2223 ---------------------------- components/drivers/tty/pty.c | 326 ---- components/drivers/tty/tty.c | 504 ------- components/drivers/tty/tty_ioctl.c | 122 -- components/drivers/tty/tty_ldisc.c | 178 --- 10 files changed, 4088 deletions(-) delete mode 100644 components/drivers/tty/SConscript delete mode 100644 components/drivers/tty/console.c delete mode 100644 components/drivers/tty/include/console.h delete mode 100644 components/drivers/tty/include/tty.h delete mode 100644 components/drivers/tty/include/tty_ldisc.h delete mode 100644 components/drivers/tty/n_tty.c delete mode 100644 components/drivers/tty/pty.c delete mode 100644 components/drivers/tty/tty.c delete mode 100644 components/drivers/tty/tty_ioctl.c delete mode 100644 components/drivers/tty/tty_ldisc.c (limited to 'components/drivers/tty') diff --git a/components/drivers/tty/SConscript b/components/drivers/tty/SConscript deleted file mode 100644 index d972879b70..0000000000 --- a/components/drivers/tty/SConscript +++ /dev/null @@ -1,10 +0,0 @@ -from building import * - -# The set of source files associated with this SConscript file. -src = Glob('*.c') -cwd = GetCurrentDir() -CPPPATH = [cwd + "/include"] - -group = DefineGroup('tty', src, depend = ['RT_USING_SMART', 'RT_USING_TTY'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/drivers/tty/console.c b/components/drivers/tty/console.c deleted file mode 100644 index a9c9b88731..0000000000 --- a/components/drivers/tty/console.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021.12.07 linzhenxing first version - */ -#include -#include -#include -#include - -#define DBG_TAG "CONSOLE" -#ifdef RT_TTY_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_TTY_DEBUG */ -#include - -#include -#include - -static struct tty_struct console_dev; -static struct rt_ringbuffer console_rx_ringbuffer; -static struct rt_wqueue console_rx_wqueue; -static rt_thread_t console_rx_thread; -static const size_t rb_bufsz = 0x1000; - -static void console_rx_work(void *parameter) -{ - int len; - char ch; - int lens; - static char buf[0x1000]; - - struct tty_struct *console; - console = &console_dev; - - while (1) - { - rt_wqueue_wait(&console_rx_wqueue, 0, RT_WAITING_FOREVER); - lens = 0; - - while (lens < sizeof(buf)) - { - len = rt_ringbuffer_get(&console_rx_ringbuffer, (void *)&ch, sizeof(ch)); - if (len == 0) - { - break; - } - lens += len; - buf[lens-1] = ch; - } - - if (lens && console->ldisc->ops->receive_buf) - { - console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens); - } - } -} - -static int rx_thread_init(void) -{ - void *rb_buffer; - rt_thread_t thread; - - rb_buffer = rt_malloc(rb_bufsz); - rt_ringbuffer_init(&console_rx_ringbuffer, rb_buffer, rb_bufsz); - rt_wqueue_init(&console_rx_wqueue); - - thread = rt_thread_create("console_rx", console_rx_work, &console_dev, rb_bufsz, 10, 10); - if (thread != RT_NULL) - { - rt_thread_startup(thread); - console_rx_thread = thread; - } - - return 0; -} -INIT_COMPONENT_EXPORT(rx_thread_init); - -static void console_rx_notify(struct rt_device *dev) -{ - struct tty_struct *console = NULL; - int len = 0; - int lens = 0; - char ch = 0; - - console = (struct tty_struct *)dev; - RT_ASSERT(console != RT_NULL); - - while (1) - { - len = rt_device_read(console->io_dev, -1, &ch, 1); - if (len == 0) - { - break; - } - lens += len; - rt_ringbuffer_put(&console_rx_ringbuffer, (void *)&ch, sizeof(ch)); - if (lens > rb_bufsz) - { - break; - } - } - if (console_rx_thread) - rt_wqueue_wakeup(&console_rx_wqueue, 0); -} - -struct tty_struct *console_tty_get(void) -{ - return &console_dev; -} - -static void iodev_close(struct tty_struct *console) -{ - struct rt_device_notify rx_notify; - - rx_notify.notify = RT_NULL; - rx_notify.dev = RT_NULL; - - /* clear notify */ - 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) -{ - rt_err_t ret = RT_EOK; - struct rt_device_notify rx_notify; - rt_uint16_t oflags = 0; - - rt_device_control(console->io_dev, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags); - - ret = rt_device_open(console->io_dev, oflags); - if (ret != RT_EOK) - { - return -RT_ERROR; - } - - rx_notify.notify = console_rx_notify; - rx_notify.dev = (struct rt_device *)console; - rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); - return RT_EOK; -} - -struct rt_device *console_get_iodev(void) -{ - return console_dev.io_dev; -} - -struct rt_device *console_set_iodev(struct rt_device *iodev) -{ - rt_base_t level = 0; - struct rt_device *io_before = RT_NULL; - struct tty_struct *console = RT_NULL; - - RT_ASSERT(iodev != RT_NULL); - - console = &console_dev; - - level = rt_spin_lock_irqsave(&console->spinlock); - - RT_ASSERT(console->init_flag >= TTY_INIT_FLAG_REGED); - - io_before = console->io_dev; - if (iodev == io_before) - { - goto exit; - } - - if (console->init_flag >= TTY_INIT_FLAG_INITED) - { - /* close old device */ - iodev_close(console); - } - - console->io_dev = iodev; - if (console->init_flag >= TTY_INIT_FLAG_INITED) - { - rt_err_t ret; - /* open new device */ - ret = iodev_open(console); - RT_ASSERT(ret == RT_EOK); - } - -exit: - rt_spin_unlock_irqrestore(&console->spinlock, level); - return io_before; -} - -/* RT-Thread Device Interface */ -/* - * This function initializes console device. - */ -static rt_err_t rt_console_init(struct rt_device *dev) -{ - rt_base_t level = 0; - rt_err_t result = RT_EOK; - struct tty_struct *console = RT_NULL; - - RT_ASSERT(dev != RT_NULL); - - console = (struct tty_struct *)dev; - - level = rt_spin_lock_irqsave(&console->spinlock); - - RT_ASSERT(console->init_flag == TTY_INIT_FLAG_REGED); - - result = iodev_open(console); - if (result != RT_EOK) - { - goto exit; - } - - console->init_flag = TTY_INIT_FLAG_INITED; -exit: - rt_spin_unlock_irqrestore(&console->spinlock, level); - return result; -} - -static rt_err_t rt_console_open(struct rt_device *dev, rt_uint16_t oflag) -{ - rt_err_t result = RT_EOK; - struct tty_struct *console = RT_NULL; - - RT_ASSERT(dev != RT_NULL); - console = (struct tty_struct *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED); - return result; -} - -static rt_err_t rt_console_close(struct rt_device *dev) -{ - rt_err_t result = RT_EOK; - struct tty_struct *console = RT_NULL; - - console = (struct tty_struct *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED); - return result; -} - -static rt_ssize_t rt_console_read(struct rt_device *dev, - rt_off_t pos, - void *buffer, - rt_size_t size) -{ - rt_size_t len = 0; - return len; -} - -static rt_ssize_t rt_console_write(struct rt_device *dev, - rt_off_t pos, - const void *buffer, - rt_size_t size) -{ - rt_size_t len = 0; - struct tty_struct *console = RT_NULL; - - console = (struct tty_struct *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED); - - len = rt_device_write((struct rt_device *)console->io_dev, -1, buffer, size); - - return len; -} - -static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args) -{ - rt_size_t len = 0; - struct tty_struct *console = RT_NULL; - - console = (struct tty_struct *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED); - - len = rt_device_control((struct rt_device *)console->io_dev, cmd, args); - - return len; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops console_ops = -{ - rt_console_init, - rt_console_open, - rt_console_close, - rt_console_read, - rt_console_write, - rt_console_control, -}; -#endif - -/* - * console register - */ -static struct dfs_file_ops con_fops; -rt_err_t console_register(const char *name, struct rt_device *iodev) -{ - rt_err_t ret = RT_EOK; - struct rt_device *device = RT_NULL; - struct tty_struct *console = &console_dev; - - 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 - device->ops = &console_ops; -#else - device->init = rt_console_init; - device->open = rt_console_open; - device->close = rt_console_close; - device->read = rt_console_read; - device->write = rt_console_write; - 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"); - } - else - { -#ifdef RT_USING_POSIX_DEVIO - /* set fops */ - memcpy(&con_fops, tty_get_fops(), sizeof(struct dfs_file_ops)); - device->fops = &con_fops; -#endif - } - - return ret; -} diff --git a/components/drivers/tty/include/console.h b/components/drivers/tty/include/console.h deleted file mode 100644 index 653b31fade..0000000000 --- a/components/drivers/tty/include/console.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021.12.07 linzhenxing first version - */ -#ifndef __CONSOLE_ -#define __CONSOLE_ -#include -#include "tty.h" - -struct tty_struct *console_tty_get(void); -struct rt_device *console_get_iodev(void); -struct rt_device *console_set_iodev(struct rt_device *iodev); -rt_err_t console_register(const char *name, struct rt_device *iodev); -#endif diff --git a/components/drivers/tty/include/tty.h b/components/drivers/tty/include/tty.h deleted file mode 100644 index 79e30b6f51..0000000000 --- a/components/drivers/tty/include/tty.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021.12.07 linzhenxing first version - */ -#ifndef __TTY_H__ -#define __TTY_H__ -#include -#include -#include -#ifdef RT_USING_SMART -#include -#endif -#if defined(RT_USING_POSIX_TERMIOS) -#include -#include -#endif - -#ifndef ENOIOCTLCMD -#define ENOIOCTLCMD (515) /* No ioctl command */ -#endif - -#define current lwp_self() -#define __DISABLED_CHAR '\0' - -struct tty_node -{ - struct rt_lwp *lwp; - struct tty_node *next; -}; - -void tty_initstack(struct tty_node *node); -int tty_push(struct tty_node **head, struct rt_lwp *lwp); -struct rt_lwp *tty_pop(struct tty_node **head, struct rt_lwp *target_lwp); -/* - * When a break, frame error, or parity error happens, these codes are - * stuffed into the flags buffer. - */ -#define TTY_NORMAL 0 -#define TTY_BREAK 1 -#define TTY_FRAME 2 -#define TTY_PARITY 3 -#define TTY_OVERRUN 4 - -#define INTR_CHAR(tty) ((tty)->init_termios.c_cc[VINTR]) -#define QUIT_CHAR(tty) ((tty)->init_termios.c_cc[VQUIT]) -#define ERASE_CHAR(tty) ((tty)->init_termios.c_cc[VERASE]) -#define KILL_CHAR(tty) ((tty)->init_termios.c_cc[VKILL]) -#define EOF_CHAR(tty) ((tty)->init_termios.c_cc[VEOF]) -#define TIME_CHAR(tty) ((tty)->init_termios.c_cc[VTIME]) -#define MIN_CHAR(tty) ((tty)->init_termios.c_cc[VMIN]) -#define SWTC_CHAR(tty) ((tty)->init_termios.c_cc[VSWTC]) -#define START_CHAR(tty) ((tty)->init_termios.c_cc[VSTART]) -#define STOP_CHAR(tty) ((tty)->init_termios.c_cc[VSTOP]) -#define SUSP_CHAR(tty) ((tty)->init_termios.c_cc[VSUSP]) -#define EOL_CHAR(tty) ((tty)->init_termios.c_cc[VEOL]) -#define REPRINT_CHAR(tty) ((tty)->init_termios.c_cc[VREPRINT]) -#define DISCARD_CHAR(tty) ((tty)->init_termios.c_cc[VDISCARD]) -#define WERASE_CHAR(tty) ((tty)->init_termios.c_cc[VWERASE]) -#define LNEXT_CHAR(tty) ((tty)->init_termios.c_cc[VLNEXT]) -#define EOL2_CHAR(tty) ((tty)->init_termios.c_cc[VEOL2]) - -#define _I_FLAG(tty,f) ((tty)->init_termios.c_iflag & (f)) -#define _O_FLAG(tty,f) ((tty)->init_termios.c_oflag & (f)) -#define _C_FLAG(tty,f) ((tty)->init_termios.c_cflag & (f)) -#define _L_FLAG(tty,f) ((tty)->init_termios.c_lflag & (f)) - -#define I_IGNBRK(tty) _I_FLAG((tty),IGNBRK) -#define I_BRKINT(tty) _I_FLAG((tty),BRKINT) -#define I_IGNPAR(tty) _I_FLAG((tty),IGNPAR) -#define I_PARMRK(tty) _I_FLAG((tty),PARMRK) -#define I_INPCK(tty) _I_FLAG((tty),INPCK) -#define I_ISTRIP(tty) _I_FLAG((tty),ISTRIP) -#define I_INLCR(tty) _I_FLAG((tty),INLCR) -#define I_IGNCR(tty) _I_FLAG((tty),IGNCR) -#define I_ICRNL(tty) _I_FLAG((tty),ICRNL) -#define I_IUCLC(tty) _I_FLAG((tty),IUCLC) -#define I_IXON(tty) _I_FLAG((tty),IXON) -#define I_IXANY(tty) _I_FLAG((tty),IXANY) -#define I_IXOFF(tty) _I_FLAG((tty),IXOFF) -#define I_IMAXBEL(tty) _I_FLAG((tty),IMAXBEL) -#define I_IUTF8(tty) _I_FLAG((tty), IUTF8) - -#define O_OPOST(tty) _O_FLAG((tty),OPOST) -#define O_OLCUC(tty) _O_FLAG((tty),OLCUC) -#define O_ONLCR(tty) _O_FLAG((tty),ONLCR) -#define O_OCRNL(tty) _O_FLAG((tty),OCRNL) -#define O_ONOCR(tty) _O_FLAG((tty),ONOCR) -#define O_ONLRET(tty) _O_FLAG((tty),ONLRET) -#define O_OFILL(tty) _O_FLAG((tty),OFILL) -#define O_OFDEL(tty) _O_FLAG((tty),OFDEL) -#define O_NLDLY(tty) _O_FLAG((tty),NLDLY) -#define O_CRDLY(tty) _O_FLAG((tty),CRDLY) -#define O_TABDLY(tty) _O_FLAG((tty),TABDLY) -#define O_BSDLY(tty) _O_FLAG((tty),BSDLY) -#define O_VTDLY(tty) _O_FLAG((tty),VTDLY) -#define O_FFDLY(tty) _O_FLAG((tty),FFDLY) - -#define C_BAUD(tty) _C_FLAG((tty),CBAUD) -#define C_CSIZE(tty) _C_FLAG((tty),CSIZE) -#define C_CSTOPB(tty) _C_FLAG((tty),CSTOPB) -#define C_CREAD(tty) _C_FLAG((tty),CREAD) -#define C_PARENB(tty) _C_FLAG((tty),PARENB) -#define C_PARODD(tty) _C_FLAG((tty),PARODD) -#define C_HUPCL(tty) _C_FLAG((tty),HUPCL) -#define C_CLOCAL(tty) _C_FLAG((tty),CLOCAL) -#define C_CIBAUD(tty) _C_FLAG((tty),CIBAUD) -#define C_CRTSCTS(tty) _C_FLAG((tty),CRTSCTS) - -#define L_ISIG(tty) _L_FLAG((tty),ISIG) -#define L_ICANON(tty) _L_FLAG((tty),ICANON) -#define L_XCASE(tty) _L_FLAG((tty),XCASE) -#define L_ECHO(tty) _L_FLAG((tty),ECHO) -#define L_ECHOE(tty) _L_FLAG((tty),ECHOE) -#define L_ECHOK(tty) _L_FLAG((tty),ECHOK) -#define L_ECHONL(tty) _L_FLAG((tty),ECHONL) -#define L_NOFLSH(tty) _L_FLAG((tty),NOFLSH) -#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP) -#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) -#define L_ECHOPRT(tty) _L_FLAG((tty),ECHOPRT) -#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE) -#define L_FLUSHO(tty) _L_FLAG((tty),FLUSHO) -#define L_PENDIN(tty) _L_FLAG((tty),PENDIN) -#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN) -#define L_EXTPROC(tty) _L_FLAG((tty), EXTPROC) - -/* - * Where all of the state associated with a tty is kept while the tty - * is open. Since the termios state should be kept even if the tty - * has been closed --- for things like the baud rate, etc --- it is - * not stored here, but rather a pointer to the real state is stored - * here. Possible the winsize structure should have the same - * treatment, but (1) the default 80x24 is usually right and (2) it's - * most often used by a windowing system, which will set the correct - * size each time the window is created or resized anyway. - * - TYT, 9/14/92 - */ -struct tty_struct -{ - struct rt_device parent; - int type; - int subtype; - int init_flag; - int index; //for pty - int pts_lock; //for pty - - struct tty_struct *other_struct; //for pty - - struct termios init_termios; - struct winsize winsize; - struct rt_mutex lock; - pid_t pgrp; - pid_t session; - struct rt_lwp *foreground; - struct tty_node *head; - - struct tty_ldisc *ldisc; - void *disc_data; - struct rt_device *io_dev; - - struct rt_wqueue wait_queue; - -#define RT_TTY_BUF 1024 - rt_list_t tty_drivers; - struct rt_spinlock spinlock; -}; - -enum -{ - TTY_INIT_FLAG_NONE = 0, - TTY_INIT_FLAG_ALLOCED, - TTY_INIT_FLAG_REGED, - TTY_INIT_FLAG_INITED, -}; - -#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 - -/* tty magic number */ -#define TTY_MAGIC 0x5401 - -/* - * 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 */ -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 /* X.25 async */ -#define N_6PACK 7 -#define N_MASC 8 /* Reserved for Mobitex module */ -#define N_R3964 9 /* Reserved for Simatic R3964 module */ -#define N_PROFIBUS_FDL 10 /* Reserved for Profibus */ -#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */ -#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data */ - /* cards about SMS messages */ -#define N_HDLC 13 /* synchronous HDLC */ -#define N_SYNC_PPP 14 /* synchronous PPP */ -#define N_HCI 15 /* Bluetooth HCI UART */ -#define N_GIGASET_M101 16 /* Siemens Gigaset M101 serial DECT adapter */ -#define N_SLCAN 17 /* Serial / USB serial CAN Adaptors */ -#define N_PPS 18 /* Pulse per Second */ -#define N_V253 19 /* Codec control over voice modem */ -#define N_CAIF 20 /* CAIF protocol for talking to modems */ -#define N_GSM0710 21 /* GSM 0710 Mux */ -#define N_TI_WL 22 /* for TI's WL BT, FM, GPS combo chips */ -#define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */ -#define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */ -#define N_NCI 25 /* NFC NCI UART */ - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -/* pty subtypes */ -#define PTY_TYPE_MASTER 0x0001 -#define PTY_TYPE_SLAVE 0x0002 - -/* serial subtype definitions */ -#define SERIAL_TYPE_NORMAL 1 - -#define max(a, b) ({\ - typeof(a) _a = a;\ - typeof(b) _b = b;\ - _a > _b ? _a : _b; }) - -#define min(a, b) ({\ - typeof(a) _a = a;\ - typeof(b) _b = b;\ - _a < _b ? _a : _b; }) - -void mutex_lock(rt_mutex_t mutex); -void mutex_unlock(rt_mutex_t mutex); -int __tty_check_change(struct tty_struct *tty, int sig); -int tty_check_change(struct tty_struct *tty); - -rt_inline struct rt_wqueue *wait_queue_get(struct rt_lwp *lwp, struct tty_struct *tty) -{ - if (lwp == RT_NULL) - { - return &tty->wait_queue; - } - return &lwp->wait_queue; -} - -rt_inline struct rt_wqueue *wait_queue_current_get(struct rt_lwp *lwp, struct tty_struct *tty) -{ - return wait_queue_get(lwp, tty); -} - -rt_inline void tty_wakeup_check(struct tty_struct *tty) -{ - struct rt_wqueue *wq = NULL; - - wq = wait_queue_current_get(tty->foreground, tty); - rt_wqueue_wakeup(wq, (void*)POLLIN); -} - -int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev); -const struct dfs_file_ops *tty_get_fops(void); - -int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *arg); - -void console_ldata_init(struct tty_struct *tty); -int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count); - -#endif /*__TTY_H__*/ diff --git a/components/drivers/tty/include/tty_ldisc.h b/components/drivers/tty/include/tty_ldisc.h deleted file mode 100644 index 9b95fd3591..0000000000 --- a/components/drivers/tty/include/tty_ldisc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021.12.07 linzhenxing first version - */ -#ifndef __TTY_LDISC_ -#define __TTY_LDISC_ -#include -#include -#include -#include -#if defined(RT_USING_POSIX_TERMIOS) -#include -#endif -struct tty_struct; - -struct tty_ldisc_ops -{ - char *name; - int num; - - int (*open) (struct dfs_file *fd); - int (*close) (struct tty_struct *tty); - int (*ioctl) (struct dfs_file *fd, int cmd, void *args); - int (*read) (struct dfs_file *fd, void *buf, size_t count); - int (*write) (struct dfs_file *fd, const void *buf, size_t count); - int (*flush) (struct dfs_file *fd); - int (*lseek) (struct dfs_file *fd, off_t offset); - int (*getdents) (struct dfs_file *fd, struct dirent *dirp, uint32_t count); - - int (*poll) (struct dfs_file *fd, struct rt_pollreq *req); - void (*set_termios) (struct tty_struct *tty, struct termios *old); - int (*receive_buf) (struct tty_struct *tty,char *cp, int count); - - int refcount; -}; - -struct tty_ldisc -{ - struct tty_ldisc_ops *ops; - struct tty_struct *tty; -}; - -#define TTY_LDISC_MAGIC 0x5403 - -int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); -void tty_ldisc_kill(struct tty_struct *tty); -void tty_ldisc_init(struct tty_struct *tty); -void tty_ldisc_release(struct tty_struct *tty); -void n_tty_init(void); - -#endif // __TTY_LDISC_ diff --git a/components/drivers/tty/n_tty.c b/components/drivers/tty/n_tty.c deleted file mode 100644 index bf1156ba38..0000000000 --- a/components/drivers/tty/n_tty.c +++ /dev/null @@ -1,2223 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021.12.07 linzhenxing first version - */ -#include -#include -#include -#include -#if defined(RT_USING_POSIX_TERMIOS) -#include -#endif -#include - -#define DBG_TAG "N_TTY" -#ifdef RT_TTY_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_TTY_DEBUG */ -#include - -/* number of characters left in xmit buffer before select has we have room */ -#define WAKEUP_CHARS 256 - -/* - * This defines the low- and high-watermarks for throttling and - * unthrottling the TTY driver. These watermarks are used for - * controlling the space in the read buffer. - */ -#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ -#define TTY_THRESHOLD_UNTHROTTLE 128 - -/* - * Special byte codes used in the echo buffer to represent operations - * or special handling of characters. Bytes in the echo buffer that - * are not part of such special blocks are treated as normal character - * codes. - */ -#define ECHO_OP_START 0xff -#define ECHO_OP_MOVE_BACK_COL 0x80 -#define ECHO_OP_SET_CANON_COL 0x81 -#define ECHO_OP_ERASE_TAB 0x82 - -#define ECHO_COMMIT_WATERMARK 256 -#define ECHO_BLOCK 256 -#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32) - -static struct rt_spinlock _spinlock = RT_SPINLOCK_INIT; - -struct n_tty_data -{ - /* producer-published */ - size_t read_head; - size_t commit_head; - size_t canon_head; - size_t echo_head; - size_t echo_commit; - size_t echo_mark; - unsigned long char_map[256]; - - /* non-atomic */ - rt_bool_t no_room; - /* must hold exclusive termios_rwsem to reset these */ - unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; - unsigned char push:1; - - /* shared by producer and consumer */ - char read_buf[RT_TTY_BUF]; - unsigned long read_flags[RT_TTY_BUF]; - unsigned char echo_buf[RT_TTY_BUF]; - - /* consumer-published */ - size_t read_tail; - size_t line_start; - - /* protected by output lock */ - unsigned int column; - unsigned int canon_column; - size_t echo_tail; - - rt_mutex_t atomic_read_lock; - rt_mutex_t output_lock; -}; - -rt_inline int set_bit(int nr,int *addr) -{ - int mask, retval; - rt_base_t level; - - addr += nr >> 5; - mask = 1 << (nr & 0x1f); - level = rt_spin_lock_irqsave(&_spinlock); - retval = (mask & *addr) != 0; - *addr |= mask; - rt_spin_unlock_irqrestore(&_spinlock, level); - return retval; -} - -rt_inline int clear_bit(int nr, int *addr) -{ - int mask, retval; - rt_base_t level; - - addr += nr >> 5; - mask = 1 << (nr & 0x1f); - level = rt_spin_lock_irqsave(&_spinlock); - retval = (mask & *addr) != 0; - *addr &= ~mask; - rt_spin_unlock_irqrestore(&_spinlock, 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; - rt_base_t level; - volatile unsigned int *a = addr; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - level = rt_spin_lock_irqsave(&_spinlock); - retval = (mask & *a) != 0; - *a &= ~mask; - rt_spin_unlock_irqrestore(&_spinlock, level); - - return retval; -} - -#ifdef __GNUC__ -rt_inline unsigned long __ffs(unsigned long word) -{ - return __builtin_ffsl(word); -} -#else -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; -} -#endif - -#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; -} - -rt_inline char read_buf(struct n_tty_data *ldata, size_t i) -{ - return ldata->read_buf[i & (RT_TTY_BUF - 1)]; -} - -rt_inline char *read_buf_addr(struct n_tty_data *ldata, size_t i) -{ - return &ldata->read_buf[i & (RT_TTY_BUF - 1)]; -} - -rt_inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) -{ - return ldata->echo_buf[i & (RT_TTY_BUF - 1)]; -} - -rt_inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) -{ - return &ldata->echo_buf[i & (RT_TTY_BUF - 1)]; -} - -/** - * put_tty_queue - add character to tty - * @c: character - * @ldata: n_tty data - * - * Add a character to the tty read_buf queue. - * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem - */ -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++; -} - -/** - * reset_buffer_flags - reset buffer state - * @tty: terminal to reset - * - * Reset the read buffer counters and clear the flags. - * Called from n_tty_open() and n_tty_flush_buffer(). - * - * Locking: caller holds exclusive termios_rwsem - * (or locking is not required) - */ - -static void reset_buffer_flags(struct n_tty_data *ldata) -{ - ldata->read_head = ldata->canon_head = ldata->read_tail = 0; - ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; - ldata->commit_head = 0; - ldata->echo_mark = 0; - ldata->line_start = 0; - - ldata->erasing = 0; - rt_memset(ldata->read_flags, 0, RT_TTY_BUF); - ldata->push = 0; -} - -/** - * add_echo_byte - add a byte to the echo buffer - * @c: unicode byte to echo - * @ldata: n_tty data - * - * Add a character or operation byte to the echo buffer. - */ - -rt_inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) -{ - *echo_buf_addr(ldata, ldata->echo_head++) = c; -} - -/** - * echo_move_back_col - add operation to move back a column - * @ldata: n_tty data - * - * Add an operation to the echo buffer to move back one column. - */ - -static void echo_move_back_col(struct n_tty_data *ldata) -{ - add_echo_byte(ECHO_OP_START, ldata); - add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata); -} - -/** - * echo_set_canon_col - add operation to set the canon column - * @ldata: n_tty data - * - * Add an operation to the echo buffer to set the canon column - * to the current column. - */ - -static void echo_set_canon_col(struct n_tty_data *ldata) -{ - add_echo_byte(ECHO_OP_START, ldata); - add_echo_byte(ECHO_OP_SET_CANON_COL, ldata); -} - -/** - * echo_erase_tab - add operation to erase a tab - * @num_chars: number of character columns already used - * @after_tab: true if num_chars starts after a previous tab - * @ldata: n_tty data - * - * Add an operation to the echo buffer to erase a tab. - * - * Called by the eraser function, which knows how many character - * columns have been used since either a previous tab or the start - * of input. This information will be used later, along with - * canon column (if applicable), to go back the correct number - * of columns. - */ - -static void echo_erase_tab(unsigned int num_chars, int after_tab, - struct n_tty_data *ldata) -{ - add_echo_byte(ECHO_OP_START, ldata); - add_echo_byte(ECHO_OP_ERASE_TAB, ldata); - - /* We only need to know this modulo 8 (tab spacing) */ - num_chars &= 7; - - /* Set the high bit as a flag if num_chars is after a previous tab */ - if (after_tab) - { - num_chars |= 0x80; - } - - add_echo_byte(num_chars, ldata); -} - -/** - * echo_char_raw - echo a character raw - * @c: unicode byte to echo - * @tty: terminal device - * - * Echo user input back onto the screen. This must be called only when - * L_ECHO(tty) is true. Called from the driver receive_buf path. - * - * This variant does not treat control characters specially. - */ - -static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) -{ - if (c == ECHO_OP_START) - { - add_echo_byte(ECHO_OP_START, ldata); - add_echo_byte(ECHO_OP_START, ldata); - } - else - { - add_echo_byte(c, ldata); - } -} - -/** - * echo_char - echo a character - * @c: unicode byte to echo - * @tty: terminal device - * - * Echo user input back onto the screen. This must be called only when - * L_ECHO(tty) is true. Called from the driver receive_buf path. - * - * This variant tags control characters to be echoed as "^X" - * (where X is the letter representing the control char). - */ - -static void echo_char(unsigned char c, struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (c == ECHO_OP_START) - { - add_echo_byte(ECHO_OP_START, ldata); - add_echo_byte(ECHO_OP_START, ldata); - } - else - { - if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') - { - add_echo_byte(ECHO_OP_START, ldata); - } - add_echo_byte(c, ldata); - } -} - -/** - * finish_erasing - complete erase - * @ldata: n_tty data - */ - -rt_inline void finish_erasing(struct n_tty_data *ldata) -{ - if (ldata->erasing) - { - echo_char_raw('/', ldata); - ldata->erasing = 0; - } -} - -/** - * is_utf8_continuation - utf8 multibyte check - * @c: byte to check - * - * Returns true if the utf8 character 'c' is a multibyte continuation - * character. We use this to correctly compute the on screen size - * of the character when printing - */ - -rt_inline int is_utf8_continuation(unsigned char c) -{ - return (c & 0xc0) == 0x80; -} - -/** - * is_continuation - multibyte check - * @c: byte to check - * - * Returns true if the utf8 character 'c' is a multibyte continuation - * character and the terminal is in unicode mode. - */ - -rt_inline int is_continuation(unsigned char c, struct tty_struct *tty) -{ - return I_IUTF8(tty) && is_utf8_continuation(c); -} - -/** - * eraser - handle erase function - * @c: character input - * @tty: terminal device - * - * Perform erase and necessary output when an erase character is - * present in the stream from the driver layer. Handles the complexities - * of UTF-8 multibyte symbols. - * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem - */ - -static void eraser(unsigned char c, struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - enum { KERASE, WERASE, KILL } kill_type; - size_t head = 0; - size_t cnt = 0; - int seen_alnums = 0; - - if (ldata->read_head == ldata->canon_head) - { - /* process_output('\a', tty); */ /* what do you think? */ - return; - } - - if (c == ERASE_CHAR(tty)) - { - kill_type = KERASE; - } - else if (c == WERASE_CHAR(tty)) - { - kill_type = WERASE; - } - else - { - if (!L_ECHO(tty)) - { - ldata->read_head = ldata->canon_head; - return; - } - - if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) - { - ldata->read_head = ldata->canon_head; - finish_erasing(ldata); - echo_char(KILL_CHAR(tty), tty); - /* Add a newline if ECHOK is on and ECHOKE is off. */ - if (L_ECHOK(tty)) - { - echo_char_raw('\n', ldata); - } - return; - } - kill_type = KILL; - } - - seen_alnums = 0; - while (ldata->read_head != ldata->canon_head) - { - head = ldata->read_head; - - /* erase a single possibly multibyte character */ - do - { - head--; - c = read_buf(ldata, head); - } while (is_continuation(c, tty) && head != ldata->canon_head); - - /* do not partially erase */ - if (is_continuation(c, tty)) - { - break; - } - - if (kill_type == WERASE) - { - /* Equivalent to BSD's ALTWERASE. */ - if (isalnum(c) || c == '_') - { - seen_alnums++; - } - else if (seen_alnums) - { - break; - } - } - cnt = ldata->read_head - head; - ldata->read_head = head; - if (L_ECHO(tty)) - { - if (L_ECHOPRT(tty)) - { - if (!ldata->erasing) - { - echo_char_raw('\\', ldata); - ldata->erasing = 1; - } - /* if cnt > 1, output a multi-byte character */ - echo_char(c, tty); - while (--cnt > 0) - { - head++; - echo_char_raw(read_buf(ldata, head), ldata); - echo_move_back_col(ldata); - } - } - else if (kill_type == KERASE && !L_ECHOE(tty)) - { - echo_char(ERASE_CHAR(tty), tty); - } - else if (c == '\t') - { - unsigned int num_chars = 0; - int after_tab = 0; - size_t tail = ldata->read_head; - - /* - * Count the columns used for characters - * since the start of input or after a - * previous tab. - * This info is used to go back the correct - * number of columns. - */ - while (tail != ldata->canon_head) - { - tail--; - c = read_buf(ldata, tail); - if (c == '\t') - { - after_tab = 1; - break; - } - else if (iscntrl(c)) - { - if (L_ECHOCTL(tty)) - { - num_chars += 2; - } - } - else if (!is_continuation(c, tty)) - { - num_chars++; - } - } - echo_erase_tab(num_chars, after_tab, ldata); - } - else - { - if (iscntrl(c) && L_ECHOCTL(tty)) - { - echo_char_raw('\b', ldata); - echo_char_raw(' ', ldata); - echo_char_raw('\b', ldata); - } - if (!iscntrl(c) || L_ECHOCTL(tty)) - { - echo_char_raw('\b', ldata); - echo_char_raw(' ', ldata); - echo_char_raw('\b', ldata); - } - } - } - if (kill_type == KERASE) - { - break; - } - } - if (ldata->read_head == ldata->canon_head && L_ECHO(tty)) - { - finish_erasing(ldata); - } -} - -/** - * isig - handle the ISIG optio - * @sig: signal - * @tty: terminal - * - * Called when a signal is being sent due to terminal input. - * Called from the driver receive_buf path so serialized. - * - * Performs input and output flush if !NOFLSH. In this context, the echo - * buffer is 'output'. The signal is processed first to alert any current - * readers or writers to discontinue and exit their i/o loops. - * - * Locking: ctrl_lock - */ - -static void __isig(int sig, struct tty_struct *tty) -{ - struct rt_lwp *lwp = tty->foreground; - struct tty_ldisc *ld = RT_NULL; - struct termios old_termios; - struct termios *new_termios = get_old_termios(); - - if (lwp) - { - if (sig == SIGTSTP) - { - struct rt_lwp *old_lwp; - - rt_memcpy(&old_termios, &(tty->init_termios), sizeof(struct termios)); - tty->init_termios = *new_termios; - ld = tty->ldisc; - if (ld != RT_NULL) - { - if (ld->ops->set_termios) - { - ld->ops->set_termios(tty, &old_termios); - } - } - lwp_signal_kill(lwp, SIGTTOU, SI_USER, 0); - old_lwp = tty_pop(&tty->head, RT_NULL); - tty->foreground = old_lwp; - } - else - { - lwp_signal_kill(lwp, sig, SI_USER, 0); - } - } -} - -static void isig(int sig, struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (L_NOFLSH(tty)) - { - /* signal only */ - __isig(sig, tty); - - } - else - { /* signal and flush */ - __isig(sig, tty); - - /* clear echo buffer */ - ldata->echo_head = ldata->echo_tail = 0; - ldata->echo_mark = ldata->echo_commit = 0; - - /* clear input buffer */ - reset_buffer_flags(tty->disc_data); - } -} - -/** - * do_output_char - output one character - * @c: character (or partial unicode symbol) - * @tty: terminal device - * @space: space available in tty driver write buffer - * - * This is a helper function that handles one output character - * (including special characters like TAB, CR, LF, etc.), - * doing OPOST processing and putting the results in the - * tty driver's write buffer. - * - * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY - * and NLDLY. They simply aren't relevant in the world today. - * If you ever need them, add them here. - * - * Returns the number of bytes of buffer space used or -1 if - * no space left. - * - * Locking: should be called under the output_lock to protect - * the column state and space left in the buffer - */ - -static int do_output_char(unsigned char c, struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - int spaces = 0; - char *ch = RT_NULL; - - switch (c) - { - case '\n': - if (O_ONLRET(tty)) - { - ldata->column = 0; - } - - if (O_ONLCR(tty)) - { - ldata->canon_column = ldata->column = 0; - ch = "\r\n"; - rt_device_write((rt_device_t)tty, -1, ch, 2); - return 2; - } - ldata->canon_column = ldata->column; - break; - case '\r': - if (O_ONOCR(tty) && ldata->column == 0) - { - return 0; - } - - if (O_OCRNL(tty)) - { - c = '\n'; - if (O_ONLRET(tty)) - { - ldata->canon_column = ldata->column = 0; - } - break; - } - ldata->canon_column = ldata->column = 0; - break; - case '\t': - spaces = 8 - (ldata->column & 7); - if (O_TABDLY(tty) == XTABS) - { - ldata->column += spaces; - ch = " "; - rt_device_write((rt_device_t)tty, -1, &ch, spaces); - return spaces; - } - ldata->column += spaces; - break; - case '\b': - if (ldata->column > 0) - { - ldata->column--; - } - ch = "\b \b"; - rt_device_write((rt_device_t)tty, -1, ch, strlen(ch)); - return 1; - default: - if (!iscntrl(c)) - { - if (O_OLCUC(tty)) - { - c = toupper(c); - } - - if (!is_continuation(c, tty)) - { - ldata->column++; - } - } - break; - } - - rt_device_write((rt_device_t)tty, -1, &c, 1); - return 1; -} - -/** - * process_output - output post processor - * @c: character (or partial unicode symbol) - * @tty: terminal device - * - * Output one character with OPOST processing. - * Returns -1 when the output device is full and the character - * must be retried. - * - * Locking: output_lock to protect column state and space left - * (also, this is called from n_tty_write under the - * tty layer write lock) - */ - -static int process_output(unsigned char c, struct tty_struct *tty) -{ - int retval = 0; - - retval = do_output_char(c, tty); - if (retval < 0) - { - return -1; - } - else - { - return 0; - } -} - -/** - * process_output_block - block post processor - * @tty: terminal device - * @buf: character buffer - * @nr: number of bytes to output - * - * Output a block of characters with OPOST processing. - * Returns the number of characters output. - * - * This path is used to speed up block console writes, among other - * things when processing blocks of output data. It handles only - * the simple cases normally found and helps to generate blocks of - * symbols for the console driver and thus improve performance. - * - * Locking: output_lock to protect column state and space left - * (also, this is called from n_tty_write under the - * tty layer write lock) - */ - -static ssize_t process_output_block(struct tty_struct *tty, - const char *buf, unsigned int nr) -{ - struct n_tty_data *ldata = tty->disc_data; - int i = 0; - ssize_t size = 0; - const char *cp = RT_NULL; - - for (i = 0, cp = buf; i < nr; i++, cp++) - { - char c = *cp; - - switch (c) - { - case '\n': - if (O_ONLRET(tty)) - { - ldata->column = 0; - } - - if (O_ONLCR(tty)) - { - goto break_out; - } - ldata->canon_column = ldata->column; - break; - case '\r': - if (O_ONOCR(tty) && ldata->column == 0) - { - goto break_out; - } - - if (O_OCRNL(tty)) - { - goto break_out; - } - - ldata->canon_column = ldata->column = 0; - break; - case '\t': - goto break_out; - case '\b': - if (ldata->column > 0) - { - ldata->column--; - } - break; - default: - if (!iscntrl(c)) - { - if (O_OLCUC(tty)) - { - goto break_out; - } - - if (!is_continuation(c, tty)) - { - ldata->column++; - } - } - break; - } - } -break_out: - size = rt_device_write((rt_device_t)tty, -1, buf, i); - return size; -} - -static size_t __process_echoes(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - size_t tail = 0; - unsigned char c = 0; - char ch = 0; - unsigned char num_chars = 0, num_bs = 0; - - tail = ldata->echo_tail; - while (ldata->echo_commit != tail) - { - c = echo_buf(ldata, tail); - if (c == ECHO_OP_START) - { - unsigned char op = 0; - - /* - * If the buffer byte is the start of a multi-byte - * operation, get the next byte, which is either the - * op code or a control character value. - */ - op = echo_buf(ldata, tail + 1); - - switch (op) - { - case ECHO_OP_ERASE_TAB: - num_chars = echo_buf(ldata, tail + 2); - - /* - * Determine how many columns to go back - * in order to erase the tab. - * This depends on the number of columns - * used by other characters within the tab - * area. If this (modulo 8) count is from - * the start of input rather than from a - * previous tab, we offset by canon column. - * Otherwise, tab spacing is normal. - */ - if (!(num_chars & 0x80)) - { - num_chars += ldata->canon_column; - } - num_bs = 8 - (num_chars & 7); - - while (num_bs--) - { - ch = '\b'; - rt_device_write((rt_device_t)tty, -1, &ch, 1); - if (ldata->column > 0) - { - ldata->column--; - } - } - tail += 3; - break; - - case ECHO_OP_SET_CANON_COL: - ldata->canon_column = ldata->column; - tail += 2; - break; - - case ECHO_OP_MOVE_BACK_COL: - if (ldata->column > 0) - { - ldata->column--; - } - tail += 2; - break; - - case ECHO_OP_START: - ch = ECHO_OP_START; - rt_device_write((rt_device_t)tty, -1, &ch, 1); - ldata->column++; - tail += 2; - break; - - default: - /* - * If the op is not a special byte code, - * it is a ctrl char tagged to be echoed - * as "^X" (where X is the letter - * representing the control char). - * Note that we must ensure there is - * enough space for the whole ctrl pair. - * - */ - ch = '^'; - rt_device_write((rt_device_t)tty, -1, &ch, 1); - ch = op ^ 0100; - rt_device_write((rt_device_t)tty, -1, &ch, 1); - ldata->column += 2; - tail += 2; - } - } - else - { - if (O_OPOST(tty)) - { - int retval = do_output_char(c, tty); - if (retval < 0) - { - break; - } - } - else - { - rt_device_write((rt_device_t)tty, -1, &c, 1); - } - tail += 1; - } - } - - /* If the echo buffer is nearly full (so that the possibility exists - * of echo overrun before the next commit), then discard enough - * data at the tail to prevent a subsequent overrun */ - while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) - { - if (echo_buf(ldata, tail) == ECHO_OP_START) - { - if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB) - { - tail += 3; - } - else - { - tail += 2; - } - } - else - { - tail++; - } - } - - ldata->echo_tail = tail; - return 0; -} - -static void commit_echoes(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - size_t nr = 0, old = 0; - size_t head = 0; - - head = ldata->echo_head; - ldata->echo_mark = head; - old = ldata->echo_commit - ldata->echo_tail; - - /* Process committed echoes if the accumulated # of bytes - * is over the threshold (and try again each time another - * block is accumulated) */ - nr = head - ldata->echo_tail; - if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) - { - return; - } - - ldata->echo_commit = head; - __process_echoes(tty); -} - -static void process_echoes(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (ldata->echo_mark == ldata->echo_tail) - { - return; - } - - ldata->echo_commit = ldata->echo_mark; - __process_echoes(tty); -} - -/* NB: echo_mark and echo_head should be equivalent here */ -static void flush_echoes(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - - if ((!L_ECHO(tty) && !L_ECHONL(tty)) || - ldata->echo_commit == ldata->echo_head) - { - return; - } - - ldata->echo_commit = ldata->echo_head; - __process_echoes(tty); -} -/** - * n_tty_set_termios - termios data changed - * @tty: terminal - * @old: previous data - * - * Called by the tty layer when the user changes termios flags so - * that the line discipline can plan ahead. This function cannot sleep - * and is protected from re-entry by the tty layer. The user is - * guaranteed that this function will not be re-entered or in progress - * when the ldisc is closed. - * - * Locking: Caller holds tty->termios_rwsem - */ - -static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (!old || (old->c_lflag ^ tty->init_termios.c_lflag) & (ICANON | EXTPROC)) - { - rt_memset(ldata->read_flags, 0, RT_TTY_BUF); - ldata->line_start = ldata->read_tail; - if (!L_ICANON(tty) || !read_cnt(ldata)) - { - ldata->canon_head = ldata->read_tail; - ldata->push = 0; - } - else - { - set_bit((ldata->read_head - 1) & (RT_TTY_BUF - 1),(int *)ldata->read_flags); - ldata->canon_head = ldata->read_head; - ldata->push = 1; - } - ldata->commit_head = ldata->read_head; - ldata->erasing = 0; - ldata->lnext = 0; - } - - ldata->icanon = (L_ICANON(tty) != 0); - - if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || - I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || - I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || - I_PARMRK(tty)) - { - rt_memset(ldata->char_map, 0, 256); - if (I_IGNCR(tty) || I_ICRNL(tty)) - { - set_bit('\r', (int *)ldata->char_map); - } - - if (I_INLCR(tty)) - { - set_bit('\n', (int *)ldata->char_map); - } - - if (L_ICANON(tty)) - { - set_bit(ERASE_CHAR(tty), (int *)ldata->char_map); - set_bit(KILL_CHAR(tty),(int *) ldata->char_map); - set_bit(EOF_CHAR(tty), (int *)ldata->char_map); - set_bit('\n',(int *) ldata->char_map); - set_bit(EOL_CHAR(tty),(int *) ldata->char_map); - if (L_IEXTEN(tty)) - { - set_bit(WERASE_CHAR(tty), (int *)ldata->char_map); - set_bit(LNEXT_CHAR(tty), (int *)ldata->char_map); - set_bit(EOL2_CHAR(tty), (int *)ldata->char_map); - if (L_ECHO(tty)) - { - set_bit(REPRINT_CHAR(tty), - (int *)ldata->char_map); - } - } - } - if (I_IXON(tty)) - { - set_bit(START_CHAR(tty), (int *)ldata->char_map); - set_bit(STOP_CHAR(tty), (int *)ldata->char_map); - } - if (L_ISIG(tty)) - { - set_bit(INTR_CHAR(tty), (int *)ldata->char_map); - set_bit(QUIT_CHAR(tty), (int *)ldata->char_map); - set_bit(SUSP_CHAR(tty), (int *)ldata->char_map); - } - clear_bit(__DISABLED_CHAR, (int *)ldata->char_map); - ldata->raw = 0; - ldata->real_raw = 0; - } - else - { - ldata->raw = 1; - if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) && - (I_IGNPAR(tty) || !I_INPCK(tty))/* && - (tty->driver->flags & TTY_DRIVER_REAL_RAW)*/) - { - ldata->real_raw = 1; - } - else - { - ldata->real_raw = 0; - } - } -} - -void console_ldata_init(struct tty_struct *tty) -{ - struct n_tty_data *ldata = RT_NULL; - - ldata = rt_malloc(sizeof(struct n_tty_data)); - if (ldata == RT_NULL) - { - LOG_E("console_ldata_init ldata malloc fail"); - return; - } - tty->disc_data = ldata; - reset_buffer_flags(ldata); - ldata->column = 0; - ldata->canon_column = 0; - ldata->no_room = 0; - ldata->lnext = 0; - n_tty_set_termios(tty, RT_NULL); - return; -} - -static int n_tty_open(struct dfs_file *fd) -{ - int ret = 0; - struct n_tty_data *ldata = RT_NULL; - struct tty_struct *tty = (struct tty_struct*)fd->vnode->data; - - ldata = rt_malloc(sizeof(struct n_tty_data)); - if (ldata == RT_NULL) - { - LOG_E("n_tty_open ldata malloc fail"); - return -1; - } - - ldata->atomic_read_lock = rt_mutex_create("atomic_read_lock",RT_IPC_FLAG_FIFO); - if(ldata->atomic_read_lock == RT_NULL) - { - LOG_E("n_tty_open atomic_read_lock create fail"); - return -1; - } - - ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO); - if(ldata->output_lock == RT_NULL) - { - LOG_E("n_tty_open output_lock create fail"); - return -1; - } - - tty->disc_data = ldata; - reset_buffer_flags(ldata); - ldata->column = 0; - ldata->canon_column = 0; - ldata->lnext = 0; - n_tty_set_termios(tty, RT_NULL); - return ret; -} - -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; - - if (ldata->icanon && !L_EXTPROC(tty)) - { - return ldata->canon_head != ldata->read_tail; - } - else - { - return ldata->commit_head - ldata->read_tail >= amt; - } -} - -/** - * copy_from_read_buf - copy read data directly - * @tty: terminal device - * @b: user data - * @nr: size of data - * - * Helper function to speed up n_tty_read. It is only called when - * ICANON is off; it copies characters straight from the tty queue to - * user space directly. It can be profitably called twice; once to - * drain the space from the tail pointer to the (physical) end of the - * buffer, and once to drain the space from the (physical) beginning of - * the buffer to head pointer. - * - * Called under the ldata->atomic_read_lock sem - * - * n_tty_read()/consumer path: - * caller holds non-exclusive termios_rwsem - * read_tail published - */ - -static int copy_from_read_buf(struct tty_struct *tty,char *b,size_t nr) -{ - struct n_tty_data *ldata = tty->disc_data; - size_t n = 0; - rt_bool_t is_eof = 0; - size_t head = ldata->commit_head; - size_t tail = ldata->read_tail & (RT_TTY_BUF - 1); - - n = min(head - ldata->read_tail, RT_TTY_BUF - tail); - n = min(nr, n); - if (n) - { - const char *from = read_buf_addr(ldata, tail); - memcpy(b, from, n); - is_eof = n == 1 && *from == EOF_CHAR(tty); - ldata->read_tail += n; - /* Turn single EOF into zero-length read */ - if (L_EXTPROC(tty) && ldata->icanon && is_eof && - (head == ldata->read_tail)) - { - n = 0; - } - - } - return n; -} - -/** - * canon_copy_from_read_buf - copy read data in canonical mode - * @tty: terminal device - * @b: user data - * @nr: size of data - * - * Helper function for n_tty_read. It is only called when ICANON is on; - * it copies one line of input up to and including the line-delimiting - * character into the user-space buffer. - * - * NB: When termios is changed from non-canonical to canonical mode and - * the read buffer contains data, n_tty_set_termios() simulates an EOF - * push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer. - * This causes data already processed as input to be immediately available - * as input although a newline has not been received. - * - * Called under the atomic_read_lock mutex - * - * n_tty_read()/consumer path: - * caller holds non-exclusive termios_rwsem - * read_tail published - */ - -static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) -{ - struct n_tty_data *ldata = tty->disc_data; - size_t n = 0, size = 0, more = 0, c = 0; - size_t eol = 0; - size_t tail = 0; - int found = 0; - - /* N.B. avoid overrun if nr == 0 */ - if (nr == 0) - { - return 0; - } - - n = min(nr + 1, ldata->canon_head - ldata->read_tail); - - tail = ldata->read_tail & (RT_TTY_BUF - 1); - size = min(tail + n, RT_TTY_BUF); - - eol = find_next_bit(ldata->read_flags, size, tail); - more = n - (size - tail); - if (eol == RT_TTY_BUF && more) - { - /* scan wrapped without finding set bit */ - eol = find_next_bit(ldata->read_flags, more, 0); - found = eol != more; - } - else - { - found = eol != size; - } - - n = eol - tail; - if (n > RT_TTY_BUF) - { - n += RT_TTY_BUF; - } - c = n + found; - - if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) - { - c = min(nr, c); - n = c; - } - - size_t buf_size = RT_TTY_BUF - tail; - const void *from = read_buf_addr(ldata, tail); - size_t temp_n = n; - if (n > buf_size) - { - memcpy(b, from, buf_size); - b += buf_size; - temp_n -= buf_size; - from = ldata->read_buf; - } - memcpy(b, from, temp_n); - - if (found) - { - clear_bit(eol, (int *)ldata->read_flags); - } - ldata->read_tail = ldata->read_tail + c; - - if (found) - { - if (!ldata->push) - { - ldata->line_start = ldata->read_tail; - } - else - { - ldata->push = 0; - } - } - return n; -} - - -static int n_tty_close(struct tty_struct *tty) -{ - int ret = 0; - struct n_tty_data *ldata = RT_NULL; - struct tty_struct *o_tty = RT_NULL; - - RT_ASSERT(tty != RT_NULL); - if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) - { - o_tty = tty->other_struct; - } - else - { - o_tty = tty; - } - - ldata = o_tty->disc_data; - rt_free(ldata); - o_tty->disc_data = RT_NULL; - return ret; -} - -static int n_tty_ioctl(struct dfs_file *fd, int cmd, void *args) -{ - int ret = 0; - struct tty_struct *real_tty = RT_NULL; - struct tty_struct *tty = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) - { - real_tty = tty->other_struct; - } - else - { - real_tty = tty; - } - - switch(cmd) - { - - default: - ret = n_tty_ioctl_extend(real_tty, cmd, args); - if (ret != -ENOIOCTLCMD) - { - return ret; - } - } - - ret = rt_device_control((rt_device_t)real_tty, cmd, args); - if (ret != -ENOIOCTLCMD) - { - return ret; - } - return ret; -} - -static void -n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) -{ - isig(signal, tty); - if (L_ECHO(tty)) - { - echo_char(c, tty); - commit_echoes(tty); - } - else - { - process_echoes(tty); - } - return; -} - -/** - * n_tty_receive_char - perform processing - * @tty: terminal device - * @c: character - * - * Process an individual character of input received from the driver. - * This is serialized with respect to itself by the rules for the - * driver above. - * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem - * publishes canon_head if canonical mode is active - * - * Returns 1 if LNEXT was received, else returns 0 - */ - -static int n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (I_IXON(tty)) - { - if (c == START_CHAR(tty)) /*ctrl + p realize missing*/ - { - process_echoes(tty); - return 0; - } - if (c == STOP_CHAR(tty)) /*ctrl + s realize missing*/ - { - return 0; - } - } - - if (L_ISIG(tty)) - { - if (c == INTR_CHAR(tty)) /*ctrl + c realize missing*/ - { - n_tty_receive_signal_char(tty, SIGINT, c); - return 0; - } - else if (c == QUIT_CHAR(tty)) /*ctrl + d realize missing*/ - { - n_tty_receive_signal_char(tty, SIGQUIT, c); - return 0; - } - else if (c == SUSP_CHAR(tty)) /*ctrl + z realize missing*/ - { - n_tty_receive_signal_char(tty, SIGTSTP, c); - return 0; - } - } - - if (c == '\r') - { - if (I_IGNCR(tty)) - { - return 0; - } - - if (I_ICRNL(tty)) - { - c = '\n'; - } - } - else if (c == '\n' && I_INLCR(tty)) - { - c = '\r'; - } - - if (ldata->icanon) - { - if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || - (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) - { - eraser(c, tty); - commit_echoes(tty); - return 0; - } - if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) - { - ldata->lnext = 1; - if (L_ECHO(tty)) - { - finish_erasing(ldata); - if (L_ECHOCTL(tty)) - { - echo_char_raw('^', ldata); - echo_char_raw('\b', ldata); - commit_echoes(tty); - } - } - return 1; - } - if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) - { - size_t tail = ldata->canon_head; - - finish_erasing(ldata); - echo_char(c, tty); - echo_char_raw('\n', ldata); - while (tail != ldata->read_head) - { - echo_char(read_buf(ldata, tail), tty); - tail++; - } - commit_echoes(tty); - return 0; - } - if (c == '\n') - { - if (L_ECHO(tty) || L_ECHONL(tty)) - { - echo_char_raw('\n', ldata); - commit_echoes(tty); - } - goto handle_newline; - } - if (c == EOF_CHAR(tty)) - { - c = __DISABLED_CHAR; - goto handle_newline; - } - if ((c == EOL_CHAR(tty)) || - (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) - { - /* - * XXX are EOL_CHAR and EOL2_CHAR echoed?!? - */ - if (L_ECHO(tty)) - { - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - { - echo_set_canon_col(ldata); - } - - echo_char(c, tty); - commit_echoes(tty); - } - /* - * XXX does PARMRK doubling happen for - * EOL_CHAR and EOL2_CHAR? - */ - if (c == (unsigned char) '\377' && I_PARMRK(tty)) - { - put_tty_queue(c, ldata); - } - -handle_newline: - set_bit(ldata->read_head & (RT_TTY_BUF - 1), (int *)ldata->read_flags); - put_tty_queue(c, ldata); - ldata->canon_head = ldata->read_head; - tty_wakeup_check(tty); - return 0; - } - } - - if (L_ECHO(tty)) - { - finish_erasing(ldata); - if (c == '\n') - { - echo_char_raw('\n', ldata); - } - else - { - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - { - echo_set_canon_col(ldata); - } - echo_char(c, tty); - } - commit_echoes(tty); - } - - /* PARMRK doubling check */ - if (c == (unsigned char) '\377' && I_PARMRK(tty)) - { - put_tty_queue(c, ldata); - } - - put_tty_queue(c, ldata); - return 0; -} - -rt_inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (L_ECHO(tty)) - { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - { - echo_set_canon_col(ldata); - } - - echo_char(c, tty); - commit_echoes(tty); - } - /* PARMRK doubling check */ - if (c == (unsigned char) '\377' && I_PARMRK(tty)) - { - put_tty_queue(c, ldata); - } - - put_tty_queue(c, ldata); -} - -static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) -{ - n_tty_receive_char_inline(tty, c); -} - -static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) -{ - struct n_tty_data *ldata = tty->disc_data; - - ldata->lnext = 0; - if (flag == TTY_NORMAL) - { - if (I_ISTRIP(tty)) - { - c &= 0x7f; - } - - if (I_IUCLC(tty) && L_IEXTEN(tty)) - { - c = tolower(c); - } - - n_tty_receive_char(tty, c); - } - else - { - //n_tty_receive_char_flagged(tty, c, flag); - } - -} - -static void n_tty_receive_buf_real_raw(struct tty_struct *tty, char *cp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - size_t n = 0, head = 0; - - head = ldata->read_head & (RT_TTY_BUF - 1); - n = min(count, RT_TTY_BUF - head); - rt_memcpy(read_buf_addr(ldata, head), cp, n); - ldata->read_head += n; - cp += n; - count -= n; - - head = ldata->read_head & (RT_TTY_BUF - 1); - n = min(count, RT_TTY_BUF - head); - rt_memcpy(read_buf_addr(ldata, head), cp, n); - ldata->read_head += n; -} - -static void n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - char flag = TTY_NORMAL; - - while (count--) - { - if (flag == TTY_NORMAL) - { - put_tty_queue(*cp++, ldata); - } - } -} - -static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - char flag = TTY_NORMAL; - - while (count--) - { - char c = *cp++; - - if (I_ISTRIP(tty)) - { - c &= 0x7f; - } - - if (I_IUCLC(tty) && L_IEXTEN(tty)) - { - c = tolower(c); - } - - if (L_EXTPROC(tty)) - { - put_tty_queue(c, ldata); - continue; - } - - if (!test_bit(c, (int *)ldata->char_map)) - { - n_tty_receive_char_inline(tty, c); - } - else if (n_tty_receive_char_special(tty, c) && count) - { - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - } -} - -rt_inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (L_ECHO(tty)) - { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - { - echo_set_canon_col(ldata); - } - - echo_char(c, tty); - commit_echoes(tty); - } - put_tty_queue(c, ldata); -} - -static void n_tty_receive_buf_fast(struct tty_struct *tty, char *cp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - char flag = TTY_NORMAL; - - while (count--) - { - unsigned char c = *cp++; - - if (!test_bit(c, (int *)ldata->char_map)) - { - n_tty_receive_char_fast(tty, c); - } - else if (n_tty_receive_char_special(tty, c) && count) - { - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - } -} - -static void __receive_buf(struct tty_struct *tty, char *cp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - rt_bool_t preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty)); - - if (ldata->real_raw) - { - n_tty_receive_buf_real_raw(tty, cp, count); - } - - else if (ldata->raw || (L_EXTPROC(tty) && !preops)) - { - n_tty_receive_buf_raw(tty, cp, count); - } - else - { - if (!preops && !I_PARMRK(tty)) - { - n_tty_receive_buf_fast(tty, cp, count); - } - else - { - n_tty_receive_buf_standard(tty, cp, count); - } - flush_echoes(tty); - } - - if (ldata->icanon && !L_EXTPROC(tty)) - return; - - /* publish read_head to consumer */ - ldata->commit_head = ldata->read_head; - - if (read_cnt(ldata)) - { - tty_wakeup_check(tty); - } -} - -int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) -{ - int size = 0; - struct n_tty_data *ldata = tty->disc_data; - int room = 0, n = 0, rcvd = 0, overflow = 0; - - size = count; - while(1) - { - size_t tail = ldata->read_tail; - - room = RT_TTY_BUF - (ldata->read_head - tail); - - if (I_PARMRK(tty)) - { - room = (room +2)/3; - } - room--; - if (room <= 0) - { - overflow = ldata->icanon && ldata->canon_head == tail; - if (overflow && room < 0) - { - ldata->read_head--; - } - - room = overflow; - } - else - { - overflow = 0; - } - - n = min(size, room); - - if (!n) - { - break; - } - - if (!overflow) - { - __receive_buf(tty, cp, n); - } - - cp += n; - size -= n; - rcvd += n; - } - return count - size; -} - -/** - * job_control - check job control - * @tty: tty - * @file: file handle - * - * Perform job control management checks on this file/tty descriptor - * and if appropriate send any needed signals and return a negative - * error code if action should be taken. - * - * Locking: redirected write test is safe - * current->signal->tty check is safe - * ctrl_lock to safely reference tty->pgrp - */ - -static int job_control(struct tty_struct *tty) -{ - return __tty_check_change(tty, SIGTTIN); -} - -static struct rt_wqueue *_wait_queue_current_get(struct tty_struct *tty) -{ - struct rt_lwp *lwp; - - lwp = lwp_self(); - if (!lwp || !lwp->tty) - lwp = RT_NULL; - - return wait_queue_get(lwp, tty); -} - -static int n_tty_read(struct dfs_file *fd, void *buf, size_t count) -{ - rt_base_t level = 0; - char *b = (char *)buf; - struct tty_struct *tty = RT_NULL; - struct rt_wqueue *wq = RT_NULL; - int wait_ret = 0; - int retval = 0; - int c = 0; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - c = job_control(tty); - if (c < 0) - { - return c; - } - - struct n_tty_data *ldata = tty->disc_data; - - wq = _wait_queue_current_get(tty); - - while(count) - { - if ((!input_available_p(tty, 0))) - { - if (fd->flags & O_NONBLOCK) - { - retval = -EAGAIN; - break; - } - - wait_ret = rt_wqueue_wait_interruptible(wq, 0, RT_WAITING_FOREVER); - - if (wait_ret != 0) - { - break; - } - } - - level = rt_spin_lock_irqsave(&tty->spinlock); - if (ldata->icanon && !L_EXTPROC(tty)) - { - retval = canon_copy_from_read_buf(tty, b, count); - } - else - { - retval = copy_from_read_buf(tty, b, count); - } - rt_spin_unlock_irqrestore(&tty->spinlock, level); - - if (retval >= 1) - { - break; - } - } - - return retval; -} - -static int n_tty_write(struct dfs_file *fd, const void *buf, size_t count) -{ - int retval = 0; - char *b = (char *)buf; - int c = 0; - struct tty_struct *tty = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - retval = tty_check_change(tty); - if (retval) - { - return retval; - } - - process_echoes(tty); - retval = count; - while(1) - { - if (O_OPOST(tty)) - { - while (count > 0) - { - ssize_t num = process_output_block(tty, b, count); - if (num < 0) - { - if (num == -EAGAIN) - { - break; - } - - retval = num; - goto break_out; - } - b += num; - count -= num; - if (count == 0) - { - break; - } - - c = *b; - if (process_output(c, tty) < 0) - { - break; - } - - b++; - count--; - } - retval -= count; - } - else - { - while (count > 0) - { - c = rt_device_write((rt_device_t)tty, -1, b, count); - if (c < 0) - { - retval = c; - goto break_out; - } - b += c; - count -= c; - } - retval -= count; - } - - if (!count) - { - break; - } - if (fd->flags & O_NONBLOCK) - { - break; - } - } -break_out: - return retval; -} - -static int n_tty_flush(struct dfs_file *fd) -{ - return 0; -} - -static int n_tty_lseek(struct dfs_file *fd, off_t offset) -{ - return 0; -} - -static int n_tty_getdents(struct dfs_file *fd, struct dirent *dirp, uint32_t count) -{ - return 0; -} - -static int n_tty_poll(struct dfs_file *fd, struct rt_pollreq *req) -{ - rt_base_t level = 0; - int mask = POLLOUT; - struct tty_struct *tty = RT_NULL; - struct rt_wqueue *wq = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - - RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED); - - wq = _wait_queue_current_get(tty); - rt_poll_add(wq, req); - - level = rt_spin_lock_irqsave(&tty->spinlock); - if (input_available_p(tty, 1)) - { - mask |= POLLIN; - } - rt_spin_unlock_irqrestore(&tty->spinlock, level); - - return mask; -} - -struct tty_ldisc_ops n_tty_ops = { - "n_tty", - 0, - n_tty_open, - n_tty_close, - n_tty_ioctl, - n_tty_read, - n_tty_write, - n_tty_flush, - n_tty_lseek, - n_tty_getdents, - n_tty_poll, - n_tty_set_termios, - n_tty_receive_buf, - 0, -}; diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c deleted file mode 100644 index b6cbda5574..0000000000 --- a/components/drivers/tty/pty.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021.12.07 linzhenxing first version - */ -#include -#include -#include - -#define DBG_TAG "PTY" -#ifdef RT_TTY_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_TTY_DEBUG */ -#include - -#define PTY_PTS_SIZE 10 -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 *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_devs[i].init_flag == TTY_INIT_FLAG_NONE) - { - pts_devs[i].init_flag = TTY_INIT_FLAG_ALLOCED; - return &pts_devs[i]; - } - } - return RT_NULL; -} - -/* Set the lock flag on a pty */ -static int pty_set_lock(struct tty_struct *tty, int *arg) -{ - int val = *arg; - - if (val) - { - tty->pts_lock = val; - } - else - { - tty->pts_lock = val; - } - return 0; -} - -static int pty_get_lock(struct tty_struct *tty, int *arg) -{ - *arg = tty->pts_lock; - return 0; -} - -static int pty_get_index(struct tty_struct *tty, int *arg) -{ - *arg = tty->index; - return 0; -} -/* RT-Thread Device Interface */ -/* - * This function initializes console device. - */ -static rt_err_t pty_device_init(struct rt_device *dev) -{ - rt_err_t result = RT_EOK; - struct tty_struct *tty = RT_NULL; - - RT_ASSERT(dev != RT_NULL); - tty = (struct tty_struct *)dev; - - RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_REGED); - tty->init_flag = TTY_INIT_FLAG_INITED; - - return result; -} - -static rt_err_t pty_device_open(struct rt_device *dev, rt_uint16_t oflag) -{ - rt_err_t result = RT_EOK; - return result; -} - -static rt_err_t pty_device_close(struct rt_device *dev) -{ - rt_err_t result = RT_EOK; - struct tty_struct *tty = (struct tty_struct*)dev; - //struct tty_struct *to = RT_NULL; - - if (tty->subtype == PTY_TYPE_MASTER) - { - // to = tty->other_struct; - // to->init_flag = TTY_INIT_FLAG_NONE; - // to->other_struct = RT_NULL; - // to->foreground = RT_NULL; - // to->index = -1; - // tty_ldisc_kill(to); - // tty->other_struct = RT_NULL; - } - else - { - // to = tty->other_struct; - // to->other_struct = RT_NULL; - // tty->init_flag = TTY_INIT_FLAG_NONE; - // tty->other_struct = RT_NULL; - // tty->foreground = RT_NULL; - // tty->index = -1; - // tty->other_struct = RT_NULL; - // tty_ldisc_kill(tty); - } - - return result; -} - -static rt_ssize_t pty_device_read(struct rt_device *dev, - rt_off_t pos, - void *buffer, - rt_size_t size) -{ - rt_size_t len = 0; - - return len; -} - -static rt_ssize_t pty_device_write(struct rt_device *dev, - rt_off_t pos, - const void *buffer, - rt_size_t size) -{ - rt_size_t len = 0; - rt_base_t level = 0; - struct tty_struct *tty = RT_NULL; - struct tty_struct *to = RT_NULL; - - tty = (struct tty_struct *)dev; - RT_ASSERT(tty != RT_NULL); - RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED); - to = tty->other_struct; - - level = rt_spin_lock_irqsave(&tty->spinlock); - if (to->ldisc->ops->receive_buf) - { - len = to->ldisc->ops->receive_buf(to, (char *)buffer, size); - } - rt_spin_unlock_irqrestore(&tty->spinlock, level); - - return len; -} - -static rt_err_t pty_device_control(rt_device_t dev, int cmd, void *args) -{ - struct tty_struct *tty = (struct tty_struct *)dev; - - switch (cmd) - { - case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ - return pty_set_lock(tty, (int *)args); - case TIOCGPTLCK: /* Get PT Lock status */ - return pty_get_lock(tty, (int *)args); - case TIOCGPTN: /* Get PT Number */ - return pty_get_index(tty, (int *)args); - } - - return -ENOIOCTLCMD; -} - -static int ptmx_open(struct dfs_file *fd) -{ - int ret = 0; - struct tty_struct *tty = RT_NULL; - struct tty_struct *pts = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - - pts = find_freepts(); - if (pts == RT_NULL) - { - LOG_E("No free PTS device found.\n"); - return -1; - } - ret = pts_register(tty, pts, pts_index); - if (ret < 0) - { - LOG_E("pts register fail\n"); - rt_free(pts); - return -1; - } - pts_index++; - tty->other_struct = pts; - - ld = tty->ldisc; - if (ld->ops->open) - { - ret = ld->ops->open(fd); - } - - rt_device_t device = (rt_device_t)fd->vnode->data; - if(fd->vnode->ref_count == 1) - { - ret = rt_device_open(device, fd->flags); - } - - return ret; -} -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops pty_device_ops = -{ - pty_device_init, - pty_device_open, - pty_device_close, - pty_device_read, - pty_device_write, - 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 *ptmx, struct tty_struct *pts, int pts_index) -{ - char name[20]; - rt_err_t ret = RT_EOK; - struct rt_device *device = RT_NULL; - - RT_ASSERT(ptmx!=RT_NULL); - - if (pts->init_flag != TTY_INIT_FLAG_ALLOCED) - { - LOG_E("pts%d has been registered\n", pts_index); - ret = (-RT_EBUSY); - } - 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->parent; - device->type = RT_Device_Class_Char; -#ifdef RT_USING_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; -#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; - } - else - { -#ifdef RT_USING_POSIX_DEVIO - /* set fops */ - memcpy(&pts_fops, tty_get_fops(), sizeof(struct dfs_file_ops)); - device->fops = &pts_fops; -#endif - } - } - - return ret; -} - -static int ptmx_register(void) -{ - rt_err_t ret = RT_EOK; - struct rt_device *device = RT_NULL; - struct tty_struct *ptmx = &ptm_dev; - - RT_ASSERT(ptmx->init_flag == TTY_INIT_FLAG_NONE); - - 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 - 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; -#endif /* RT_USING_DEVICE_OPS */ - - ret = rt_device_register(device, "ptmx", RT_DEVICE_FLAG_RDWR); - if (ret != RT_EOK) - { - LOG_E("ptmx register fail\n"); - ret = -RT_EIO; - } - else - { -#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 - } - - return ret; -} -INIT_DEVICE_EXPORT(ptmx_register); diff --git a/components/drivers/tty/tty.c b/components/drivers/tty/tty.c deleted file mode 100644 index 075b177d5c..0000000000 --- a/components/drivers/tty/tty.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-12-07 linzhenxing first version - * 2023-06-26 WangXiaoyao fix bug on foreground app switch - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(RT_USING_POSIX_DEVIO) -#include -#endif - -#define DBG_TAG "TTY" -#ifdef RT_TTY_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_TTY_DEBUG */ -#include - -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, - .c_lflag = ISIG | ECHOE | TOSTOP | NOFLSH, - RT_NULL,/* .c_line = N_TTY, */ - .c_cc = INIT_C_CC, - .__c_ispeed = 38400, - .__c_ospeed = 38400 -}; - -void tty_initstack(struct tty_node *node) -{ - node->lwp = RT_NULL; - node->next = RT_NULL; -} - -static struct tty_node tty_node_cache = { RT_NULL, RT_NULL }; - -static struct tty_node *_tty_node_alloc(void) -{ - struct tty_node *node = tty_node_cache.next; - - if (node == RT_NULL) - { - node = rt_calloc(1, sizeof(struct tty_node)); - } - else - { - tty_node_cache.next = node->next; - } - - return node; -} - -static void _tty_node_free(struct tty_node *node) -{ - node->next = tty_node_cache.next; - tty_node_cache.next = node; -} - -int tty_push(struct tty_node **head, struct rt_lwp *lwp) -{ - struct tty_node *node = _tty_node_alloc(); - - if (!node) - { - return -1; - } - - node->lwp = lwp; - node->next = *head; - *head = node; - - return 0; -} - -struct rt_lwp *tty_pop(struct tty_node **head, struct rt_lwp *target_lwp) -{ - struct tty_node *node; - struct rt_lwp *lwp = RT_NULL; - - if (!head || !*head) - { - return RT_NULL; - } - - node = *head; - - if (target_lwp != RT_NULL && node->lwp != target_lwp) - { - struct tty_node *prev = RT_NULL; - - while (node != RT_NULL && node->lwp != target_lwp) - { - prev = node; - node = node->next; - } - - if (node != RT_NULL) - { - /* prev is impossible equ RT_NULL */ - prev->next = node->next; - lwp = target_lwp; - _tty_node_free(node); - } - } - else - { - lwp = (*head)->lwp; - *head = (*head)->next; - node->lwp = RT_NULL; - _tty_node_free(node); - } - - return lwp; -} - -/** - * tty_check_change - check for POSIX terminal changes - * @tty: tty to check - * - * If we try to write to, or set the state of, a terminal and we're - * not in the foreground, send a SIGTTOU. If the signal is blocked or - * ignored, go ahead and perform the operation. (POSIX 7.2) - * - * Locking: ctrl_lock - */ - -int __tty_check_change(struct tty_struct *tty, int sig) -{ - pid_t pgrp = 0, tty_pgrp = 0; - int ret = 0; - struct rt_lwp *lwp; - - lwp = lwp_self(); - - if (lwp == RT_NULL) - { - return 0; - } - - if (lwp->tty != tty) - { - return 0; - } - - pgrp = lwp->__pgrp; - tty_pgrp = tty->pgrp; - - if (tty_pgrp && (pgrp != tty->pgrp)) - { - lwp_signal_kill(lwp, sig, SI_USER, 0); - } - - if (!tty_pgrp) - { - LOG_D("sig=%d, tty->pgrp == -1!\n", sig); - } - return ret; -} - -int tty_check_change(struct tty_struct *tty) -{ - return __tty_check_change(tty, SIGTTOU); -} - -static int tty_open(struct dfs_file *fd) -{ - int ret = 0; - int noctty = 0; - struct tty_struct *tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - - ld = tty->ldisc; - if (ld->ops->open) - { - ret = ld->ops->open(fd); - } - noctty = (fd->flags & O_NOCTTY); - - rt_device_t device = (rt_device_t)fd->vnode->data; - if (fd->vnode->ref_count == 1) - { - ret = rt_device_open(device, fd->flags); - } - if (current == RT_NULL) //kernel mode not lwp - { - return ret; - } - - if (!noctty && - current->leader && - !current->tty && - tty->session == -1) - { - current->tty = tty; - current->tty_old_pgrp = 0; - tty->session = current->session; - tty->pgrp = current->__pgrp; - tty->foreground = current; - } - - return ret; -} - -static int tty_close(struct dfs_file *fd) -{ - int ret = 0; - struct tty_struct *tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - ld = tty->ldisc; - if (ld->ops->close) - { - //ld->ops->close(tty); - } - if (fd->vnode->ref_count == 1) - { - ret = rt_device_close((rt_device_t)tty); - } - return ret; -} - -static int tiocsctty(struct tty_struct *tty, int arg) -{ - if (current->leader && - (current->session == tty->session)) - { - return 0; - } - - /* - * The process must be a session leader and - * not have a controlling tty already. - */ - if (!current->leader || current->tty) - { - return -EPERM; - } - - if (tty->session > 0) - { - LOG_E("this tty have control process\n"); - - } - current->tty = tty; - current->tty_old_pgrp = 0; - tty->session = current->session; - tty->pgrp = current->__pgrp; - tty->foreground = current; - if (tty->type == TTY_DRIVER_TYPE_PTY) - { - tty->other_struct->foreground = current; - } - return 0; -} - -static int tiocswinsz(struct tty_struct *tty, struct winsize *p_winsize) -{ - rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row); - return 0; -} - -static int tiocgwinsz(struct tty_struct *tty, struct winsize *p_winsize) -{ - if(rt_thread_self() != rt_thread_find(FINSH_THREAD_NAME)) - { - /* only can be used in tshell thread; otherwise, return default size */ - p_winsize->ws_col = 80; - p_winsize->ws_row = 24; - } - else - { - #define _TIO_BUFLEN 20 - char _tio_buf[_TIO_BUFLEN]; - unsigned char cnt1, cnt2, cnt3, i; - char row_s[4], col_s[4]; - char *p; - - rt_memset(_tio_buf, 0, _TIO_BUFLEN); - - /* send the command to terminal for getting the window size of the terminal */ - rt_kprintf("\033[18t"); - - /* waiting for the response from the terminal */ - i = 0; - while(i < _TIO_BUFLEN) - { - _tio_buf[i] = finsh_getchar(); - if(_tio_buf[i] != 't') - { - i ++; - } - else - { - break; - } - } - if(i == _TIO_BUFLEN) - { - /* buffer overloaded, and return default size */ - p_winsize->ws_col = 80; - p_winsize->ws_row = 24; - return 0; - } - - /* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */ - rt_memset(row_s,0,4); - rt_memset(col_s,0,4); - cnt1 = 0; - while(cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';') - { - cnt1++; - } - cnt2 = ++cnt1; - while(cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';') - { - cnt2++; - } - p = row_s; - while(cnt1 < cnt2) - { - *p++ = _tio_buf[cnt1++]; - } - p = col_s; - cnt2++; - cnt3 = rt_strlen(_tio_buf) - 1; - while(cnt2 < cnt3) - { - *p++ = _tio_buf[cnt2++]; - } - - /* load the window size date */ - p_winsize->ws_col = atoi(col_s); - p_winsize->ws_row = atoi(row_s); - #undef _TIO_BUFLEN - } - - p_winsize->ws_xpixel = 0;/* unused */ - p_winsize->ws_ypixel = 0;/* unused */ - - return 0; -} - -static int tty_ioctl(struct dfs_file *fd, int cmd, void *args) -{ - int ret = 0; - void *p = (void *)args; - struct tty_struct *tty = RT_NULL; - struct tty_struct *real_tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - - if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) - { - real_tty = tty->other_struct; - } - else - { - real_tty = tty; - } - - switch (cmd) - { - case TIOCSCTTY: - return tiocsctty(real_tty, 1); - case TIOCGWINSZ: - return tiocgwinsz(real_tty, p); - case TIOCSWINSZ: - return tiocswinsz(real_tty, p); - } - - ld = tty->ldisc; - if (ld->ops->ioctl) - { - ret = ld->ops->ioctl(fd, cmd, args); - } - return ret; -} - -#ifdef RT_USING_DFS_V2 -static ssize_t tty_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos) -#else -static ssize_t tty_read(struct dfs_file *fd, void *buf, size_t count) -#endif -{ - int ret = 0; - struct tty_struct *tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - - ld = tty->ldisc; - if (ld && ld->ops->read) - { - ret = ld->ops->read(fd, buf, count); - } - return ret; -} - -#ifdef RT_USING_DFS_V2 -static ssize_t tty_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos) -#else -static ssize_t tty_write(struct dfs_file *fd, const void *buf, size_t count ) -#endif -{ - int ret = 0; - struct tty_struct *tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - - ld = tty->ldisc; - if (ld && ld->ops->write) - { - ret = ld->ops->write(fd, buf, count); - } - - return ret; -} - -static int tty_poll(struct dfs_file *fd, struct rt_pollreq *req) -{ - int ret = 0; - struct tty_struct *tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; - - tty = (struct tty_struct *)fd->vnode->data; - RT_ASSERT(tty != RT_NULL); - ld = tty->ldisc; - if (ld->ops->poll) - { - ret = ld->ops->poll(fd, req); - } - return ret; -} - -static const struct dfs_file_ops tty_fops = -{ - .open = tty_open, - .close = tty_close, - .ioctl = tty_ioctl, - .read = tty_read, - .write = tty_write, - .poll = tty_poll, -}; - -const struct dfs_file_ops *tty_get_fops(void) -{ - return &tty_fops; -} - -int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev) -{ - if (tty) - { - struct tty_node *node = NULL; - - 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); - rt_spin_lock_init(&tty->spinlock); - - 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_ioctl.c b/components/drivers/tty/tty_ioctl.c deleted file mode 100644 index 92206266c3..0000000000 --- a/components/drivers/tty/tty_ioctl.c +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include -#if defined(RT_USING_POSIX_DEVIO) -#include -#endif - -#define DBG_TAG "TTY_IOCTL" -#ifdef RT_TTY_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_TTY_DEBUG */ -#include - -/* - * Internal flag options for termios setting behavior - */ -#define TERMIOS_FLUSH 1 -#define TERMIOS_WAIT 2 -#define TERMIOS_TERMIO 4 -#define TERMIOS_OLD 8 - -/** - * set_termios - set termios values for a tty - * @tty: terminal device - * @arg: user data - * @opt: option information - * - * Helper function to prepare termios data and run necessary other - * functions before using tty_set_termios to do the actual changes. - * - * Locking: - * Called functions take ldisc and termios_rwsem locks - */ - -static int set_termios(struct tty_struct *tty, void *arg, int opt) -{ - struct termios old_termios; - struct tty_ldisc *ld = RT_NULL; - struct termios *new_termios = (struct termios *)arg; - rt_base_t level = 0; - int retval = tty_check_change(tty); - - if (retval) - { - return retval; - } - - memcpy(&old_termios, &(tty->init_termios), sizeof(struct termios)); - level = rt_spin_lock_irqsave(&tty->spinlock); - tty->init_termios = *new_termios; - rt_spin_unlock_irqrestore(&tty->spinlock, level); - ld = tty->ldisc; - if (ld != NULL) - { - if (ld->ops->set_termios) - { - ld->ops->set_termios(tty, &old_termios); - } - } - return 0; -} - -int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *args) -{ - int ret = 0; - void *p = (void *)args; - struct tty_struct *real_tty = RT_NULL; - - if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) - { - real_tty = tty->other_struct; - } - else - { - real_tty = tty; - } - - switch(cmd) - { - case TCGETS: - case TCGETA: - { - struct termios *tio = (struct termios *)p; - if (tio == RT_NULL) - { - return -RT_EINVAL; - } - - memcpy(tio, &real_tty->init_termios, sizeof(real_tty->init_termios)); - return ret; - } - case TCSETSF: - { - return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); - } - case TCSETSW: - { - return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); - } - case TCSETS: - { - return set_termios(real_tty, p, TERMIOS_OLD); - } - case TCSETAF: - { - return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); - } - case TCSETAW: - { - return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); - } - case TCSETA: - { - return set_termios(real_tty, p, TERMIOS_TERMIO); - } - default: - break; - } - return -ENOIOCTLCMD; -} diff --git a/components/drivers/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c deleted file mode 100644 index f2aef64bcc..0000000000 --- a/components/drivers/tty/tty_ldisc.c +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include - -#define DBG_TAG "TTY_LDISC" -#ifdef RT_TTY_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_TTY_DEBUG */ -#include - -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 rt_spinlock _spinlock = RT_SPINLOCK_INIT; - -static struct tty_ldisc_ops *get_ldops(int disc) -{ - struct tty_ldisc_ops *ldops = RT_NULL; - rt_base_t level = 0; - level = rt_spin_lock_irqsave(&_spinlock); - ldops = tty_ldiscs[disc]; - if (ldops) - { - ldops->refcount++; - } - rt_spin_unlock_irqrestore(&_spinlock, level); - return ldops; -} - -static void put_ldops(struct tty_ldisc_ops *ldops) -{ - rt_base_t level = 0; - - level = rt_spin_lock_irqsave(&_spinlock); - ldops->refcount--; - rt_spin_unlock_irqrestore(&_spinlock, level); -} - -static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) -{ - struct tty_ldisc *ld = RT_NULL; - struct tty_ldisc_ops *ldops = RT_NULL; - - if (disc < N_TTY || disc >= NR_LDISCS) - { - return RT_NULL; - } - - ldops = get_ldops(disc); - if (ldops == RT_NULL) - { - LOG_E("tty ldisc get error\n"); - return RT_NULL; - } - - ld = rt_malloc(sizeof(struct tty_ldisc)); - if (ld == RT_NULL) - { - ldops->refcount--; - return RT_NULL; - } - - ld->ops = ldops; - ld->tty = tty; - - return ld; -} - -/** - * tty_ldisc_put - release the ldisc - * - * Complement of tty_ldisc_get(). - */ -static void tty_ldisc_put(struct tty_ldisc *ld) -{ - if (ld) - { - put_ldops(ld->ops); - rt_free(ld); - } -} - -/** - * tty_ldisc_close - close a line discipline - * @tty: tty we are opening the ldisc on - * @ld: discipline to close - * - * 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 && ld->ops->close) - { - ld->ops->close(tty); - } -} - -/** - * tty_ldisc_kill - teardown ldisc - * @tty: tty being released - * - * Perform final close of the ldisc and reset tty->ldisc - */ -void tty_ldisc_kill(struct tty_struct *tty) -{ - if (tty && tty->ldisc) - { - /* - * 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) -{ - int ret = 0; - rt_base_t level = 0; - - if (disc < N_TTY || disc >= NR_LDISCS) - { - return -EINVAL; - } - - level = rt_spin_lock_irqsave(&_spinlock); - tty_ldiscs[disc] = new_ldisc; - new_ldisc->num = disc; - new_ldisc->refcount = 0; - rt_spin_unlock_irqrestore(&_spinlock, level); - - return ret; -} - -/** - * tty_ldisc_release - release line discipline - * @tty: tty being shut down (or one end of pty pair) - * - * Called during the final close of a tty or a pty pair in order to shut - * down the line discpline layer. On exit, each tty's ldisc is NULL. - */ - -void tty_ldisc_release(struct tty_struct *tty) -{ - struct tty_struct *o_tty = tty->other_struct; - - /* - * Shutdown this line discipline. As this is the final close, - * it does not race with the set_ldisc code path. - */ - tty_ldisc_kill(tty); - if (o_tty) - { - tty_ldisc_kill(o_tty); - } -} - -/** - * tty_ldisc_init - ldisc setup for new tty - * @tty: tty being allocated - * - * Set up the line discipline objects for a newly allocated tty. Note that - * the tty structure is not completely set up when this call is made. - */ - -void tty_ldisc_init(struct tty_struct *tty) -{ - if (tty) - { - tty->ldisc = tty_ldisc_get(tty, N_TTY); - } -} -- cgit v1.3.1