From d7bebbe7bd4bb3422db0fc1b3297043643f3a047 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Mon, 6 Dec 2021 15:54:22 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0tty=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-vexpress-a9/.config | 12 +- bsp/qemu-vexpress-a9/drivers/board.c | 1 + bsp/qemu-vexpress-a9/rtconfig.h | 4 +- components/libc/termios/posix_termios.h | 8 + components/lwp/lwp.c | 42 +- components/lwp/lwp.h | 11 + components/lwp/lwp_pid.c | 17 +- components/lwp/lwp_syscall.c | 20 +- components/tty/SConscript | 12 + components/tty/console.c | 296 ++++ components/tty/include/console.h | 8 + components/tty/include/tty.h | 434 ++++++ components/tty/include/tty_ldisc.h | 48 + components/tty/n_tty.c | 1760 +++++++++++++++++++++++ components/tty/pty.c | 332 +++++ components/tty/tty_io.c | 220 +++ components/tty/tty_ioctl.c | 179 +++ components/tty/tty_ldisc.c | 76 + include/libc/libc_errno.h | 1 + src/kservice.c | 4 +- 20 files changed, 3459 insertions(+), 26 deletions(-) create mode 100644 components/tty/SConscript create mode 100644 components/tty/console.c create mode 100644 components/tty/include/console.h create mode 100644 components/tty/include/tty.h create mode 100644 components/tty/include/tty_ldisc.h create mode 100644 components/tty/n_tty.c create mode 100644 components/tty/pty.c create mode 100644 components/tty/tty_io.c create mode 100644 components/tty/tty_ioctl.c create mode 100644 components/tty/tty_ldisc.c diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index 505e9b1c22..7007125092 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -108,7 +108,7 @@ CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=10 CONFIG_FINSH_USING_SYMTAB=y CONFIG_FINSH_USING_DESCRIPTION=y -# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_ECHO_DISABLE_DEFAULT=y CONFIG_FINSH_THREAD_PRIORITY=20 CONFIG_FINSH_THREAD_STACK_SIZE=4096 CONFIG_FINSH_CMD_SIZE=256 @@ -439,7 +439,6 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set -# CONFIG_PKG_USING_SMALL_MODBUS is not set # # security packages @@ -541,13 +540,6 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set -# -# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard -# -# CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_5_AUX is not set -# CONFIG_PKG_USING_CMSIS_RTOS2 is not set - # # Micrium: Micrium software products porting for RT-Thread # @@ -566,6 +558,7 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set # CONFIG_PKG_USING_DFS_JFFS2 is not set @@ -665,7 +658,6 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_MISAKA_RGB_BLING is not set # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set -# CONFIG_PKG_USING_MB85RS16 is not set # # AI packages diff --git a/bsp/qemu-vexpress-a9/drivers/board.c b/bsp/qemu-vexpress-a9/drivers/board.c index 2c6e172f0b..076fb0afb9 100644 --- a/bsp/qemu-vexpress-a9/drivers/board.c +++ b/bsp/qemu-vexpress-a9/drivers/board.c @@ -81,6 +81,7 @@ void rt_hw_board_init(void) rt_system_heap_init(HEAP_BEGIN, HEAP_END); rt_components_board_init(); + console_init(); rt_console_set_device(RT_CONSOLE_DEVICE_NAME); rt_thread_idle_sethook(idle_wfi); diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index 896f1e8ebf..5b105cdece 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -80,6 +80,7 @@ #define FINSH_HISTORY_LINES 10 #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION +#define FINSH_ECHO_DISABLE_DEFAULT #define FINSH_THREAD_PRIORITY 20 #define FINSH_THREAD_STACK_SIZE 4096 #define FINSH_CMD_SIZE 256 @@ -279,9 +280,6 @@ /* acceleration: Assembly language or algorithmic acceleration packages */ -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - /* Micrium: Micrium software products porting for RT-Thread */ diff --git a/components/libc/termios/posix_termios.h b/components/libc/termios/posix_termios.h index c61191b7dc..1f57420444 100644 --- a/components/libc/termios/posix_termios.h +++ b/components/libc/termios/posix_termios.h @@ -186,6 +186,14 @@ struct termios { #define XTABS 0014000 +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 +*/ +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" + speed_t cfgetospeed (const struct termios *); speed_t cfgetispeed (const struct termios *); int cfsetospeed (struct termios *, speed_t); diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index 26aa5762b1..ab84b621c7 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -23,6 +23,8 @@ #endif #include "lwp.h" +#include "lwp_arch.h" +#include "console.h" #define DBG_TAG "LWP" #define DBG_LVL DBG_WARNING @@ -1188,11 +1190,46 @@ pid_t lwp_execve(char *filename, int argc, char **argv, char **envp) self_lwp = lwp_self(); if (self_lwp) { + //lwp->tgroup_leader = &thread; //add thread group leader for lwp + lwp->__pgrp = tid; + lwp->session = self_lwp->session; /* lwp add to children link */ lwp->sibling = self_lwp->first_child; self_lwp->first_child = lwp; lwp->parent = self_lwp; } + else + { + //lwp->tgroup_leader = &thread; //add thread group leader for lwp + lwp->__pgrp = tid; + } + if (!bg) + { + if (lwp->session == -1) + { + struct tty_struct *tty = RT_NULL; + tty = (struct tty_struct *)console_tty_get(); + lwp->tty = tty; + lwp->tty->pgrp = lwp->__pgrp; + lwp->tty->session = lwp->session; + lwp->tty->foreground = lwp; + } + else + { + if (self_lwp != RT_NULL) + { + lwp->tty = self_lwp->tty; + lwp->tty->pgrp = lwp->__pgrp; + lwp->tty->session = lwp->session; + lwp->tty->foreground = lwp; + } + else + { + lwp->tty = RT_NULL; + } + + } + } thread->lwp = lwp; #ifndef ARCH_MM_MMU struct lwp_app_head *app_head = (struct lwp_app_head*)lwp->text_entry; @@ -1214,11 +1251,6 @@ pid_t lwp_execve(char *filename, int argc, char **argv, char **envp) lwp->debug = debug; } #endif - - if ((rt_console_get_foreground() == self_lwp) && !bg) - { - rt_console_set_foreground(lwp); - } rt_hw_interrupt_enable(level); rt_thread_startup(thread); diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h index ef8c6dfdfb..b091873ed4 100644 --- a/components/lwp/lwp.h +++ b/components/lwp/lwp.h @@ -22,6 +22,9 @@ #include #include #include +#ifdef RT_USING_TTY +#include +#endif #include "lwp_pid.h" #include "lwp_ipc.h" @@ -86,7 +89,12 @@ struct rt_lwp void *args; uint32_t args_length; pid_t pid; + pid_t __pgrp; /*Accessed via process_group()*/ + pid_t tty_old_pgrp; + pid_t session; rt_list_t t_grp; + + int leader; /*boolean value for session group_leader*/ struct dfs_fdtable fdt; char cmd[RT_NAME_MAX]; @@ -102,6 +110,7 @@ struct rt_lwp struct rt_user_context user_ctx; struct rt_wqueue wait_queue; /*for console */ + struct tty_struct *tty; /* NULL if no tty */ struct lwp_avl_struct *address_search_head; /* for addressed object fast rearch */ char working_directory[DFS_PATH_MAX]; @@ -137,6 +146,8 @@ void lwp_tid_set_thread(int tid, rt_thread_t thread); size_t lwp_user_strlen(const char *s, int *err); +/*create by lwp_setsid.c*/ +int setsid(void); #ifdef RT_USING_USERSPACE void lwp_mmu_switch(struct rt_thread *thread); #endif diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index e99cdc37d3..f353856e81 100644 --- a/components/lwp/lwp_pid.c +++ b/components/lwp/lwp_pid.c @@ -16,6 +16,7 @@ #include "lwp.h" #include "lwp_pid.h" #include "lwp_console.h" +#include "tty.h" #ifdef RT_USING_USERSPACE #include "lwp_user_mm.h" @@ -332,6 +333,10 @@ struct rt_lwp* lwp_new(void) rt_memset(lwp, 0, sizeof(*lwp)); rt_list_init(&lwp->wait_list); lwp->pid = pid; + lwp->leader = 0; + lwp->session = -1; + lwp->tty = RT_NULL; + //lwp->tgroup_leader = RT_NULL; lwp_pid_set_lwp(pid, lwp); rt_list_init(&lwp->t_grp); lwp_user_object_lock_init(lwp); @@ -434,12 +439,14 @@ void lwp_free(struct rt_lwp* lwp) /* for parent */ { - struct rt_lwp *console_lwp; - - console_lwp = rt_console_get_foreground(); - if (lwp == console_lwp) + struct rt_lwp *self_lwp = (struct rt_lwp *)lwp_self(); + if (lwp->tty != RT_NULL) { - rt_console_set_foreground(lwp->parent); + if (lwp->tty->foreground == lwp) + { + lwp->tty->foreground = self_lwp; + lwp->tty = RT_NULL; + } } if (lwp->parent) diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index a8705c6cd3..4d16cd27fa 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -55,6 +55,7 @@ #endif /* RT_USING_SAL */ #include +#include #include "lwp_ipc_internal.h" #define SET_ERRNO(no) rt_set_errno(-(no)) @@ -1550,6 +1551,11 @@ static void lwp_struct_copy(struct rt_lwp *dst, struct rt_lwp *src) dst->data_entry = src->data_entry; dst->data_size = src->data_size; dst->args = src->args; + dst->leader = 0; + dst->session = src->session; + dst->tty_old_pgrp = 0; + dst->__pgrp = src->__pgrp; + dst->tty = src->tty; rt_memcpy(dst->cmd, src->cmd, RT_NAME_MAX); dst->sa_flags = src->sa_flags; @@ -1716,9 +1722,9 @@ int _sys_fork(void) user_stack, &thread->sp); /* new thread never reach there */ level = rt_hw_interrupt_disable(); - if (rt_console_get_foreground() == self_lwp) + if (lwp->tty != RT_NULL) { - rt_console_set_foreground(lwp); + lwp->tty->foreground = lwp; } rt_hw_interrupt_enable(level); rt_thread_startup(thread); @@ -3897,6 +3903,15 @@ int sys_setrlimit(unsigned int resource, struct rlimit *rlim) return -ENOSYS; } +int sys_setsid(void) +{ + int ret = 0; + ret = setsid(); + return (ret < 0 ? GET_ERRNO() : ret); +} + +int sys_cacheflush(void *addr, int len, int cache); + const static void* func_table[] = { (void *)sys_exit, /* 01 */ @@ -4080,6 +4095,7 @@ const static void* func_table[] = (void *)sys_prlimit64, /* 140 */ (void *)sys_getrlimit, (void *)sys_setrlimit, + (void *)sys_setsid, }; const void *lwp_get_sys_api(rt_uint32_t number) diff --git a/components/tty/SConscript b/components/tty/SConscript new file mode 100644 index 0000000000..b5bacc32bf --- /dev/null +++ b/components/tty/SConscript @@ -0,0 +1,12 @@ +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 = [''], CPPPATH = CPPPATH) + + +Return('group') diff --git a/components/tty/console.c b/components/tty/console.c new file mode 100644 index 0000000000..8bf292a32f --- /dev/null +++ b/components/tty/console.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include "tty.h" + +static struct tty_struct console_driver; + +static void console_rx_notify(struct rt_device *dev) +{ + struct tty_struct *console = NULL; + int len = 0; + char ch = 0; + + console = (struct tty_struct *)dev; + RT_ASSERT(console != RT_NULL); + + len = rt_device_read(console->driver, -1, &ch, 1); + if (len == 0) + { + return; + } + if (console->ldisc->ops->receive_buf) + { + console->ldisc->ops->receive_buf((struct tty_struct *)console, &ch, len); + } +} + +struct tty_struct *console_tty_get(void) +{ + return &console_driver; +} + +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->driver, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); + rt_device_close(console->driver); +} + +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->driver, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags); + + ret = rt_device_open(console->driver, 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->driver, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); + return RT_EOK; +} + +struct rt_device *console_get_iodev(void) +{ + rt_base_t level = 0; + struct rt_device *iodev = RT_NULL; + + level = rt_hw_interrupt_disable(); + iodev = console_driver.driver; + rt_hw_interrupt_enable(level); + return iodev; +} + +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_driver; + + level = rt_hw_interrupt_disable(); + + RT_ASSERT(console->init_flag >= TTY_INIT_FLAG_REGED); + + io_before = console->driver; + + if (iodev == io_before) + { + goto exit; + } + + if (console->init_flag >= TTY_INIT_FLAG_INITED) + { + /* close old device */ + iodev_close(console); + } + + console->driver = 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_hw_interrupt_enable(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_hw_interrupt_disable(); + + 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_hw_interrupt_enable(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_size_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_size_t rt_console_write(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + rt_base_t level = 0; + 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); + + level = rt_hw_interrupt_disable(); + len = rt_device_write((struct rt_device *)console->driver, -1, buffer, size); + rt_hw_interrupt_enable(level); + + return len; +} + +static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args) +{ + rt_base_t level = 0; + 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); + + level = rt_hw_interrupt_disable(); + len = rt_device_control((struct rt_device *)console->driver, cmd, args); + rt_hw_interrupt_enable(level); + + 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_base_t level = 0; + rt_err_t ret = RT_EOK; + struct rt_device *device = RT_NULL; + struct tty_struct *console = &console_driver; + + level = rt_hw_interrupt_disable(); + RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE); + RT_ASSERT(iodev != RT_NULL); + + 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) + { + goto exit; + } + +#ifdef RT_USING_POSIX + /* 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->pgrp = -1; + console->session = -1; + console->foreground = RT_NULL; + rt_wqueue_init(&console->wait_queue); + + tty_ldisc_init(console); + +#if defined(RT_USING_POSIX_TERMIOS) +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; +#endif /* RT_USING_POSIX_TERMIOS */ + + console_ldata_init(console); + console->init_flag = TTY_INIT_FLAG_REGED; +exit: + rt_hw_interrupt_enable(level); + return ret; +} \ No newline at end of file diff --git a/components/tty/include/console.h b/components/tty/include/console.h new file mode 100644 index 0000000000..612334e406 --- /dev/null +++ b/components/tty/include/console.h @@ -0,0 +1,8 @@ +#ifndef __CONSOLE_ +#define __CONSOLE_ +#include +#include "tty.h" + +struct tty_struct *console_tty_get(void); +rt_err_t console_register(const char *name, struct rt_device *iodev); +#endif \ No newline at end of file diff --git a/components/tty/include/tty.h b/components/tty/include/tty.h new file mode 100644 index 0000000000..5d2fbfa434 --- /dev/null +++ b/components/tty/include/tty.h @@ -0,0 +1,434 @@ +#ifndef __TTY_H__ +#define __TTY_H__ +#include +#include +#include +#include "lwp.h" + +#ifdef RT_USING_POSIX_TERMIOS +#include +#endif + +#define current lwp_self() +#define __DISABLED_CHAR '\0' + +/* + * 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 winsize winsize; + struct termios init_termios; + struct rt_mutex mutex; + + pid_t pgrp; + pid_t session; + struct rt_lwp *foreground; + + struct tty_ldisc *ldisc; + void *disc_data; + struct rt_device *driver; + + struct rt_wqueue wait_queue; + +#define RT_TTY_BUF 1024 + rt_list_t tty_drivers; + +}; + +extern rt_list_t tty_drivers; + +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 + +/* + * 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 + +/* 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 + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 + +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); + +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); +} + +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; + + /*如果BITS_PER_LONG等于64,要先对低32位进行检查;否则(即BITS_PER_LONG等于32),直接对低16位进行检查*/ + #if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { //如果与0xffffffff相与得0,说明word的低32位全为0 + num += 32; //索引加32 + word >>= 32; //word右移32位,把低32位的0移走 + } + #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__*/ \ No newline at end of file diff --git a/components/tty/include/tty_ldisc.h b/components/tty/include/tty_ldisc.h new file mode 100644 index 0000000000..bc0e6c87c3 --- /dev/null +++ b/components/tty/include/tty_ldisc.h @@ -0,0 +1,48 @@ +#ifndef __TTY_LDISC_ +#define __TTY_LDISC_ +#include +#include +#include +#include + +#ifdef RT_USING_POSIX_TERMIOS +#include +#endif +struct tty_struct; + +struct tty_ldisc_ops +{ + char *name; + int num; + + int (*open) (struct dfs_fd *fd); + int (*close) (struct dfs_fd *fd); + int (*ioctl) (struct dfs_fd *fd, int cmd, void *args); + int (*read) (struct dfs_fd *fd, void *buf, size_t count); + int (*write) (struct dfs_fd *fd, const void *buf, size_t count); + int (*flush) (struct dfs_fd *fd); + int (*lseek) (struct dfs_fd *fd, off_t offset); + int (*getdents) (struct dfs_fd *fd, struct dirent *dirp, uint32_t count); + + int (*poll) (struct dfs_fd *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 + +void console_ldata_init(struct tty_struct *tty); +int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count); +int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); +void tty_ldisc_init(struct tty_struct *tty); +void n_tty_init(void); + +#endif // __TTY_LDISC_ \ No newline at end of file diff --git a/components/tty/n_tty.c b/components/tty/n_tty.c new file mode 100644 index 0000000000..29d008eae9 --- /dev/null +++ b/components/tty/n_tty.c @@ -0,0 +1,1760 @@ +#include +#include +#include + +#ifdef RT_USING_POSIX_TERMIOS +#include +#endif + +/* 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) + +#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) +{ + rt_err_t result = -RT_EBUSY; + + while (result == -RT_EBUSY) + { + result = rt_mutex_take(mutex, RT_WAITING_FOREVER); + } + + if (result != RT_EOK) + { + RT_ASSERT(0); + } + return; +} + +void mutex_unlock(rt_mutex_t mutex) +{ + rt_mutex_release(mutex); + return; +} +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; + + struct mutex *atomic_read_lock; + struct mutex *output_lock; +}; + +static 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) +{ + return ldata->read_buf[i & (RT_TTY_BUF - 1)]; +} + +static 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) +{ + return ldata->echo_buf[i & (RT_TTY_BUF - 1)]; +} + +static 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 + */ + +static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) +{ + *read_buf_addr(ldata, ldata->read_head) = c; + ldata->read_head++; +} + +/** + * 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. + */ + +static 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 + */ + +static 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 + */ + +static 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. + */ + +static 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; + size_t cnt; + int seen_alnums; + + 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); +} + +/** + * 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; + char *ch; + + 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--; + break; + 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; + int level; + + level = rt_hw_interrupt_disable(); + retval = do_output_char(c, tty); + rt_hw_interrupt_enable(level); + 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; + ssize_t size; + const char *cp; + int level; + + level = rt_hw_interrupt_disable(); + + 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); + rt_hw_interrupt_enable(level); + return size; +} + +static size_t __process_echoes(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + size_t tail; + unsigned char c; + char ch; + + tail = ldata->echo_tail; + while (ldata->echo_commit != tail) + { + c = echo_buf(ldata, tail); + if (c == ECHO_OP_START) + { + unsigned char op; + //int no_space_left = 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) + { + unsigned int num_chars, num_bs; + + 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++; + //space--; + 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, old; + size_t head; + int level; + + 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; + + level = rt_hw_interrupt_disable(); + ldata->echo_commit = head; + __process_echoes(tty); + rt_hw_interrupt_enable(level); +} + +static void process_echoes(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + int level; + if (ldata->echo_mark == ldata->echo_tail) + return; + + level = rt_hw_interrupt_disable(); + ldata->echo_commit = ldata->echo_mark; + __process_echoes(tty); + rt_hw_interrupt_enable(level); +} + +/* 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; + int level; + + if ((!L_ECHO(tty) && !L_ECHONL(tty)) || + ldata->echo_commit == ldata->echo_head) + return; + + level = rt_hw_interrupt_disable(); + ldata->echo_commit = ldata->echo_head; + __process_echoes(tty); + rt_hw_interrupt_enable(level); +} +/** + * 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; + + ldata = rt_malloc(sizeof(struct n_tty_data)); + + tty->disc_data = 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_fd *fd) +{ + int ret = 0; + struct n_tty_data *ldata; + struct tty_struct *tty = (struct tty_struct*)fd->fnode->data; + + ldata = rt_malloc(sizeof(struct n_tty_data)); + + //ldata->atomic_read_lock = rt_mutex_create("atomic_read_lock",RT_IPC_FLAG_FIFO); + //ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO); + tty->disc_data = ldata; + ldata->column = 0; + ldata->canon_column = 0; + ldata->lnext = 0; + n_tty_set_termios(tty, RT_NULL); + + rt_device_t device = (rt_device_t)fd->fnode->data; + if (fd->fnode->ref_count == 1) + { + ret = rt_device_open(device, fd->flags); + } + return ret; +} + +static 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; + rt_bool_t is_eof; + 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); + rt_memcpy(b, from, n); + is_eof = n == 1 && *from == EOF_CHAR(tty); + //ldata->read_tail = ldata->read_tail + n; + 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, size, more, c; + size_t eol; + size_t tail; + 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); + if (n > buf_size) + { + rt_memcpy(b, from, buf_size); + b += buf_size; + n -= buf_size; + from = ldata->read_buf; + } + rt_memcpy(b, from, 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 dfs_fd *fd) +{ + int ret = 0; + struct rt_device *device = RT_NULL; + + device = (struct rt_device *)fd->fnode->data; + RT_ASSERT(device != RT_NULL); + + if (fd->fnode->ref_count == 1) + { + ret = rt_device_close(device); + } + return ret; +} + +static int n_tty_ioctl(struct dfs_fd *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->fnode->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; +} + +/** + * 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)) + { + //start_tty(tty); + process_echoes(tty); + return 0; + } + if (c == STOP_CHAR(tty)) + { + //stop_tty(tty); + return 0; + } + } + + if (L_ISIG(tty)) + { + if (c == INTR_CHAR(tty)) + { + //n_tty_receive_signal_char(tty, SIGINT, c); + return 0; + } + else if (c == QUIT_CHAR(tty)) + { + //n_tty_receive_signal_char(tty, SIGQUIT, c); + return 0; + } + else if (c == SUSP_CHAR(tty)) + { + //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; +} + +static 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, head; + + 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 (fp) + // flag = *fp++; + if (flag == TTY_NORMAL) + put_tty_queue(*cp++, ldata); + //else + //n_tty_receive_char_flagged(tty, *cp++, flag); + } +} + +// static void +// n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, +// char *fp, int count) +// { +// char flag = TTY_NORMAL; + +// while (count--) { +// if (fp) +// flag = *fp++; +// if (likely(flag == TTY_NORMAL)) +// n_tty_receive_char_closing(tty, *cp++); +// } +// } + +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--; + } + } +} + +static 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; + struct n_tty_data *ldata = tty->disc_data; + int room, n, rcvd = 0, overflow; + + 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; + //ldata->no_room = flow && !room; + } + 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; +} + +static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) +{ + int level; + char *b = (char *)buf; + struct tty_struct *tty = RT_NULL; + struct rt_lwp *lwp = RT_NULL; + struct rt_wqueue *wq = RT_NULL; + int wait_ret = 0; + //size_t tail; + int retval; + + level = rt_hw_interrupt_disable(); + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + + struct n_tty_data *ldata = tty->disc_data; + + lwp = (struct rt_lwp *)(rt_thread_self()->lwp); + wq = wait_queue_get(lwp, tty); + + level = rt_hw_interrupt_disable(); + //tail = ldata->read_tail; + 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; + } + } + + if (ldata->icanon && !L_EXTPROC(tty)) + { + retval = canon_copy_from_read_buf(tty, b, count); + } + else + { + retval = copy_from_read_buf(tty, b, count); + } + + if (retval >= 1) + break; + + } + rt_hw_interrupt_enable(level); + return retval; +} + +static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + int retval = 0; + char *b = (char *)buf; + int c; + struct tty_struct *tty = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + + 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) + { + //retval += num; + break; + } + + c = *b; + if (process_output(c, tty) < 0) + break; + b++; count--; + + } + retval -= count; + } + else + { + int level; + while (count > 0) + { + level = rt_hw_interrupt_disable(); + c = rt_device_write((rt_device_t)tty, -1, b, count); + rt_hw_interrupt_enable(level); + 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_fd *fd) +{ + return 0; +} + +static int n_tty_lseek(struct dfs_fd *fd, off_t offset) +{ + return 0; +} + +static int n_tty_getdents(struct dfs_fd *fd, struct dirent *dirp, uint32_t count) +{ + return 0; +} + +static int n_tty_poll(struct dfs_fd *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; + struct rt_lwp *lwp = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + + RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED); + + lwp = (struct rt_lwp *)(rt_thread_self()->lwp); + wq = wait_queue_get(lwp, tty); + rt_poll_add(wq, req); + level = rt_hw_interrupt_disable(); + if (lwp == tty->foreground) + { + if (input_available_p(tty, 1)) + { + mask |= POLLIN; + } + } + rt_hw_interrupt_enable(level); + + return mask; +} + +static 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, +}; + +void n_tty_init(void) +{ + tty_register_ldisc(N_TTY, &n_tty_ops); +} diff --git a/components/tty/pty.c b/components/tty/pty.c new file mode 100644 index 0000000000..00d064f01d --- /dev/null +++ b/components/tty/pty.c @@ -0,0 +1,332 @@ +#include +#include + +#define PTY_PTS_SIZE 1024 +static struct tty_struct ptm_driver; +static struct tty_struct pts_drivers[PTY_PTS_SIZE]; +//rt_list_t pts_drivers; +static int pts_index = 0; + +static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, int pts_index); + +/* 查找空闲 pts 设备 */ +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) + { + pts_drivers[i].init_flag = TTY_INIT_FLAG_ALLOCED; + return &pts_drivers[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) + //set_bit(TTY_PTY_LOCK, &tty->flags); + tty->pts_lock = val; + else + //clear_bit(TTY_PTY_LOCK, &tty->flags); + tty->pts_lock = val; + return 0; +} + +static int pty_get_lock(struct tty_struct *tty, int *arg) +{ + // int locked = test_bit(TTY_PTY_LOCK, &tty->flags); + // return put_user(locked, 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; + int level; + struct tty_struct *tty= 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; +} + +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; + return result; +} + +static rt_size_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_size_t pty_device_write(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + rt_base_t level = 0; + rt_size_t len = 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_hw_interrupt_disable(); + + if (to->ldisc->ops->receive_buf) + { + len = to->ldisc->ops->receive_buf(to, (char *)buffer, size); + } + rt_hw_interrupt_enable(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 TIOCPKT: /* Set PT packet mode */ + //return pty_set_pktmode(tty, (int __user *)arg); + case TIOCGPKT: /* Get PT packet mode */ + //return pty_get_pktmode(tty, (int __user *)arg); + case TIOCGPTN: /* Get PT Number */ + return pty_get_index(tty, (int *)args); + //case TIOCSIG: /* Send signal to other side of pty */ + //return pty_signal(tty, (int) arg); + } + + return -ENOIOCTLCMD; +} + +static int ptmx_open(struct dfs_fd *fd) +{ + int ret = 0; + struct tty_struct *tty = RT_NULL; + struct tty_struct *pts_drv = RT_NULL; + struct tty_ldisc *ld = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + + pts_drv = find_freepts(); + if (pts_drv == RT_NULL) + { + return -1; + } + ret = pts_register(tty, pts_drv, pts_index); + if (ret < 0) + { + rt_free(pts_drv); + return -1; + } + pts_index++; + tty->other_struct = pts_drv; + ld = tty->ldisc; + if (ld->ops->open) + { + ret = ld->ops->open(fd); + } + + 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 *ptm_drv, struct tty_struct *pts_drv, int pts_index) +{ + rt_err_t ret = RT_EOK; + rt_base_t level = 0; + struct rt_device *device = RT_NULL; + char name[20]; + + RT_ASSERT(ptm_drv!=RT_NULL); + level = rt_hw_interrupt_disable(); + + if (pts_drv->init_flag != TTY_INIT_FLAG_ALLOCED) + { + //LOG_E("pts%d has been registered", pts_index); + ret = (-RT_EBUSY); + goto _exit; + } + + device = &pts_drv->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", pts_index); + ret = -RT_EIO; + goto _exit; + } + +#ifdef RT_USING_POSIX + /* set fops */ + tty_set_fops(&pts_fops); + 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); +#if defined(RT_USING_POSIX_TERMIOS) +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 |= ICANON; + pts_drv->init_termios.__c_ispeed = 38400; + pts_drv->init_termios.__c_ospeed = 38400; +#endif /* RT_USING_POSIX_TERMIOS */ + + 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; + + level = rt_hw_interrupt_disable(); + RT_ASSERT(ptm_drv->init_flag == TTY_INIT_FLAG_NONE); + + level = rt_hw_interrupt_disable(); + device = &(ptm_drv->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) + { + ret = -RT_EIO; + goto _exit; + } + +#ifdef RT_USING_POSIX + /* 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->pgrp = -1; + ptm_drv->session = -1; + ptm_drv->foreground = RT_NULL; + rt_wqueue_init(&ptm_drv->wait_queue); + + tty_ldisc_init(ptm_drv); + +#if defined(RT_USING_POSIX_TERMIOS) +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; +#endif /* RT_USING_POSIX_TERMIOS */ + + ptm_drv->init_flag = TTY_INIT_FLAG_REGED; + +_exit: + rt_hw_interrupt_enable(level); + + return ret; +} +INIT_DEVICE_EXPORT(ptmx_register); \ No newline at end of file diff --git a/components/tty/tty_io.c b/components/tty/tty_io.c new file mode 100644 index 0000000000..29ab9b1bdc --- /dev/null +++ b/components/tty/tty_io.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#ifdef RT_USING_POSIX_TERMIOS +#include +#endif + +#ifdef RT_USING_POSIX_TERMIOS +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 | ECHO | ECHOE | TOSTOP | NOFLSH, + RT_NULL,/* .c_line = N_TTY, */ + .c_cc = INIT_C_CC, + .__c_ispeed = 38400, + .__c_ospeed = 38400 +}; +#endif /*RT_USING_POSIX_TERMIOS*/ + +static int tty_open(struct dfs_fd *fd) +{ + int ret = 0; + int noctty; + struct tty_struct *tty = RT_NULL; + struct tty_ldisc *ld = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; + if (ld->ops->open) + { + ret = ld->ops->open(fd); + } + noctty = (fd->flags & O_NOCTTY); + + if (current == RT_NULL) //kernel mode not lwp + { + return ret; + } + + if (!noctty && + current->leader && + !current->tty && + tty->session == 0) + { + 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_fd *fd) +{ + int ret = 0; + struct tty_struct *tty = RT_NULL; + struct tty_ldisc *ld = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; + if (ld->ops->close) + { + + ret = ld->ops->close(fd); + } + 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) + { + rt_kprintf("this tty have control process\n"); + + } + current->tty = tty; + current->tty_old_pgrp = 0; + tty->session = current->session; + tty->pgrp = current->__pgrp; + return 0; +} + +static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) +{ + int ret = 0; + struct tty_struct *tty = RT_NULL; + struct tty_struct *real_tty = RT_NULL; + struct tty_ldisc *ld = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->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); + } + ld = tty->ldisc; + if (ld->ops->ioctl) + { + ret = ld->ops->ioctl(fd, cmd, args); + } + return ret; +} + +static int tty_read(struct dfs_fd *fd, void *buf, size_t count) +{ + int ret = 0; + struct tty_struct *tty = RT_NULL; + struct tty_ldisc *ld = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; + if (ld->ops->read) + { + ret = ld->ops->read(fd, buf, count); + } + return ret; +} + +static int tty_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + int ret = 0; + struct tty_struct *tty = RT_NULL; + struct tty_ldisc *ld = RT_NULL; + + tty = (struct tty_struct *)fd->fnode->data; + RT_ASSERT(tty != RT_NULL); + ld = tty->ldisc; + if (ld->ops->write) + { + ret = ld->ops->write(fd, buf, count); + } + return ret; +} + +static int tty_poll(struct dfs_fd *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->fnode->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 = +{ + tty_open, + tty_close, + tty_ioctl, + tty_read, + tty_write, + RT_NULL, /* flush */ + RT_NULL, /* lseek */ + 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() +{ + n_tty_init(); +} + +void tty_set_fops(struct dfs_file_ops *fops) +{ + *fops = tty_fops; +} + +void console_set_fops(struct dfs_file_ops *fops) +{ + *fops = console_fops; +} + +// void tty_system_init(void) +// { + +// } +// INIT_DEVICE_EXPORT(tty_system_init); diff --git a/components/tty/tty_ioctl.c b/components/tty/tty_ioctl.c new file mode 100644 index 0000000000..e7ddea248b --- /dev/null +++ b/components/tty/tty_ioctl.c @@ -0,0 +1,179 @@ +#include +#include +#include + +#ifdef RT_USING_POSIX_TERMIOS +#include +#endif + +/* + * Internal flag options for termios setting behavior + */ +#define TERMIOS_FLUSH 1 +#define TERMIOS_WAIT 2 +#define TERMIOS_TERMIO 4 +#define TERMIOS_OLD 8 + +/** + * tty_set_termios - update termios values + * @tty: tty to update + * @new_termios: desired new value + * + * Perform updates to the termios values set on this terminal. + * A master pty's termios should never be set. + * + * Locking: termios_rwsem + */ + +// int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) +// { +// struct ktermios old_termios; +// struct tty_ldisc *ld; + +// // WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY && +// // tty->driver->subtype == PTY_TYPE_MASTER); +// /* +// * Perform the actual termios internal changes under lock. +// */ + + +// /* FIXME: we need to decide on some locking/ordering semantics +// for the set_termios notification eventually */ +// down_write(&tty->termios_rwsem); +// old_termios = tty->termios; +// tty->termios = *new_termios; +// unset_locked_termios(tty, &old_termios); + +// if (tty->ops->set_termios) +// tty->ops->set_termios(tty, &old_termios); +// else +// tty_termios_copy_hw(&tty->termios, &old_termios); + +// ld = tty_ldisc_ref(tty); +// if (ld != NULL) { +// if (ld->ops->set_termios) +// ld->ops->set_termios(tty, &old_termios); +// tty_ldisc_deref(ld); +// } +// up_write(&tty->termios_rwsem); +// return 0; +// } + +/** + * 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 = &tty->init_termios; + struct tty_ldisc *ld; + struct termios *new_termios = (struct termios *)arg; + // int retval = tty_check_change(tty); + + // if (retval) + // return retval; + +// down_read(&tty->termios_rwsem); +// tmp_termios = tty->termios; +// up_read(&tty->termios_rwsem); + +// if (opt & TERMIOS_TERMIO) { +// if (user_termio_to_kernel_termios(&tmp_termios, +// (struct termio __user *)arg)) +// return -EFAULT; +// #ifdef TCGETS2 +// } else if (opt & TERMIOS_OLD) { +// if (user_termios_to_kernel_termios_1(&tmp_termios, +// (struct termios __user *)arg)) +// return -EFAULT; +// } else { +// if (user_termios_to_kernel_termios(&tmp_termios, +// (struct termios2 __user *)arg)) +// return -EFAULT; +// } +// #else +// } else if (user_termios_to_kernel_termios(&tmp_termios, +// (struct termios __user *)arg)) +// return -EFAULT; +// #endif + + /* If old style Bfoo values are used then load c_ispeed/c_ospeed + * with the real speed so its unconditionally usable */ + //tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); + //tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); + + // ld = tty_ldisc_ref(tty); + + // if (ld != NULL) { + // if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) + // ld->ops->flush_buffer(tty); + // tty_ldisc_deref(ld); + // } + + // if (opt & TERMIOS_WAIT) { + // tty_wait_until_sent(tty, 0); + // if (signal_pending(current)) + // return -ERESTARTSYS; + // } + + //tty_set_termios(tty, &tmp_termios); + tty->init_termios = *new_termios; + ld = tty->ldisc; + if (ld != NULL) + { + if (ld->ops->set_termios) + ld->ops->set_termios(tty, old_termios); + } + /* FIXME: Arguably if tmp_termios == tty->termios AND the + actual requested termios was not tmp_termios then we may + want to return an error as no user requested change has + succeeded */ + 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; + + 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: + { + struct termios *tio = (struct termios *)p; + if (tio == RT_NULL) return -RT_EINVAL; + rt_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); + } + default: + break; + } + return -ENOIOCTLCMD; +} \ No newline at end of file diff --git a/components/tty/tty_ldisc.c b/components/tty/tty_ldisc.c new file mode 100644 index 0000000000..4568f5d6d1 --- /dev/null +++ b/components/tty/tty_ldisc.c @@ -0,0 +1,76 @@ +#include + +static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; + +static struct tty_ldisc_ops *get_ldops(int disc) +{ + struct tty_ldisc_ops *ldops; + int level; + level = rt_hw_interrupt_disable(); + ldops = tty_ldiscs[disc]; + if (ldops) + { + ldops->refcount++; + } + rt_hw_interrupt_enable(level); + return ldops; +} + +static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) +{ + struct tty_ldisc *ld; + struct tty_ldisc_ops *ldops; + + if (disc < N_TTY || disc >= NR_LDISCS) + return RT_NULL; + + ldops = get_ldops(disc); + if (ldops == RT_NULL) + { + 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; +} + +int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) +{ + int ret = 0; + int level; + + if (disc < N_TTY || disc >= NR_LDISCS) + return -EINVAL; + + level = rt_hw_interrupt_disable(); + tty_ldiscs[disc] = new_ldisc; + new_ldisc->num = disc; + new_ldisc->refcount = 0; + rt_hw_interrupt_enable(level); + + return ret; +} + +/** + * 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) +{ + struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); + RT_ASSERT(ld != RT_NULL); + tty->ldisc = ld; +} \ No newline at end of file diff --git a/include/libc/libc_errno.h b/include/libc/libc_errno.h index d34a143fae..c5471c51b9 100644 --- a/include/libc/libc_errno.h +++ b/include/libc/libc_errno.h @@ -16,6 +16,7 @@ #if defined(RT_USING_NEWLIB) || defined(RT_USING_MUSL) || defined(_WIN32) || defined(__ARMCC_GNUC__) /* use errno.h file in toolchains */ #include +#define ENOIOCTLCMD (ERROR_BASE_NO + 515) /* No ioctl command */ #endif #if defined(__CC_ARM) diff --git a/src/kservice.c b/src/kservice.c index a19852d4c3..a077d20490 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -30,6 +30,7 @@ #include #include #include +#include #endif /* use precision */ @@ -1143,7 +1144,8 @@ rt_device_t rt_console_set_device(const char *name) } else { - rt_console_register("console", new_iodev); + //rt_console_register("console", new_iodev); + console_register("console", new_iodev); _console_device = rt_device_find("console"); rt_device_open(_console_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM); } -- Gitee From de736a1a2a6b2c95562a34c46fa5d61ddd44866f Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Mon, 6 Dec 2021 16:04:54 +0800 Subject: [PATCH 02/13] format code --- components/lwp/lwp_setsid.c | 28 + components/tty/console.c | 14 +- components/tty/include/console.h | 2 +- components/tty/include/tty.h | 332 ++-- components/tty/include/tty_ldisc.h | 8 +- components/tty/n_tty.c | 2636 ++++++++++++++-------------- components/tty/pty.c | 76 +- components/tty/tty_io.c | 74 +- components/tty/tty_ioctl.c | 226 +-- components/tty/tty_ldisc.c | 80 +- 10 files changed, 1752 insertions(+), 1724 deletions(-) create mode 100644 components/lwp/lwp_setsid.c diff --git a/components/lwp/lwp_setsid.c b/components/lwp/lwp_setsid.c new file mode 100644 index 0000000000..f0417fdee6 --- /dev/null +++ b/components/lwp/lwp_setsid.c @@ -0,0 +1,28 @@ +#include +#include + +#include "lwp.h" +//#include "lwp_tid.h" +#include "lwp_pid.h" + + +int setsid(void) +{ + int err = -EPERM; + struct rt_thread *current_thread = rt_thread_self(); + struct rt_lwp *current_lwp = (struct rt_lwp *)rt_thread_self()->lwp; + + if (current_lwp->session == current_thread->tid) + { + return err; + } + + current_lwp->session = current_thread->tid; + current_lwp->__pgrp = current_thread->tid; + current_lwp->leader = 1; + current_lwp->tty = RT_NULL; + current_lwp->tty_old_pgrp = 0; + + err = current_lwp->session; + return err; +} \ No newline at end of file diff --git a/components/tty/console.c b/components/tty/console.c index 8bf292a32f..31317da459 100644 --- a/components/tty/console.c +++ b/components/tty/console.c @@ -199,7 +199,7 @@ static rt_size_t rt_console_write(struct rt_device *dev, static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args) { - rt_base_t level = 0; + rt_base_t level = 0; rt_size_t len = 0; struct tty_struct *console = RT_NULL; @@ -281,11 +281,11 @@ rt_err_t console_register(const char *name, struct rt_device *iodev) #if defined(RT_USING_POSIX_TERMIOS) 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->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; #endif /* RT_USING_POSIX_TERMIOS */ console_ldata_init(console); @@ -293,4 +293,4 @@ extern struct termios tty_std_termios; exit: rt_hw_interrupt_enable(level); return ret; -} \ No newline at end of file +} diff --git a/components/tty/include/console.h b/components/tty/include/console.h index 612334e406..9e21d008f9 100644 --- a/components/tty/include/console.h +++ b/components/tty/include/console.h @@ -5,4 +5,4 @@ struct tty_struct *console_tty_get(void); rt_err_t console_register(const char *name, struct rt_device *iodev); -#endif \ No newline at end of file +#endif diff --git a/components/tty/include/tty.h b/components/tty/include/tty.h index 5d2fbfa434..1a6289ea9b 100644 --- a/components/tty/include/tty.h +++ b/components/tty/include/tty.h @@ -16,11 +16,11 @@ * 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 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]) @@ -37,72 +37,72 @@ #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 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) +#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 @@ -113,7 +113,7 @@ * 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 + * - TYT, 9/14/92 */ struct tty_struct { @@ -155,15 +155,15 @@ enum 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 +#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 +#define TTY_MAGIC 0x5401 /* * These bits are used in the flags field of the tty structure. @@ -189,7 +189,7 @@ enum /* * 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 @@ -209,60 +209,60 @@ enum #define TTY_PTY_LOCK 16 #define TTY_NO_WRITE_SPLIT 17 -#define NR_LDISCS 30 +#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 */ +#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 +#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 /* 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 +#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 +#define PTY_TYPE_MASTER 0x0001 +#define PTY_TYPE_SLAVE 0x0002 /* serial subtype definitions */ -#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_NORMAL 1 void tty_set_fops(struct dfs_file_ops *fops); void console_set_fops(struct dfs_file_ops *fops); @@ -328,23 +328,23 @@ rt_inline int test_bit(int nr, int *addr) rt_inline int test_and_clear_bit(int nr, volatile void *addr) { - int mask, retval, level; - volatile unsigned int *a = 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); + 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; + return retval; } rt_inline unsigned long __ffs(unsigned long word) { int num = 0; - + /*如果BITS_PER_LONG等于64,要先对低32位进行检查;否则(即BITS_PER_LONG等于32),直接对低16位进行检查*/ #if BITS_PER_LONG == 64 if ((word & 0xffffffff) == 0) { //如果与0xffffffff相与得0,说明word的低32位全为0 @@ -377,50 +377,50 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) return num; } #define BITS_PER_LONG 32 -#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) +#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) + 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) + 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)) + 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; + 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. */ + tmp &= (~0UL >> (BITS_PER_LONG - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ found_middle: - return result + __ffs(tmp); + return result + __ffs(tmp); } /*create by tty_ioctl.c*/ @@ -431,4 +431,4 @@ 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__*/ \ No newline at end of file +#endif /*__TTY_H__*/ diff --git a/components/tty/include/tty_ldisc.h b/components/tty/include/tty_ldisc.h index bc0e6c87c3..bb3bf42b8b 100644 --- a/components/tty/include/tty_ldisc.h +++ b/components/tty/include/tty_ldisc.h @@ -12,8 +12,8 @@ struct tty_struct; struct tty_ldisc_ops { - char *name; - int num; + char *name; + int num; int (*open) (struct dfs_fd *fd); int (*close) (struct dfs_fd *fd); @@ -37,7 +37,7 @@ struct tty_ldisc struct tty_struct *tty; }; -#define TTY_LDISC_MAGIC 0x5403 +#define TTY_LDISC_MAGIC 0x5403 void console_ldata_init(struct tty_struct *tty); int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count); @@ -45,4 +45,4 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); void tty_ldisc_init(struct tty_struct *tty); void n_tty_init(void); -#endif // __TTY_LDISC_ \ No newline at end of file +#endif // __TTY_LDISC_ diff --git a/components/tty/n_tty.c b/components/tty/n_tty.c index 29d008eae9..3e4c1d2624 100644 --- a/components/tty/n_tty.c +++ b/components/tty/n_tty.c @@ -14,8 +14,8 @@ * 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 +#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 @@ -28,19 +28,19 @@ #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) +#define ECHO_COMMIT_WATERMARK 256 +#define ECHO_BLOCK 256 +#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32) #define max(a, b) ({\ - typeof(a) _a = a;\ - typeof(b) _b = b;\ - _a > _b ? _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; }) + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a < _b ? _a : _b; }) void mutex_lock(rt_mutex_t mutex) { @@ -65,892 +65,892 @@ void mutex_unlock(rt_mutex_t mutex) } 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; - - struct mutex *atomic_read_lock; - struct mutex *output_lock; + /* 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; + + struct mutex *atomic_read_lock; + struct mutex *output_lock; }; static inline size_t read_cnt(struct n_tty_data *ldata) { - return ldata->read_head - ldata->read_tail; + return ldata->read_head - ldata->read_tail; } static inline char read_buf(struct n_tty_data *ldata, size_t i) { - return ldata->read_buf[i & (RT_TTY_BUF - 1)]; + return ldata->read_buf[i & (RT_TTY_BUF - 1)]; } static inline char *read_buf_addr(struct n_tty_data *ldata, size_t i) { - return &ldata->read_buf[i & (RT_TTY_BUF - 1)]; + return &ldata->read_buf[i & (RT_TTY_BUF - 1)]; } static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) { - return ldata->echo_buf[i & (RT_TTY_BUF - 1)]; + return ldata->echo_buf[i & (RT_TTY_BUF - 1)]; } static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) { - return &ldata->echo_buf[i & (RT_TTY_BUF - 1)]; + return &ldata->echo_buf[i & (RT_TTY_BUF - 1)]; } /** - * put_tty_queue - add character to tty - * @c: character - * @ldata: n_tty data + * put_tty_queue - add character to tty + * @c: character + * @ldata: n_tty data * - * Add a character to the tty read_buf queue. + * Add a character to the tty read_buf queue. * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem + * 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) { - *read_buf_addr(ldata, ldata->read_head) = c; - ldata->read_head++; + *read_buf_addr(ldata, ldata->read_head) = c; + ldata->read_head++; } /** - * add_echo_byte - add a byte to the echo buffer - * @c: unicode byte to echo - * @ldata: n_tty data + * 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. + * Add a character or operation byte to the echo buffer. */ static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { - *echo_buf_addr(ldata, ldata->echo_head++) = c; + *echo_buf_addr(ldata, ldata->echo_head++) = c; } /** - * echo_move_back_col - add operation to move back a column - * @ldata: n_tty data + * 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. + * 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); + 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 + * 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. + * 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); + 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 + * 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. + * 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. + * 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) + struct n_tty_data *ldata) { - add_echo_byte(ECHO_OP_START, ldata); - add_echo_byte(ECHO_OP_ERASE_TAB, 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; + /* 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; + /* 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); + add_echo_byte(num_chars, ldata); } /** - * echo_char_raw - echo a character raw - * @c: unicode byte to echo - * @tty: terminal device + * 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. + * 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. + * 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); - } + 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_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. + * 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). + * 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); - } + 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 + * finish_erasing - complete erase + * @ldata: n_tty data */ static inline void finish_erasing(struct n_tty_data *ldata) { - if (ldata->erasing) - { - echo_char_raw('/', ldata); - ldata->erasing = 0; - } + if (ldata->erasing) + { + echo_char_raw('/', ldata); + ldata->erasing = 0; + } } /** - * is_utf8_continuation - utf8 multibyte check - * @c: byte to check + * 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 + * 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 */ static inline int is_utf8_continuation(unsigned char c) { - return (c & 0xc0) == 0x80; + return (c & 0xc0) == 0x80; } /** - * is_continuation - multibyte check - * @c: byte to check + * 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. + * Returns true if the utf8 character 'c' is a multibyte continuation + * character and the terminal is in unicode mode. */ static inline int is_continuation(unsigned char c, struct tty_struct *tty) { - return I_IUTF8(tty) && is_utf8_continuation(c); + return I_IUTF8(tty) && is_utf8_continuation(c); } /** - * eraser - handle erase function - * @c: character input - * @tty: terminal device + * 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. + * 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 + * 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; - size_t cnt; - int seen_alnums; - - 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); + struct n_tty_data *ldata = tty->disc_data; + enum { KERASE, WERASE, KILL } kill_type; + size_t head; + size_t cnt; + int seen_alnums; + + 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); } /** - * do_output_char - output one character - * @c: character (or partial unicode symbol) - * @tty: terminal device - * @space: space available in tty driver write buffer + * 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. + * 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. + * 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. + * 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 + * 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; - char *ch; - - 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--; - break; - 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; + struct n_tty_data *ldata = tty->disc_data; + int spaces; + char *ch; + + 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--; + break; + 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 + * 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. + * 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) + * 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; - int level; - - level = rt_hw_interrupt_disable(); - retval = do_output_char(c, tty); - rt_hw_interrupt_enable(level); - if (retval < 0) - return -1; - else - return 0; + int retval; + int level; + + level = rt_hw_interrupt_disable(); + retval = do_output_char(c, tty); + rt_hw_interrupt_enable(level); + 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 + * 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. + * 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. + * 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) + * 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) + const char *buf, unsigned int nr) { - struct n_tty_data *ldata = tty->disc_data; - int i; - ssize_t size; - const char *cp; - int level; - - level = rt_hw_interrupt_disable(); - - 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; - } - } + struct n_tty_data *ldata = tty->disc_data; + int i; + ssize_t size; + const char *cp; + int level; + + level = rt_hw_interrupt_disable(); + + 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); - rt_hw_interrupt_enable(level); - return size; + size = rt_device_write((rt_device_t)tty, -1, buf, i); + rt_hw_interrupt_enable(level); + return size; } static size_t __process_echoes(struct tty_struct *tty) { - struct n_tty_data *ldata = tty->disc_data; - size_t tail; - unsigned char c; - char ch; - - tail = ldata->echo_tail; - while (ldata->echo_commit != tail) - { - c = echo_buf(ldata, tail); - if (c == ECHO_OP_START) - { - unsigned char op; - //int no_space_left = 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) - { - unsigned int num_chars, num_bs; - - 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++; - //space--; - 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; + struct n_tty_data *ldata = tty->disc_data; + size_t tail; + unsigned char c; + char ch; + + tail = ldata->echo_tail; + while (ldata->echo_commit != tail) + { + c = echo_buf(ldata, tail); + if (c == ECHO_OP_START) + { + unsigned char op; + //int no_space_left = 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) + { + unsigned int num_chars, num_bs; + + 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++; + //space--; + 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, old; - size_t head; - int level; - - 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; - - level = rt_hw_interrupt_disable(); - ldata->echo_commit = head; - __process_echoes(tty); - rt_hw_interrupt_enable(level); + struct n_tty_data *ldata = tty->disc_data; + size_t nr, old; + size_t head; + int level; + + 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; + + level = rt_hw_interrupt_disable(); + ldata->echo_commit = head; + __process_echoes(tty); + rt_hw_interrupt_enable(level); } static void process_echoes(struct tty_struct *tty) { - struct n_tty_data *ldata = tty->disc_data; - int level; - if (ldata->echo_mark == ldata->echo_tail) - return; - - level = rt_hw_interrupt_disable(); - ldata->echo_commit = ldata->echo_mark; - __process_echoes(tty); - rt_hw_interrupt_enable(level); + struct n_tty_data *ldata = tty->disc_data; + int level; + if (ldata->echo_mark == ldata->echo_tail) + return; + + level = rt_hw_interrupt_disable(); + ldata->echo_commit = ldata->echo_mark; + __process_echoes(tty); + rt_hw_interrupt_enable(level); } /* 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; - int level; + struct n_tty_data *ldata = tty->disc_data; + int level; - if ((!L_ECHO(tty) && !L_ECHONL(tty)) || - ldata->echo_commit == ldata->echo_head) - return; + if ((!L_ECHO(tty) && !L_ECHONL(tty)) || + ldata->echo_commit == ldata->echo_head) + return; - level = rt_hw_interrupt_disable(); - ldata->echo_commit = ldata->echo_head; - __process_echoes(tty); - rt_hw_interrupt_enable(level); + level = rt_hw_interrupt_disable(); + ldata->echo_commit = ldata->echo_head; + __process_echoes(tty); + rt_hw_interrupt_enable(level); } /** - * n_tty_set_termios - termios data changed - * @tty: terminal - * @old: previous data + * 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. + * 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 + * 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; - } + 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; + struct n_tty_data *ldata; - ldata = rt_malloc(sizeof(struct n_tty_data)); + ldata = rt_malloc(sizeof(struct n_tty_data)); - tty->disc_data = ldata; - ldata->column = 0; - ldata->canon_column = 0; - ldata->no_room = 0; - ldata->lnext = 0; - n_tty_set_termios(tty, RT_NULL); + tty->disc_data = 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_fd *fd) { - int ret = 0; - struct n_tty_data *ldata; - struct tty_struct *tty = (struct tty_struct*)fd->fnode->data; - - ldata = rt_malloc(sizeof(struct n_tty_data)); - - //ldata->atomic_read_lock = rt_mutex_create("atomic_read_lock",RT_IPC_FLAG_FIFO); - //ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO); - tty->disc_data = ldata; - ldata->column = 0; - ldata->canon_column = 0; - ldata->lnext = 0; - n_tty_set_termios(tty, RT_NULL); - - rt_device_t device = (rt_device_t)fd->fnode->data; - if (fd->fnode->ref_count == 1) + int ret = 0; + struct n_tty_data *ldata; + struct tty_struct *tty = (struct tty_struct*)fd->fnode->data; + + ldata = rt_malloc(sizeof(struct n_tty_data)); + + //ldata->atomic_read_lock = rt_mutex_create("atomic_read_lock",RT_IPC_FLAG_FIFO); + //ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO); + tty->disc_data = ldata; + ldata->column = 0; + ldata->canon_column = 0; + ldata->lnext = 0; + n_tty_set_termios(tty, RT_NULL); + + rt_device_t device = (rt_device_t)fd->fnode->data; + if (fd->fnode->ref_count == 1) { ret = rt_device_open(device, fd->flags); } @@ -959,151 +959,151 @@ static int n_tty_open(struct dfs_fd *fd) static 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; + 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; + 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 + * 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. + * 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 + * Called under the ldata->atomic_read_lock sem * - * n_tty_read()/consumer path: - * caller holds non-exclusive termios_rwsem - * read_tail published + * 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; - rt_bool_t is_eof; - 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); - rt_memcpy(b, from, n); - is_eof = n == 1 && *from == EOF_CHAR(tty); - //ldata->read_tail = ldata->read_tail + n; - 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; + struct n_tty_data *ldata = tty->disc_data; + size_t n; + rt_bool_t is_eof; + 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); + rt_memcpy(b, from, n); + is_eof = n == 1 && *from == EOF_CHAR(tty); + //ldata->read_tail = ldata->read_tail + n; + 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 + * 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. + * 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. + * 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 + * Called under the atomic_read_lock mutex * - * n_tty_read()/consumer path: - * caller holds non-exclusive termios_rwsem - * read_tail published + * 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, size, more, c; - size_t eol; - size_t tail; - 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); - if (n > buf_size) - { - rt_memcpy(b, from, buf_size); - b += buf_size; - n -= buf_size; - from = ldata->read_buf; - } - rt_memcpy(b, from, 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; + struct n_tty_data *ldata = tty->disc_data; + size_t n, size, more, c; + size_t eol; + size_t tail; + 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); + if (n > buf_size) + { + rt_memcpy(b, from, buf_size); + b += buf_size; + n -= buf_size; + from = ldata->read_buf; + } + rt_memcpy(b, from, 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 dfs_fd *fd) { - int ret = 0; + int ret = 0; struct rt_device *device = RT_NULL; device = (struct rt_device *)fd->fnode->data; @@ -1118,577 +1118,577 @@ static int n_tty_close(struct dfs_fd *fd) static int n_tty_ioctl(struct dfs_fd *fd, int cmd, void *args) { - int ret = 0; + int ret = 0; struct tty_struct *real_tty = RT_NULL; - struct tty_struct *tty = RT_NULL; + struct tty_struct *tty = RT_NULL; tty = (struct tty_struct *)fd->fnode->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; + if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) + real_tty = tty->other_struct; + else + real_tty = tty; - switch(cmd) - { + switch(cmd) + { - default: - ret = n_tty_ioctl_extend(real_tty, cmd, args); - if (ret != -ENOIOCTLCMD) - return ret; - } + 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; + ret = rt_device_control((rt_device_t)real_tty, cmd, args); + if (ret != -ENOIOCTLCMD) + return ret; - return ret; + return ret; } /** - * n_tty_receive_char - perform processing - * @tty: terminal device - * @c: character + * 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. + * 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 + * 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 + * 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)) - { - //start_tty(tty); - process_echoes(tty); - return 0; - } - if (c == STOP_CHAR(tty)) - { - //stop_tty(tty); - return 0; - } - } - - if (L_ISIG(tty)) - { - if (c == INTR_CHAR(tty)) - { - //n_tty_receive_signal_char(tty, SIGINT, c); - return 0; - } - else if (c == QUIT_CHAR(tty)) - { - //n_tty_receive_signal_char(tty, SIGQUIT, c); - return 0; - } - else if (c == SUSP_CHAR(tty)) - { - //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); + struct n_tty_data *ldata = tty->disc_data; + + if (I_IXON(tty)) + { + if (c == START_CHAR(tty)) + { + //start_tty(tty); + process_echoes(tty); + return 0; + } + if (c == STOP_CHAR(tty)) + { + //stop_tty(tty); + return 0; + } + } + + if (L_ISIG(tty)) + { + if (c == INTR_CHAR(tty)) + { + //n_tty_receive_signal_char(tty, SIGINT, c); + return 0; + } + else if (c == QUIT_CHAR(tty)) + { + //n_tty_receive_signal_char(tty, SIGQUIT, c); + return 0; + } + else if (c == SUSP_CHAR(tty)) + { + //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; + 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; } static 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); + 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); + 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); - } + 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, head; - - 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; + struct n_tty_data *ldata = tty->disc_data; + size_t n, head; + + 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 (fp) - // flag = *fp++; - if (flag == TTY_NORMAL) - put_tty_queue(*cp++, ldata); - //else - //n_tty_receive_char_flagged(tty, *cp++, flag); - } + struct n_tty_data *ldata = tty->disc_data; + char flag = TTY_NORMAL; + + while (count--) + { + //if (fp) + // flag = *fp++; + if (flag == TTY_NORMAL) + put_tty_queue(*cp++, ldata); + //else + //n_tty_receive_char_flagged(tty, *cp++, flag); + } } // static void // n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, -// char *fp, int count) +// char *fp, int count) // { -// char flag = TTY_NORMAL; - -// while (count--) { -// if (fp) -// flag = *fp++; -// if (likely(flag == TTY_NORMAL)) -// n_tty_receive_char_closing(tty, *cp++); -// } +// char flag = TTY_NORMAL; + +// while (count--) { +// if (fp) +// flag = *fp++; +// if (likely(flag == TTY_NORMAL)) +// n_tty_receive_char_closing(tty, *cp++); +// } // } 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--; - } - } + 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--; + } + } } static 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); + 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--; - } - } + 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); - } + 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; - struct n_tty_data *ldata = tty->disc_data; - int room, n, rcvd = 0, overflow; - - 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; - //ldata->no_room = flow && !room; - } - 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; + int size; + struct n_tty_data *ldata = tty->disc_data; + int room, n, rcvd = 0, overflow; + + 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; + //ldata->no_room = flow && !room; + } + 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; } static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) { - int level; - char *b = (char *)buf; - struct tty_struct *tty = RT_NULL; + int level; + char *b = (char *)buf; + struct tty_struct *tty = RT_NULL; struct rt_lwp *lwp = RT_NULL; struct rt_wqueue *wq = RT_NULL; int wait_ret = 0; - //size_t tail; - int retval; + //size_t tail; + int retval; level = rt_hw_interrupt_disable(); tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); - struct n_tty_data *ldata = tty->disc_data; - - lwp = (struct rt_lwp *)(rt_thread_self()->lwp); - wq = wait_queue_get(lwp, tty); - - level = rt_hw_interrupt_disable(); - //tail = ldata->read_tail; - 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; - } - } - - if (ldata->icanon && !L_EXTPROC(tty)) - { - retval = canon_copy_from_read_buf(tty, b, count); - } - else - { - retval = copy_from_read_buf(tty, b, count); - } - - if (retval >= 1) - break; - - } - rt_hw_interrupt_enable(level); + struct n_tty_data *ldata = tty->disc_data; + + lwp = (struct rt_lwp *)(rt_thread_self()->lwp); + wq = wait_queue_get(lwp, tty); + + level = rt_hw_interrupt_disable(); + //tail = ldata->read_tail; + 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; + } + } + + if (ldata->icanon && !L_EXTPROC(tty)) + { + retval = canon_copy_from_read_buf(tty, b, count); + } + else + { + retval = copy_from_read_buf(tty, b, count); + } + + if (retval >= 1) + break; + + } + rt_hw_interrupt_enable(level); return retval; } static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) { - int retval = 0; - char *b = (char *)buf; - int c; - struct tty_struct *tty = RT_NULL; + int retval = 0; + char *b = (char *)buf; + int c; + struct tty_struct *tty = RT_NULL; tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); - 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) - { - //retval += num; - break; - } - - c = *b; - if (process_output(c, tty) < 0) - break; - b++; count--; - - } - retval -= count; - } - else - { - int level; - while (count > 0) - { - level = rt_hw_interrupt_disable(); - c = rt_device_write((rt_device_t)tty, -1, b, count); - rt_hw_interrupt_enable(level); - if (c < 0) - { - retval = c; - goto break_out; - } - b += c; - count -= c; - } - retval -= count; - } - - if (!count) - { - break; - } - if (fd->flags & O_NONBLOCK) - { - break; - } - } + 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) + { + //retval += num; + break; + } + + c = *b; + if (process_output(c, tty) < 0) + break; + b++; count--; + + } + retval -= count; + } + else + { + int level; + while (count > 0) + { + level = rt_hw_interrupt_disable(); + c = rt_device_write((rt_device_t)tty, -1, b, count); + rt_hw_interrupt_enable(level); + 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; } @@ -1738,23 +1738,23 @@ static int n_tty_poll(struct dfs_fd *fd, struct rt_pollreq *req) } static struct tty_ldisc_ops n_tty_ops = { - "n_tty", - 0, - n_tty_open, - n_tty_close, + "n_tty", + 0, + n_tty_open, + n_tty_close, n_tty_ioctl, - n_tty_read, - n_tty_write, + 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, + n_tty_poll, + n_tty_set_termios, + n_tty_receive_buf, + 0, }; void n_tty_init(void) { - tty_register_ldisc(N_TTY, &n_tty_ops); + tty_register_ldisc(N_TTY, &n_tty_ops); } diff --git a/components/tty/pty.c b/components/tty/pty.c index 00d064f01d..8ffdee2e99 100644 --- a/components/tty/pty.c +++ b/components/tty/pty.c @@ -26,21 +26,21 @@ static struct tty_struct *find_freepts(void) /* Set the lock flag on a pty */ static int pty_set_lock(struct tty_struct *tty, int *arg) { - int val = *arg; + int val = *arg; - if (val) - //set_bit(TTY_PTY_LOCK, &tty->flags); + if (val) + //set_bit(TTY_PTY_LOCK, &tty->flags); tty->pts_lock = val; - else - //clear_bit(TTY_PTY_LOCK, &tty->flags); + else + //clear_bit(TTY_PTY_LOCK, &tty->flags); tty->pts_lock = val; - return 0; + return 0; } static int pty_get_lock(struct tty_struct *tty, int *arg) { - // int locked = test_bit(TTY_PTY_LOCK, &tty->flags); - // return put_user(locked, arg); + // int locked = test_bit(TTY_PTY_LOCK, &tty->flags); + // return put_user(locked, arg); *arg = tty->pts_lock; return 0; } @@ -124,28 +124,28 @@ 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) + 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 TIOCPKT: /* Set PT packet mode */ - //return pty_set_pktmode(tty, (int __user *)arg); - case TIOCGPKT: /* Get PT packet mode */ - //return pty_get_pktmode(tty, (int __user *)arg); - case TIOCGPTN: /* Get PT Number */ + 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 TIOCPKT: /* Set PT packet mode */ + //return pty_set_pktmode(tty, (int __user *)arg); + case TIOCGPKT: /* Get PT packet mode */ + //return pty_get_pktmode(tty, (int __user *)arg); + case TIOCGPTN: /* Get PT Number */ return pty_get_index(tty, (int *)args); - //case TIOCSIG: /* Send signal to other side of pty */ - //return pty_signal(tty, (int) arg); - } + //case TIOCSIG: /* Send signal to other side of pty */ + //return pty_signal(tty, (int) arg); + } - return -ENOIOCTLCMD; + return -ENOIOCTLCMD; } static int ptmx_open(struct dfs_fd *fd) { - int ret = 0; + int ret = 0; struct tty_struct *tty = RT_NULL; struct tty_struct *pts_drv = RT_NULL; struct tty_ldisc *ld = RT_NULL; @@ -172,7 +172,7 @@ static int ptmx_open(struct dfs_fd *fd) ret = ld->ops->open(fd); } - return ret; + return ret; } #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops pty_device_ops = @@ -233,7 +233,7 @@ static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, #endif pts_drv->type = TTY_DRIVER_TYPE_PTY; - pts_drv->subtype = PTY_TYPE_SLAVE; + pts_drv->subtype = PTY_TYPE_SLAVE; pts_drv->pgrp = -1; pts_drv->session = -1; @@ -246,15 +246,15 @@ static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, tty_ldisc_init(pts_drv); #if defined(RT_USING_POSIX_TERMIOS) 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 = tty_std_termios; + pts_drv->init_termios.c_cflag = B38400 | CS8 | CREAD; pts_drv->init_termios.c_lflag |= ICANON; - pts_drv->init_termios.__c_ispeed = 38400; - pts_drv->init_termios.__c_ospeed = 38400; + pts_drv->init_termios.__c_ispeed = 38400; + pts_drv->init_termios.__c_ospeed = 38400; #endif /* RT_USING_POSIX_TERMIOS */ pts_drv->other_struct = ptm_drv; - + pts_drv->init_flag = TTY_INIT_FLAG_REGED; _exit: rt_hw_interrupt_enable(level); @@ -311,15 +311,15 @@ static int ptmx_register(void) rt_wqueue_init(&ptm_drv->wait_queue); tty_ldisc_init(ptm_drv); - + #if defined(RT_USING_POSIX_TERMIOS) 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_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; #endif /* RT_USING_POSIX_TERMIOS */ ptm_drv->init_flag = TTY_INIT_FLAG_REGED; @@ -329,4 +329,4 @@ _exit: return ret; } -INIT_DEVICE_EXPORT(ptmx_register); \ No newline at end of file +INIT_DEVICE_EXPORT(ptmx_register); diff --git a/components/tty/tty_io.c b/components/tty/tty_io.c index 29ab9b1bdc..71e3141779 100644 --- a/components/tty/tty_io.c +++ b/components/tty/tty_io.c @@ -10,21 +10,21 @@ #endif #ifdef RT_USING_POSIX_TERMIOS -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 | ECHO | ECHOE | TOSTOP | NOFLSH, +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 | ECHO | ECHOE | TOSTOP | NOFLSH, RT_NULL,/* .c_line = N_TTY, */ - .c_cc = INIT_C_CC, + .c_cc = INIT_C_CC, .__c_ispeed = 38400, - .__c_ospeed = 38400 + .__c_ospeed = 38400 }; #endif /*RT_USING_POSIX_TERMIOS*/ static int tty_open(struct dfs_fd *fd) { - int ret = 0; + int ret = 0; int noctty; struct tty_struct *tty = RT_NULL; struct tty_ldisc *ld = RT_NULL; @@ -45,8 +45,8 @@ static int tty_open(struct dfs_fd *fd) if (!noctty && current->leader && - !current->tty && - tty->session == 0) + !current->tty && + tty->session == 0) { current->tty = tty; current->tty_old_pgrp = 0; @@ -55,7 +55,7 @@ static int tty_open(struct dfs_fd *fd) tty->foreground = current; } - return ret; + return ret; } static int tty_close(struct dfs_fd *fd) @@ -72,30 +72,30 @@ static int tty_close(struct dfs_fd *fd) ret = ld->ops->close(fd); } - return ret; + 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) + 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) { rt_kprintf("this tty have control process\n"); - } - current->tty = tty; - current->tty_old_pgrp = 0; - tty->session = current->session; - tty->pgrp = current->__pgrp; - return 0; + } + current->tty = tty; + current->tty_old_pgrp = 0; + tty->session = current->session; + tty->pgrp = current->__pgrp; + return 0; } static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) @@ -109,20 +109,20 @@ static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) 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; + real_tty = tty->other_struct; + else + real_tty = tty; switch (cmd) { case TIOCSCTTY: - return tiocsctty(real_tty, 1); + return tiocsctty(real_tty, 1); } ld = tty->ldisc; if (ld->ops->ioctl) { ret = ld->ops->ioctl(fd, cmd, args); } - return ret; + return ret; } static int tty_read(struct dfs_fd *fd, void *buf, size_t count) @@ -138,7 +138,7 @@ static int tty_read(struct dfs_fd *fd, void *buf, size_t count) { ret = ld->ops->read(fd, buf, count); } - return ret; + return ret; } static int tty_write(struct dfs_fd *fd, const void *buf, size_t count) @@ -154,7 +154,7 @@ static int tty_write(struct dfs_fd *fd, const void *buf, size_t count) { ret = ld->ops->write(fd, buf, count); } - return ret; + return ret; } static int tty_poll(struct dfs_fd *fd, struct rt_pollreq *req) @@ -170,7 +170,7 @@ static int tty_poll(struct dfs_fd *fd, struct rt_pollreq *req) { ret = ld->ops->poll(fd, req); } - return ret; + return ret; } static const struct dfs_file_ops tty_fops = @@ -200,7 +200,7 @@ static const struct dfs_file_ops console_fops = void console_init() { - n_tty_init(); + n_tty_init(); } void tty_set_fops(struct dfs_file_ops *fops) diff --git a/components/tty/tty_ioctl.c b/components/tty/tty_ioctl.c index e7ddea248b..32dfd855cc 100644 --- a/components/tty/tty_ioctl.c +++ b/components/tty/tty_ioctl.c @@ -9,171 +9,171 @@ /* * Internal flag options for termios setting behavior */ -#define TERMIOS_FLUSH 1 -#define TERMIOS_WAIT 2 -#define TERMIOS_TERMIO 4 -#define TERMIOS_OLD 8 +#define TERMIOS_FLUSH 1 +#define TERMIOS_WAIT 2 +#define TERMIOS_TERMIO 4 +#define TERMIOS_OLD 8 /** - * tty_set_termios - update termios values - * @tty: tty to update - * @new_termios: desired new value + * tty_set_termios - update termios values + * @tty: tty to update + * @new_termios: desired new value * - * Perform updates to the termios values set on this terminal. - * A master pty's termios should never be set. + * Perform updates to the termios values set on this terminal. + * A master pty's termios should never be set. * - * Locking: termios_rwsem + * Locking: termios_rwsem */ // int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) // { -// struct ktermios old_termios; -// struct tty_ldisc *ld; - -// // WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY && -// // tty->driver->subtype == PTY_TYPE_MASTER); -// /* -// * Perform the actual termios internal changes under lock. -// */ - - -// /* FIXME: we need to decide on some locking/ordering semantics -// for the set_termios notification eventually */ -// down_write(&tty->termios_rwsem); -// old_termios = tty->termios; -// tty->termios = *new_termios; -// unset_locked_termios(tty, &old_termios); - -// if (tty->ops->set_termios) -// tty->ops->set_termios(tty, &old_termios); -// else -// tty_termios_copy_hw(&tty->termios, &old_termios); - -// ld = tty_ldisc_ref(tty); -// if (ld != NULL) { -// if (ld->ops->set_termios) -// ld->ops->set_termios(tty, &old_termios); -// tty_ldisc_deref(ld); -// } -// up_write(&tty->termios_rwsem); -// return 0; +// struct ktermios old_termios; +// struct tty_ldisc *ld; + +// // WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY && +// // tty->driver->subtype == PTY_TYPE_MASTER); +// /* +// * Perform the actual termios internal changes under lock. +// */ + + +// /* FIXME: we need to decide on some locking/ordering semantics +// for the set_termios notification eventually */ +// down_write(&tty->termios_rwsem); +// old_termios = tty->termios; +// tty->termios = *new_termios; +// unset_locked_termios(tty, &old_termios); + +// if (tty->ops->set_termios) +// tty->ops->set_termios(tty, &old_termios); +// else +// tty_termios_copy_hw(&tty->termios, &old_termios); + +// ld = tty_ldisc_ref(tty); +// if (ld != NULL) { +// if (ld->ops->set_termios) +// ld->ops->set_termios(tty, &old_termios); +// tty_ldisc_deref(ld); +// } +// up_write(&tty->termios_rwsem); +// return 0; // } /** - * set_termios - set termios values for a tty - * @tty: terminal device - * @arg: user data - * @opt: option information + * 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. + * 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 + * 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 = &tty->init_termios; - struct tty_ldisc *ld; + struct termios *old_termios = &tty->init_termios; + struct tty_ldisc *ld; struct termios *new_termios = (struct termios *)arg; - // int retval = tty_check_change(tty); + // int retval = tty_check_change(tty); - // if (retval) - // return retval; + // if (retval) + // return retval; -// down_read(&tty->termios_rwsem); -// tmp_termios = tty->termios; -// up_read(&tty->termios_rwsem); +// down_read(&tty->termios_rwsem); +// tmp_termios = tty->termios; +// up_read(&tty->termios_rwsem); -// if (opt & TERMIOS_TERMIO) { -// if (user_termio_to_kernel_termios(&tmp_termios, -// (struct termio __user *)arg)) -// return -EFAULT; +// if (opt & TERMIOS_TERMIO) { +// if (user_termio_to_kernel_termios(&tmp_termios, +// (struct termio __user *)arg)) +// return -EFAULT; // #ifdef TCGETS2 -// } else if (opt & TERMIOS_OLD) { -// if (user_termios_to_kernel_termios_1(&tmp_termios, -// (struct termios __user *)arg)) -// return -EFAULT; -// } else { -// if (user_termios_to_kernel_termios(&tmp_termios, -// (struct termios2 __user *)arg)) -// return -EFAULT; -// } +// } else if (opt & TERMIOS_OLD) { +// if (user_termios_to_kernel_termios_1(&tmp_termios, +// (struct termios __user *)arg)) +// return -EFAULT; +// } else { +// if (user_termios_to_kernel_termios(&tmp_termios, +// (struct termios2 __user *)arg)) +// return -EFAULT; +// } // #else -// } else if (user_termios_to_kernel_termios(&tmp_termios, -// (struct termios __user *)arg)) -// return -EFAULT; +// } else if (user_termios_to_kernel_termios(&tmp_termios, +// (struct termios __user *)arg)) +// return -EFAULT; // #endif - /* If old style Bfoo values are used then load c_ispeed/c_ospeed - * with the real speed so its unconditionally usable */ - //tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); - //tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); + /* If old style Bfoo values are used then load c_ispeed/c_ospeed + * with the real speed so its unconditionally usable */ + //tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); + //tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); - // ld = tty_ldisc_ref(tty); + // ld = tty_ldisc_ref(tty); - // if (ld != NULL) { - // if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) - // ld->ops->flush_buffer(tty); - // tty_ldisc_deref(ld); - // } + // if (ld != NULL) { + // if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) + // ld->ops->flush_buffer(tty); + // tty_ldisc_deref(ld); + // } - // if (opt & TERMIOS_WAIT) { - // tty_wait_until_sent(tty, 0); - // if (signal_pending(current)) - // return -ERESTARTSYS; - // } + // if (opt & TERMIOS_WAIT) { + // tty_wait_until_sent(tty, 0); + // if (signal_pending(current)) + // return -ERESTARTSYS; + // } - //tty_set_termios(tty, &tmp_termios); + //tty_set_termios(tty, &tmp_termios); tty->init_termios = *new_termios; - ld = tty->ldisc; - if (ld != NULL) + ld = tty->ldisc; + if (ld != NULL) { - if (ld->ops->set_termios) - ld->ops->set_termios(tty, old_termios); - } - /* FIXME: Arguably if tmp_termios == tty->termios AND the - actual requested termios was not tmp_termios then we may - want to return an error as no user requested change has - succeeded */ - return 0; + if (ld->ops->set_termios) + ld->ops->set_termios(tty, old_termios); + } + /* FIXME: Arguably if tmp_termios == tty->termios AND the + actual requested termios was not tmp_termios then we may + want to return an error as no user requested change has + succeeded */ + 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; + struct tty_struct *real_tty; - if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) - real_tty = tty->other_struct; - else - real_tty = tty; + 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: { struct termios *tio = (struct termios *)p; - if (tio == RT_NULL) return -RT_EINVAL; - rt_memcpy(tio, &real_tty->init_termios, sizeof(real_tty->init_termios)); - return ret; + if (tio == RT_NULL) return -RT_EINVAL; + rt_memcpy(tio, &real_tty->init_termios, sizeof(real_tty->init_termios)); + return ret; } - case TCSETSF: + case TCSETSF: { return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); } - case TCSETSW: + case TCSETSW: { - return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); + return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); } - case TCSETS: + case TCSETS: { - return set_termios(real_tty, p, TERMIOS_OLD); + return set_termios(real_tty, p, TERMIOS_OLD); } default: break; } - return -ENOIOCTLCMD; -} \ No newline at end of file + return -ENOIOCTLCMD; +} diff --git a/components/tty/tty_ldisc.c b/components/tty/tty_ldisc.c index 4568f5d6d1..ce41c785a4 100644 --- a/components/tty/tty_ldisc.c +++ b/components/tty/tty_ldisc.c @@ -4,73 +4,73 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; static struct tty_ldisc_ops *get_ldops(int disc) { - struct tty_ldisc_ops *ldops; - int level; - level = rt_hw_interrupt_disable(); - ldops = tty_ldiscs[disc]; - if (ldops) + struct tty_ldisc_ops *ldops; + int level; + level = rt_hw_interrupt_disable(); + ldops = tty_ldiscs[disc]; + if (ldops) { ldops->refcount++; - } - rt_hw_interrupt_enable(level); - return ldops; + } + rt_hw_interrupt_enable(level); + return ldops; } static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld; - struct tty_ldisc_ops *ldops; + struct tty_ldisc *ld; + struct tty_ldisc_ops *ldops; - if (disc < N_TTY || disc >= NR_LDISCS) - return RT_NULL; + if (disc < N_TTY || disc >= NR_LDISCS) + return RT_NULL; - ldops = get_ldops(disc); - if (ldops == RT_NULL) + ldops = get_ldops(disc); + if (ldops == RT_NULL) { return RT_NULL; - } + } - ld = rt_malloc(sizeof(struct tty_ldisc)); - if (ld == RT_NULL) + ld = rt_malloc(sizeof(struct tty_ldisc)); + if (ld == RT_NULL) { - ldops->refcount--; - return RT_NULL; - } + ldops->refcount--; + return RT_NULL; + } - ld->ops = ldops; - ld->tty = tty; + ld->ops = ldops; + ld->tty = tty; - return ld; + return ld; } int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) { - int ret = 0; - int level; + int ret = 0; + int level; - if (disc < N_TTY || disc >= NR_LDISCS) - return -EINVAL; + if (disc < N_TTY || disc >= NR_LDISCS) + return -EINVAL; - level = rt_hw_interrupt_disable(); - tty_ldiscs[disc] = new_ldisc; - new_ldisc->num = disc; - new_ldisc->refcount = 0; - rt_hw_interrupt_enable(level); + level = rt_hw_interrupt_disable(); + tty_ldiscs[disc] = new_ldisc; + new_ldisc->num = disc; + new_ldisc->refcount = 0; + rt_hw_interrupt_enable(level); - return ret; + return ret; } /** - * tty_ldisc_init - ldisc setup for new tty - * @tty: tty being allocated + * 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. + * 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) { - struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); + struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); RT_ASSERT(ld != RT_NULL); - tty->ldisc = ld; -} \ No newline at end of file + tty->ldisc = ld; +} -- Gitee From 7f3b1a7a41ff73e11e3812011918fac903c2cb03 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Mon, 6 Dec 2021 16:13:28 +0800 Subject: [PATCH 03/13] format code --- components/libc/termios/posix_termios.c | 2 +- components/libc/termios/posix_termios.h | 12 ++++++------ components/lwp/lwp_setsid.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 7051ac54c2..a47a02b15e 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/components/libc/termios/posix_termios.h b/components/libc/termios/posix_termios.h index 1f57420444..45db6a6242 100644 --- a/components/libc/termios/posix_termios.h +++ b/components/libc/termios/posix_termios.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -186,11 +186,11 @@ struct termios { #define XTABS 0014000 -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 */ #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" diff --git a/components/lwp/lwp_setsid.c b/components/lwp/lwp_setsid.c index f0417fdee6..99ca5890bf 100644 --- a/components/lwp/lwp_setsid.c +++ b/components/lwp/lwp_setsid.c @@ -25,4 +25,4 @@ int setsid(void) err = current_lwp->session; return err; -} \ No newline at end of file +} -- Gitee From 67bca8b9300f4928dcc1c6463e599243990ee3d8 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 8 Dec 2021 16:59:17 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9Bbug?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0pty=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/lwp/lwp.c | 2 - components/lwp/lwp_console.c | 546 --------------------------- components/lwp/lwp_console.h | 49 --- components/lwp/lwp_pid.c | 7 +- components/lwp/lwp_setsid.c | 1 - components/lwp/lwp_syscall.c | 1 - components/lwp/unix98pty/lwp_ptmx.c | 463 ----------------------- components/lwp/unix98pty/lwp_pts.c | 557 ---------------------------- components/lwp/unix98pty/lwp_pty.h | 119 ------ components/tty/console.c | 25 +- components/tty/include/console.h | 11 + components/tty/include/tty.h | 25 +- components/tty/include/tty_ldisc.h | 14 +- components/tty/n_tty.c | 143 ++++--- components/tty/pty.c | 37 +- components/tty/{tty_io.c => tty.c} | 35 +- components/tty/tty_ioctl.c | 13 +- components/tty/tty_ldisc.c | 93 +++++ src/kservice.c | 2 - 19 files changed, 312 insertions(+), 1831 deletions(-) delete mode 100644 components/lwp/lwp_console.c delete mode 100644 components/lwp/lwp_console.h delete mode 100644 components/lwp/unix98pty/lwp_ptmx.c delete mode 100644 components/lwp/unix98pty/lwp_pts.c delete mode 100644 components/lwp/unix98pty/lwp_pty.h rename components/tty/{tty_io.c => tty.c} (86%) diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index ab84b621c7..46641acd19 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -16,7 +16,6 @@ #include #include -#include #ifndef RT_USING_DFS #error "lwp need file system(RT_USING_DFS)" @@ -46,7 +45,6 @@ extern char working_directory[]; #endif extern void lwp_user_entry(void *args, const void *text, void *ustack, void *k_stack); -extern int libc_stdio_get_console(void); int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *const envp[]); void lwp_setcwd(char *buf) diff --git a/components/lwp/lwp_console.c b/components/lwp/lwp_console.c deleted file mode 100644 index 5b91700a8d..0000000000 --- a/components/lwp/lwp_console.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-02-23 Jesven first version - */ - -#include -#include - -#include "lwp_console.h" - -#define DBG_TAG "CONSOLE" -#define DBG_LVL DBG_INFO -#include - -#define CHAR_CTRL_D 0x4 -#define CHAR_CTRL_C 0x3 - -enum -{ - CONSOLE_INIT_FLAG_NONE = 0, - CONSOLE_INIT_FLAG_REGED, - CONSOLE_INIT_FLAG_INITED, -}; - -static struct rt_console_device _console; - -rt_inline struct rt_wqueue *wait_queue_get(struct rt_lwp * lwp) -{ - if (lwp == RT_PROCESS_KERNEL) - { - return &_console.wait_queue; - } - return &lwp->wait_queue; -} - -rt_inline struct rt_wqueue *wait_queue_current_get(void) -{ - return wait_queue_get(_console.foreground); -} - -static void console_wakeup_check(struct rt_console_device *console) -{ - rt_size_t len = 0; - struct rt_wqueue *wq = NULL; - - len = rt_ringbuffer_data_len(&console->input_rb); - if (len) - { - wq = wait_queue_current_get(); - rt_wqueue_wakeup(wq, (void*)POLLIN); - } -} - -static void console_rx_notify(struct rt_device *dev) -{ - struct rt_console_device *console = NULL; - rt_size_t len = 0; - rt_uint8_t ch = 0; - - console = (struct rt_console_device *)dev; - RT_ASSERT(console != RT_NULL); - - while (1) - { - len = rt_device_read(console->iodev, -1, &ch, 1); - if (len == 0) - { - break; - } - if (ch == CHAR_CTRL_D) /* ctrl-d */ - { - console->foreground = RT_PROCESS_KERNEL; - } - else if (ch == CHAR_CTRL_C) /* ctrl-c */ - { - struct rt_lwp *lwp = console->foreground; - - if (lwp) - { - lwp_kill(lwp_to_pid(lwp), SIGINT); - } - } - else - { - rt_ringbuffer_put_force(&console->input_rb, &ch, 1); - } - } - console_wakeup_check(console); -} - -void rt_console_set_foreground(struct rt_lwp *lwp) -{ - rt_base_t level = 0; - - level = rt_hw_interrupt_disable(); - if (_console.init_flag != CONSOLE_INIT_FLAG_INITED) - { - goto exit; - } - _console.foreground = lwp; - console_wakeup_check(&_console); - -exit: - rt_hw_interrupt_enable(level); -} - -struct rt_lwp * rt_console_get_foreground(void) -{ - struct rt_lwp *lwp = RT_NULL; - rt_base_t level = 0; - - level = rt_hw_interrupt_disable(); - lwp = _console.foreground; - rt_hw_interrupt_enable(level); - - return lwp; -} - -static void iodev_close(struct rt_console_device *console) -{ - struct rt_device_notify rx_notify; - - rx_notify.notify = RT_NULL; - rx_notify.dev = RT_NULL; - - /* clear notify */ - rt_device_control(console->iodev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); - rt_device_close(console->iodev); -} - -static rt_err_t iodev_open(struct rt_console_device *console) -{ - rt_err_t ret = RT_EOK; - struct rt_device_notify rx_notify; - rt_uint16_t oflags = 0; - - rt_device_control(console->iodev, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags); - - ret = rt_device_open(console->iodev, 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->iodev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify); - return RT_EOK; -} - -struct rt_device *rt_console_get_iodev(void) -{ - rt_base_t level = 0; - struct rt_device *iodev = RT_NULL; - - level = rt_hw_interrupt_disable(); - iodev = _console.iodev; - rt_hw_interrupt_enable(level); - return iodev; -} - -struct rt_device *rt_console_set_iodev(struct rt_device *iodev) -{ - rt_base_t level = 0; - struct rt_device *io_before = RT_NULL; - struct rt_console_device *console = RT_NULL; - - RT_ASSERT(iodev != RT_NULL); - - console = &_console; - - level = rt_hw_interrupt_disable(); - - RT_ASSERT(console->init_flag >= CONSOLE_INIT_FLAG_REGED); - - io_before = console->iodev; - - if (iodev == io_before) - { - goto exit; - } - - if (console->init_flag >= CONSOLE_INIT_FLAG_INITED) - { - /* close old device */ - iodev_close(console); - } - - console->iodev = iodev; - - if (console->init_flag >= CONSOLE_INIT_FLAG_INITED) - { - rt_err_t ret; - /* open new device */ - ret = iodev_open(console); - RT_ASSERT(ret == RT_EOK); - } - -exit: - rt_hw_interrupt_enable(level); - return io_before; -} - -#ifdef RT_USING_POSIX - -/* fops for console */ -static int console_fops_open(struct dfs_fd *fd) -{ - int ret = 0; - struct rt_device *device = RT_NULL; - - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - - if (fd->fnode->ref_count == 1) - { - ret = rt_device_open(device, fd->flags); - } - return ret; -} - -static int console_fops_close(struct dfs_fd *fd) -{ - int ret = 0; - struct rt_device *device = RT_NULL; - - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - - if (fd->fnode->ref_count == 1) - { - ret = rt_device_close(device); - } - return ret; -} - -static int console_fops_read(struct dfs_fd *fd, void *buf, size_t count) -{ - rt_base_t level = 0; - int size = 0; - struct rt_console_device *console = RT_NULL; - struct rt_lwp *lwp = RT_NULL; - struct rt_wqueue *wq = RT_NULL; - int wait_ret = 0; - - console = (struct rt_console_device *)fd->fnode->data; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - - lwp = (struct rt_lwp *)(rt_thread_self()->lwp); - - wq = wait_queue_get(lwp); - - level = rt_hw_interrupt_disable(); - while (count) - { - size = rt_device_read((struct rt_device *)console, -1, buf, count); - if (size > 0) - { - break; - } - if (fd->flags & O_NONBLOCK) - { - break; - } - wait_ret = rt_wqueue_wait_interruptible(wq, 0, RT_WAITING_FOREVER); - if (wait_ret != 0) - { - break; - } - } - rt_hw_interrupt_enable(level); - if (size < 0) - { - size = 0; - } - return size; -} - -static int console_fops_write(struct dfs_fd *fd, const void *buf, size_t count) -{ - int size = 0; - struct rt_device *device = RT_NULL; - - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - size = rt_device_write(device, -1, buf, count); - return size; -} - -static int console_fops_ioctl(struct dfs_fd *fd, int cmd, void *args) -{ - int size = 0; - struct rt_device *device = RT_NULL; - - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - size = rt_device_control(device, cmd, args); - return size; -} -static int console_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) -{ - rt_base_t level = 0; - int mask = POLLOUT; - struct rt_device *device = RT_NULL; - struct rt_console_device *console = RT_NULL; - struct rt_wqueue *wq = RT_NULL; - struct rt_lwp *lwp = RT_NULL; - - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - - console = (struct rt_console_device *)device; - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - - lwp = (struct rt_lwp *)(rt_thread_self()->lwp); - wq = wait_queue_get(lwp); - rt_poll_add(wq, req); - - level = rt_hw_interrupt_disable(); - if (lwp == console->foreground) - { - rt_size_t len; - - len = rt_ringbuffer_data_len(&console->input_rb); - if (len) - { - mask |= POLLIN; - } - } - rt_hw_interrupt_enable(level); - - return mask; -} - -const static struct dfs_file_ops _console_fops = -{ - console_fops_open, - console_fops_close, - console_fops_ioctl, - console_fops_read, - console_fops_write, - RT_NULL, /* flush */ - RT_NULL, /* lseek */ - RT_NULL, /* getdents */ - console_fops_poll, -}; - -#endif - -/* 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 rt_console_device *console = RT_NULL; - - RT_ASSERT(dev != RT_NULL); - - console = (struct rt_console_device *)dev; - - level = rt_hw_interrupt_disable(); - - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_REGED); - - result = iodev_open(console); - if (result != RT_EOK) - { - goto exit; - } - - console->init_flag = CONSOLE_INIT_FLAG_INITED; -exit: - rt_hw_interrupt_enable(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 rt_console_device *console = RT_NULL; - - RT_ASSERT(dev != RT_NULL); - console = (struct rt_console_device *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - return result; -} - -static rt_err_t rt_console_close(struct rt_device *dev) -{ - rt_err_t result = RT_EOK; - struct rt_console_device *console = RT_NULL; - - console = (struct rt_console_device *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - return result; -} - -static rt_size_t rt_console_read(struct rt_device *dev, - rt_off_t pos, - void *buffer, - rt_size_t size) -{ - rt_base_t level = 0; - rt_size_t len = 0; - struct rt_lwp *lwp = RT_NULL; - struct rt_console_device *console = RT_NULL; - - console = (struct rt_console_device *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - - level = rt_hw_interrupt_disable(); - if (size) - { - lwp = lwp_self(); - if (lwp == console->foreground) - { - len = rt_ringbuffer_data_len(&console->input_rb); - if (len > size) - { - len = size; - } - if (len) - { - len = rt_ringbuffer_get(&console->input_rb, buffer, len); - } - } - } - rt_hw_interrupt_enable(level); - - return len; -} - -static rt_size_t rt_console_write(struct rt_device *dev, - rt_off_t pos, - const void *buffer, - rt_size_t size) -{ - rt_base_t level = 0; - rt_size_t len = 0; - struct rt_console_device *console = RT_NULL; - - console = (struct rt_console_device *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - - level = rt_hw_interrupt_disable(); - len = rt_device_write((struct rt_device *)console->iodev, -1, buffer, size); - rt_hw_interrupt_enable(level); - - return len; -} - -static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args) -{ - rt_base_t level = 0; - rt_size_t len = 0; - struct rt_console_device *console = RT_NULL; - - console = (struct rt_console_device *)dev; - RT_ASSERT(console != RT_NULL); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_INITED); - - level = rt_hw_interrupt_disable(); - len = rt_device_control((struct rt_device *)console->iodev, cmd, args); - rt_hw_interrupt_enable(level); - - 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 - */ -rt_err_t rt_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 rt_console_device *console = &_console; - - level = rt_hw_interrupt_disable(); - RT_ASSERT(console->init_flag == CONSOLE_INIT_FLAG_NONE); - RT_ASSERT(iodev != RT_NULL); - - 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) - { - goto exit; - } - -#ifdef RT_USING_POSIX - /* set fops */ - device->fops = &_console_fops; -#endif - - console->iodev = iodev; - console->foreground = RT_PROCESS_KERNEL; - rt_wqueue_init(&(console->wait_queue)); - - RT_ASSERT(LWP_CONSOLE_INPUT_BUFFER_SIZE > 0); - rt_ringbuffer_init(&console->input_rb, console->input_buf, LWP_CONSOLE_INPUT_BUFFER_SIZE); - - console->init_flag = CONSOLE_INIT_FLAG_REGED; -exit: - rt_hw_interrupt_enable(level); - return ret; -} diff --git a/components/lwp/lwp_console.h b/components/lwp/lwp_console.h deleted file mode 100644 index 5b17026507..0000000000 --- a/components/lwp/lwp_console.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-02-23 Jesven first version. - */ -#ifndef LWP_CONSOLE_H__ -#define LWP_CONSOLE_H__ - -#include -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define RT_PROCESS_KERNEL RT_NULL - -struct rt_console_device -{ - struct rt_device parent; - int init_flag; - struct rt_device *iodev; - struct rt_lwp *foreground; - struct rt_wqueue wait_queue; /* for kernel when current == 0 */ - struct rt_ringbuffer input_rb; - rt_uint8_t input_buf[LWP_CONSOLE_INPUT_BUFFER_SIZE]; -}; - -rt_err_t rt_console_register(const char *name, struct rt_device *iodev); - -struct rt_device *rt_console_set_iodev(struct rt_device *iodev); -struct rt_device *rt_console_get_iodev(void); - -void rt_console_set_foreground(struct rt_lwp *lwp); -struct rt_lwp* rt_console_get_foreground(void); - -#ifdef __cplusplus -} -#endif - -#endif /* LWP_CONSOLE_H__*/ diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index f353856e81..b89320384e 100644 --- a/components/lwp/lwp_pid.c +++ b/components/lwp/lwp_pid.c @@ -15,7 +15,6 @@ #include "lwp.h" #include "lwp_pid.h" -#include "lwp_console.h" #include "tty.h" #ifdef RT_USING_USERSPACE @@ -131,8 +130,6 @@ static void lwp_pid_set_lwp(pid_t pid, struct rt_lwp *lwp) rt_hw_interrupt_enable(level); } -int libc_stdio_get_console(void); - static void __exit_files(struct rt_lwp *lwp) { int fd = lwp->fdt.maxfd - 1; @@ -444,8 +441,8 @@ void lwp_free(struct rt_lwp* lwp) { if (lwp->tty->foreground == lwp) { - lwp->tty->foreground = self_lwp; - lwp->tty = RT_NULL; + lwp->tty->foreground = self_lwp; + lwp->tty = RT_NULL; } } diff --git a/components/lwp/lwp_setsid.c b/components/lwp/lwp_setsid.c index 99ca5890bf..d72363bde5 100644 --- a/components/lwp/lwp_setsid.c +++ b/components/lwp/lwp_setsid.c @@ -5,7 +5,6 @@ //#include "lwp_tid.h" #include "lwp_pid.h" - int setsid(void) { int err = -EPERM; diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 4d16cd27fa..18013d0c92 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -54,7 +54,6 @@ #include #endif /* RT_USING_SAL */ -#include #include #include "lwp_ipc_internal.h" diff --git a/components/lwp/unix98pty/lwp_ptmx.c b/components/lwp/unix98pty/lwp_ptmx.c deleted file mode 100644 index 2a857c204f..0000000000 --- a/components/lwp/unix98pty/lwp_ptmx.c +++ /dev/null @@ -1,463 +0,0 @@ -/* -* Copyright (c) 2006-2018, RT-Thread Development Team -* -* SPDX-License-Identifier: Apache-2.0 -*/ -#include "lwp_pty.h" - -static struct rt_ptmx_device ptmx, *_ptmx = &ptmx; - -rt_inline struct rt_wqueue *ptmx_get_wq(struct rt_lwp *lwp) -{ - if (lwp == RT_NULL) - { - return &_ptmx->wq; - } - return &lwp->wait_queue; -} - -/* 查找空闲 pts 设备 */ -static struct rt_pts_device *find_freepts(void) -{ - for(int i = 0; i < LWP_PTY_PTS_SIZE; i++) - { - if (_ptmx->pts[i].flags == PTY_INIT_FLAG_NONE) - { - _ptmx->pts[i].flags = PTY_INIT_FLAG_ALLOCED; - return &_ptmx->pts[i]; - } - } - return RT_NULL; -} - -/* 通过 fd(ptmx) 获取 pts 设备句柄 */ -static struct rt_pts_device *ptmxfd2pts(struct dfs_fd *fd) -{ - int ptmx_fd; - - ptmx_fd = fd_get_fd_index(fd); - for(int i = 0; i < LWP_PTY_PTS_SIZE; i++) - { - if (_ptmx->pts[i].flags != PTY_INIT_FLAG_NONE) - { - if (_ptmx->pts[i].ptmx_fd == ptmx_fd) - { - return &_ptmx->pts[i]; - } - } - } - return RT_NULL; -} - -static rt_size_t ptmx_read(struct rt_pts_device *pts, rt_off_t pos, void *buffer, rt_size_t size) -{ - rt_base_t level = 0; - rt_size_t len = 0; - - level = rt_hw_interrupt_disable(); - if (size) - { - len = rt_ringbuffer_data_len(&pts->srb); - if (len > size) - { - len = size; - } - if (len) - { - len = rt_ringbuffer_get(&pts->srb, buffer, len); - } - } - rt_hw_interrupt_enable(level); - - return len; -} - -static rt_size_t ptmx_write(struct rt_pts_device *pts, rt_off_t pos, const void *buffer, rt_size_t count) -{ - rt_base_t level = 0; - rt_size_t size = 0; - - if (*(char *)buffer == '\r') - { - *(char *)buffer = '\n'; - } - - level = rt_hw_interrupt_disable(); - size = lwp_pts_push_mrb(pts, (void *)buffer, count); - rt_hw_interrupt_enable(level); - - return size; -} - -static int ptmx_file_open(struct dfs_fd *fd) -{ - rt_base_t level = 0; - int ret = -1; - struct rt_ptmx_device *ptmx = LWP_PTY_GET_PTMX(fd); - struct rt_pts_device *pts = RT_NULL; - int ptmx_fd = -1; - struct rt_device *device = RT_NULL; - struct rt_lwp *lwp = RT_NULL; - struct rt_wqueue *wq = RT_NULL; - - level = rt_hw_interrupt_disable(); - - pts = find_freepts(); - if (pts == RT_NULL) - { - LOG_E("no pts device, maximum number is %d", LWP_PTY_PTS_SIZE); - ret = (-ENODEV); - goto _exit; - } - - /* 注册 pts 设备 */ - ptmx_fd = fd_get_fd_index(fd); - if (ptmx_fd < 0) - { - pts->flags = PTY_INIT_FLAG_NONE; /* free pts */ - } - ret = lwp_pts_register(pts, ptmx_fd, ptmx->pts_index); - if (ret != RT_EOK) - { - fd_release(ptmx_fd); - pts->flags = PTY_INIT_FLAG_NONE; /* free pts */ - LOG_E("register pts%d fail", ptmx->pts_index); - ret = (-EIO); - goto _exit; - } - - /* 打开设备 */ - device = (struct rt_device *)fd->fnode->data; - if (fd->fnode->ref_count == 1) - { - ret = rt_device_open(device, fd->flags); - RT_ASSERT(ret == 0); - } - - lwp = (struct rt_lwp *)(rt_thread_self()->lwp); - wq = ptmx_get_wq(lwp); - pts->swq = wq; /* 将当前等待队列设置到 pts 中,用于 ptmx 写数据后唤醒 lwp 读数据 */ - pts->ptmx_fd = ptmx_fd; - ptmx->pts_index++; - - ret = 0; - -_exit: - rt_hw_interrupt_enable(level); - return ret; -} - -static int ptmx_file_close(struct dfs_fd *fd) -{ - rt_base_t level = 0; - int ret = 0; - struct rt_device *device = RT_NULL; - struct rt_pts_device *pts = RT_NULL; - - level = rt_hw_interrupt_disable(); - if (fd->fnode->ref_count == 1) - { - pts = ptmxfd2pts(fd); - if (pts && pts->mwq) - { - pts->ptmx_fd = RT_NULL; - rt_wqueue_wakeup(pts->mwq, (void*)POLLIN); - } - device = (struct rt_device *)fd->fnode->data; - ret = rt_device_close(device); - } - rt_hw_interrupt_enable(level); - - return ret; -} - -static int ptmx_file_read(struct dfs_fd *fd, void *buf, size_t count) -{ - rt_base_t level = 0; - size_t size = 0; - struct rt_pts_device *pts = RT_NULL; - int wait_ret = 0; - - level = rt_hw_interrupt_disable(); - - pts = ptmxfd2pts(fd); - if (pts) - { - while (count) - { - size = ptmx_read(pts, -1, buf, count); - if (size > 0) - { - break; - } - - if (fd->flags & O_NONBLOCK) - { - break; - } - - /* 当直接读的时候,没有数据就挂起,等待 ptmx 写入数据后唤醒 */ - wait_ret = rt_wqueue_wait_interruptible(pts->swq, 0, RT_WAITING_FOREVER); - if (wait_ret != 0) - { - break; - } - } - - } - rt_hw_interrupt_enable(level); - - if (size < 0) - { - size = 0; - } - - return size; -} - -static int ptmx_file_write(struct dfs_fd *fd, const void *buf, size_t count) -{ - int size = 0; - struct rt_pts_device *pts = RT_NULL; - rt_base_t level = 0; - - level = rt_hw_interrupt_disable(); - - pts = ptmxfd2pts(fd); - if (pts) - { - size = ptmx_write(pts, -1, buf, count); - } - - rt_hw_interrupt_enable(level); - - return size; -} - -static int ptmx_file_ioctl(struct dfs_fd *fd, int cmd, void *args) -{ - rt_base_t level = 0; - - level = rt_hw_interrupt_disable(); - - switch (cmd) { - case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ - { - struct rt_pts_device *pts = ptmxfd2pts(fd); - if (pts) - { - pts->pts_lock = *(int *)args; - rt_hw_interrupt_enable(level); - return 0; - } - else - { - rt_hw_interrupt_enable(level); - return (-EIO); - } - } - case TIOCGPTLCK: /* Get PT Lock status */ - { - struct rt_pts_device *pts = ptmxfd2pts(fd); - if (pts) - { - *(int *)args = pts->pts_lock; - rt_hw_interrupt_enable(level); - return 0; - } - else - { - rt_hw_interrupt_enable(level); - return (-EIO); - } - } - case TIOCPKT: /* Set PT packet mode */ - // return pty_set_pktmode(tty, (int __user *)arg); - rt_hw_interrupt_enable(level); - return 0; - case TIOCGPKT: /* Get PT packet mode */ - // return pty_get_pktmode(tty, (int __user *)arg); - rt_hw_interrupt_enable(level); - return 0; - case TIOCGPTN: /* Get PT Number */ - { - struct rt_pts_device *pts = ptmxfd2pts(fd); - if (pts) - { - /* 获取 ptmx 对应的 pts 的编号 */ - *(int *)args = pts->pts_index; - rt_hw_interrupt_enable(level); - return 0; - } - else - { - rt_hw_interrupt_enable(level); - return (-EIO); - } - } - case TIOCSIG: /* Send signal to other side of pty */ - // return pty_signal(tty, (int) arg); - rt_hw_interrupt_enable(level); - return 0; - -#if defined(RT_USING_POSIX_TERMIOS) - case TCSETS: - { - // pts = ptmxfd2pts(fd); - // rt_memcpy(&pts->tio, args, sizeof(struct termios)); - rt_hw_interrupt_enable(level); - return (-EINVAL); - } - case TCGETS: - { - // pts = ptmxfd2pts(fd); - // rt_memcpy(args, &pts->tio, sizeof(struct termios)); - rt_hw_interrupt_enable(level); - return (-EINVAL); - } -#endif /* RT_USING_POSIX_TERMIOS */ - } - - rt_hw_interrupt_enable(level); - return (-EINVAL); -} - -static int ptmx_file_poll(struct dfs_fd *fd, struct rt_pollreq *req) -{ - rt_base_t level = 0; - int mask = POLLOUT; - rt_size_t len; - struct rt_pts_device *pts = RT_NULL; - - level = rt_hw_interrupt_disable(); - - pts = ptmxfd2pts(fd); - if (!pts) - { - mask |= POLLIN; - goto _exit; - } - - rt_poll_add(pts->swq, req); - - /* 判断是否有数据可以 read 设备 */ - len = rt_ringbuffer_data_len(&pts->srb); - if (len) - { - mask |= POLLIN; - } - -_exit: - rt_hw_interrupt_enable(level); - - return mask; -} - -static rt_err_t ptmx_device_init(struct rt_device *dev) -{ - return RT_EOK; -} - -static rt_err_t ptmx_device_open(struct rt_device *dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t ptmx_device_close(struct rt_device *dev) -{ - return RT_EOK; -} - -static rt_size_t ptmx_device_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - return size; -} - -static rt_size_t ptmx_device_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) -{ - return size; -} - -static rt_err_t ptmx_device_control(rt_device_t dev, int cmd, void *args) -{ - return RT_EOK; -} - -#ifdef RT_USING_POSIX -const static struct dfs_file_ops ptmx_file_ops = -{ - ptmx_file_open, - ptmx_file_close, - ptmx_file_ioctl, - ptmx_file_read, - ptmx_file_write, - RT_NULL, /* flush */ - RT_NULL, /* lseek */ - RT_NULL, /* getdents */ - ptmx_file_poll, -}; -#endif /* RT_USING_POSIX */ - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops ptmx_device_ops = -{ - ptmx_device_init, - ptmx_device_open, - ptmx_device_close, - ptmx_device_read, - ptmx_device_write, - ptmx_device_control, -}; -#endif /* RT_USING_DEVICE_OPS */ - -static int lwp_ptmx_register(void) -{ - rt_err_t ret = RT_EOK; - rt_base_t level = 0; - struct rt_device *device = RT_NULL; - - level = rt_hw_interrupt_disable(); - - if (_ptmx->flags != PTY_INIT_FLAG_NONE) - { - ret = (-RT_EBUSY); - goto _exit; - } - - device = &_ptmx->parent; - device->type = RT_Device_Class_Char; -#ifdef RT_USING_DEVICE_OPS - device->ops = &ptmx_device_ops; -#else - device->init = ptmx_device_init; - device->open = ptmx_device_open; - device->close = ptmx_device_close; - device->read = ptmx_device_read; - device->write = ptmx_device_write; - device->control = ptmx_device_control; -#endif /* RT_USING_DEVICE_OPS */ - - ret = rt_device_register(device, "ptmx", RT_DEVICE_FLAG_RDWR); - if (ret != RT_EOK) - { - ret = -RT_EIO; - goto _exit; - } - -#ifdef RT_USING_POSIX - /* set fops */ - device->fops = &ptmx_file_ops; -#endif - - rt_wqueue_init(&_ptmx->wq); - rt_mutex_init(&_ptmx->mutex, "ptmx", RT_IPC_FLAG_FIFO); - rt_memset(_ptmx->pts, 0x00, sizeof(struct rt_pts_device)*LWP_PTY_PTS_SIZE); - _ptmx->pts_index = 0; - _ptmx->flags = PTY_INIT_FLAG_REGED; - -_exit: - rt_hw_interrupt_enable(level); - - return ret; -} -INIT_DEVICE_EXPORT(lwp_ptmx_register); diff --git a/components/lwp/unix98pty/lwp_pts.c b/components/lwp/unix98pty/lwp_pts.c deleted file mode 100644 index fc16d761c4..0000000000 --- a/components/lwp/unix98pty/lwp_pts.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "lwp_pty.h" - -rt_inline struct rt_wqueue *pts_get_wq(struct rt_pts_device *pts, struct rt_lwp *lwp) -{ - if (lwp == RT_NULL) - { - return &pts->wq; - } - return &lwp->wait_queue; -} - -static int pts_file_open(struct dfs_fd *fd) -{ - int ret = 0; - struct rt_device *device = RT_NULL; - rt_base_t level = 0; - struct rt_lwp *lwp = RT_NULL; - struct rt_wqueue *wq = RT_NULL; - - level = rt_hw_interrupt_disable(); - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - - if (fd->fnode->ref_count == 1) - { - struct rt_pts_device *pts = LWP_PTY_GET_PTS(fd); - - lwp = (struct rt_lwp *)(rt_thread_self()->lwp); - wq = pts_get_wq(pts, lwp); - pts->mwq = wq; - - ret = rt_device_open(device, fd->flags); - } - rt_hw_interrupt_enable(level); - return ret; -} - -static int pts_file_close(struct dfs_fd *fd) -{ - int ret = 0; - struct rt_device *device = RT_NULL; - struct rt_pts_device *pts = LWP_PTY_GET_PTS(fd); - rt_base_t level = 0; - - level = rt_hw_interrupt_disable(); - - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - - if (fd->fnode->ref_count == 1) - { - ret = rt_device_close(device); - lwp_pts_unregister(pts); - } - - rt_hw_interrupt_enable(level); - - return ret; -} - -static int pts_file_read(struct dfs_fd *fd, void *buf, size_t count) -{ - rt_base_t level = 0; - size_t size = 0; - struct rt_pts_device *pts = LWP_PTY_GET_PTS(fd); - int wait_ret = 0; - - level = rt_hw_interrupt_disable(); - - while (count) - { - size = rt_device_read(&pts->parent, -1, buf, count); - if (size > 0) - { - break; - } - - if (fd->flags & O_NONBLOCK) - { - break; - } - - if (!pts->ptmx_fd) /* ptmux closed */ - { - break; - } - - /* 当直接读的时候,没有数据就挂起,等待 ptmx 写入数据后唤醒 */ - wait_ret = rt_wqueue_wait_interruptible(pts->mwq, 0, RT_WAITING_FOREVER); - if (wait_ret != 0) - { - break; - } - } - - rt_hw_interrupt_enable(level); - - if (size < 0) - { - size = 0; - } - - return size; -} - -static int pts_file_write(struct dfs_fd *fd, const void *buf, size_t count) -{ - int size = 0; - rt_base_t level = 0; - - level = rt_hw_interrupt_disable(); - - struct rt_pts_device *pts = LWP_PTY_GET_PTS(fd); - RT_ASSERT(pts != RT_NULL); - size = rt_device_write((struct rt_device *)pts, -1, buf, count); - - rt_hw_interrupt_enable(level); - - return size; -} - -static int pts_file_ioctl(struct dfs_fd *fd, int cmd, void *args) -{ - rt_base_t level = 0; - struct rt_pts_device *pts = LWP_PTY_GET_PTS(fd); - - level = rt_hw_interrupt_disable(); - - switch (cmd) { - case TIOCSWINSZ: - rt_memcpy(&pts->winsize, args, sizeof(struct winsize)); - LOG_D("set /dev/pts/%d winsize: %d %d %d %d", - pts->pts_index, - pts->winsize.ws_row, pts->winsize.ws_col, - pts->winsize.ws_xpixel, pts->winsize.ws_ypixel); - rt_hw_interrupt_enable(level); - return 0; - case TIOCGWINSZ: - rt_memcpy(args, &pts->winsize, sizeof(struct winsize)); - rt_hw_interrupt_enable(level); - return 0; - - case TIOCSCTTY: - LOG_D("TODO PTS TIOCSCTTY CMD"); - rt_hw_interrupt_enable(level); - return 0; - -#if defined(RT_USING_POSIX_TERMIOS) - case TCSETS: - rt_memcpy(&pts->tio, args, sizeof(struct termios)); - rt_hw_interrupt_enable(level); - return 0; - case TCGETS: - rt_memcpy(args, &pts->tio, sizeof(struct termios)); - rt_hw_interrupt_enable(level); - return 0; -#endif /* RT_USING_POSIX_TERMIOS */ - } - - rt_hw_interrupt_enable(level); - return -EINVAL; -} - -static int pts_file_poll(struct dfs_fd *fd, struct rt_pollreq *req) -{ - rt_base_t level = 0; - int mask = POLLOUT; - rt_size_t len; - struct rt_pts_device *pts = LWP_PTY_GET_PTS(fd); - - level = rt_hw_interrupt_disable(); - - rt_poll_add(pts->mwq, req); - - /* 判断是否有数据可以 read 设备 */ - len = rt_ringbuffer_data_len(&pts->mrb); - if (len) - { - mask |= POLLIN; - } - - rt_hw_interrupt_enable(level); - - return mask; -} - -static rt_err_t pts_device_init(struct rt_device *dev) -{ - return RT_EOK; -} - -static rt_err_t pts_device_open(struct rt_device *dev, rt_uint16_t oflag) -{ - // TODO: oflag = O_NOCTTY - return RT_EOK; -} - -static rt_err_t pts_device_close(struct rt_device *dev) -{ - return RT_EOK; -} - -static rt_size_t pts_device_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - rt_base_t level = 0; - rt_size_t len = 0; - struct rt_pts_device *pts = (struct rt_pts_device *)dev; - - level = rt_hw_interrupt_disable(); - if (size) - { - len = rt_ringbuffer_data_len(&pts->mrb); - if (len > size) - { - len = size; - } - if (len) - { - len = rt_ringbuffer_get(&pts->mrb, buffer, len); - } - } - rt_hw_interrupt_enable(level); - - return len; -} - -static rt_size_t pts_device_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t count) -{ - rt_base_t level = 0; - rt_size_t size = 0; - struct rt_pts_device *pts = RT_NULL; - - level = rt_hw_interrupt_disable(); - pts = (struct rt_pts_device *)dev; - size = lwp_pts_push_srb(pts, (void *)buffer, count); - rt_hw_interrupt_enable(level); - - return size; -} - -static rt_err_t pts_device_control(rt_device_t dev, int cmd, void *args) -{ - return RT_EOK; -} - -#ifdef RT_USING_POSIX -const static struct dfs_file_ops pts_file_ops = -{ - pts_file_open, - pts_file_close, - pts_file_ioctl, - pts_file_read, - pts_file_write, - RT_NULL, /* flush */ - RT_NULL, /* lseek */ - RT_NULL, /* getdents */ - pts_file_poll, -}; -#endif /* RT_USING_POSIX */ - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops pts_device_ops = -{ - pts_device_init, - pts_device_open, - pts_device_close, - pts_device_read, - pts_device_write, - pts_device_control, -}; -#endif /* RT_USING_DEVICE_OPS */ - -int lwp_pts_isbusy(struct rt_pts_device *pts) -{ - RT_ASSERT(pts != RT_NULL); - return (pts->parent.ref_count > 0) ? 1 : 0; -} - -static rt_size_t dispose_char(struct rt_pts_device *pts, char ch) -{ - rt_uint8_t is_lfcr = 0; - - if (ch < 0) - { - return 0; - } - - /* 判断输入是否超过了缓存, 截断超出部分 */ - if (pts->line_position >= LWP_PTY_INPUT_BFSZ && ch != '\r' && ch != '\n') - { - return 0; - } - - /* handle control key: - * up key : 0x1b 0x5b 0x41 - * down key: 0x1b 0x5b 0x42 - * right key:0x1b 0x5b 0x43 - * left key: 0x1b 0x5b 0x44 - */ - if (ch == 0x1b) - { - pts->stat = LWP_PTS_INPUT_WAIT_SPEC_KEY; - return 0; - } - else if (pts->stat == LWP_PTS_INPUT_WAIT_SPEC_KEY) - { - if (ch == 0x5b) - { - pts->stat = LWP_PTS_INPUT_WAIT_FUNC_KEY; - return 0; - } - - pts->stat = LWP_PTS_INPUT_WAIT_NORMAL; - } - else if (pts->stat == LWP_PTS_INPUT_WAIT_FUNC_KEY) - { - pts->stat = LWP_PTS_INPUT_WAIT_NORMAL; - - if (ch == 0x41) /* up key */ - { - LOG_D("find input UP key"); - char buff[] = "^[[A"; - rt_ringbuffer_put_force(&pts->srb, (void *)buff, rt_strlen(buff)); /* 回显 */ - return 0; - } - else if (ch == 0x42) /* down key */ - { - LOG_D("find input DOWN key"); - char buff[] = "^[[B"; - rt_ringbuffer_put_force(&pts->srb, (void *)buff, rt_strlen(buff)); /* 回显 */ - return 0; - } - else if (ch == 0x44) /* left key */ - { - LOG_D("find input RIGHT key"); - char buff[] = "^[[C"; - rt_ringbuffer_put_force(&pts->srb, (void *)buff, rt_strlen(buff)); /* 回显 */ - return 0; - } - else if (ch == 0x43) /* right key */ - { - LOG_D("find input LEFT key"); - char buff[] = "^[[D"; - rt_ringbuffer_put_force(&pts->srb, (void *)buff, rt_strlen(buff)); /* 回显 */ - return 0; - } - } - - /* received null or error */ - if (ch == '\0' || ch == 0xFF) return 0; - else if (ch == '\t') - { - /* 补全不回显, 但是由会传递给 sh 处理 */ - pts->line[pts->line_position] = ch; - pts->line_position++; - return 0; - } - else if (ch == 0x7f || ch == 0x08) /* handle backspace key */ - { - LOG_D("find input backspace key"); - - char buff[] = "\b \b"; - rt_ringbuffer_put_force(&pts->srb, (void *)buff, rt_strlen(buff)); /* 回显 */ - pts->line_position--; - return 0; - } - - /* handle end of line, break */ - else if (ch == '\r' || ch == '\n') - { - is_lfcr = 1; - } - - rt_ringbuffer_put_force(&pts->srb, (void *)&ch, 1); /* 回显 */ - - /* 将没有回车的一行输入缓存到 line 中, 当发现回车换行后再统一输出到 ptmx 处理 */ - // LOG_D("%d", ch); - pts->line[pts->line_position] = ch; - pts->line_position++; - - return is_lfcr; -} - -rt_size_t lwp_pts_push_mrb(struct rt_pts_device *pts, void *buffer, rt_size_t size) -{ - rt_size_t len = 0; - rt_uint8_t is_lfcr = 0; - RT_ASSERT(pts != RT_NULL); - - if (pts->echo) - { - /* 按照字符处理 */ - for(int index = 0; index < size; index++) - { - char *ptr = (char *)buffer; - is_lfcr = dispose_char(pts, *(ptr + index)); - } - - /* 判断是否发现回车换行了 */ - if (is_lfcr) - { - // LOG_D("pts->line_position = %d", pts->line_position); - rt_ringbuffer_put_force(&pts->mrb, (void *)pts->line, pts->line_position); - pts->line_position = 0; - rt_memset(pts->line, 0x00, LWP_PTY_INPUT_BFSZ+1); - } - } - else /* 不处理直接传递给 sh 处理回显和字符 */ - { - rt_ringbuffer_put_force(&pts->mrb, buffer, size); - } - - len = rt_ringbuffer_data_len(&pts->mrb); - if (len && pts->mwq) - { - // 先读阻塞,用于唤醒阻塞的 lwp 进程 - rt_wqueue_wakeup(pts->mwq, (void*)POLLIN); - } - - return len; -} - -rt_size_t lwp_pts_push_srb(struct rt_pts_device *pts, void *buffer, rt_size_t size) -{ - rt_size_t len = 0; - RT_ASSERT(pts != RT_NULL); - rt_ringbuffer_put_force(&pts->srb, buffer, size); - len = rt_ringbuffer_data_len(&pts->srb); - - if (len && pts->swq) - { - // 先读阻塞,用于唤醒阻塞的 lwp 进程 - rt_wqueue_wakeup(pts->swq, (void*)POLLIN); - } - return len; -} - -int lwp_pts_unregister(struct rt_pts_device *pts) -{ - rt_err_t ret = RT_EOK; - rt_base_t level = 0; - struct rt_wqueue *wq = RT_NULL; - - level = rt_hw_interrupt_disable(); - if (pts->parent.ref_count > 0) - { - ret = (-RT_EBUSY); - goto _exit; - } - - wq = pts->swq; - rt_mutex_detach(&pts->mutex); - rt_memset(&pts->winsize, 0x00, sizeof(struct winsize)); - pts->pts_lock = 0; - pts->ptmx_fd = 0; - pts->pts_index = 0; - pts->flags = PTY_INIT_FLAG_NONE; - if (wq) - { - rt_wqueue_wakeup(wq, (void*)POLLIN); - } - rt_hw_interrupt_enable(level); - ret = rt_device_unregister(&pts->parent); - -_exit: - rt_hw_interrupt_enable(level); - - return ret; -} - -int lwp_pts_register(struct rt_pts_device *pts, int ptmx_fd, int pts_index) -{ - rt_err_t ret = RT_EOK; - rt_base_t level = 0; - struct rt_device *device = RT_NULL; - char name[20]; - - level = rt_hw_interrupt_disable(); - - if (pts->flags != PTY_INIT_FLAG_ALLOCED) - { - LOG_E("pts%d has been registered", pts_index); - ret = (-RT_EBUSY); - goto _exit; - } - - device = &pts->parent; - device->type = RT_Device_Class_Char; -#ifdef RT_USING_DEVICE_OPS - device->ops = &pts_device_ops; -#else - device->init = pts_device_init; - device->open = pts_device_open; - device->close = pts_device_close; - device->read = pts_device_read; - device->write = pts_device_write; - device->control = pts_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", pts_index); - ret = -RT_EIO; - goto _exit; - } - -#ifdef RT_USING_POSIX - /* set fops */ - device->fops = &pts_file_ops; -#endif - - rt_wqueue_init(&pts->wq); - rt_ringbuffer_init(&pts->mrb, pts->mbuf, LWP_PTY_INPUT_BFSZ); - rt_ringbuffer_init(&pts->srb, pts->sbuf, LWP_PTY_INPUT_BFSZ); - - pts->echo = 1; - pts->stat = LWP_PTS_INPUT_WAIT_NORMAL; - pts->line_position = 0; - rt_memset(pts->line, 0x00, sizeof(pts->line)); - - rt_mutex_init(&pts->mutex, name, RT_IPC_FLAG_FIFO); - pts->mwq = RT_NULL; - rt_memset(&pts->winsize, 0x00, sizeof(struct winsize)); - pts->pts_lock = 1; - pts->ptmx_fd = ptmx_fd; - pts->pts_index = pts_index; - pts->flags = PTY_INIT_FLAG_REGED; - -_exit: - rt_hw_interrupt_enable(level); - - return ret; -} - -#include -#include -int pts_dump(int argc, char *argv[]) -{ - struct rt_pts_device *pts = RT_NULL; - int mrblen = 0, srblen = 0; - rt_device_t dev = rt_device_find(argv[1]); - - pts = (struct rt_pts_device *)dev; - mrblen = rt_ringbuffer_data_len(&pts->mrb); - srblen = rt_ringbuffer_data_len(&pts->srb); - - LOG_I("dev %s mrblen = %d srblen = %d", argv[1], mrblen, srblen); - return 0; -} -MSH_CMD_EXPORT(pts_dump, dump /dev/pts/%d device ringbuffer info.); diff --git a/components/lwp/unix98pty/lwp_pty.h b/components/lwp/unix98pty/lwp_pty.h deleted file mode 100644 index 7a78259c47..0000000000 --- a/components/lwp/unix98pty/lwp_pty.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __LWP_PTY_H__ -#define __LWP_PTY_H__ - -#include -#include -#include -#include - -#if defined(RT_USING_POSIX_TERMIOS) -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define DBG_ENABLE -#if defined(LWP_PTY_USING_DEBUG) -#define DBG_LEVEL DBG_LOG -#else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR -#include - -#ifndef LWP_PTY_INPUT_BFSZ -#define LWP_PTY_INPUT_BFSZ 1024 -#endif /* LWP_PTY_INPUT_BFSZ */ - -#ifndef LWP_PTY_PTS_SIZE -#define LWP_PTY_PTS_SIZE 3 -#endif /* LWP_PTY_PTS_SIZE */ - -#ifndef LWP_PTY_HISTORY_LINE_SIZE -#define LWP_PTY_HISTORY_LINE_SIZE 5 -#endif /* LWP_PTY_HISTORY_LINE_SIZE */ - -#define LWP_PTY_GET_PTMX(fd) ((struct rt_ptmx_device *)(fd->fnode->data)) -#define LWP_PTY_GET_PTS(fd) ((struct rt_pts_device *)(fd->fnode->data)) - -enum lwp_pty_init_flag -{ - PTY_INIT_FLAG_NONE = 0, - PTY_INIT_FLAG_ALLOCED, - PTY_INIT_FLAG_REGED, -}; -typedef enum lwp_pty_init_flag lwp_pty_init_flag_t; - -enum lwp_pts_input_stat -{ - LWP_PTS_INPUT_WAIT_NORMAL = 0, - LWP_PTS_INPUT_WAIT_SPEC_KEY, - LWP_PTS_INPUT_WAIT_FUNC_KEY, -}; -typedef enum lwp_pts_input_stat lwp_pts_input_stat_t; - -struct rt_pts_device -{ - struct rt_device parent; - int flags; - int pts_lock; - int pts_index; /* index = /dev/pts/%d */ - struct rt_mutex mutex; - - // ptmx - struct rt_ptmx_device *ptmx; - int ptmx_fd; - - // win attribute - struct winsize winsize; - -#if defined(RT_USING_POSIX_TERMIOS) - struct termios tio; -#endif /* RT_USING_POSIX_TERMIOS */ - - /* console echo */ - lwp_pts_input_stat_t stat; - rt_uint8_t echo; - char line[LWP_PTY_INPUT_BFSZ+1]; - rt_uint16_t line_position; - - struct rt_wqueue *mwq; - struct rt_wqueue *swq; - struct rt_wqueue wq; /* for kernel */ - struct rt_ringbuffer mrb; /* ptmx w(master) ==> pts r(slave) */ - struct rt_ringbuffer srb; /* pts w(slave) ==> ptmx r(master) */ - rt_uint8_t mbuf[LWP_PTY_INPUT_BFSZ]; - rt_uint8_t sbuf[LWP_PTY_INPUT_BFSZ]; -}; - -struct rt_ptmx_device -{ - struct rt_device parent; - int flags; - struct rt_mutex mutex; - struct rt_wqueue wq; - - int pts_index; - struct rt_pts_device pts[LWP_PTY_PTS_SIZE]; -}; - -/* pty */ -extern int lwp_pts_isbusy(struct rt_pts_device *pts); -extern rt_size_t lwp_pts_push_mrb(struct rt_pts_device *pts, void *buffer, rt_size_t size); -extern rt_size_t lwp_pts_push_srb(struct rt_pts_device *pts, void *buffer, rt_size_t size); -extern int lwp_pts_unregister(struct rt_pts_device *pts); -extern int lwp_pts_register(struct rt_pts_device *pts, int ptmx_fd, int pts_index); - -#ifdef __cplusplus -} -#endif - -#endif /* __LWP_PTY_H__ */ diff --git a/components/tty/console.c b/components/tty/console.c index 31317da459..bde9b53b4f 100644 --- a/components/tty/console.c +++ b/components/tty/console.c @@ -1,7 +1,25 @@ +/* + * Copyright (c) 2006-2021, 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 "tty.h" +#include + +#define DBG_ENABLE +#if defined(RT_USING_TTY) +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#define DBG_COLOR +#include static struct tty_struct console_driver; @@ -62,7 +80,7 @@ static rt_err_t iodev_open(struct tty_struct *console) return RT_EOK; } -struct rt_device *console_get_iodev(void) +struct rt_device *rt_console_get_iodev(void) { rt_base_t level = 0; struct rt_device *iodev = RT_NULL; @@ -73,7 +91,7 @@ struct rt_device *console_get_iodev(void) return iodev; } -struct rt_device *console_set_iodev(struct rt_device *iodev) +struct rt_device *rt_console_set_iodev(struct rt_device *iodev) { rt_base_t level = 0; struct rt_device *io_before = RT_NULL; @@ -260,6 +278,7 @@ rt_err_t console_register(const char *name, struct rt_device *iodev) ret = rt_device_register(device, name, 0); if (ret != RT_EOK) { + LOG_E("console driver register fail\n"); goto exit; } diff --git a/components/tty/include/console.h b/components/tty/include/console.h index 9e21d008f9..1a78c9e750 100644 --- a/components/tty/include/console.h +++ b/components/tty/include/console.h @@ -1,8 +1,19 @@ +/* + * Copyright (c) 2006-2021, 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 *rt_console_get_iodev(void); +struct rt_device *rt_console_set_iodev(struct rt_device *iodev); rt_err_t console_register(const char *name, struct rt_device *iodev); #endif diff --git a/components/tty/include/tty.h b/components/tty/include/tty.h index 1a6289ea9b..3d4b4877e1 100644 --- a/components/tty/include/tty.h +++ b/components/tty/include/tty.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2006-2021, 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 @@ -142,11 +151,8 @@ struct tty_struct #define RT_TTY_BUF 1024 rt_list_t tty_drivers; - }; -extern rt_list_t tty_drivers; - enum { TTY_INIT_FLAG_NONE = 0, @@ -264,6 +270,16 @@ enum /* 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 tty_set_fops(struct dfs_file_ops *fops); void console_set_fops(struct dfs_file_ops *fops); void mutex_lock(rt_mutex_t mutex); @@ -347,7 +363,8 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) /*如果BITS_PER_LONG等于64,要先对低32位进行检查;否则(即BITS_PER_LONG等于32),直接对低16位进行检查*/ #if BITS_PER_LONG == 64 - if ((word & 0xffffffff) == 0) { //如果与0xffffffff相与得0,说明word的低32位全为0 + if ((word & 0xffffffff) == 0) + { //如果与0xffffffff相与得0,说明word的低32位全为0 num += 32; //索引加32 word >>= 32; //word右移32位,把低32位的0移走 } diff --git a/components/tty/include/tty_ldisc.h b/components/tty/include/tty_ldisc.h index bb3bf42b8b..8020ea2150 100644 --- a/components/tty/include/tty_ldisc.h +++ b/components/tty/include/tty_ldisc.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2006-2021, 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 @@ -16,7 +25,7 @@ struct tty_ldisc_ops int num; int (*open) (struct dfs_fd *fd); - int (*close) (struct dfs_fd *fd); + int (*close) (struct tty_struct *tty); int (*ioctl) (struct dfs_fd *fd, int cmd, void *args); int (*read) (struct dfs_fd *fd, void *buf, size_t count); int (*write) (struct dfs_fd *fd, const void *buf, size_t count); @@ -39,10 +48,9 @@ struct tty_ldisc #define TTY_LDISC_MAGIC 0x5403 -void console_ldata_init(struct tty_struct *tty); -int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count); int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); 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/tty/n_tty.c b/components/tty/n_tty.c index 3e4c1d2624..6009928c8e 100644 --- a/components/tty/n_tty.c +++ b/components/tty/n_tty.c @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021.12.07 linzhenxing first version + */ #include #include #include @@ -6,6 +15,15 @@ #include #endif +#define DBG_ENABLE +#if defined(RT_USING_TTY) +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#define DBG_COLOR +#include + /* number of characters left in xmit buffer before select has we have room */ #define WAKEUP_CHARS 256 @@ -32,16 +50,6 @@ #define ECHO_BLOCK 256 #define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32) -#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) { rt_err_t result = -RT_EBUSY; @@ -94,8 +102,8 @@ struct n_tty_data unsigned int canon_column; size_t echo_tail; - struct mutex *atomic_read_lock; - struct mutex *output_lock; + rt_mutex_t atomic_read_lock; + rt_mutex_t output_lock; }; static inline size_t read_cnt(struct n_tty_data *ldata) @@ -140,6 +148,30 @@ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) 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 @@ -228,7 +260,8 @@ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); - } else + } + else { add_echo_byte(c, ldata); } @@ -923,8 +956,13 @@ void console_ldata_init(struct tty_struct *tty) struct n_tty_data *ldata; 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; @@ -940,10 +978,16 @@ static int n_tty_open(struct dfs_fd *fd) struct tty_struct *tty = (struct tty_struct*)fd->fnode->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); - //ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO); + ldata->atomic_read_lock = rt_mutex_create("atomic_read_lock",RT_IPC_FLAG_FIFO); + ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO); tty->disc_data = ldata; + reset_buffer_flags(ldata); ldata->column = 0; ldata->canon_column = 0; ldata->lnext = 0; @@ -1003,7 +1047,6 @@ static int copy_from_read_buf(struct tty_struct *tty,char *b,size_t nr) const char *from = read_buf_addr(ldata, tail); rt_memcpy(b, from, n); is_eof = n == 1 && *from == EOF_CHAR(tty); - //ldata->read_tail = ldata->read_tail + n; ldata->read_tail += n; /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && @@ -1101,18 +1144,15 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) } -static int n_tty_close(struct dfs_fd *fd) +static int n_tty_close(struct tty_struct *tty) { int ret = 0; - struct rt_device *device = RT_NULL; + struct n_tty_data *ldata = RT_NULL; - device = (struct rt_device *)fd->fnode->data; - RT_ASSERT(device != RT_NULL); - - if (fd->fnode->ref_count == 1) - { - ret = rt_device_close(device); - } + RT_ASSERT(tty != RT_NULL); + ldata = tty->disc_data; + rt_free(ldata); + tty->disc_data = RT_NULL; return ret; } @@ -1168,32 +1208,30 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (I_IXON(tty)) { - if (c == START_CHAR(tty)) + if (c == START_CHAR(tty)) /*ctrl + p realize missing*/ { - //start_tty(tty); process_echoes(tty); return 0; } - if (c == STOP_CHAR(tty)) + if (c == STOP_CHAR(tty)) /*ctrl + s realize missing*/ { - //stop_tty(tty); return 0; } } if (L_ISIG(tty)) { - if (c == INTR_CHAR(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)) + 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)) + else if (c == SUSP_CHAR(tty)) /*ctrl + z realize missing*/ { //n_tty_receive_signal_char(tty, SIGTSTP, c); return 0; @@ -1316,8 +1354,7 @@ handle_newline: return 0; } -static inline void -n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) +static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1341,8 +1378,7 @@ 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) +static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) { struct n_tty_data *ldata = tty->disc_data; @@ -1362,8 +1398,7 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) } -static void -n_tty_receive_buf_real_raw(struct tty_struct *tty, char *cp, int count) +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, head; @@ -1381,16 +1416,13 @@ n_tty_receive_buf_real_raw(struct tty_struct *tty, char *cp, int count) ldata->read_head += n; } -static void -n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count) +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 (fp) - // flag = *fp++; if (flag == TTY_NORMAL) put_tty_queue(*cp++, ldata); //else @@ -1398,8 +1430,7 @@ n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count) } } -// static void -// n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, +// static void n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, // char *fp, int count) // { // char flag = TTY_NORMAL; @@ -1412,8 +1443,7 @@ n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count) // } // } -static void -n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int count) +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; @@ -1441,8 +1471,7 @@ n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int count) } } -static inline void -n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) +static inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1458,8 +1487,7 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) put_tty_queue(c, ldata); } -static void -n_tty_receive_buf_fast(struct tty_struct *tty, char *cp, int count) +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; @@ -1571,7 +1599,6 @@ static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) struct rt_lwp *lwp = RT_NULL; struct rt_wqueue *wq = RT_NULL; int wait_ret = 0; - //size_t tail; int retval; level = rt_hw_interrupt_disable(); @@ -1583,8 +1610,6 @@ static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) lwp = (struct rt_lwp *)(rt_thread_self()->lwp); wq = wait_queue_get(lwp, tty); - level = rt_hw_interrupt_disable(); - //tail = ldata->read_tail; while(count) { if ((!input_available_p(tty, 0))) @@ -1649,7 +1674,6 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) count -= num; if (count == 0) { - //retval += num; break; } @@ -1725,13 +1749,12 @@ static int n_tty_poll(struct dfs_fd *fd, struct rt_pollreq *req) wq = wait_queue_get(lwp, tty); rt_poll_add(wq, req); level = rt_hw_interrupt_disable(); - if (lwp == tty->foreground) + + if (input_available_p(tty, 1)) { - if (input_available_p(tty, 1)) - { - mask |= POLLIN; - } + mask |= POLLIN; } + rt_hw_interrupt_enable(level); return mask; diff --git a/components/tty/pty.c b/components/tty/pty.c index 8ffdee2e99..c02d8f06bb 100644 --- a/components/tty/pty.c +++ b/components/tty/pty.c @@ -1,15 +1,32 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021.12.07 linzhenxing first version + */ #include #include +#define DBG_ENABLE +#if defined(RT_USING_TTY) +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#define DBG_COLOR +#include + #define PTY_PTS_SIZE 1024 static struct tty_struct ptm_driver; static struct tty_struct pts_drivers[PTY_PTS_SIZE]; -//rt_list_t pts_drivers; static int pts_index = 0; static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, int pts_index); -/* 查找空闲 pts 设备 */ +/* check free pts device */ static struct tty_struct *find_freepts(void) { for(int i = 0; i < PTY_PTS_SIZE; i++) @@ -62,11 +79,8 @@ static rt_err_t pty_device_init(struct rt_device *dev) 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; @@ -81,6 +95,7 @@ static rt_err_t pty_device_open(struct rt_device *dev, rt_uint16_t oflag) static rt_err_t pty_device_close(struct rt_device *dev) { rt_err_t result = RT_EOK; + return result; } @@ -149,6 +164,8 @@ static int ptmx_open(struct dfs_fd *fd) struct tty_struct *tty = RT_NULL; struct tty_struct *pts_drv = RT_NULL; struct tty_ldisc *ld = RT_NULL; + struct rt_lwp *lwp = RT_NULL; + struct rt_wqueue *wq = RT_NULL; tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); @@ -156,15 +173,20 @@ static int ptmx_open(struct dfs_fd *fd) pts_drv = find_freepts(); if (pts_drv == RT_NULL) { + LOG_E("free pts driver find fail\n"); return -1; } ret = pts_register(tty, pts_drv, pts_index); if (ret < 0) { + LOG_E("pts register fail\n"); rt_free(pts_drv); return -1; } pts_index++; + lwp = (struct rt_lwp *)(rt_thread_self()->lwp); + wq = wait_queue_get(lwp, tty); + pts_drv->wait_queue = *wq; tty->other_struct = pts_drv; ld = tty->ldisc; if (ld->ops->open) @@ -199,7 +221,7 @@ static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, if (pts_drv->init_flag != TTY_INIT_FLAG_ALLOCED) { - //LOG_E("pts%d has been registered", pts_index); + LOG_E("pts%d has been registered\n", pts_index); ret = (-RT_EBUSY); goto _exit; } @@ -221,7 +243,7 @@ static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); if (ret != RT_EOK) { - //LOG_E("pts%d register failed", pts_index); + LOG_E("pts%d register failed\n", pts_index); ret = -RT_EIO; goto _exit; } @@ -291,6 +313,7 @@ static int ptmx_register(void) ret = rt_device_register(device, "ptmx", RT_DEVICE_FLAG_RDWR); if (ret != RT_EOK) { + LOG_E("ptmx register fail\n"); ret = -RT_EIO; goto _exit; } diff --git a/components/tty/tty_io.c b/components/tty/tty.c similarity index 86% rename from components/tty/tty_io.c rename to components/tty/tty.c index 71e3141779..862a545b57 100644 --- a/components/tty/tty_io.c +++ b/components/tty/tty.c @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021.12.07 linzhenxing first version + */ #include #include #include @@ -9,6 +18,15 @@ #include #endif +#define DBG_ENABLE +#if defined(RT_USING_TTY) +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#define DBG_COLOR +#include + #ifdef RT_USING_POSIX_TERMIOS struct termios tty_std_termios = { /* for the benefit of tty drivers */ .c_iflag = IMAXBEL | IUCLC | INLCR | ICRNL | IGNPAR, @@ -46,7 +64,7 @@ static int tty_open(struct dfs_fd *fd) if (!noctty && current->leader && !current->tty && - tty->session == 0) + tty->session == -1) { current->tty = tty; current->tty_old_pgrp = 0; @@ -62,15 +80,13 @@ static int tty_close(struct dfs_fd *fd) { int ret = 0; struct tty_struct *tty = RT_NULL; - struct tty_ldisc *ld = RT_NULL; tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); - ld = tty->ldisc; - if (ld->ops->close) + tty_ldisc_release(tty); + if (fd->fnode->ref_count == 1) { - - ret = ld->ops->close(fd); + ret = rt_device_close((rt_device_t)tty); } return ret; } @@ -88,13 +104,18 @@ static int tiocsctty(struct tty_struct *tty, int arg) return -EPERM; if (tty->session > 0) { - rt_kprintf("this tty have control process\n"); + 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; } diff --git a/components/tty/tty_ioctl.c b/components/tty/tty_ioctl.c index 32dfd855cc..aa1955a1d9 100644 --- a/components/tty/tty_ioctl.c +++ b/components/tty/tty_ioctl.c @@ -6,6 +6,15 @@ #include #endif +#define DBG_ENABLE +#if defined(RT_USING_TTY) +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#define DBG_COLOR +#include + /* * Internal flag options for termios setting behavior */ @@ -74,7 +83,7 @@ static int set_termios(struct tty_struct *tty, void *arg, int opt) { - struct termios *old_termios = &tty->init_termios; + struct termios old_termios = tty->init_termios; struct tty_ldisc *ld; struct termios *new_termios = (struct termios *)arg; // int retval = tty_check_change(tty); @@ -131,7 +140,7 @@ static int set_termios(struct tty_struct *tty, void *arg, int opt) if (ld != NULL) { if (ld->ops->set_termios) - ld->ops->set_termios(tty, old_termios); + ld->ops->set_termios(tty, &old_termios); } /* FIXME: Arguably if tmp_termios == tty->termios AND the actual requested termios was not tmp_termios then we may diff --git a/components/tty/tty_ldisc.c b/components/tty/tty_ldisc.c index ce41c785a4..15befb2d0e 100644 --- a/components/tty/tty_ldisc.c +++ b/components/tty/tty_ldisc.c @@ -1,4 +1,14 @@ #include +#include + +#define DBG_ENABLE +#if defined(RT_USING_TTY) +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#define DBG_COLOR +#include static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; @@ -16,6 +26,14 @@ static struct tty_ldisc_ops *get_ldops(int disc) return ldops; } +static void put_ldops(struct tty_ldisc_ops *ldops) +{ + int level; + + level = rt_hw_interrupt_disable(); + ldops->refcount--; + rt_hw_interrupt_enable(level); +} static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; @@ -27,6 +45,7 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) ldops = get_ldops(disc); if (ldops == RT_NULL) { + LOG_E("tty ldisc get error\n"); return RT_NULL; } @@ -43,6 +62,54 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) return ld; } +/** + * tty_ldisc_put - release the ldisc + * + * Complement of tty_ldisc_get(). + */ +static void tty_ldisc_put(struct tty_ldisc *ld) +{ + if (ld == RT_NULL) + return; + + 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->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 + */ +static void tty_ldisc_kill(struct tty_struct *tty) +{ + if (!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; +} + int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) { int ret = 0; @@ -60,6 +127,32 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) 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) +{ + int level; + 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. + */ + + level = rt_hw_interrupt_disable(); + tty_ldisc_kill(tty); + if (o_tty) + tty_ldisc_kill(o_tty); + rt_hw_interrupt_enable(level); + +} + /** * tty_ldisc_init - ldisc setup for new tty * @tty: tty being allocated diff --git a/src/kservice.c b/src/kservice.c index a077d20490..7a3dcebfd5 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -29,7 +29,6 @@ #ifdef RT_USING_LWP #include #include -#include #include #endif @@ -1144,7 +1143,6 @@ rt_device_t rt_console_set_device(const char *name) } else { - //rt_console_register("console", new_iodev); console_register("console", new_iodev); _console_device = rt_device_find("console"); rt_device_open(_console_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM); -- Gitee From 5154ee629535ecff56c249017bdd7822a3b845d5 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 8 Dec 2021 18:46:24 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E5=85=B3=E4=BA=8Epty=E4=B8=BB=E4=BB=8E?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E8=BF=98=E6=9C=89bug=EF=BC=8C=E8=BF=99?= =?UTF-8?q?=E9=87=8C=E8=BF=98=E8=A6=81=E8=80=83=E8=99=91=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/tty/tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/tty/tty.c b/components/tty/tty.c index 862a545b57..eea7c63a86 100644 --- a/components/tty/tty.c +++ b/components/tty/tty.c @@ -83,7 +83,7 @@ static int tty_close(struct dfs_fd *fd) tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); - tty_ldisc_release(tty); + //tty_ldisc_release(tty); if (fd->fnode->ref_count == 1) { ret = rt_device_close((rt_device_t)tty); -- Gitee From 5a6c7f189e01eb8c183069524a513c7de02d8b5b Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Thu, 9 Dec 2021 09:40:04 +0800 Subject: [PATCH 06/13] format code --- components/tty/include/tty.h | 72 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/components/tty/include/tty.h b/components/tty/include/tty.h index 3d4b4877e1..850c977dc4 100644 --- a/components/tty/include/tty.h +++ b/components/tty/include/tty.h @@ -357,42 +357,42 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) return retval; } - rt_inline unsigned long __ffs(unsigned long word) - { - int num = 0; - - /*如果BITS_PER_LONG等于64,要先对低32位进行检查;否则(即BITS_PER_LONG等于32),直接对低16位进行检查*/ - #if BITS_PER_LONG == 64 - if ((word & 0xffffffff) == 0) - { //如果与0xffffffff相与得0,说明word的低32位全为0 - num += 32; //索引加32 - word >>= 32; //word右移32位,把低32位的0移走 - } - #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; - } +rt_inline unsigned long __ffs(unsigned long word) +{ + int num = 0; + +/*如果BITS_PER_LONG等于64,要先对低32位进行检查;否则(即BITS_PER_LONG等于32),直接对低16位进行检查*/ +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) + { //如果与0xffffffff相与得0,说明word的低32位全为0 + num += 32; //索引加32 + word >>= 32; //word右移32位,把低32位的0移走 + } +#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) -- Gitee From f5554dd7bffd5dd26b1cff755c70fe0299204801 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Sat, 11 Dec 2021 10:07:45 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ktermios.c=E5=92=8Ckter?= =?UTF-8?q?mios.h=E5=9C=A8tty=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-vexpress-a9/.config | 3 +- bsp/qemu-vexpress-a9/rtconfig.h | 2 - components/drivers/serial/serial.c | 8 +-- components/finsh/shell.c | 4 +- components/libc/Kconfig | 4 -- components/libc/termios/SConscript | 13 ----- components/tty/console.c | 22 +++++--- .../include/ktermios.h} | 30 ++++++----- components/tty/include/tty.h | 5 +- components/tty/include/tty_ldisc.h | 6 +-- .../posix_termios.c => tty/ktermios.c} | 5 +- components/tty/n_tty.c | 34 ++++++------- components/tty/pty.c | 6 +-- components/tty/tty.c | 10 ++-- components/tty/tty_ioctl.c | 50 +------------------ components/tty/tty_ldisc.c | 2 +- 16 files changed, 68 insertions(+), 136 deletions(-) delete mode 100644 components/libc/termios/SConscript rename components/{libc/termios/posix_termios.h => tty/include/ktermios.h} (88%) rename components/{libc/termios/posix_termios.c => tty/ktermios.c} (94%) diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index 7007125092..fc4fc77cc4 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -107,7 +107,7 @@ CONFIG_FINSH_THREAD_NAME="tshell" CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=10 CONFIG_FINSH_USING_SYMTAB=y -CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_USING_DESCRIPTION is not set CONFIG_FINSH_ECHO_DISABLE_DEFAULT=y CONFIG_FINSH_THREAD_PRIORITY=20 CONFIG_FINSH_THREAD_STACK_SIZE=4096 @@ -226,7 +226,6 @@ CONFIG_RT_USING_MUSL=y # CONFIG_RT_USING_PTHREADS is not set CONFIG_RT_USING_POSIX=y CONFIG_RT_USING_POSIX_MMAP=y -CONFIG_RT_USING_POSIX_TERMIOS=y # CONFIG_RT_USING_POSIX_GETLINE is not set CONFIG_RT_USING_POSIX_AIO=y CONFIG_RT_POSIX_AIO_THREAD_STACK_SIZE=2048 diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index 5b105cdece..e57653c49e 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -79,7 +79,6 @@ #define FINSH_USING_HISTORY #define FINSH_HISTORY_LINES 10 #define FINSH_USING_SYMTAB -#define FINSH_USING_DESCRIPTION #define FINSH_ECHO_DISABLE_DEFAULT #define FINSH_THREAD_PRIORITY 20 #define FINSH_THREAD_STACK_SIZE 4096 @@ -154,7 +153,6 @@ #define RT_USING_MUSL #define RT_USING_POSIX #define RT_USING_POSIX_MMAP -#define RT_USING_POSIX_TERMIOS #define RT_USING_POSIX_AIO #define RT_POSIX_AIO_THREAD_STACK_SIZE 2048 #define RT_USING_POSIX_CLOCKTIME diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index f0050278ed..33102c1d72 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -38,9 +38,8 @@ #include #include -#ifdef RT_USING_POSIX_TERMIOS -#include -#endif +#include + /* it's possible the 'getc/putc' is defined by stdio.h in gcc/newlib. */ #ifdef getc @@ -894,7 +893,6 @@ static rt_size_t rt_serial_write(struct rt_device *dev, } } -#ifdef RT_USING_POSIX_TERMIOS struct speed_baudrate_item { speed_t speed; @@ -989,8 +987,6 @@ static void _tc_flush(struct rt_serial_device *serial, int queue) } -#endif - static rt_err_t rt_serial_control(struct rt_device *dev, int cmd, void *args) diff --git a/components/finsh/shell.c b/components/finsh/shell.c index dbf285ae86..0e5ae802e3 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -585,7 +585,7 @@ void finsh_thread_entry(void *parameter) shell->line_position - shell->line_curpos); shell->line[shell->line_position] = 0; - rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]); + //rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]); /* move the cursor to the origin position */ for (i = shell->line_curpos; i <= shell->line_position; i++) @@ -593,7 +593,7 @@ void finsh_thread_entry(void *parameter) } else { - rt_kprintf("\b \b"); + //rt_kprintf("\b \b"); shell->line[shell->line_position] = 0; } diff --git a/components/libc/Kconfig b/components/libc/Kconfig index 1379e6a408..ae8131703d 100644 --- a/components/libc/Kconfig +++ b/components/libc/Kconfig @@ -47,10 +47,6 @@ if RT_USING_LIBC && RT_USING_DFS bool "Enable mmap() API" default n - config RT_USING_POSIX_TERMIOS - bool "Enable termios APIs" - default n - config RT_USING_POSIX_GETLINE bool "Enable getline()/getdelim() APIs" default n diff --git a/components/libc/termios/SConscript b/components/libc/termios/SConscript deleted file mode 100644 index 381eb5ad8b..0000000000 --- a/components/libc/termios/SConscript +++ /dev/null @@ -1,13 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') -CPPPATH = [cwd] - -group = DefineGroup('libc', src, - depend = ['RT_USING_LIBC', 'RT_USING_POSIX', 'RT_USING_POSIX_TERMIOS'], - CPPPATH = CPPPATH) - -Return('group') diff --git a/components/tty/console.c b/components/tty/console.c index bde9b53b4f..ea4d6141a2 100644 --- a/components/tty/console.c +++ b/components/tty/console.c @@ -27,19 +27,31 @@ static void console_rx_notify(struct rt_device *dev) { struct tty_struct *console = NULL; int len = 0; + int lens = 0; char ch = 0; + char buf[1024] = {0}; console = (struct tty_struct *)dev; RT_ASSERT(console != RT_NULL); - len = rt_device_read(console->driver, -1, &ch, 1); - if (len == 0) + while (1) { - return; + len = rt_device_read(console->driver, -1, &ch, 1); + if (len == 0) + { + break; + } + lens += len; + buf[lens-1] = ch; + if (lens > 1024) + { + break; + } } + if (console->ldisc->ops->receive_buf) { - console->ldisc->ops->receive_buf((struct tty_struct *)console, &ch, len); + console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens); } } @@ -298,14 +310,12 @@ rt_err_t console_register(const char *name, struct rt_device *iodev) tty_ldisc_init(console); -#if defined(RT_USING_POSIX_TERMIOS) 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; -#endif /* RT_USING_POSIX_TERMIOS */ console_ldata_init(console); console->init_flag = TTY_INIT_FLAG_REGED; diff --git a/components/libc/termios/posix_termios.h b/components/tty/include/ktermios.h similarity index 88% rename from components/libc/termios/posix_termios.h rename to components/tty/include/ktermios.h index 45db6a6242..3620a6d7b6 100644 --- a/components/libc/termios/posix_termios.h +++ b/components/tty/include/ktermios.h @@ -1,14 +1,15 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2017/08/30 Bernard The first version + * 2021/12/10 linzhenxing posix_termios.h->ktermios.h and put tty system */ -#ifndef TERMIOS_H__ -#define TERMIOS_H__ +#ifndef KTERMIOS_H__ +#define KTERMIOS_H__ #include #include @@ -34,6 +35,7 @@ struct termios { speed_t __c_ospeed; }; +/* c_cc characters */ #define VINTR 0 #define VQUIT 1 #define VERASE 2 @@ -52,6 +54,7 @@ struct termios { #define VLNEXT 15 #define VEOL2 16 +/* c_iflag bits */ #define IGNBRK 0000001 #define BRKINT 0000002 #define IGNPAR 0000004 @@ -68,6 +71,7 @@ struct termios { #define IMAXBEL 0020000 #define IUTF8 0040000 +/* c_oflag bits */ #define OPOST 0000001 #define OLCUC 0000002 #define ONLCR 0000004 @@ -80,10 +84,10 @@ struct termios { #define NL0 0000000 #define NL1 0000400 #define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 +#define KCR0 0000000 +#define KCR1 0001000 +#define KCR2 0002000 +#define KCR3 0003000 #define TABDLY 0014000 #define TAB0 0000000 #define TAB1 0004000 @@ -100,6 +104,7 @@ struct termios { #define VT0 0000000 #define VT1 0040000 +/* c_cflag bit meaning */ #define B0 0000000 #define B50 0000001 #define B75 0000002 @@ -145,6 +150,7 @@ struct termios { #define HUPCL 0002000 #define CLOCAL 0004000 +/* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 #define ECHO 0000010 @@ -186,11 +192,11 @@ struct termios { #define XTABS 0014000 -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 */ #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" diff --git a/components/tty/include/tty.h b/components/tty/include/tty.h index 850c977dc4..62a57e9efd 100644 --- a/components/tty/include/tty.h +++ b/components/tty/include/tty.h @@ -13,10 +13,7 @@ #include #include #include "lwp.h" - -#ifdef RT_USING_POSIX_TERMIOS -#include -#endif +#include #define current lwp_self() #define __DISABLED_CHAR '\0' diff --git a/components/tty/include/tty_ldisc.h b/components/tty/include/tty_ldisc.h index 8020ea2150..a25f66cfed 100644 --- a/components/tty/include/tty_ldisc.h +++ b/components/tty/include/tty_ldisc.h @@ -13,10 +13,7 @@ #include #include #include - -#ifdef RT_USING_POSIX_TERMIOS -#include -#endif +#include struct tty_struct; struct tty_ldisc_ops @@ -49,6 +46,7 @@ struct tty_ldisc #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); diff --git a/components/libc/termios/posix_termios.c b/components/tty/ktermios.c similarity index 94% rename from components/libc/termios/posix_termios.c rename to components/tty/ktermios.c index a47a02b15e..a9b9aa095f 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/tty/ktermios.c @@ -1,18 +1,19 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2017/08/30 Bernard The first version + * 2021/12/10 linzhenxing posix_termios.c->ktermios.c and put tty system */ #include #include #include #include -#include +#include int tcgetattr(int fd, struct termios *tio) { diff --git a/components/tty/n_tty.c b/components/tty/n_tty.c index 6009928c8e..a7d4dc69a7 100644 --- a/components/tty/n_tty.c +++ b/components/tty/n_tty.c @@ -10,10 +10,7 @@ #include #include #include - -#ifdef RT_USING_POSIX_TERMIOS -#include -#endif +#include #define DBG_ENABLE #if defined(RT_USING_TTY) @@ -52,25 +49,26 @@ void mutex_lock(rt_mutex_t mutex) { - rt_err_t result = -RT_EBUSY; - - while (result == -RT_EBUSY) - { - result = rt_mutex_take(mutex, RT_WAITING_FOREVER); - } - - if (result != RT_EOK) - { - RT_ASSERT(0); - } - return; + rt_err_t result = -RT_EBUSY; + + while (result == -RT_EBUSY) + { + result = rt_mutex_take(mutex, RT_WAITING_FOREVER); + } + + if (result != RT_EOK) + { + RT_ASSERT(0); + } + return; } void mutex_unlock(rt_mutex_t mutex) { - rt_mutex_release(mutex); - return; + rt_mutex_release(mutex); + return; } + struct n_tty_data { /* producer-published */ diff --git a/components/tty/pty.c b/components/tty/pty.c index c02d8f06bb..70d469b0c3 100644 --- a/components/tty/pty.c +++ b/components/tty/pty.c @@ -9,6 +9,7 @@ */ #include #include +#include #define DBG_ENABLE #if defined(RT_USING_TTY) @@ -266,14 +267,13 @@ static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, tty_ldisc_init(pts_drv); -#if defined(RT_USING_POSIX_TERMIOS) + 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 |= ICANON; pts_drv->init_termios.__c_ispeed = 38400; pts_drv->init_termios.__c_ospeed = 38400; -#endif /* RT_USING_POSIX_TERMIOS */ pts_drv->other_struct = ptm_drv; @@ -335,7 +335,6 @@ static int ptmx_register(void) tty_ldisc_init(ptm_drv); -#if defined(RT_USING_POSIX_TERMIOS) extern struct termios tty_std_termios; ptm_drv->init_termios.c_iflag = 0; ptm_drv->init_termios.c_oflag = 0; @@ -343,7 +342,6 @@ extern struct termios tty_std_termios; ptm_drv->init_termios.c_lflag = 0; ptm_drv->init_termios.__c_ispeed = 38400; ptm_drv->init_termios.__c_ospeed = 38400; -#endif /* RT_USING_POSIX_TERMIOS */ ptm_drv->init_flag = TTY_INIT_FLAG_REGED; diff --git a/components/tty/tty.c b/components/tty/tty.c index eea7c63a86..3fd6f02b68 100644 --- a/components/tty/tty.c +++ b/components/tty/tty.c @@ -14,9 +14,7 @@ #include #include #include -#ifdef RT_USING_POSIX_TERMIOS -#include -#endif +#include #define DBG_ENABLE #if defined(RT_USING_TTY) @@ -27,18 +25,16 @@ #define DBG_COLOR #include -#ifdef RT_USING_POSIX_TERMIOS 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 | ECHO | ECHOE | TOSTOP | NOFLSH, + .c_lflag = ISIG | ICANON | ECHO | ECHOE | TOSTOP | NOFLSH, RT_NULL,/* .c_line = N_TTY, */ .c_cc = INIT_C_CC, .__c_ispeed = 38400, .__c_ospeed = 38400 }; -#endif /*RT_USING_POSIX_TERMIOS*/ static int tty_open(struct dfs_fd *fd) { @@ -136,7 +132,7 @@ static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) switch (cmd) { case TIOCSCTTY: - return tiocsctty(real_tty, 1); + return tiocsctty(real_tty, 1); } ld = tty->ldisc; if (ld->ops->ioctl) diff --git a/components/tty/tty_ioctl.c b/components/tty/tty_ioctl.c index aa1955a1d9..8f6eb0e283 100644 --- a/components/tty/tty_ioctl.c +++ b/components/tty/tty_ioctl.c @@ -1,10 +1,7 @@ #include #include #include - -#ifdef RT_USING_POSIX_TERMIOS -#include -#endif +#include #define DBG_ENABLE #if defined(RT_USING_TTY) @@ -23,51 +20,6 @@ #define TERMIOS_TERMIO 4 #define TERMIOS_OLD 8 -/** - * tty_set_termios - update termios values - * @tty: tty to update - * @new_termios: desired new value - * - * Perform updates to the termios values set on this terminal. - * A master pty's termios should never be set. - * - * Locking: termios_rwsem - */ - -// int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) -// { -// struct ktermios old_termios; -// struct tty_ldisc *ld; - -// // WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY && -// // tty->driver->subtype == PTY_TYPE_MASTER); -// /* -// * Perform the actual termios internal changes under lock. -// */ - - -// /* FIXME: we need to decide on some locking/ordering semantics -// for the set_termios notification eventually */ -// down_write(&tty->termios_rwsem); -// old_termios = tty->termios; -// tty->termios = *new_termios; -// unset_locked_termios(tty, &old_termios); - -// if (tty->ops->set_termios) -// tty->ops->set_termios(tty, &old_termios); -// else -// tty_termios_copy_hw(&tty->termios, &old_termios); - -// ld = tty_ldisc_ref(tty); -// if (ld != NULL) { -// if (ld->ops->set_termios) -// ld->ops->set_termios(tty, &old_termios); -// tty_ldisc_deref(ld); -// } -// up_write(&tty->termios_rwsem); -// return 0; -// } - /** * set_termios - set termios values for a tty * @tty: terminal device diff --git a/components/tty/tty_ldisc.c b/components/tty/tty_ldisc.c index 15befb2d0e..17214a7470 100644 --- a/components/tty/tty_ldisc.c +++ b/components/tty/tty_ldisc.c @@ -97,7 +97,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) * * Perform final close of the ldisc and reset tty->ldisc */ -static void tty_ldisc_kill(struct tty_struct *tty) +void tty_ldisc_kill(struct tty_struct *tty) { if (!tty->ldisc) return; -- Gitee From 0e53526a343debd236169e87518c797c07225223 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Tue, 14 Dec 2021 13:48:33 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9tty=E5=88=B0components/?= =?UTF-8?q?drivers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/imx6ull-artpi-smart/drivers/board.c | 1 + bsp/qemu-vexpress-a9/.config | 8 +- bsp/qemu-vexpress-a9/drivers/board.c | 1 - bsp/qemu-vexpress-a9/rtconfig.h | 4 +- components/drivers/Kconfig | 10 ++ components/drivers/serial/serial.c | 2 +- components/{ => drivers}/tty/SConscript | 5 +- components/{ => drivers}/tty/console.c | 15 ++- .../{ => drivers}/tty/include/console.h | 4 +- .../tty/include/posix_termios.h} | 87 +++++++------ components/{ => drivers}/tty/include/tty.h | 80 ++++++------ .../{ => drivers}/tty/include/tty_ldisc.h | 4 +- components/{ => drivers}/tty/n_tty.c | 116 +++++++++++++----- components/{ => drivers}/tty/pty.c | 36 +++++- components/{ => drivers}/tty/tty.c | 25 ++-- components/{ => drivers}/tty/tty_ioctl.c | 15 +-- components/{ => drivers}/tty/tty_ldisc.c | 11 +- components/finsh/shell.c | 5 +- components/lwp/lwp.c | 5 + components/lwp/lwp.h | 7 +- components/lwp/lwp_pid.c | 5 + src/kservice.c | 5 +- 22 files changed, 288 insertions(+), 163 deletions(-) rename components/{ => drivers}/tty/SConscript (60%) rename components/{ => drivers}/tty/console.c (96%) rename components/{ => drivers}/tty/include/console.h (78%) rename components/{tty/include/ktermios.h => drivers/tty/include/posix_termios.h} (78%) rename components/{ => drivers}/tty/include/tty.h (93%) rename components/{ => drivers}/tty/include/tty_ldisc.h (95%) rename components/{ => drivers}/tty/n_tty.c (95%) rename components/{ => drivers}/tty/pty.c (90%) rename components/{ => drivers}/tty/tty.c (92%) rename components/{ => drivers}/tty/tty_ioctl.c (94%) rename components/{ => drivers}/tty/tty_ldisc.c (95%) diff --git a/bsp/imx6ull-artpi-smart/drivers/board.c b/bsp/imx6ull-artpi-smart/drivers/board.c index d7590bc35c..246266b4d4 100644 --- a/bsp/imx6ull-artpi-smart/drivers/board.c +++ b/bsp/imx6ull-artpi-smart/drivers/board.c @@ -106,6 +106,7 @@ void rt_hw_board_init(void) SystemClockInit(); rt_components_board_init(); + console_init(); rt_console_set_device(RT_CONSOLE_DEVICE_NAME); rt_thread_idle_sethook(idle_wfi); diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index fc4fc77cc4..b8cc05afd4 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -45,7 +45,7 @@ CONFIG_RT_USING_MUTEX=y CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MAILBOX=y CONFIG_RT_USING_MESSAGEQUEUE=y -CONFIG_RT_USING_SIGNALS=y +# CONFIG_RT_USING_SIGNALS is not set # # Memory Management @@ -107,8 +107,8 @@ CONFIG_FINSH_THREAD_NAME="tshell" CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=10 CONFIG_FINSH_USING_SYMTAB=y -# CONFIG_FINSH_USING_DESCRIPTION is not set -CONFIG_FINSH_ECHO_DISABLE_DEFAULT=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set CONFIG_FINSH_THREAD_PRIORITY=20 CONFIG_FINSH_THREAD_STACK_SIZE=4096 CONFIG_FINSH_CMD_SIZE=256 @@ -161,6 +161,8 @@ CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=256 +CONFIG_RT_USING_TTY=y +# CONFIG_RT_TTY_DEBUG is not set # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set diff --git a/bsp/qemu-vexpress-a9/drivers/board.c b/bsp/qemu-vexpress-a9/drivers/board.c index 076fb0afb9..2c6e172f0b 100644 --- a/bsp/qemu-vexpress-a9/drivers/board.c +++ b/bsp/qemu-vexpress-a9/drivers/board.c @@ -81,7 +81,6 @@ void rt_hw_board_init(void) rt_system_heap_init(HEAP_BEGIN, HEAP_END); rt_components_board_init(); - console_init(); rt_console_set_device(RT_CONSOLE_DEVICE_NAME); rt_thread_idle_sethook(idle_wfi); diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index e57653c49e..a0e50b4e24 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -30,7 +30,6 @@ #define RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS /* Memory Management */ @@ -79,7 +78,7 @@ #define FINSH_USING_HISTORY #define FINSH_HISTORY_LINES 10 #define FINSH_USING_SYMTAB -#define FINSH_ECHO_DISABLE_DEFAULT +#define FINSH_USING_DESCRIPTION #define FINSH_THREAD_PRIORITY 20 #define FINSH_THREAD_STACK_SIZE 4096 #define FINSH_CMD_SIZE 256 @@ -119,6 +118,7 @@ #define RT_USING_SERIAL #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 256 +#define RT_USING_TTY #define RT_USING_I2C #define RT_USING_I2C_BITOPS #define RT_USING_PIN diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 52e8c7a909..8e6a17eef5 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -45,6 +45,16 @@ if RT_USING_SERIAL endif +config RT_USING_TTY + bool "Using TTY SYSTEM" + default y + +if RT_USING_TTY + config RT_TTY_DEBUG + bool "Using TTY DEBUG" + default n +endif + config RT_USING_CAN bool "Using CAN device drivers" default n diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 33102c1d72..a58f2264ff 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -38,7 +38,7 @@ #include #include -#include +#include /* it's possible the 'getc/putc' is defined by stdio.h in gcc/newlib. */ diff --git a/components/tty/SConscript b/components/drivers/tty/SConscript similarity index 60% rename from components/tty/SConscript rename to components/drivers/tty/SConscript index b5bacc32bf..55595aabc2 100644 --- a/components/tty/SConscript +++ b/components/drivers/tty/SConscript @@ -5,8 +5,7 @@ src = Glob('*.c') cwd = GetCurrentDir() CPPPATH = [cwd + "/include"] - -group = DefineGroup('tty', src, depend = [''], CPPPATH = CPPPATH) - +if GetDepend('RT_USING_LWP'): + group = DefineGroup('tty', src, depend = ['RT_USING_TTY'], CPPPATH = CPPPATH) Return('group') diff --git a/components/tty/console.c b/components/drivers/tty/console.c similarity index 96% rename from components/tty/console.c rename to components/drivers/tty/console.c index ea4d6141a2..bdc44dca2e 100644 --- a/components/tty/console.c +++ b/components/drivers/tty/console.c @@ -12,13 +12,12 @@ #include #include -#define DBG_ENABLE -#if defined(RT_USING_TTY) -#define DBG_LEVEL DBG_LOG +#define DBG_TAG "CONSOLE" +#ifdef RT_TTY_DEBUG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_TTY_DEBUG */ #include static struct tty_struct console_driver; @@ -92,7 +91,7 @@ static rt_err_t iodev_open(struct tty_struct *console) return RT_EOK; } -struct rt_device *rt_console_get_iodev(void) +struct rt_device *console_get_iodev(void) { rt_base_t level = 0; struct rt_device *iodev = RT_NULL; @@ -103,7 +102,7 @@ struct rt_device *rt_console_get_iodev(void) return iodev; } -struct rt_device *rt_console_set_iodev(struct rt_device *iodev) +struct rt_device *console_set_iodev(struct rt_device *iodev) { rt_base_t level = 0; struct rt_device *io_before = RT_NULL; diff --git a/components/tty/include/console.h b/components/drivers/tty/include/console.h similarity index 78% rename from components/tty/include/console.h rename to components/drivers/tty/include/console.h index 1a78c9e750..779d816d4b 100644 --- a/components/tty/include/console.h +++ b/components/drivers/tty/include/console.h @@ -13,7 +13,7 @@ #include "tty.h" struct tty_struct *console_tty_get(void); -struct rt_device *rt_console_get_iodev(void); -struct rt_device *rt_console_set_iodev(struct rt_device *iodev); +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/tty/include/ktermios.h b/components/drivers/tty/include/posix_termios.h similarity index 78% rename from components/tty/include/ktermios.h rename to components/drivers/tty/include/posix_termios.h index 3620a6d7b6..4d640569ce 100644 --- a/components/tty/include/ktermios.h +++ b/components/drivers/tty/include/posix_termios.h @@ -6,7 +6,7 @@ * Change Logs: * Date Author Notes * 2017/08/30 Bernard The first version - * 2021/12/10 linzhenxing posix_termios.h->ktermios.h and put tty system + * 2021/12/10 linzhenxing put tty system */ #ifndef KTERMIOS_H__ #define KTERMIOS_H__ @@ -73,36 +73,40 @@ struct termios { /* c_oflag bits */ #define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 +#define ONLCR 0000002 +#define OLCUC 0000004 + #define OCRNL 0000010 #define ONOCR 0000020 #define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define KCR0 0000000 -#define KCR1 0001000 -#define KCR2 0002000 -#define KCR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 + +#define OFILL 00000100 +#define OFDEL 00000200 +#define NLDLY 00001400 +#define NL0 00000000 +#define NL1 00000400 +#define NL2 00001000 +#define NL3 00001400 +#define TABDLY 00006000 +#define TAB0 00000000 +#define TAB1 00002000 +#define TAB2 00004000 +#define TAB3 00006000 +#define CRDLY 00030000 +#define KCR0 00000000 +#define KCR1 00010000 +#define KCR2 00020000 +#define KCR3 00030000 +#define FFDLY 00040000 +#define FF0 00000000 +#define FF1 00040000 +#define BSDLY 00100000 +#define BS0 00000000 +#define BS1 00100000 +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 +#define XTABS 01000000 /* c_cflag bit meaning */ #define B0 0000000 @@ -151,15 +155,22 @@ struct termios { #define CLOCAL 0004000 /* c_lflag bits */ -#define ISIG 0000001 -#define ICANON 0000002 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define IEXTEN 0100000 +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define IEXTEN 0100000 +#define EXTPROC 0200000 #define TCOOFF 0 #define TCOON 1 @@ -190,8 +201,6 @@ struct termios { #define PENDIN 0040000 #define EXTPROC 0200000 -#define XTABS 0014000 - /* intr=^C quit=^| erase=del kill=^U eof=^D vtime=\0 vmin=\1 sxtc=\0 start=^Q stop=^S susp=^Z eol=\0 diff --git a/components/tty/include/tty.h b/components/drivers/tty/include/tty.h similarity index 93% rename from components/tty/include/tty.h rename to components/drivers/tty/include/tty.h index 62a57e9efd..c93e65a402 100644 --- a/components/tty/include/tty.h +++ b/components/drivers/tty/include/tty.h @@ -12,8 +12,13 @@ #include #include #include -#include "lwp.h" -#include +#ifdef RT_USING_LWP +#include +#endif +#if defined(RT_USING_POSIX) +#include +#include +#endif #define current lwp_self() #define __DISABLED_CHAR '\0' @@ -354,42 +359,41 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) return retval; } -rt_inline unsigned long __ffs(unsigned long word) -{ - int num = 0; - -/*如果BITS_PER_LONG等于64,要先对低32位进行检查;否则(即BITS_PER_LONG等于32),直接对低16位进行检查*/ -#if BITS_PER_LONG == 64 - if ((word & 0xffffffff) == 0) - { //如果与0xffffffff相与得0,说明word的低32位全为0 - num += 32; //索引加32 - word >>= 32; //word右移32位,把低32位的0移走 - } -#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; -} + 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) diff --git a/components/tty/include/tty_ldisc.h b/components/drivers/tty/include/tty_ldisc.h similarity index 95% rename from components/tty/include/tty_ldisc.h rename to components/drivers/tty/include/tty_ldisc.h index a25f66cfed..6accb118ea 100644 --- a/components/tty/include/tty_ldisc.h +++ b/components/drivers/tty/include/tty_ldisc.h @@ -13,7 +13,9 @@ #include #include #include -#include +#if defined(RT_USING_POSIX) +#include +#endif struct tty_struct; struct tty_ldisc_ops diff --git a/components/tty/n_tty.c b/components/drivers/tty/n_tty.c similarity index 95% rename from components/tty/n_tty.c rename to components/drivers/tty/n_tty.c index a7d4dc69a7..e99359ce80 100644 --- a/components/tty/n_tty.c +++ b/components/drivers/tty/n_tty.c @@ -10,15 +10,16 @@ #include #include #include -#include +#if defined(RT_USING_POSIX) +#include +#endif -#define DBG_ENABLE -#if defined(RT_USING_TTY) -#define DBG_LEVEL DBG_LOG +#define DBG_TAG "N_TTY" +#ifdef RT_TTY_DEBUG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_TTY_DEBUG */ #include /* number of characters left in xmit buffer before select has we have room */ @@ -68,7 +69,6 @@ void mutex_unlock(rt_mutex_t mutex) rt_mutex_release(mutex); return; } - struct n_tty_data { /* producer-published */ @@ -254,13 +254,10 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) { - if (c == ECHO_OP_START) - { + if (c == ECHO_OP_START) { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); - } - else - { + } else { add_echo_byte(c, ldata); } } @@ -281,13 +278,10 @@ static void echo_char(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - if (c == ECHO_OP_START) - { + if (c == ECHO_OP_START) { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); - } - else - { + } else { if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(c, ldata); @@ -428,8 +422,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) echo_char_raw(read_buf(ldata, head), ldata); echo_move_back_col(ldata); } - } - else if (kill_type == KERASE && !L_ECHOE(tty)) + } else if (kill_type == KERASE && !L_ECHOE(tty)) { echo_char(ERASE_CHAR(tty), tty); } @@ -490,6 +483,53 @@ static void eraser(unsigned char c, struct tty_struct *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; + if (lwp) + { + lwp_kill(lwp_to_pid(lwp), sig); + } +} + +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) @@ -558,7 +598,10 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) case '\b': if (ldata->column > 0) ldata->column--; - break; + ch = "\b \b"; + rt_device_write((rt_device_t)tty, -1, ch, strlen(ch)); +// ldata->canon_head = ldata->read_tail -= 2; + return 1; default: if (!iscntrl(c)) { @@ -793,8 +836,7 @@ static size_t __process_echoes(struct tty_struct *tty) tail += 3; else tail += 2; - } - else + } else tail++; } @@ -1146,11 +1188,17 @@ 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); - ldata = tty->disc_data; + 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); - tty->disc_data = RT_NULL; + o_tty->disc_data = RT_NULL; return ret; } @@ -1183,6 +1231,18 @@ static int n_tty_ioctl(struct dfs_fd *fd, int cmd, void *args) 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 @@ -1221,17 +1281,17 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { if (c == INTR_CHAR(tty)) /*ctrl + c realize missing*/ { - //n_tty_receive_signal_char(tty, SIGINT, c); + 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); + 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); + n_tty_receive_signal_char(tty, SIGTSTP, c); return 0; } } diff --git a/components/tty/pty.c b/components/drivers/tty/pty.c similarity index 90% rename from components/tty/pty.c rename to components/drivers/tty/pty.c index 70d469b0c3..874e32202f 100644 --- a/components/tty/pty.c +++ b/components/drivers/tty/pty.c @@ -11,18 +11,18 @@ #include #include -#define DBG_ENABLE -#if defined(RT_USING_TTY) -#define DBG_LEVEL DBG_LOG +#define DBG_TAG "PTY" +#ifdef RT_TTY_DEBUG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_TTY_DEBUG */ #include #define PTY_PTS_SIZE 1024 static struct tty_struct ptm_driver; static struct tty_struct pts_drivers[PTY_PTS_SIZE]; +//static struct tty_struct ptm_drivers[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); @@ -96,6 +96,30 @@ static rt_err_t pty_device_open(struct rt_device *dev, rt_uint16_t oflag) 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; } diff --git a/components/tty/tty.c b/components/drivers/tty/tty.c similarity index 92% rename from components/tty/tty.c rename to components/drivers/tty/tty.c index 3fd6f02b68..e08dadba8a 100644 --- a/components/tty/tty.c +++ b/components/drivers/tty/tty.c @@ -14,22 +14,23 @@ #include #include #include -#include +#if defined(RT_USING_POSIX) +#include +#endif -#define DBG_ENABLE -#if defined(RT_USING_TTY) -#define DBG_LEVEL DBG_LOG +#define DBG_TAG "TTY" +#ifdef RT_TTY_DEBUG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_TTY_DEBUG */ #include 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 | ICANON | ECHO | ECHOE | TOSTOP | NOFLSH, + .c_lflag = ISIG | ECHOE | TOSTOP | NOFLSH, RT_NULL,/* .c_line = N_TTY, */ .c_cc = INIT_C_CC, .__c_ispeed = 38400, @@ -76,10 +77,14 @@ static int tty_close(struct dfs_fd *fd) { int ret = 0; struct tty_struct *tty = RT_NULL; - + struct tty_ldisc *ld = RT_NULL; tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); - //tty_ldisc_release(tty); + ld = tty->ldisc; + if (ld->ops->close) + { + //ld->ops->close(tty); + } if (fd->fnode->ref_count == 1) { ret = rt_device_close((rt_device_t)tty); diff --git a/components/tty/tty_ioctl.c b/components/drivers/tty/tty_ioctl.c similarity index 94% rename from components/tty/tty_ioctl.c rename to components/drivers/tty/tty_ioctl.c index 8f6eb0e283..8427bfad35 100644 --- a/components/tty/tty_ioctl.c +++ b/components/drivers/tty/tty_ioctl.c @@ -1,15 +1,16 @@ #include #include #include -#include +#if defined(RT_USING_POSIX) +#include +#endif -#define DBG_ENABLE -#if defined(RT_USING_TTY) -#define DBG_LEVEL DBG_LOG +#define DBG_TAG "TTY_IOCTL" +#ifdef RT_TTY_DEBUG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_TTY_DEBUG */ #include /* diff --git a/components/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c similarity index 95% rename from components/tty/tty_ldisc.c rename to components/drivers/tty/tty_ldisc.c index 17214a7470..b273de52cc 100644 --- a/components/tty/tty_ldisc.c +++ b/components/drivers/tty/tty_ldisc.c @@ -1,13 +1,12 @@ #include #include -#define DBG_ENABLE -#if defined(RT_USING_TTY) -#define DBG_LEVEL DBG_LOG +#define DBG_TAG "TTY_LDISC" +#ifdef RT_TTY_DEBUG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_TTY_DEBUG */ #include static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 0e5ae802e3..3e110408ba 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -585,7 +585,7 @@ void finsh_thread_entry(void *parameter) shell->line_position - shell->line_curpos); shell->line[shell->line_position] = 0; - //rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]); + rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]); /* move the cursor to the origin position */ for (i = shell->line_curpos; i <= shell->line_position; i++) @@ -593,7 +593,8 @@ void finsh_thread_entry(void *parameter) } else { - //rt_kprintf("\b \b"); + if (shell->echo_mode) + rt_kprintf("\b \b"); shell->line[shell->line_position] = 0; } diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index 46641acd19..d230167eca 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -43,6 +43,7 @@ static const char elf_magic[] = {0x7f, 'E', 'L', 'F'}; #ifdef DFS_USING_WORKDIR extern char working_directory[]; #endif +struct termios stdin_termios, old_stdin_termios; extern void lwp_user_entry(void *args, const void *text, void *ustack, void *k_stack); int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *const envp[]); @@ -1211,6 +1212,10 @@ pid_t lwp_execve(char *filename, int argc, char **argv, char **envp) lwp->tty->pgrp = lwp->__pgrp; lwp->tty->session = lwp->session; lwp->tty->foreground = lwp; + tcgetattr(1, &stdin_termios); + old_stdin_termios = stdin_termios; + stdin_termios.c_lflag |= ICANON | ECHO | ECHOCTL; + tcsetattr(1, 0, &stdin_termios); } else { diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h index b091873ed4..99db3f0363 100644 --- a/components/lwp/lwp.h +++ b/components/lwp/lwp.h @@ -22,9 +22,6 @@ #include #include #include -#ifdef RT_USING_TTY -#include -#endif #include "lwp_pid.h" #include "lwp_ipc.h" @@ -44,7 +41,9 @@ #ifdef RT_USING_MUSL #include -typedef int32_t pid_t; +#endif +#ifdef RT_USING_TTY +struct tty_struct; #endif #ifdef __cplusplus diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index b89320384e..94962a7feb 100644 --- a/components/lwp/lwp_pid.c +++ b/components/lwp/lwp_pid.c @@ -436,7 +436,12 @@ void lwp_free(struct rt_lwp* lwp) /* for parent */ { + extern struct termios old_stdin_termios; struct rt_lwp *self_lwp = (struct rt_lwp *)lwp_self(); + if (lwp->session == -1) + { + tcsetattr(1, 0, &old_stdin_termios); + } if (lwp->tty != RT_NULL) { if (lwp->tty->foreground == lwp) diff --git a/src/kservice.c b/src/kservice.c index 7a3dcebfd5..531a18f9b6 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -1132,14 +1132,15 @@ rt_device_t rt_console_set_device(const char *name) { #ifdef RT_USING_LWP rt_device_t new_iodev, 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) { if (_console_device != RT_NULL) { - old_iodev = rt_console_set_iodev(new_iodev); + old_iodev = console_set_iodev(new_iodev); } else { -- Gitee From d3f71b76e6effc16dee8897f26032f2e21f12e53 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Tue, 14 Dec 2021 14:03:55 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9tty=E5=88=B0components/?= =?UTF-8?q?drivers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{tty/ktermios.c => drivers/tty/posix_termios.c} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename components/{tty/ktermios.c => drivers/tty/posix_termios.c} (89%) diff --git a/components/tty/ktermios.c b/components/drivers/tty/posix_termios.c similarity index 89% rename from components/tty/ktermios.c rename to components/drivers/tty/posix_termios.c index a9b9aa095f..2bfd6ea682 100644 --- a/components/tty/ktermios.c +++ b/components/drivers/tty/posix_termios.c @@ -6,19 +6,19 @@ * Change Logs: * Date Author Notes * 2017/08/30 Bernard The first version - * 2021/12/10 linzhenxing posix_termios.c->ktermios.c and put tty system + * 2021/12/10 linzhenxing put tty system */ #include #include #include #include -#include +#include int tcgetattr(int fd, struct termios *tio) { /* Get the current serial port settings. */ - if (ioctl(fd, TCGETA, tio)) + if (ioctl(fd, TCGETS, tio)) return -1; return 0; @@ -30,19 +30,19 @@ int tcsetattr(int fd, int act, const struct termios *tio) { case TCSANOW: /* make the change immediately */ - return (ioctl(fd, TCSETA, (void*)tio)); + return (ioctl(fd, TCSETS, (void*)tio)); case TCSADRAIN: /* * Don't make the change until all currently written data * has been transmitted. */ - return (ioctl(fd, TCSETAW, (void*)tio)); + return (ioctl(fd, TCSETSW, (void*)tio)); case TCSAFLUSH: /* Don't make the change until all currently written data * has been transmitted, at which point any received but * unread data is also discarded. */ - return (ioctl(fd, TCSETAF, (void*)tio)); + return (ioctl(fd, TCSETSF, (void*)tio)); default: errno = EINVAL; return (-1); -- Gitee From a2288459cb1e9944c499c8e9f0c35379244aa06e Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 15 Dec 2021 10:38:25 +0800 Subject: [PATCH 10/13] format code --- components/drivers/tty/include/tty.h | 29 +- components/drivers/tty/n_tty.c | 382 ++++++++++++++++++++------- components/drivers/tty/pty.c | 16 +- components/drivers/tty/tty.c | 82 +++++- components/drivers/tty/tty_ioctl.c | 67 ++--- components/drivers/tty/tty_ldisc.c | 16 +- 6 files changed, 424 insertions(+), 168 deletions(-) diff --git a/components/drivers/tty/include/tty.h b/components/drivers/tty/include/tty.h index c93e65a402..53a335c4b4 100644 --- a/components/drivers/tty/include/tty.h +++ b/components/drivers/tty/include/tty.h @@ -286,6 +286,8 @@ 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); +int tty_check_change(struct tty_struct *tty); rt_inline struct rt_wqueue *wait_queue_get(struct rt_lwp *lwp, struct tty_struct *tty) { @@ -416,27 +418,44 @@ rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long s tmp = *(p++); tmp &= (~0UL << offset); if (size < BITS_PER_LONG) - goto found_first; + { + goto found_first; + } + if (tmp) - goto found_middle; + { + goto found_middle; + } + size -= BITS_PER_LONG; result += BITS_PER_LONG; } + while (size & ~(BITS_PER_LONG-1)) { if ((tmp = *(p++))) - goto found_middle; + { + goto found_middle; + } + result += BITS_PER_LONG; size -= BITS_PER_LONG; } + if (!size) - return result; + { + return result; + } + tmp = *p; found_first: tmp &= (~0UL >> (BITS_PER_LONG - size)); if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ + { + return result + size; /* Nope. */ + } + found_middle: return result + __ffs(tmp); } diff --git a/components/drivers/tty/n_tty.c b/components/drivers/tty/n_tty.c index e99359ce80..7d0835a2a1 100644 --- a/components/drivers/tty/n_tty.c +++ b/components/drivers/tty/n_tty.c @@ -236,7 +236,9 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, /* Set the high bit as a flag if num_chars is after a previous tab */ if (after_tab) - num_chars |= 0x80; + { + num_chars |= 0x80; + } add_echo_byte(num_chars, ldata); } @@ -254,10 +256,13 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) { - if (c == ECHO_OP_START) { + if (c == ECHO_OP_START) + { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); - } else { + } + else + { add_echo_byte(c, ldata); } } @@ -278,12 +283,17 @@ static void echo_char(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - if (c == ECHO_OP_START) { + if (c == ECHO_OP_START) + { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); - } else { + } + else + { if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') - add_echo_byte(ECHO_OP_START, ldata); + { + add_echo_byte(ECHO_OP_START, ldata); + } add_echo_byte(c, ldata); } } @@ -355,10 +365,15 @@ static void eraser(unsigned char c, struct tty_struct *tty) /* 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)) @@ -366,6 +381,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) ldata->read_head = ldata->canon_head; return; } + if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) { ldata->read_head = ldata->canon_head; @@ -373,7 +389,9 @@ static void eraser(unsigned char c, struct tty_struct *tty) 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); + { + echo_char_raw('\n', ldata); + } return; } kill_type = KILL; @@ -393,15 +411,21 @@ static void eraser(unsigned char c, struct tty_struct *tty) /* do not partially erase */ if (is_continuation(c, tty)) - break; + { + 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; @@ -422,7 +446,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) echo_char_raw(read_buf(ldata, head), ldata); echo_move_back_col(ldata); } - } else if (kill_type == KERASE && !L_ECHOE(tty)) + } + else if (kill_type == KERASE && !L_ECHOE(tty)) { echo_char(ERASE_CHAR(tty), tty); } @@ -451,7 +476,9 @@ static void eraser(unsigned char c, struct tty_struct *tty) else if (iscntrl(c)) { if (L_ECHOCTL(tty)) - num_chars += 2; + { + num_chars += 2; + } } else if (!is_continuation(c, tty)) { @@ -477,10 +504,14 @@ static void eraser(unsigned char c, struct tty_struct *tty) } } if (kill_type == KERASE) - break; + { + break; + } } if (ldata->read_head == ldata->canon_head && L_ECHO(tty)) - finish_erasing(ldata); + { + finish_erasing(ldata); + } } /** @@ -562,7 +593,10 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) { case '\n': if (O_ONLRET(tty)) - ldata->column = 0; + { + ldata->column = 0; + } + if (O_ONLCR(tty)) { ldata->canon_column = ldata->column = 0; @@ -574,12 +608,17 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) break; case '\r': if (O_ONOCR(tty) && ldata->column == 0) - return 0; + { + return 0; + } + if (O_OCRNL(tty)) { c = '\n'; if (O_ONLRET(tty)) - ldata->canon_column = ldata->column = 0; + { + ldata->canon_column = ldata->column = 0; + } break; } ldata->canon_column = ldata->column = 0; @@ -597,18 +636,24 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) break; case '\b': if (ldata->column > 0) - ldata->column--; + { + ldata->column--; + } ch = "\b \b"; rt_device_write((rt_device_t)tty, -1, ch, strlen(ch)); -// ldata->canon_head = ldata->read_tail -= 2; return 1; default: if (!iscntrl(c)) { if (O_OLCUC(tty)) + { c = toupper(c); + } + if (!is_continuation(c, tty)) + { ldata->column++; + } } break; } @@ -640,9 +685,13 @@ static int process_output(unsigned char c, struct tty_struct *tty) retval = do_output_char(c, tty); rt_hw_interrupt_enable(level); if (retval < 0) + { return -1; + } else + { return 0; + } } /** @@ -683,31 +732,49 @@ static ssize_t process_output_block(struct tty_struct *tty, { case '\n': if (O_ONLRET(tty)) - ldata->column = 0; + { + ldata->column = 0; + } + if (O_ONLCR(tty)) - goto break_out; + { + goto break_out; + } ldata->canon_column = ldata->column; break; case '\r': if (O_ONOCR(tty) && ldata->column == 0) - goto break_out; + { + goto break_out; + } + if (O_OCRNL(tty)) - goto break_out; + { + goto break_out; + } + ldata->canon_column = ldata->column = 0; break; case '\t': goto break_out; case '\b': if (ldata->column > 0) - ldata->column--; + { + ldata->column--; + } break; default: if (!iscntrl(c)) { if (O_OLCUC(tty)) - goto break_out; + { + goto break_out; + } + if (!is_continuation(c, tty)) - ldata->column++; + { + ldata->column++; + } } break; } @@ -732,7 +799,6 @@ static size_t __process_echoes(struct tty_struct *tty) if (c == ECHO_OP_START) { unsigned char op; - //int no_space_left = 0; /* * If the buffer byte is the start of a multi-byte @@ -759,7 +825,9 @@ static size_t __process_echoes(struct tty_struct *tty) * Otherwise, tab spacing is normal. */ if (!(num_chars & 0x80)) - num_chars += ldata->canon_column; + { + num_chars += ldata->canon_column; + } num_bs = 8 - (num_chars & 7); while (num_bs--) @@ -767,7 +835,9 @@ static size_t __process_echoes(struct tty_struct *tty) ch = '\b'; rt_device_write((rt_device_t)tty, -1, &ch, 1); if (ldata->column > 0) - ldata->column--; + { + ldata->column--; + } } tail += 3; break; @@ -779,7 +849,9 @@ static size_t __process_echoes(struct tty_struct *tty) case ECHO_OP_MOVE_BACK_COL: if (ldata->column > 0) - ldata->column--; + { + ldata->column--; + } tail += 2; break; @@ -787,7 +859,6 @@ static size_t __process_echoes(struct tty_struct *tty) ch = ECHO_OP_START; rt_device_write((rt_device_t)tty, -1, &ch, 1); ldata->column++; - //space--; tail += 2; break; @@ -815,7 +886,9 @@ static size_t __process_echoes(struct tty_struct *tty) { int retval = do_output_char(c, tty); if (retval < 0) - break; + { + break; + } } else { @@ -833,11 +906,18 @@ static size_t __process_echoes(struct tty_struct *tty) 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++; + } + } + else + { + tail++; + } } ldata->echo_tail = tail; @@ -860,7 +940,9 @@ static void commit_echoes(struct tty_struct *tty) * block is accumulated) */ nr = head - ldata->echo_tail; if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) - return; + { + return; + } level = rt_hw_interrupt_disable(); ldata->echo_commit = head; @@ -873,7 +955,9 @@ static void process_echoes(struct tty_struct *tty) struct n_tty_data *ldata = tty->disc_data; int level; if (ldata->echo_mark == ldata->echo_tail) - return; + { + return; + } level = rt_hw_interrupt_disable(); ldata->echo_commit = ldata->echo_mark; @@ -889,7 +973,9 @@ static void flush_echoes(struct tty_struct *tty) if ((!L_ECHO(tty) && !L_ECHONL(tty)) || ldata->echo_commit == ldata->echo_head) - return; + { + return; + } level = rt_hw_interrupt_disable(); ldata->echo_commit = ldata->echo_head; @@ -943,9 +1029,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) { 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); + { + set_bit('\n', (int *)ldata->char_map); + } if (L_ICANON(tty)) { @@ -960,8 +1051,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) 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); + (int *)ldata->char_map); + } } } if (I_IXON(tty)) @@ -985,9 +1078,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) 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; + { + ldata->real_raw = 1; + } else - ldata->real_raw = 0; + { + ldata->real_raw = 0; + } } } @@ -1047,9 +1144,13 @@ static inline int input_available_p(struct tty_struct *tty, int poll) 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; + } } /** @@ -1091,7 +1192,10 @@ static int copy_from_read_buf(struct tty_struct *tty,char *b,size_t nr) /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && (head == ldata->read_tail)) - n = 0; + { + n = 0; + } + } return n; } @@ -1129,7 +1233,9 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) /* N.B. avoid overrun if nr == 0 */ if (nr == 0) - return 0; + { + return 0; + } n = min(nr + 1, ldata->canon_head - ldata->read_tail); @@ -1145,11 +1251,15 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) found = eol != more; } else - found = eol != size; + { + found = eol != size; + } n = eol - tail; if (n > RT_TTY_BUF) - n += RT_TTY_BUF; + { + n += RT_TTY_BUF; + } c = n + found; if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) @@ -1170,15 +1280,21 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) rt_memcpy(b, from, n); if (found) - clear_bit(eol, (int *)ldata->read_flags); + { + 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; } @@ -1192,9 +1308,13 @@ static int n_tty_close(struct tty_struct *tty) 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); @@ -1211,9 +1331,13 @@ static int n_tty_ioctl(struct dfs_fd *fd, int cmd, void *args) tty = (struct tty_struct *)fd->fnode->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) { @@ -1221,13 +1345,16 @@ static int n_tty_ioctl(struct dfs_fd *fd, int cmd, void *args) default: ret = n_tty_ioctl_extend(real_tty, cmd, args); if (ret != -ENOIOCTLCMD) - return ret; + { + return ret; + } } ret = rt_device_control((rt_device_t)real_tty, cmd, args); if (ret != -ENOIOCTLCMD) - return ret; - + { + return ret; + } return ret; } @@ -1235,11 +1362,15 @@ static void n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) { isig(signal, tty); - if (L_ECHO(tty)) { + if (L_ECHO(tty)) + { echo_char(c, tty); commit_echoes(tty); - } else - process_echoes(tty); + } + else + { + process_echoes(tty); + } return; } @@ -1299,12 +1430,19 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (c == '\r') { if (I_IGNCR(tty)) + { return 0; + } + if (I_ICRNL(tty)) + { c = '\n'; + } } else if (c == '\n' && I_INLCR(tty)) - c = '\r'; + { + c = '\r'; + } if (ldata->icanon) { @@ -1369,7 +1507,10 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); + { + echo_set_canon_col(ldata); + } + echo_char(c, tty); commit_echoes(tty); } @@ -1378,7 +1519,9 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) * EOL_CHAR and EOL2_CHAR? */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) - put_tty_queue(c, ldata); + { + put_tty_queue(c, ldata); + } handle_newline: set_bit(ldata->read_head & (RT_TTY_BUF - 1), (int *)ldata->read_flags); @@ -1393,12 +1536,16 @@ handle_newline: { finish_erasing(ldata); if (c == '\n') - echo_char_raw('\n', ldata); + { + 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_set_canon_col(ldata); + } echo_char(c, tty); } commit_echoes(tty); @@ -1406,7 +1553,9 @@ handle_newline: /* PARMRK doubling check */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) - put_tty_queue(c, ldata); + { + put_tty_queue(c, ldata); + } put_tty_queue(c, ldata); return 0; @@ -1421,13 +1570,19 @@ static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned ch finish_erasing(ldata); /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); + { + 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); + } + put_tty_queue(c, ldata); } @@ -1444,9 +1599,15 @@ static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, ch if (flag == TTY_NORMAL) { if (I_ISTRIP(tty)) - c &= 0x7f; + { + c &= 0x7f; + } + if (I_IUCLC(tty) && L_IEXTEN(tty)) - c = tolower(c); + { + c = tolower(c); + } + n_tty_receive_char(tty, c); } else @@ -1482,25 +1643,12 @@ static void n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count) while (count--) { if (flag == TTY_NORMAL) - put_tty_queue(*cp++, ldata); - //else - //n_tty_receive_char_flagged(tty, *cp++, flag); + { + put_tty_queue(*cp++, ldata); + } } } -// static void n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, -// char *fp, int count) -// { -// char flag = TTY_NORMAL; - -// while (count--) { -// if (fp) -// flag = *fp++; -// if (likely(flag == TTY_NORMAL)) -// n_tty_receive_char_closing(tty, *cp++); -// } -// } - static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int count) { struct n_tty_data *ldata = tty->disc_data; @@ -1511,16 +1659,25 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int cou char c = *cp++; if (I_ISTRIP(tty)) + { c &= 0x7f; + } + if (I_IUCLC(tty) && L_IEXTEN(tty)) - c = tolower(c); + { + 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); + { + 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); @@ -1538,7 +1695,10 @@ static inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char finish_erasing(ldata); /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); + { + echo_set_canon_col(ldata); + } + echo_char(c, tty); commit_echoes(tty); } @@ -1555,7 +1715,9 @@ static void n_tty_receive_buf_fast(struct tty_struct *tty, char *cp, int count) unsigned char c = *cp++; if (!test_bit(c, (int *)ldata->char_map)) - n_tty_receive_char_fast(tty, c); + { + 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); @@ -1625,12 +1787,16 @@ int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) { overflow = ldata->icanon && ldata->canon_head == tail; if (overflow && room < 0) - ldata->read_head--; + { + ldata->read_head--; + } + room = overflow; - //ldata->no_room = flow && !room; } else - overflow = 0; + { + overflow = 0; + } n = min(size, room); @@ -1640,7 +1806,9 @@ int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) } if (!overflow) - __receive_buf(tty, cp, n); + { + __receive_buf(tty, cp, n); + } cp += n; size -= n; @@ -1649,6 +1817,25 @@ int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) 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 int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) { int level; @@ -1658,10 +1845,16 @@ static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) struct rt_wqueue *wq = RT_NULL; int wait_ret = 0; int retval; + int c; level = rt_hw_interrupt_disable(); tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); + c = job_control(tty); + if (c < 0) + { + return c; + } struct n_tty_data *ldata = tty->disc_data; @@ -1695,8 +1888,9 @@ static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) } if (retval >= 1) - break; - + { + break; + } } rt_hw_interrupt_enable(level); return retval; @@ -1711,6 +1905,11 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) tty = (struct tty_struct *)fd->fnode->data; RT_ASSERT(tty != RT_NULL); + retval = tty_check_change(tty); + if (retval) + { + return retval; + } process_echoes(tty); retval = count; @@ -1724,7 +1923,10 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) if (num < 0) { if (num == -EAGAIN) - break; + { + break; + } + retval = num; goto break_out; } @@ -1737,9 +1939,11 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) c = *b; if (process_output(c, tty) < 0) - break; - b++; count--; + { + break; + } + b++; count--; } retval -= count; } diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c index 874e32202f..965546b4df 100644 --- a/components/drivers/tty/pty.c +++ b/components/drivers/tty/pty.c @@ -22,7 +22,6 @@ #define PTY_PTS_SIZE 1024 static struct tty_struct ptm_driver; static struct tty_struct pts_drivers[PTY_PTS_SIZE]; -//static struct tty_struct ptm_drivers[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); @@ -47,18 +46,18 @@ static int pty_set_lock(struct tty_struct *tty, int *arg) int val = *arg; if (val) - //set_bit(TTY_PTY_LOCK, &tty->flags); + { tty->pts_lock = val; + } else - //clear_bit(TTY_PTY_LOCK, &tty->flags); + { tty->pts_lock = val; + } return 0; } static int pty_get_lock(struct tty_struct *tty, int *arg) { - // int locked = test_bit(TTY_PTY_LOCK, &tty->flags); - // return put_user(locked, arg); *arg = tty->pts_lock; return 0; } @@ -170,14 +169,8 @@ static rt_err_t pty_device_control(rt_device_t dev, int cmd, void *args) return pty_set_lock(tty, (int *)args); case TIOCGPTLCK: /* Get PT Lock status */ return pty_get_lock(tty, (int *)args); - case TIOCPKT: /* Set PT packet mode */ - //return pty_set_pktmode(tty, (int __user *)arg); - case TIOCGPKT: /* Get PT packet mode */ - //return pty_get_pktmode(tty, (int __user *)arg); case TIOCGPTN: /* Get PT Number */ return pty_get_index(tty, (int *)args); - //case TIOCSIG: /* Send signal to other side of pty */ - //return pty_signal(tty, (int) arg); } return -ENOIOCTLCMD; @@ -289,7 +282,6 @@ static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, pts_drv->pts_lock = 1; rt_wqueue_init(&pts_drv->wait_queue); - tty_ldisc_init(pts_drv); extern struct termios tty_std_termios; diff --git a/components/drivers/tty/tty.c b/components/drivers/tty/tty.c index e08dadba8a..0c293b4974 100644 --- a/components/drivers/tty/tty.c +++ b/components/drivers/tty/tty.c @@ -37,6 +37,76 @@ struct termios tty_std_termios = { /* for the benefit of tty drivers */ .__c_ospeed = 38400 }; +static int is_ignored(int sig) +{ + return (sigismember(¤t->signal, sig) || + current->signal_handler[sig-1] == SIG_IGN); +} + +/** + * 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) +{ + unsigned long flags; + pid_t pgrp, tty_pgrp; + struct rt_lwp *lwp = tty->foreground; + int ret = 0; + int level; + + level = rt_hw_interrupt_disable(); + if (current == RT_NULL) + { + return 0; + } + + if (current->tty != tty) + { + return 0; + } + + pgrp = current->__pgrp; + tty_pgrp = tty->pgrp; + + if (tty_pgrp && pgrp != tty->pgrp) + { + if (is_ignored(sig)) + { + if (sig == SIGTTIN) + { + ret = -EIO; + } + } + else + { + if (lwp) + { + lwp_kill(lwp_to_pid(lwp), sig); + } + } + } + rt_hw_interrupt_enable(level); + + if (!tty_pgrp) + { + LOG_D(tty, "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_fd *fd) { int ret = 0; @@ -131,9 +201,13 @@ static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) 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; + { + real_tty = tty; + } switch (cmd) { case TIOCSCTTY: @@ -234,9 +308,3 @@ void console_set_fops(struct dfs_file_ops *fops) { *fops = console_fops; } - -// void tty_system_init(void) -// { - -// } -// INIT_DEVICE_EXPORT(tty_system_init); diff --git a/components/drivers/tty/tty_ioctl.c b/components/drivers/tty/tty_ioctl.c index 8427bfad35..06aaf56fb0 100644 --- a/components/drivers/tty/tty_ioctl.c +++ b/components/drivers/tty/tty_ioctl.c @@ -39,66 +39,25 @@ static int set_termios(struct tty_struct *tty, void *arg, int opt) struct termios old_termios = tty->init_termios; struct tty_ldisc *ld; struct termios *new_termios = (struct termios *)arg; - // int retval = tty_check_change(tty); + int level; + int retval = tty_check_change(tty); - // if (retval) - // return retval; - -// down_read(&tty->termios_rwsem); -// tmp_termios = tty->termios; -// up_read(&tty->termios_rwsem); - -// if (opt & TERMIOS_TERMIO) { -// if (user_termio_to_kernel_termios(&tmp_termios, -// (struct termio __user *)arg)) -// return -EFAULT; -// #ifdef TCGETS2 -// } else if (opt & TERMIOS_OLD) { -// if (user_termios_to_kernel_termios_1(&tmp_termios, -// (struct termios __user *)arg)) -// return -EFAULT; -// } else { -// if (user_termios_to_kernel_termios(&tmp_termios, -// (struct termios2 __user *)arg)) -// return -EFAULT; -// } -// #else -// } else if (user_termios_to_kernel_termios(&tmp_termios, -// (struct termios __user *)arg)) -// return -EFAULT; -// #endif - - /* If old style Bfoo values are used then load c_ispeed/c_ospeed - * with the real speed so its unconditionally usable */ - //tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); - //tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); - - // ld = tty_ldisc_ref(tty); - - // if (ld != NULL) { - // if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) - // ld->ops->flush_buffer(tty); - // tty_ldisc_deref(ld); - // } - - // if (opt & TERMIOS_WAIT) { - // tty_wait_until_sent(tty, 0); - // if (signal_pending(current)) - // return -ERESTARTSYS; - // } + if (retval) + { + return retval; + } - //tty_set_termios(tty, &tmp_termios); + level = rt_hw_interrupt_disable(); tty->init_termios = *new_termios; + rt_hw_interrupt_enable(level); ld = tty->ldisc; if (ld != NULL) { if (ld->ops->set_termios) - ld->ops->set_termios(tty, &old_termios); + { + ld->ops->set_termios(tty, &old_termios); + } } - /* FIXME: Arguably if tmp_termios == tty->termios AND the - actual requested termios was not tmp_termios then we may - want to return an error as no user requested change has - succeeded */ return 0; } @@ -109,9 +68,13 @@ int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *args) struct tty_struct *real_tty; if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) + { real_tty = tty->other_struct; + } else + { real_tty = tty; + } switch(cmd) { diff --git a/components/drivers/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c index b273de52cc..5d11911512 100644 --- a/components/drivers/tty/tty_ldisc.c +++ b/components/drivers/tty/tty_ldisc.c @@ -39,7 +39,9 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) struct tty_ldisc_ops *ldops; if (disc < N_TTY || disc >= NR_LDISCS) - return RT_NULL; + { + return RT_NULL; + } ldops = get_ldops(disc); if (ldops == RT_NULL) @@ -69,7 +71,9 @@ 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) - return; + { + return; + } put_ldops(ld->ops); rt_free(ld); @@ -87,7 +91,9 @@ static void tty_ldisc_put(struct tty_ldisc *ld) static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) { if (ld->ops->close) + { ld->ops->close(tty); + } } /** @@ -115,8 +121,10 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) int level; if (disc < N_TTY || disc >= NR_LDISCS) + { return -EINVAL; - + } + level = rt_hw_interrupt_disable(); tty_ldiscs[disc] = new_ldisc; new_ldisc->num = disc; @@ -147,7 +155,9 @@ void tty_ldisc_release(struct tty_struct *tty) level = rt_hw_interrupt_disable(); tty_ldisc_kill(tty); if (o_tty) + { tty_ldisc_kill(o_tty); + } rt_hw_interrupt_enable(level); } -- Gitee From 0e9d5716bd605147f3635daa03ebcd8cf38122f2 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 15 Dec 2021 14:30:57 +0800 Subject: [PATCH 11/13] format code --- components/drivers/tty/console.c | 2 +- .../drivers/tty/include/posix_termios.h | 98 ++++----- components/drivers/tty/include/tty.h | 74 ++++--- components/drivers/tty/n_tty.c | 196 +++++++++--------- components/drivers/tty/posix_termios.c | 2 +- components/drivers/tty/pty.c | 2 +- components/drivers/tty/tty.c | 79 ++++--- components/drivers/tty/tty_ioctl.c | 4 +- components/drivers/tty/tty_ldisc.c | 10 +- 9 files changed, 244 insertions(+), 223 deletions(-) diff --git a/components/drivers/tty/console.c b/components/drivers/tty/console.c index bdc44dca2e..58368ec61a 100644 --- a/components/drivers/tty/console.c +++ b/components/drivers/tty/console.c @@ -47,7 +47,7 @@ static void console_rx_notify(struct rt_device *dev) break; } } - + if (console->ldisc->ops->receive_buf) { console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens); diff --git a/components/drivers/tty/include/posix_termios.h b/components/drivers/tty/include/posix_termios.h index 4d640569ce..6f4caa230c 100644 --- a/components/drivers/tty/include/posix_termios.h +++ b/components/drivers/tty/include/posix_termios.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -80,33 +80,33 @@ struct termios { #define ONOCR 0000020 #define ONLRET 0000040 -#define OFILL 00000100 -#define OFDEL 00000200 -#define NLDLY 00001400 -#define NL0 00000000 -#define NL1 00000400 -#define NL2 00001000 -#define NL3 00001400 -#define TABDLY 00006000 -#define TAB0 00000000 -#define TAB1 00002000 -#define TAB2 00004000 -#define TAB3 00006000 -#define CRDLY 00030000 -#define KCR0 00000000 -#define KCR1 00010000 -#define KCR2 00020000 -#define KCR3 00030000 -#define FFDLY 00040000 -#define FF0 00000000 -#define FF1 00040000 -#define BSDLY 00100000 -#define BS0 00000000 -#define BS1 00100000 -#define VTDLY 00200000 -#define VT0 00000000 -#define VT1 00200000 -#define XTABS 01000000 +#define OFILL 00000100 +#define OFDEL 00000200 +#define NLDLY 00001400 +#define NL0 00000000 +#define NL1 00000400 +#define NL2 00001000 +#define NL3 00001400 +#define TABDLY 00006000 +#define TAB0 00000000 +#define TAB1 00002000 +#define TAB2 00004000 +#define TAB3 00006000 +#define CRDLY 00030000 +#define KCR0 00000000 +#define KCR1 00010000 +#define KCR2 00020000 +#define KCR3 00030000 +#define FFDLY 00040000 +#define FF0 00000000 +#define FF1 00040000 +#define BSDLY 00100000 +#define BS0 00000000 +#define BS1 00100000 +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 +#define XTABS 01000000 /* c_cflag bit meaning */ #define B0 0000000 @@ -155,22 +155,22 @@ struct termios { #define CLOCAL 0004000 /* c_lflag bits */ -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 -#define EXTPROC 0200000 +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define IEXTEN 0100000 +#define EXTPROC 0200000 #define TCOOFF 0 #define TCOON 1 @@ -201,11 +201,11 @@ struct termios { #define PENDIN 0040000 #define EXTPROC 0200000 -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 */ #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" diff --git a/components/drivers/tty/include/tty.h b/components/drivers/tty/include/tty.h index 53a335c4b4..a185b6109f 100644 --- a/components/drivers/tty/include/tty.h +++ b/components/drivers/tty/include/tty.h @@ -363,38 +363,41 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) rt_inline unsigned long __ffs(unsigned long word) { - int num = 0; + int num = 0; #if BITS_PER_LONG == 64 - if ((word & 0xffffffff) == 0) - { - num += 32; - word >>= 32; - } + 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; + 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) @@ -410,7 +413,10 @@ rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long s unsigned long tmp; if (offset >= size) + { return size; + } + size -= result; offset %= BITS_PER_LONG; if (offset) @@ -419,12 +425,12 @@ rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long s tmp &= (~0UL << offset); if (size < BITS_PER_LONG) { - goto found_first; + goto found_first; } if (tmp) { - goto found_middle; + goto found_middle; } size -= BITS_PER_LONG; @@ -435,7 +441,7 @@ rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long s { if ((tmp = *(p++))) { - goto found_middle; + goto found_middle; } result += BITS_PER_LONG; @@ -444,7 +450,7 @@ rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long s if (!size) { - return result; + return result; } tmp = *p; @@ -453,7 +459,7 @@ found_first: tmp &= (~0UL >> (BITS_PER_LONG - size)); if (tmp == 0UL) /* Are any bits set? */ { - return result + size; /* Nope. */ + return result + size; /* Nope. */ } found_middle: diff --git a/components/drivers/tty/n_tty.c b/components/drivers/tty/n_tty.c index 7d0835a2a1..8e7685aecc 100644 --- a/components/drivers/tty/n_tty.c +++ b/components/drivers/tty/n_tty.c @@ -237,7 +237,7 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, /* Set the high bit as a flag if num_chars is after a previous tab */ if (after_tab) { - num_chars |= 0x80; + num_chars |= 0x80; } add_echo_byte(num_chars, ldata); @@ -292,7 +292,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty) { if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') { - add_echo_byte(ECHO_OP_START, ldata); + add_echo_byte(ECHO_OP_START, ldata); } add_echo_byte(c, ldata); } @@ -390,7 +390,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) /* Add a newline if ECHOK is on and ECHOKE is off. */ if (L_ECHOK(tty)) { - echo_char_raw('\n', ldata); + echo_char_raw('\n', ldata); } return; } @@ -412,7 +412,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) /* do not partially erase */ if (is_continuation(c, tty)) { - break; + break; } if (kill_type == WERASE) @@ -477,7 +477,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) { if (L_ECHOCTL(tty)) { - num_chars += 2; + num_chars += 2; } } else if (!is_continuation(c, tty)) @@ -505,28 +505,28 @@ static void eraser(unsigned char c, struct tty_struct *tty) } if (kill_type == KERASE) { - break; + break; } } if (ldata->read_head == ldata->canon_head && L_ECHO(tty)) { - finish_erasing(ldata); + finish_erasing(ldata); } } /** - * isig - handle the ISIG optio - * @sig: signal - * @tty: terminal + * 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. + * 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. + * 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 + * Locking: ctrl_lock */ static void __isig(int sig, struct tty_struct *tty) @@ -540,25 +540,25 @@ static void __isig(int sig, struct tty_struct *tty) static void isig(int sig, struct tty_struct *tty) { - struct n_tty_data *ldata = tty->disc_data; + struct n_tty_data *ldata = tty->disc_data; - if (L_NOFLSH(tty)) + if (L_NOFLSH(tty)) { - /* signal only */ - __isig(sig, tty); + /* signal only */ + __isig(sig, tty); - } + } else { /* signal and flush */ - __isig(sig, tty); + __isig(sig, tty); - /* clear echo buffer */ - ldata->echo_head = ldata->echo_tail = 0; - ldata->echo_mark = ldata->echo_commit = 0; + /* 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); - } + /* clear input buffer */ + reset_buffer_flags(tty->disc_data); + } } /** @@ -594,7 +594,7 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) case '\n': if (O_ONLRET(tty)) { - ldata->column = 0; + ldata->column = 0; } if (O_ONLCR(tty)) @@ -609,7 +609,7 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) case '\r': if (O_ONOCR(tty) && ldata->column == 0) { - return 0; + return 0; } if (O_OCRNL(tty)) @@ -617,7 +617,7 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) c = '\n'; if (O_ONLRET(tty)) { - ldata->canon_column = ldata->column = 0; + ldata->canon_column = ldata->column = 0; } break; } @@ -637,7 +637,7 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) case '\b': if (ldata->column > 0) { - ldata->column--; + ldata->column--; } ch = "\b \b"; rt_device_write((rt_device_t)tty, -1, ch, strlen(ch)); @@ -733,24 +733,24 @@ static ssize_t process_output_block(struct tty_struct *tty, case '\n': if (O_ONLRET(tty)) { - ldata->column = 0; + ldata->column = 0; } if (O_ONLCR(tty)) { - goto break_out; + goto break_out; } ldata->canon_column = ldata->column; break; case '\r': if (O_ONOCR(tty) && ldata->column == 0) { - goto break_out; + goto break_out; } if (O_OCRNL(tty)) { - goto break_out; + goto break_out; } ldata->canon_column = ldata->column = 0; @@ -760,7 +760,7 @@ static ssize_t process_output_block(struct tty_struct *tty, case '\b': if (ldata->column > 0) { - ldata->column--; + ldata->column--; } break; default: @@ -768,12 +768,12 @@ static ssize_t process_output_block(struct tty_struct *tty, { if (O_OLCUC(tty)) { - goto break_out; + goto break_out; } if (!is_continuation(c, tty)) { - ldata->column++; + ldata->column++; } } break; @@ -826,7 +826,7 @@ static size_t __process_echoes(struct tty_struct *tty) */ if (!(num_chars & 0x80)) { - num_chars += ldata->canon_column; + num_chars += ldata->canon_column; } num_bs = 8 - (num_chars & 7); @@ -836,7 +836,7 @@ static size_t __process_echoes(struct tty_struct *tty) rt_device_write((rt_device_t)tty, -1, &ch, 1); if (ldata->column > 0) { - ldata->column--; + ldata->column--; } } tail += 3; @@ -850,7 +850,7 @@ static size_t __process_echoes(struct tty_struct *tty) case ECHO_OP_MOVE_BACK_COL: if (ldata->column > 0) { - ldata->column--; + ldata->column--; } tail += 2; break; @@ -887,7 +887,7 @@ static size_t __process_echoes(struct tty_struct *tty) int retval = do_output_char(c, tty); if (retval < 0) { - break; + break; } } else @@ -916,7 +916,7 @@ static size_t __process_echoes(struct tty_struct *tty) } else { - tail++; + tail++; } } @@ -941,7 +941,7 @@ static void commit_echoes(struct tty_struct *tty) nr = head - ldata->echo_tail; if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) { - return; + return; } level = rt_hw_interrupt_disable(); @@ -956,7 +956,7 @@ static void process_echoes(struct tty_struct *tty) int level; if (ldata->echo_mark == ldata->echo_tail) { - return; + return; } level = rt_hw_interrupt_disable(); @@ -974,7 +974,7 @@ static void flush_echoes(struct tty_struct *tty) if ((!L_ECHO(tty) && !L_ECHONL(tty)) || ldata->echo_commit == ldata->echo_head) { - return; + return; } level = rt_hw_interrupt_disable(); @@ -1035,7 +1035,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) if (I_INLCR(tty)) { - set_bit('\n', (int *)ldata->char_map); + set_bit('\n', (int *)ldata->char_map); } if (L_ICANON(tty)) @@ -1053,7 +1053,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) if (L_ECHO(tty)) { set_bit(REPRINT_CHAR(tty), - (int *)ldata->char_map); + (int *)ldata->char_map); } } } @@ -1079,11 +1079,11 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) (I_IGNPAR(tty) || !I_INPCK(tty))/* && (tty->driver->flags & TTY_DRIVER_REAL_RAW)*/) { - ldata->real_raw = 1; + ldata->real_raw = 1; } else { - ldata->real_raw = 0; + ldata->real_raw = 0; } } } @@ -1193,7 +1193,7 @@ static int copy_from_read_buf(struct tty_struct *tty,char *b,size_t nr) if (L_EXTPROC(tty) && ldata->icanon && is_eof && (head == ldata->read_tail)) { - n = 0; + n = 0; } } @@ -1234,7 +1234,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) /* N.B. avoid overrun if nr == 0 */ if (nr == 0) { - return 0; + return 0; } n = min(nr + 1, ldata->canon_head - ldata->read_tail); @@ -1252,13 +1252,13 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) } else { - found = eol != size; + found = eol != size; } n = eol - tail; if (n > RT_TTY_BUF) { - n += RT_TTY_BUF; + n += RT_TTY_BUF; } c = n + found; @@ -1281,7 +1281,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr) if (found) { - clear_bit(eol, (int *)ldata->read_flags); + clear_bit(eol, (int *)ldata->read_flags); } ldata->read_tail = ldata->read_tail + c; @@ -1346,14 +1346,14 @@ static int n_tty_ioctl(struct dfs_fd *fd, int cmd, void *args) ret = n_tty_ioctl_extend(real_tty, cmd, args); if (ret != -ENOIOCTLCMD) { - return ret; + return ret; } } ret = rt_device_control((rt_device_t)real_tty, cmd, args); if (ret != -ENOIOCTLCMD) { - return ret; + return ret; } return ret; } @@ -1361,17 +1361,17 @@ static int n_tty_ioctl(struct dfs_fd *fd, int cmd, void *args) static void n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) { - isig(signal, tty); - if (L_ECHO(tty)) + isig(signal, tty); + if (L_ECHO(tty)) { - echo_char(c, tty); - commit_echoes(tty); - } + echo_char(c, tty); + commit_echoes(tty); + } else { - process_echoes(tty); + process_echoes(tty); } - return; + return; } /** @@ -1441,7 +1441,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) } else if (c == '\n' && I_INLCR(tty)) { - c = '\r'; + c = '\r'; } if (ldata->icanon) @@ -1508,7 +1508,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) { - echo_set_canon_col(ldata); + echo_set_canon_col(ldata); } echo_char(c, tty); @@ -1520,7 +1520,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) { - put_tty_queue(c, ldata); + put_tty_queue(c, ldata); } handle_newline: @@ -1537,14 +1537,14 @@ handle_newline: finish_erasing(ldata); if (c == '\n') { - echo_char_raw('\n', ldata); + 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_set_canon_col(ldata); } echo_char(c, tty); } @@ -1554,7 +1554,7 @@ handle_newline: /* PARMRK doubling check */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) { - put_tty_queue(c, ldata); + put_tty_queue(c, ldata); } put_tty_queue(c, ldata); @@ -1571,7 +1571,7 @@ static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned ch /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) { - echo_set_canon_col(ldata); + echo_set_canon_col(ldata); } echo_char(c, tty); @@ -1580,7 +1580,7 @@ static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned ch /* PARMRK doubling check */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) { - put_tty_queue(c, ldata); + put_tty_queue(c, ldata); } put_tty_queue(c, ldata); @@ -1600,12 +1600,12 @@ static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, ch { if (I_ISTRIP(tty)) { - c &= 0x7f; + c &= 0x7f; } if (I_IUCLC(tty) && L_IEXTEN(tty)) { - c = tolower(c); + c = tolower(c); } n_tty_receive_char(tty, c); @@ -1644,7 +1644,7 @@ static void n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count) { if (flag == TTY_NORMAL) { - put_tty_queue(*cp++, ldata); + put_tty_queue(*cp++, ldata); } } } @@ -1665,7 +1665,7 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int cou if (I_IUCLC(tty) && L_IEXTEN(tty)) { - c = tolower(c); + c = tolower(c); } if (L_EXTPROC(tty)) @@ -1676,7 +1676,7 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int cou if (!test_bit(c, (int *)ldata->char_map)) { - n_tty_receive_char_inline(tty, c); + n_tty_receive_char_inline(tty, c); } else if (n_tty_receive_char_special(tty, c) && count) { @@ -1696,7 +1696,7 @@ static inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) { - echo_set_canon_col(ldata); + echo_set_canon_col(ldata); } echo_char(c, tty); @@ -1716,7 +1716,7 @@ static void n_tty_receive_buf_fast(struct tty_struct *tty, char *cp, int count) if (!test_bit(c, (int *)ldata->char_map)) { - n_tty_receive_char_fast(tty, c); + n_tty_receive_char_fast(tty, c); } else if (n_tty_receive_char_special(tty, c) && count) { @@ -1788,14 +1788,14 @@ int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) overflow = ldata->icanon && ldata->canon_head == tail; if (overflow && room < 0) { - ldata->read_head--; + ldata->read_head--; } room = overflow; } else { - overflow = 0; + overflow = 0; } n = min(size, room); @@ -1807,7 +1807,7 @@ int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) if (!overflow) { - __receive_buf(tty, cp, n); + __receive_buf(tty, cp, n); } cp += n; @@ -1818,22 +1818,22 @@ int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) } /** - * job_control - check job control - * @tty: tty - * @file: file handle + * 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. + * 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 + * 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); + return __tty_check_change(tty, SIGTTIN); } static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) @@ -1853,7 +1853,7 @@ static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) c = job_control(tty); if (c < 0) { - return c; + return c; } struct n_tty_data *ldata = tty->disc_data; @@ -1889,7 +1889,7 @@ static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) if (retval >= 1) { - break; + break; } } rt_hw_interrupt_enable(level); @@ -1908,7 +1908,7 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) retval = tty_check_change(tty); if (retval) { - return retval; + return retval; } process_echoes(tty); @@ -1924,7 +1924,7 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) { if (num == -EAGAIN) { - break; + break; } retval = num; @@ -1940,7 +1940,7 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) c = *b; if (process_output(c, tty) < 0) { - break; + break; } b++; count--; diff --git a/components/drivers/tty/posix_termios.c b/components/drivers/tty/posix_termios.c index 2bfd6ea682..801ace68a2 100644 --- a/components/drivers/tty/posix_termios.c +++ b/components/drivers/tty/posix_termios.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c index 965546b4df..c56584df44 100644 --- a/components/drivers/tty/pty.c +++ b/components/drivers/tty/pty.c @@ -52,7 +52,7 @@ static int pty_set_lock(struct tty_struct *tty, int *arg) else { tty->pts_lock = val; - } + } return 0; } diff --git a/components/drivers/tty/tty.c b/components/drivers/tty/tty.c index 0c293b4974..43ba85c182 100644 --- a/components/drivers/tty/tty.c +++ b/components/drivers/tty/tty.c @@ -37,74 +37,89 @@ struct termios tty_std_termios = { /* for the benefit of tty drivers */ .__c_ospeed = 38400 }; + +rt_inline int tty_sigismember(lwp_sigset_t *set, int _sig) +{ + unsigned long sig = _sig - 1; + + if (_LWP_NSIG_WORDS == 1) + { + return 1 & (set->sig[0] >> sig); + } + else + { + return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW)); + } +} + static int is_ignored(int sig) { - return (sigismember(¤t->signal, sig) || - current->signal_handler[sig-1] == SIG_IGN); + return (tty_sigismember(¤t->signal, sig) || + current->signal_handler[sig-1] == SIG_IGN); } /** - * tty_check_change - check for POSIX terminal changes - * @tty: tty to check + * 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) + * 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 + * Locking: ctrl_lock */ int __tty_check_change(struct tty_struct *tty, int sig) { - unsigned long flags; - pid_t pgrp, tty_pgrp; + unsigned long flags; + pid_t pgrp, tty_pgrp; struct rt_lwp *lwp = tty->foreground; - int ret = 0; + int ret = 0; int level; level = rt_hw_interrupt_disable(); if (current == RT_NULL) { - return 0; + return 0; } - if (current->tty != tty) + if (current->tty != tty) { - return 0; + return 0; } - pgrp = current->__pgrp; - tty_pgrp = tty->pgrp; + pgrp = current->__pgrp; + tty_pgrp = tty->pgrp; - if (tty_pgrp && pgrp != tty->pgrp) + if (tty_pgrp && pgrp != tty->pgrp) { - if (is_ignored(sig)) + if (is_ignored(sig)) { - if (sig == SIGTTIN) + if (sig == SIGTTIN) { - ret = -EIO; + ret = -EIO; } - } - else + } + else { if (lwp) { lwp_kill(lwp_to_pid(lwp), sig); } - } - } + } + } rt_hw_interrupt_enable(level); - - if (!tty_pgrp) + + if (!tty_pgrp) { - LOG_D(tty, "sig=%d, tty->pgrp == -1!\n", sig); + LOG_D(tty, "sig=%d, tty->pgrp == -1!\n", sig); } - return ret; + return ret; } int tty_check_change(struct tty_struct *tty) { - return __tty_check_change(tty, SIGTTOU); + return __tty_check_change(tty, SIGTTOU); } static int tty_open(struct dfs_fd *fd) @@ -203,11 +218,11 @@ static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) { real_tty = tty->other_struct; - } + } else { - real_tty = tty; - } + real_tty = tty; + } switch (cmd) { case TIOCSCTTY: diff --git a/components/drivers/tty/tty_ioctl.c b/components/drivers/tty/tty_ioctl.c index 06aaf56fb0..39d6f66247 100644 --- a/components/drivers/tty/tty_ioctl.c +++ b/components/drivers/tty/tty_ioctl.c @@ -44,7 +44,7 @@ static int set_termios(struct tty_struct *tty, void *arg, int opt) if (retval) { - return retval; + return retval; } level = rt_hw_interrupt_disable(); @@ -55,7 +55,7 @@ static int set_termios(struct tty_struct *tty, void *arg, int opt) { if (ld->ops->set_termios) { - ld->ops->set_termios(tty, &old_termios); + ld->ops->set_termios(tty, &old_termios); } } return 0; diff --git a/components/drivers/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c index 5d11911512..edd33f5dac 100644 --- a/components/drivers/tty/tty_ldisc.c +++ b/components/drivers/tty/tty_ldisc.c @@ -40,7 +40,7 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) if (disc < N_TTY || disc >= NR_LDISCS) { - return RT_NULL; + return RT_NULL; } ldops = get_ldops(disc); @@ -72,7 +72,7 @@ static void tty_ldisc_put(struct tty_ldisc *ld) { if (ld == RT_NULL) { - return; + return; } put_ldops(ld->ops); @@ -93,7 +93,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) if (ld->ops->close) { ld->ops->close(tty); - } + } } /** @@ -124,7 +124,7 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) { return -EINVAL; } - + level = rt_hw_interrupt_disable(); tty_ldiscs[disc] = new_ldisc; new_ldisc->num = disc; @@ -157,7 +157,7 @@ void tty_ldisc_release(struct tty_struct *tty) if (o_tty) { tty_ldisc_kill(o_tty); - } + } rt_hw_interrupt_enable(level); } -- Gitee From ebe2ea2b798f9d02a1dcc3962f6bdebb32efeb9c Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 15 Dec 2021 16:58:34 +0800 Subject: [PATCH 12/13] =?UTF-8?q?pts=5Fdrivers=E5=8D=A0=E7=94=A8=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E7=A9=BA=E9=97=B4=E5=A4=AA=E5=A4=A7=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/tty/pty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c index c56584df44..cad978a704 100644 --- a/components/drivers/tty/pty.c +++ b/components/drivers/tty/pty.c @@ -19,7 +19,7 @@ #endif /* RT_TTY_DEBUG */ #include -#define PTY_PTS_SIZE 1024 +#define PTY_PTS_SIZE 10 static struct tty_struct ptm_driver; static struct tty_struct pts_drivers[PTY_PTS_SIZE]; static int pts_index = 0; -- Gitee From 8dbb9f456bdb10cd350d1d9b643c4a3395462ffc Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 15 Dec 2021 18:33:54 +0800 Subject: [PATCH 13/13] FORMAT CODE --- components/drivers/tty/include/tty.h | 10 ++-- components/drivers/tty/n_tty.c | 72 ++++++++++++++-------------- components/drivers/tty/pty.c | 5 +- components/drivers/tty/tty.c | 11 ++--- components/drivers/tty/tty_ioctl.c | 6 +-- components/drivers/tty/tty_ldisc.c | 14 +++--- 6 files changed, 58 insertions(+), 60 deletions(-) diff --git a/components/drivers/tty/include/tty.h b/components/drivers/tty/include/tty.h index a185b6109f..681c472808 100644 --- a/components/drivers/tty/include/tty.h +++ b/components/drivers/tty/include/tty.h @@ -361,17 +361,17 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) return retval; } - rt_inline unsigned long __ffs(unsigned long word) - { +rt_inline unsigned long __ffs(unsigned long word) +{ int num = 0; - #if BITS_PER_LONG == 64 +#if BITS_PER_LONG == 64 if ((word & 0xffffffff) == 0) { num += 32; word >>= 32; } - #endif +#endif if ((word & 0xffff) == 0) { num += 16; @@ -398,7 +398,7 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr) } return num; - } +} #define BITS_PER_LONG 32 #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) diff --git a/components/drivers/tty/n_tty.c b/components/drivers/tty/n_tty.c index 8e7685aecc..2eff927891 100644 --- a/components/drivers/tty/n_tty.c +++ b/components/drivers/tty/n_tty.c @@ -356,8 +356,8 @@ 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; - size_t cnt; + size_t head = 0; + size_t cnt = 0; int seen_alnums; if (ldata->read_head == ldata->canon_head) @@ -586,8 +586,8 @@ static void isig(int sig, struct tty_struct *tty) static int do_output_char(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - int spaces; - char *ch; + int spaces = 0; + char *ch = RT_NULL; switch (c) { @@ -678,8 +678,8 @@ static int do_output_char(unsigned char c, struct tty_struct *tty) static int process_output(unsigned char c, struct tty_struct *tty) { - int retval; - int level; + int retval = 0; + int level = 0; level = rt_hw_interrupt_disable(); retval = do_output_char(c, tty); @@ -717,10 +717,10 @@ 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; - ssize_t size; - const char *cp; - int level; + int i = 0; + ssize_t size = 0; + const char *cp = RT_NULL; + int level = 0; level = rt_hw_interrupt_disable(); @@ -788,9 +788,9 @@ break_out: static size_t __process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - size_t tail; - unsigned char c; - char ch; + size_t tail = 0; + unsigned char c = 0; + char ch = 0; tail = ldata->echo_tail; while (ldata->echo_commit != tail) @@ -927,9 +927,9 @@ static size_t __process_echoes(struct tty_struct *tty) static void commit_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - size_t nr, old; - size_t head; - int level; + size_t nr = 0, old = 0; + size_t head = 0; + int level = 0; head = ldata->echo_head; ldata->echo_mark = head; @@ -953,7 +953,7 @@ static void commit_echoes(struct tty_struct *tty) static void process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - int level; + int level = 0; if (ldata->echo_mark == ldata->echo_tail) { return; @@ -969,7 +969,7 @@ static void process_echoes(struct tty_struct *tty) static void flush_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - int level; + int level = 0; if ((!L_ECHO(tty) && !L_ECHONL(tty)) || ldata->echo_commit == ldata->echo_head) @@ -1090,10 +1090,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios *old) void console_ldata_init(struct tty_struct *tty) { - struct n_tty_data *ldata; + struct n_tty_data *ldata = RT_NULL; ldata = rt_malloc(sizeof(struct n_tty_data)); - if (ldata ==RT_NULL) + if (ldata == RT_NULL) { LOG_E("console_ldata_init ldata malloc fail"); return; @@ -1111,7 +1111,7 @@ void console_ldata_init(struct tty_struct *tty) static int n_tty_open(struct dfs_fd *fd) { int ret = 0; - struct n_tty_data *ldata; + struct n_tty_data *ldata = RT_NULL; struct tty_struct *tty = (struct tty_struct*)fd->fnode->data; ldata = rt_malloc(sizeof(struct n_tty_data)); @@ -1176,8 +1176,8 @@ static inline int input_available_p(struct tty_struct *tty, int poll) 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; - rt_bool_t is_eof; + 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); @@ -1226,9 +1226,9 @@ static int copy_from_read_buf(struct tty_struct *tty,char *b,size_t nr) 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, size, more, c; - size_t eol; - size_t tail; + 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 */ @@ -1390,8 +1390,7 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) * Returns 1 if LNEXT was received, else returns 0 */ -static int -n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) +static int n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1620,7 +1619,7 @@ static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, ch 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, head; + size_t n = 0, head = 0; head = ldata->read_head & (RT_TTY_BUF - 1); n = min(count, RT_TTY_BUF - head); @@ -1767,9 +1766,9 @@ static void __receive_buf(struct tty_struct *tty, char *cp, int count) int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count) { - int size; + int size = 0; struct n_tty_data *ldata = tty->disc_data; - int room, n, rcvd = 0, overflow; + int room = 0, n = 0, rcvd = 0, overflow = 0; size = count; while(1) @@ -1838,14 +1837,14 @@ static int job_control(struct tty_struct *tty) static int n_tty_read(struct dfs_fd *fd, void *buf, size_t count) { - int level; + int level = 0; char *b = (char *)buf; struct tty_struct *tty = RT_NULL; struct rt_lwp *lwp = RT_NULL; struct rt_wqueue *wq = RT_NULL; int wait_ret = 0; - int retval; - int c; + int retval = 0; + int c = 0; level = rt_hw_interrupt_disable(); tty = (struct tty_struct *)fd->fnode->data; @@ -1900,7 +1899,7 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) { int retval = 0; char *b = (char *)buf; - int c; + int c = 0; struct tty_struct *tty = RT_NULL; tty = (struct tty_struct *)fd->fnode->data; @@ -1943,7 +1942,8 @@ static int n_tty_write(struct dfs_fd *fd, const void *buf, size_t count) break; } - b++; count--; + b++; + count--; } retval -= count; } diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c index cad978a704..050b99e2e9 100644 --- a/components/drivers/tty/pty.c +++ b/components/drivers/tty/pty.c @@ -74,8 +74,8 @@ static int pty_get_index(struct tty_struct *tty, int *arg) static rt_err_t pty_device_init(struct rt_device *dev) { rt_err_t result = RT_EOK; - int level; - struct tty_struct *tty= RT_NULL; + int level = 0; + struct tty_struct *tty = RT_NULL; RT_ASSERT(dev != RT_NULL); tty = (struct tty_struct *)dev; @@ -155,7 +155,6 @@ static rt_size_t pty_device_write(struct rt_device *dev, } rt_hw_interrupt_enable(level); - return len; } diff --git a/components/drivers/tty/tty.c b/components/drivers/tty/tty.c index 43ba85c182..0d68e9c81d 100644 --- a/components/drivers/tty/tty.c +++ b/components/drivers/tty/tty.c @@ -37,7 +37,6 @@ struct termios tty_std_termios = { /* for the benefit of tty drivers */ .__c_ospeed = 38400 }; - rt_inline int tty_sigismember(lwp_sigset_t *set, int _sig) { unsigned long sig = _sig - 1; @@ -71,11 +70,11 @@ static int is_ignored(int sig) int __tty_check_change(struct tty_struct *tty, int sig) { - unsigned long flags; - pid_t pgrp, tty_pgrp; + unsigned long flags = 0; + pid_t pgrp = 0, tty_pgrp = 0; struct rt_lwp *lwp = tty->foreground; int ret = 0; - int level; + int level = 0; level = rt_hw_interrupt_disable(); if (current == RT_NULL) @@ -125,7 +124,7 @@ int tty_check_change(struct tty_struct *tty) static int tty_open(struct dfs_fd *fd) { int ret = 0; - int noctty; + int noctty = 0; struct tty_struct *tty = RT_NULL; struct tty_ldisc *ld = RT_NULL; @@ -221,7 +220,7 @@ static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args) } else { - real_tty = tty; + real_tty = tty; } switch (cmd) { diff --git a/components/drivers/tty/tty_ioctl.c b/components/drivers/tty/tty_ioctl.c index 39d6f66247..62b1c7732d 100644 --- a/components/drivers/tty/tty_ioctl.c +++ b/components/drivers/tty/tty_ioctl.c @@ -37,9 +37,9 @@ static int set_termios(struct tty_struct *tty, void *arg, int opt) { struct termios old_termios = tty->init_termios; - struct tty_ldisc *ld; + struct tty_ldisc *ld = RT_NULL; struct termios *new_termios = (struct termios *)arg; - int level; + int level = 0; int retval = tty_check_change(tty); if (retval) @@ -65,7 +65,7 @@ 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; + struct tty_struct *real_tty = RT_NULL; if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER) { diff --git a/components/drivers/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c index edd33f5dac..350a297760 100644 --- a/components/drivers/tty/tty_ldisc.c +++ b/components/drivers/tty/tty_ldisc.c @@ -13,8 +13,8 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; static struct tty_ldisc_ops *get_ldops(int disc) { - struct tty_ldisc_ops *ldops; - int level; + struct tty_ldisc_ops *ldops = RT_NULL; + int level = 0; level = rt_hw_interrupt_disable(); ldops = tty_ldiscs[disc]; if (ldops) @@ -27,7 +27,7 @@ static struct tty_ldisc_ops *get_ldops(int disc) static void put_ldops(struct tty_ldisc_ops *ldops) { - int level; + int level = 0; level = rt_hw_interrupt_disable(); ldops->refcount--; @@ -35,8 +35,8 @@ static void put_ldops(struct tty_ldisc_ops *ldops) } static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld; - struct tty_ldisc_ops *ldops; + struct tty_ldisc *ld = RT_NULL; + struct tty_ldisc_ops *ldops = RT_NULL; if (disc < N_TTY || disc >= NR_LDISCS) { @@ -118,7 +118,7 @@ void tty_ldisc_kill(struct tty_struct *tty) int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) { int ret = 0; - int level; + int level = 0; if (disc < N_TTY || disc >= NR_LDISCS) { @@ -144,7 +144,7 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) void tty_ldisc_release(struct tty_struct *tty) { - int level; + int level = 0; struct tty_struct *o_tty = tty->other_struct; /* -- Gitee