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