[tty] change driver of tty to device and code cleanup. (#7444)

This commit is contained in:
Bernard Xiong 2023-05-05 08:19:09 +08:00 committed by GitHub
parent 0d7e18df1e
commit 8ad70ca231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 345 additions and 443 deletions

View File

@ -20,7 +20,7 @@
#endif /* RT_TTY_DEBUG */
#include <rtdbg.h>
static struct tty_struct console_driver;
static struct tty_struct console_dev;
static void console_rx_notify(struct rt_device *dev)
{
@ -35,7 +35,7 @@ static void console_rx_notify(struct rt_device *dev)
while (1)
{
len = rt_device_read(console->driver, -1, &ch, 1);
len = rt_device_read(console->io_dev, -1, &ch, 1);
if (len == 0)
{
break;
@ -56,7 +56,7 @@ static void console_rx_notify(struct rt_device *dev)
struct tty_struct *console_tty_get(void)
{
return &console_driver;
return &console_dev;
}
static void iodev_close(struct tty_struct *console)
@ -67,8 +67,8 @@ static void iodev_close(struct tty_struct *console)
rx_notify.dev = RT_NULL;
/* clear notify */
rt_device_control(console->driver, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
rt_device_close(console->driver);
rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
rt_device_close(console->io_dev);
}
static rt_err_t iodev_open(struct tty_struct *console)
@ -77,9 +77,9 @@ static rt_err_t iodev_open(struct tty_struct *console)
struct rt_device_notify rx_notify;
rt_uint16_t oflags = 0;
rt_device_control(console->driver, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags);
rt_device_control(console->io_dev, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags);
ret = rt_device_open(console->driver, oflags);
ret = rt_device_open(console->io_dev, oflags);
if (ret != RT_EOK)
{
return -RT_ERROR;
@ -87,7 +87,7 @@ static rt_err_t iodev_open(struct tty_struct *console)
rx_notify.notify = console_rx_notify;
rx_notify.dev = (struct rt_device *)console;
rt_device_control(console->driver, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
return RT_EOK;
}
@ -97,8 +97,9 @@ struct rt_device *console_get_iodev(void)
struct rt_device *iodev = RT_NULL;
level = rt_hw_interrupt_disable();
iodev = console_driver.driver;
iodev = console_dev.io_dev;
rt_hw_interrupt_enable(level);
return iodev;
}
@ -110,14 +111,13 @@ struct rt_device *console_set_iodev(struct rt_device *iodev)
RT_ASSERT(iodev != RT_NULL);
console = &console_driver;
console = &console_dev;
level = rt_hw_interrupt_disable();
RT_ASSERT(console->init_flag >= TTY_INIT_FLAG_REGED);
io_before = console->driver;
io_before = console->io_dev;
if (iodev == io_before)
{
goto exit;
@ -129,8 +129,7 @@ struct rt_device *console_set_iodev(struct rt_device *iodev)
iodev_close(console);
}
console->driver = iodev;
console->io_dev = iodev;
if (console->init_flag >= TTY_INIT_FLAG_INITED)
{
rt_err_t ret;
@ -218,7 +217,7 @@ static rt_ssize_t rt_console_write(struct rt_device *dev,
RT_ASSERT(console != RT_NULL);
RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
len = rt_device_write((struct rt_device *)console->driver, -1, buffer, size);
len = rt_device_write((struct rt_device *)console->io_dev, -1, buffer, size);
return len;
}
@ -232,7 +231,7 @@ static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args)
RT_ASSERT(console != RT_NULL);
RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
len = rt_device_control((struct rt_device *)console->driver, cmd, args);
len = rt_device_control((struct rt_device *)console->io_dev, cmd, args);
return len;
}
@ -248,23 +247,24 @@ const static struct rt_device_ops console_ops =
rt_console_control,
};
#endif
/*
* console register
*/
static struct dfs_file_ops con_fops;
static struct dfs_file_ops con_fops;
rt_err_t console_register(const char *name, struct rt_device *iodev)
{
rt_base_t level = 0;
rt_err_t ret = RT_EOK;
struct rt_device *device = RT_NULL;
struct tty_struct *console = &console_driver;
struct tty_struct *console = &console_dev;
level = rt_hw_interrupt_disable();
RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE);
RT_ASSERT(iodev != RT_NULL);
RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE);
tty_init(console, TTY_DRIVER_TYPE_CONSOLE, SERIAL_TYPE_NORMAL, iodev);
console_ldata_init(console);
device = &(console->parent);
device->type = RT_Device_Class_Char;
#ifdef RT_USING_DEVICE_OPS
@ -278,48 +278,20 @@ rt_err_t console_register(const char *name, struct rt_device *iodev)
device->control = rt_console_control;
#endif
/* register a character device */
ret = rt_device_register(device, name, 0);
if (ret != RT_EOK)
{
LOG_E("console driver register fail\n");
goto exit;
}
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
console_set_fops(&con_fops);
device->fops = &con_fops;
#endif
console->type = TTY_DRIVER_TYPE_CONSOLE;
console->subtype = SERIAL_TYPE_NORMAL;
console->driver = iodev;
console->head = rt_calloc(1, sizeof(struct tty_node));
if (!console->head)
else
{
return -RT_ENOMEM;
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
memcpy(&con_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
device->fops = &con_fops;
#endif
}
tty_initstack(console->head);
rt_mutex_init(&console->lock, "ttylock", RT_IPC_FLAG_PRIO);
console->pgrp = -1;
console->session = -1;
console->foreground = RT_NULL;
rt_wqueue_init(&console->wait_queue);
tty_ldisc_init(console);
extern struct termios tty_std_termios;
console->init_termios = tty_std_termios;
console->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL; /* is normally B9600 default... */
console->init_termios.__c_ispeed = 9600;
console->init_termios.__c_ospeed = 9600;
console_ldata_init(console);
console->init_flag = TTY_INIT_FLAG_REGED;
exit:
rt_hw_interrupt_enable(level);
return ret;
}

View File

@ -160,7 +160,7 @@ struct tty_struct
struct tty_ldisc *ldisc;
void *disc_data;
struct rt_device *driver;
struct rt_device *io_dev;
struct rt_wqueue wait_queue;
@ -208,28 +208,6 @@ enum
#define TTY_PTY_LOCK 16
#define TTY_NO_WRITE_SPLIT 17
/*
* These bits are used in the flags field of the tty structure.
*
* So that interrupts won't be able to mess up the queues,
* copy_to_cooked must be atomic with respect to itself, as must
* tty->write. Thus, you must use the inline functions set_bit() and
* clear_bit() to make things atomic.
*/
#define TTY_THROTTLED 0
#define TTY_IO_ERROR 1
#define TTY_OTHER_CLOSED 2
#define TTY_EXCLUSIVE 3
#define TTY_DEBUG 4
#define TTY_DO_WRITE_WAKEUP 5
#define TTY_PUSH 6
#define TTY_CLOSING 7
#define TTY_DONT_FLIP 8
#define TTY_HW_COOK_OUT 14
#define TTY_HW_COOK_IN 15
#define TTY_PTY_LOCK 16
#define TTY_NO_WRITE_SPLIT 17
#define NR_LDISCS 30
/* line disciplines */
@ -270,14 +248,6 @@ enum
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
/* tty driver types */
#define TTY_DRIVER_TYPE_SYSTEM 0x0001
#define TTY_DRIVER_TYPE_CONSOLE 0x0002
#define TTY_DRIVER_TYPE_SERIAL 0x0003
#define TTY_DRIVER_TYPE_PTY 0x0004
#define TTY_DRIVER_TYPE_SCC 0x0005 /* scc driver */
#define TTY_DRIVER_TYPE_SYSCONS 0x0006
/* pty subtypes */
#define PTY_TYPE_MASTER 0x0001
#define PTY_TYPE_SLAVE 0x0002
@ -295,8 +265,6 @@ enum
typeof(b) _b = b;\
_a < _b ? _a : _b; })
void tty_set_fops(struct dfs_file_ops *fops);
void console_set_fops(struct dfs_file_ops *fops);
void mutex_lock(rt_mutex_t mutex);
void mutex_unlock(rt_mutex_t mutex);
int __tty_check_change(struct tty_struct *tty, int sig);
@ -324,167 +292,12 @@ rt_inline void tty_wakeup_check(struct tty_struct *tty)
rt_wqueue_wakeup(wq, (void*)POLLIN);
}
rt_inline int set_bit(int nr,int *addr)
{
int mask, retval, level;
int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev);
const struct dfs_file_ops *tty_get_fops(void);
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
level = rt_hw_interrupt_disable();
retval = (mask & *addr) != 0;
*addr |= mask;
rt_hw_interrupt_enable(level);
return retval;
}
rt_inline int clear_bit(int nr, int *addr)
{
int mask, retval, level;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
level = rt_hw_interrupt_disable();
retval = (mask & *addr) != 0;
*addr &= ~mask;
rt_hw_interrupt_enable(level);
return retval;
}
rt_inline int test_bit(int nr, int *addr)
{
int mask;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
return ((mask & *addr) != 0);
}
rt_inline int test_and_clear_bit(int nr, volatile void *addr)
{
int mask, retval, level;
volatile unsigned int *a = addr;
a += nr >> 5;
mask = 1 << (nr & 0x1f);
level = rt_hw_interrupt_disable();
retval = (mask & *a) != 0;
*a &= ~mask;
rt_hw_interrupt_enable(level);
return retval;
}
rt_inline unsigned long __ffs(unsigned long word)
{
int num = 0;
#if BITS_PER_LONG == 64
if ((word & 0xffffffff) == 0)
{
num += 32;
word >>= 32;
}
#endif
if ((word & 0xffff) == 0)
{
num += 16;
word >>= 16;
}
if ((word & 0xff) == 0)
{
num += 8;
word >>= 8;
}
if ((word & 0xf) == 0)
{
num += 4;
word >>= 4;
}
if ((word & 0x3) == 0)
{
num += 2;
word >>= 2;
}
if ((word & 0x1) == 0)
{
num += 1;
}
return num;
}
#define BITS_PER_LONG 32
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
/*
* Find the next set bit in a memory region.
*/
rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
unsigned long offset)
{
const unsigned long *p = addr + BITOP_WORD(offset);
unsigned long result = offset & ~(BITS_PER_LONG-1);
unsigned long tmp;
if (offset >= size)
{
return size;
}
size -= result;
offset %= BITS_PER_LONG;
if (offset)
{
tmp = *(p++);
tmp &= (~0UL << offset);
if (size < BITS_PER_LONG)
{
goto found_first;
}
if (tmp)
{
goto found_middle;
}
size -= BITS_PER_LONG;
result += BITS_PER_LONG;
}
while (size & ~(BITS_PER_LONG-1))
{
if ((tmp = *(p++)))
{
goto found_middle;
}
result += BITS_PER_LONG;
size -= BITS_PER_LONG;
}
if (!size)
{
return result;
}
tmp = *p;
found_first:
tmp &= (~0UL >> (BITS_PER_LONG - size));
if (tmp == 0UL) /* Are any bits set? */
{
return result + size; /* Nope. */
}
found_middle:
return result + __ffs(tmp);
}
/*create by tty_ioctl.c*/
int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *arg);
/*create by n_tty.c*/
void console_ldata_init(struct tty_struct *tty);
int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count);
void n_tty_init(void);
#endif /*__TTY_H__*/

View File

@ -50,19 +50,6 @@
#define ECHO_BLOCK 256
#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32)
rt_inline void tty_sigaddset(lwp_sigset_t *set, int _sig)
{
unsigned long sig = _sig - 1;
if (_LWP_NSIG_WORDS == 1)
{
set->sig[0] |= 1UL << sig;
}
else
{
set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW);
}
}
struct n_tty_data
{
@ -99,27 +86,197 @@ struct n_tty_data
rt_mutex_t output_lock;
};
static inline size_t read_cnt(struct n_tty_data *ldata)
rt_inline int set_bit(int nr,int *addr)
{
int mask, retval, level;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
level = rt_hw_interrupt_disable();
retval = (mask & *addr) != 0;
*addr |= mask;
rt_hw_interrupt_enable(level);
return retval;
}
rt_inline int clear_bit(int nr, int *addr)
{
int mask, retval, level;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
level = rt_hw_interrupt_disable();
retval = (mask & *addr) != 0;
*addr &= ~mask;
rt_hw_interrupt_enable(level);
return retval;
}
rt_inline int test_bit(int nr, int *addr)
{
int mask;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
return ((mask & *addr) != 0);
}
rt_inline int test_and_clear_bit(int nr, volatile void *addr)
{
int mask, retval, level;
volatile unsigned int *a = addr;
a += nr >> 5;
mask = 1 << (nr & 0x1f);
level = rt_hw_interrupt_disable();
retval = (mask & *a) != 0;
*a &= ~mask;
rt_hw_interrupt_enable(level);
return retval;
}
rt_inline unsigned long __ffs(unsigned long word)
{
int num = 0;
#if BITS_PER_LONG == 64
if ((word & 0xffffffff) == 0)
{
num += 32;
word >>= 32;
}
#endif
if ((word & 0xffff) == 0)
{
num += 16;
word >>= 16;
}
if ((word & 0xff) == 0)
{
num += 8;
word >>= 8;
}
if ((word & 0xf) == 0)
{
num += 4;
word >>= 4;
}
if ((word & 0x3) == 0)
{
num += 2;
word >>= 2;
}
if ((word & 0x1) == 0)
{
num += 1;
}
return num;
}
#define BITS_PER_LONG 32
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
/*
* Find the next set bit in a memory region.
*/
rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
unsigned long offset)
{
const unsigned long *p = addr + BITOP_WORD(offset);
unsigned long result = offset & ~(BITS_PER_LONG-1);
unsigned long tmp;
if (offset >= size)
{
return size;
}
size -= result;
offset %= BITS_PER_LONG;
if (offset)
{
tmp = *(p++);
tmp &= (~0UL << offset);
if (size < BITS_PER_LONG)
{
goto found_first;
}
if (tmp)
{
goto found_middle;
}
size -= BITS_PER_LONG;
result += BITS_PER_LONG;
}
while (size & ~(BITS_PER_LONG-1))
{
if ((tmp = *(p++)))
{
goto found_middle;
}
result += BITS_PER_LONG;
size -= BITS_PER_LONG;
}
if (!size)
{
return result;
}
tmp = *p;
found_first:
tmp &= (~0UL >> (BITS_PER_LONG - size));
if (tmp == 0UL) /* Are any bits set? */
{
return result + size; /* Nope. */
}
found_middle:
return result + __ffs(tmp);
}
rt_inline void tty_sigaddset(lwp_sigset_t *set, int _sig)
{
unsigned long sig = _sig - 1;
if (_LWP_NSIG_WORDS == 1)
{
set->sig[0] |= 1UL << sig;
}
else
{
set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW);
}
}
rt_inline size_t read_cnt(struct n_tty_data *ldata)
{
return ldata->read_head - ldata->read_tail;
}
static inline char read_buf(struct n_tty_data *ldata, size_t i)
rt_inline char read_buf(struct n_tty_data *ldata, size_t i)
{
return ldata->read_buf[i & (RT_TTY_BUF - 1)];
}
static inline char *read_buf_addr(struct n_tty_data *ldata, size_t i)
rt_inline char *read_buf_addr(struct n_tty_data *ldata, size_t i)
{
return &ldata->read_buf[i & (RT_TTY_BUF - 1)];
}
static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i)
rt_inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i)
{
return ldata->echo_buf[i & (RT_TTY_BUF - 1)];
}
static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i)
rt_inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i)
{
return &ldata->echo_buf[i & (RT_TTY_BUF - 1)];
}
@ -134,8 +291,7 @@ static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i)
* n_tty_receive_buf()/producer path:
* caller holds non-exclusive termios_rwsem
*/
static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
rt_inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
{
*read_buf_addr(ldata, ldata->read_head) = c;
ldata->read_head++;
@ -173,7 +329,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
* Add a character or operation byte to the echo buffer.
*/
static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
rt_inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
{
*echo_buf_addr(ldata, ldata->echo_head++) = c;
}
@ -298,7 +454,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
* @ldata: n_tty data
*/
static inline void finish_erasing(struct n_tty_data *ldata)
rt_inline void finish_erasing(struct n_tty_data *ldata)
{
if (ldata->erasing)
{
@ -316,7 +472,7 @@ static inline void finish_erasing(struct n_tty_data *ldata)
* of the character when printing
*/
static inline int is_utf8_continuation(unsigned char c)
rt_inline int is_utf8_continuation(unsigned char c)
{
return (c & 0xc0) == 0x80;
}
@ -329,7 +485,7 @@ static inline int is_utf8_continuation(unsigned char c)
* character and the terminal is in unicode mode.
*/
static inline int is_continuation(unsigned char c, struct tty_struct *tty)
rt_inline int is_continuation(unsigned char c, struct tty_struct *tty)
{
return I_IUTF8(tty) && is_utf8_continuation(c);
}
@ -1148,7 +1304,7 @@ static int n_tty_open(struct dfs_file *fd)
return ret;
}
static inline int input_available_p(struct tty_struct *tty, int poll)
rt_inline int input_available_p(struct tty_struct *tty, int poll)
{
struct n_tty_data *ldata = tty->disc_data;
int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
@ -1570,7 +1726,7 @@ handle_newline:
return 0;
}
static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
rt_inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
@ -1695,7 +1851,7 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int cou
}
}
static inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c)
rt_inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
@ -2018,19 +2174,18 @@ static int n_tty_poll(struct dfs_file *fd, struct rt_pollreq *req)
lwp = (struct rt_lwp *)(rt_thread_self()->lwp);
wq = wait_queue_get(lwp, tty);
rt_poll_add(wq, req);
level = rt_hw_interrupt_disable();
level = rt_hw_interrupt_disable();
if (input_available_p(tty, 1))
{
mask |= POLLIN;
}
rt_hw_interrupt_enable(level);
return mask;
}
static struct tty_ldisc_ops n_tty_ops = {
struct tty_ldisc_ops n_tty_ops = {
"n_tty",
0,
n_tty_open,
@ -2046,8 +2201,3 @@ static struct tty_ldisc_ops n_tty_ops = {
n_tty_receive_buf,
0,
};
void n_tty_init(void)
{
tty_register_ldisc(N_TTY, &n_tty_ops);
}

View File

@ -20,21 +20,21 @@
#include <rtdbg.h>
#define PTY_PTS_SIZE 10
static struct tty_struct ptm_driver;
static struct tty_struct pts_drivers[PTY_PTS_SIZE];
static struct tty_struct ptm_dev;
static struct tty_struct pts_devs[PTY_PTS_SIZE];
static int pts_index = 0;
static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, int pts_index);
static int pts_register(struct tty_struct *ptmx, struct tty_struct *pts, int pts_index);
/* check free pts device */
static struct tty_struct *find_freepts(void)
{
for(int i = 0; i < PTY_PTS_SIZE; i++)
{
if (pts_drivers[i].init_flag == TTY_INIT_FLAG_NONE)
if (pts_devs[i].init_flag == TTY_INIT_FLAG_NONE)
{
pts_drivers[i].init_flag = TTY_INIT_FLAG_ALLOCED;
return &pts_drivers[i];
pts_devs[i].init_flag = TTY_INIT_FLAG_ALLOCED;
return &pts_devs[i];
}
}
return RT_NULL;
@ -73,16 +73,18 @@ static int pty_get_index(struct tty_struct *tty, int *arg)
*/
static rt_err_t pty_device_init(struct rt_device *dev)
{
rt_ubase_t level = 0;
rt_err_t result = RT_EOK;
int level = 0;
struct tty_struct *tty = RT_NULL;
RT_ASSERT(dev != RT_NULL);
RT_ASSERT(dev != RT_NULL);
tty = (struct tty_struct *)dev;
level = rt_hw_interrupt_disable();
RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_REGED);
tty->init_flag = TTY_INIT_FLAG_INITED;
rt_hw_interrupt_enable(level);
return result;
}
@ -138,8 +140,8 @@ static rt_ssize_t pty_device_write(struct rt_device *dev,
const void *buffer,
rt_size_t size)
{
rt_base_t level = 0;
rt_size_t len = 0;
rt_base_t level = 0;
struct tty_struct *tty = RT_NULL;
struct tty_struct *to = RT_NULL;
@ -147,8 +149,8 @@ static rt_ssize_t pty_device_write(struct rt_device *dev,
RT_ASSERT(tty != RT_NULL);
RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED);
to = tty->other_struct;
level = rt_hw_interrupt_disable();
level = rt_hw_interrupt_disable();
if (to->ldisc->ops->receive_buf)
{
len = to->ldisc->ops->receive_buf(to, (char *)buffer, size);
@ -179,7 +181,7 @@ static int ptmx_open(struct dfs_file *fd)
{
int ret = 0;
struct tty_struct *tty = RT_NULL;
struct tty_struct *pts_drv = RT_NULL;
struct tty_struct *pts = RT_NULL;
struct tty_ldisc *ld = RT_NULL;
struct rt_lwp *lwp = RT_NULL;
struct rt_wqueue *wq = RT_NULL;
@ -187,24 +189,25 @@ static int ptmx_open(struct dfs_file *fd)
tty = (struct tty_struct *)fd->vnode->data;
RT_ASSERT(tty != RT_NULL);
pts_drv = find_freepts();
if (pts_drv == RT_NULL)
pts = find_freepts();
if (pts == RT_NULL)
{
LOG_E("free pts driver find fail\n");
LOG_E("No free PTS device found.\n");
return -1;
}
ret = pts_register(tty, pts_drv, pts_index);
ret = pts_register(tty, pts, pts_index);
if (ret < 0)
{
LOG_E("pts register fail\n");
rt_free(pts_drv);
rt_free(pts);
return -1;
}
pts_index++;
lwp = (struct rt_lwp *)(rt_thread_self()->lwp);
lwp = lwp_self();
wq = wait_queue_get(lwp, tty);
pts_drv->wait_queue = *wq;
tty->other_struct = pts_drv;
pts->wait_queue = *wq;
tty->other_struct = pts;
ld = tty->ldisc;
if (ld->ops->open)
{
@ -230,94 +233,73 @@ const static struct rt_device_ops pty_device_ops =
pty_device_control,
};
#endif /* RT_USING_DEVICE_OPS */
static struct dfs_file_ops pts_fops;
static struct dfs_file_ops ptmx_fops;
static int pts_register(struct tty_struct *ptm_drv, struct tty_struct *pts_drv, int pts_index)
static int pts_register(struct tty_struct *ptmx, struct tty_struct *pts, int pts_index)
{
rt_err_t ret = RT_EOK;
rt_base_t level = 0;
struct rt_device *device = RT_NULL;
char name[20];
rt_err_t ret = RT_EOK;
struct rt_device *device = RT_NULL;
RT_ASSERT(ptm_drv!=RT_NULL);
level = rt_hw_interrupt_disable();
RT_ASSERT(ptmx!=RT_NULL);
if (pts_drv->init_flag != TTY_INIT_FLAG_ALLOCED)
if (pts->init_flag != TTY_INIT_FLAG_ALLOCED)
{
LOG_E("pts%d has been registered\n", pts_index);
ret = (-RT_EBUSY);
goto _exit;
}
else
{
tty_init(pts, TTY_DRIVER_TYPE_PTY, PTY_TYPE_SLAVE, NULL);
pts->index = pts_index;
pts->pts_lock = 1;
pts->other_struct = ptmx;
device = &pts_drv->parent;
device->type = RT_Device_Class_Char;
device = &pts->parent;
device->type = RT_Device_Class_Char;
#ifdef RT_USING_DEVICE_OPS
device->ops = &pty_device_ops;
device->ops = &pty_device_ops;
#else
device->init = pty_device_init;
device->open = pty_device_open;
device->close = pty_device_close;
device->read = pty_device_read;
device->write = pty_device_write;
device->control = pty_device_control;
device->init = pty_device_init;
device->open = pty_device_open;
device->close = pty_device_close;
device->read = pty_device_read;
device->write = pty_device_write;
device->control = pty_device_control;
#endif /* RT_USING_DEVICE_OPS */
rt_snprintf(name, sizeof(name), "pts%d", pts_index);
ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
if (ret != RT_EOK)
{
LOG_E("pts%d register failed\n", pts_index);
ret = -RT_EIO;
goto _exit;
}
rt_snprintf(name, sizeof(name), "pts%d", pts_index);
ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
if (ret != RT_EOK)
{
LOG_E("pts%d register failed\n", pts_index);
ret = -RT_EIO;
}
else
{
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
tty_set_fops(&pts_fops);
device->fops = &pts_fops;
/* set fops */
memcpy(&pts_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
device->fops = &pts_fops;
#endif
pts_drv->type = TTY_DRIVER_TYPE_PTY;
pts_drv->subtype = PTY_TYPE_SLAVE;
pts_drv->pgrp = -1;
pts_drv->session = -1;
pts_drv->foreground = RT_NULL;
pts_drv->index = pts_index;
pts_drv->pts_lock = 1;
rt_wqueue_init(&pts_drv->wait_queue);
tty_ldisc_init(pts_drv);
extern struct termios tty_std_termios;
pts_drv->init_termios = tty_std_termios;
pts_drv->init_termios.c_cflag = B38400 | CS8 | CREAD;
pts_drv->init_termios.c_lflag |= ECHO | ICANON;
pts_drv->init_termios.c_oflag |= ONLCR;
pts_drv->init_termios.__c_ispeed = 38400;
pts_drv->init_termios.__c_ospeed = 38400;
pts_drv->other_struct = ptm_drv;
pts_drv->init_flag = TTY_INIT_FLAG_REGED;
_exit:
rt_hw_interrupt_enable(level);
}
}
return ret;
}
static int ptmx_register(void)
{
rt_base_t level = 0;
rt_err_t ret = RT_EOK;
struct rt_device *device = RT_NULL;
struct tty_struct *ptm_drv = &ptm_driver;
struct tty_struct *ptmx = &ptm_dev;
level = rt_hw_interrupt_disable();
RT_ASSERT(ptm_drv->init_flag == TTY_INIT_FLAG_NONE);
RT_ASSERT(ptmx->init_flag == TTY_INIT_FLAG_NONE);
device = &(ptm_drv->parent);
tty_init(ptmx, TTY_DRIVER_TYPE_PTY, PTY_TYPE_MASTER, NULL);
device = &(ptmx->parent);
device->type = RT_Device_Class_Char;
#ifdef RT_USING_DEVICE_OPS
@ -336,44 +318,16 @@ static int ptmx_register(void)
{
LOG_E("ptmx register fail\n");
ret = -RT_EIO;
goto _exit;
}
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
tty_set_fops(&ptmx_fops);
ptmx_fops.open = ptmx_open;
device->fops = &ptmx_fops;
#endif
ptm_drv->type = TTY_DRIVER_TYPE_PTY;
ptm_drv->subtype = PTY_TYPE_MASTER;
ptm_drv->head = rt_calloc(1, sizeof(struct tty_node));
if (!ptm_drv->head)
else
{
return -RT_ENOMEM;
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
memcpy(&ptmx_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
ptmx_fops.open = ptmx_open;
device->fops = &ptmx_fops;
#endif
}
tty_initstack(ptm_drv->head);
ptm_drv->pgrp = -1;
ptm_drv->session = -1;
ptm_drv->foreground = RT_NULL;
rt_wqueue_init(&ptm_drv->wait_queue);
tty_ldisc_init(ptm_drv);
extern struct termios tty_std_termios;
ptm_drv->init_termios.c_iflag = 0;
ptm_drv->init_termios.c_oflag = 0;
ptm_drv->init_termios.c_cflag = B38400 | CS8 | CREAD;
ptm_drv->init_termios.c_lflag = 0;
ptm_drv->init_termios.__c_ispeed = 38400;
ptm_drv->init_termios.__c_ospeed = 38400;
ptm_drv->init_flag = TTY_INIT_FLAG_REGED;
_exit:
rt_hw_interrupt_enable(level);
return ret;
}

View File

@ -27,7 +27,7 @@
#endif /* RT_TTY_DEBUG */
#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_oflag = OPOST,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
@ -219,6 +219,7 @@ static int tty_open(struct dfs_file *fd)
tty = (struct tty_struct *)fd->vnode->data;
RT_ASSERT(tty != RT_NULL);
ld = tty->ldisc;
if (ld->ops->open)
{
@ -322,11 +323,13 @@ static int tty_ioctl(struct dfs_file *fd, int cmd, void *args)
{
real_tty = tty;
}
switch (cmd)
{
case TIOCSCTTY:
return tiocsctty(real_tty, 1);
}
ld = tty->ldisc;
if (ld->ops->ioctl)
{
@ -343,8 +346,9 @@ static int tty_read(struct dfs_file *fd, void *buf, size_t count)
tty = (struct tty_struct *)fd->vnode->data;
RT_ASSERT(tty != RT_NULL);
ld = tty->ldisc;
if (ld->ops->read)
if (ld && ld->ops->read)
{
ret = ld->ops->read(fd, buf, count);
}
@ -359,11 +363,13 @@ static int tty_write(struct dfs_file *fd, const void *buf, size_t count)
tty = (struct tty_struct *)fd->vnode->data;
RT_ASSERT(tty != RT_NULL);
ld = tty->ldisc;
if (ld->ops->write)
if (ld && ld->ops->write)
{
ret = ld->ops->write(fd, buf, count);
}
return ret;
}
@ -395,30 +401,40 @@ static const struct dfs_file_ops tty_fops =
RT_NULL, /* getdents */
tty_poll,
};
static const struct dfs_file_ops console_fops =
{
tty_open,
tty_close,
tty_ioctl,
tty_read,
tty_write,
RT_NULL, /* flush */
RT_NULL, /* lseek */
RT_NULL, /* getdents */
tty_poll,
};
void console_init()
const struct dfs_file_ops *tty_get_fops(void)
{
n_tty_init();
return &tty_fops;
}
void tty_set_fops(struct dfs_file_ops *fops)
int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev)
{
*fops = tty_fops;
}
if (tty)
{
struct tty_node *node = NULL;
void console_set_fops(struct dfs_file_ops *fops)
{
*fops = console_fops;
node = rt_calloc(1, sizeof(struct tty_node));
if (node)
{
tty->type = type;
tty->subtype = subtype;
tty->io_dev = iodev;
tty->head = node;
tty_initstack(tty->head);
tty->pgrp = -1;
tty->session = -1;
tty->foreground = RT_NULL;
rt_mutex_init(&tty->lock, "ttyLock", RT_IPC_FLAG_PRIO);
rt_wqueue_init(&tty->wait_queue);
tty_ldisc_init(tty);
tty->init_termios = tty_std_termios;
tty->init_flag = TTY_INIT_FLAG_REGED;
}
}
return 0;
}

View File

@ -9,7 +9,10 @@
#endif /* RT_TTY_DEBUG */
#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)
{
@ -33,6 +36,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
ldops->refcount--;
rt_hw_interrupt_enable(level);
}
static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
{
struct tty_ldisc *ld = RT_NULL;
@ -70,13 +74,11 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
*/
static void tty_ldisc_put(struct tty_ldisc *ld)
{
if (ld == RT_NULL)
if (ld)
{
return;
put_ldops(ld->ops);
rt_free(ld);
}
put_ldops(ld->ops);
rt_free(ld);
}
/**
@ -87,10 +89,9 @@ static void tty_ldisc_put(struct tty_ldisc *ld)
* A helper close method. Also a convenient debugging and check
* point.
*/
static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
{
if (ld->ops->close)
if (ld && ld->ops->close)
{
ld->ops->close(tty);
}
@ -104,18 +105,16 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
*/
void tty_ldisc_kill(struct tty_struct *tty)
{
if (!tty->ldisc)
if (tty && tty->ldisc)
{
return;
/*
* Now kill off the ldisc
*/
tty_ldisc_close(tty, tty->ldisc);
tty_ldisc_put(tty->ldisc);
/* Force an oops if we mess this up */
tty->ldisc = NULL;
}
/*
* Now kill off the ldisc
*/
tty_ldisc_close(tty, tty->ldisc);
tty_ldisc_put(tty->ldisc);
/* Force an oops if we mess this up */
tty->ldisc = NULL;
}
int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
@ -154,7 +153,6 @@ void tty_ldisc_release(struct tty_struct *tty)
* Shutdown this line discipline. As this is the final close,
* it does not race with the set_ldisc code path.
*/
level = rt_hw_interrupt_disable();
tty_ldisc_kill(tty);
if (o_tty)
@ -162,7 +160,6 @@ void tty_ldisc_release(struct tty_struct *tty)
tty_ldisc_kill(o_tty);
}
rt_hw_interrupt_enable(level);
}
/**
@ -175,7 +172,8 @@ void tty_ldisc_release(struct tty_struct *tty)
void tty_ldisc_init(struct tty_struct *tty)
{
struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
RT_ASSERT(ld != RT_NULL);
tty->ldisc = ld;
if (tty)
{
tty->ldisc = tty_ldisc_get(tty, N_TTY);
}
}

View File

@ -1370,8 +1370,7 @@ rt_device_t rt_console_set_device(const char *name)
{
#ifdef RT_USING_SMART
rt_device_t new_iodev = RT_NULL, old_iodev = RT_NULL;
extern void console_init();
console_init(); /*add line discipline*/
/* find new console device */
new_iodev = rt_device_find(name);
if (new_iodev != RT_NULL)