summaryrefslogtreecommitdiff
path: root/components/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'components/drivers')
-rwxr-xr-xcomponents/drivers/Kconfig11
-rw-r--r--components/drivers/core/device.c8
-rwxr-xr-xcomponents/drivers/include/drivers/pic.h2
-rw-r--r--components/drivers/include/drivers/serial.h1
-rw-r--r--components/drivers/include/drivers/serial_v2.h1
-rw-r--r--components/drivers/include/ipc/completion.h1
-rw-r--r--components/drivers/include/ipc/condvar.h38
-rw-r--r--components/drivers/include/ipc/pipe.h2
-rw-r--r--components/drivers/include/ipc/waitqueue.h1
-rw-r--r--components/drivers/include/rtdevice.h1
-rw-r--r--components/drivers/ipc/completion.c32
-rw-r--r--components/drivers/ipc/condvar.c173
-rw-r--r--components/drivers/ipc/pipe.c45
-rw-r--r--components/drivers/ipc/waitqueue.c89
-rw-r--r--components/drivers/ktime/inc/ktime.h1
-rw-r--r--components/drivers/ofw/base.c73
-rw-r--r--components/drivers/serial/SConscript3
-rw-r--r--components/drivers/serial/serial.c36
-rw-r--r--components/drivers/serial/serial_tty.c321
-rw-r--r--components/drivers/tty/SConscript10
-rw-r--r--components/drivers/tty/console.c346
-rw-r--r--components/drivers/tty/include/console.h19
-rw-r--r--components/drivers/tty/include/tty.h304
-rw-r--r--components/drivers/tty/include/tty_ldisc.h56
-rw-r--r--components/drivers/tty/n_tty.c2223
-rw-r--r--components/drivers/tty/pty.c326
-rw-r--r--components/drivers/tty/tty.c504
-rw-r--r--components/drivers/tty/tty_ioctl.c122
-rw-r--r--components/drivers/tty/tty_ldisc.c178
29 files changed, 768 insertions, 4159 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig
index df4ba06a91..5763ab8015 100755
--- a/components/drivers/Kconfig
+++ b/components/drivers/Kconfig
@@ -57,17 +57,6 @@ menuconfig RT_USING_SERIAL
default 64
endif
-config RT_USING_TTY
- bool "Using TTY SYSTEM"
- depends on RT_USING_SMART
- 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/core/device.c b/components/drivers/core/device.c
index 30c8adfd60..c99cddf62b 100644
--- a/components/drivers/core/device.c
+++ b/components/drivers/core/device.c
@@ -29,6 +29,10 @@
#include <rtdevice.h> /* for wqueue_init */
#endif /* RT_USING_POSIX_DEVIO */
+#ifdef RT_USING_DFS_V2
+#include <devfs.h>
+#endif /* RT_USING_DFS_V2 */
+
#ifdef RT_USING_DEVICE
#ifdef RT_USING_DEVICE_OPS
@@ -78,6 +82,10 @@ rt_err_t rt_device_register(rt_device_t dev,
rt_wqueue_init(&(dev->wait_queue));
#endif /* RT_USING_POSIX_DEVIO */
+#ifdef RT_USING_DFS_V2
+ dfs_devfs_device_add(dev);
+#endif /* RT_USING_DFS_V2 */
+
return RT_EOK;
}
RTM_EXPORT(rt_device_register);
diff --git a/components/drivers/include/drivers/pic.h b/components/drivers/include/drivers/pic.h
index 33c8c390bf..8429007d16 100755
--- a/components/drivers/include/drivers/pic.h
+++ b/components/drivers/include/drivers/pic.h
@@ -107,7 +107,7 @@ struct rt_pic_irq
rt_uint32_t mode;
rt_uint32_t priority;
- RT_DECLARE_BITMAP(affinity, RT_CPUS_NR);
+ RT_BITMAP_DECLARE(affinity, RT_CPUS_NR);
rt_list_t list;
rt_list_t children_nodes;
diff --git a/components/drivers/include/drivers/serial.h b/components/drivers/include/drivers/serial.h
index 9435249cd8..b6c3a74e73 100644
--- a/components/drivers/include/drivers/serial.h
+++ b/components/drivers/include/drivers/serial.h
@@ -179,4 +179,5 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
rt_uint32_t flag,
void *data);
+rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial);
#endif
diff --git a/components/drivers/include/drivers/serial_v2.h b/components/drivers/include/drivers/serial_v2.h
index 76c44333bd..399b3d0a59 100644
--- a/components/drivers/include/drivers/serial_v2.h
+++ b/components/drivers/include/drivers/serial_v2.h
@@ -191,4 +191,5 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
rt_uint32_t flag,
void *data);
+rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial);
#endif
diff --git a/components/drivers/include/ipc/completion.h b/components/drivers/include/ipc/completion.h
index efa2b7840d..266ddd281e 100644
--- a/components/drivers/include/ipc/completion.h
+++ b/components/drivers/include/ipc/completion.h
@@ -33,5 +33,6 @@ void rt_completion_init(struct rt_completion *completion);
rt_err_t rt_completion_wait(struct rt_completion *completion,
rt_int32_t timeout);
void rt_completion_done(struct rt_completion *completion);
+rt_err_t rt_completion_wakeup(struct rt_completion *completion);
#endif
diff --git a/components/drivers/include/ipc/condvar.h b/components/drivers/include/ipc/condvar.h
new file mode 100644
index 0000000000..1211df420d
--- /dev/null
+++ b/components/drivers/include/ipc/condvar.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-20 Shell Add cond var API in kernel
+ */
+
+#ifndef __LWP_TERMINAL_CONDVAR_H__
+#define __LWP_TERMINAL_CONDVAR_H__
+
+#include <rtthread.h>
+
+typedef struct rt_condvar
+{
+#ifdef USING_RT_OBJECT
+ struct rt_object parent;
+#endif
+ rt_atomic_t waiters_cnt;
+ rt_atomic_t waiting_mtx;
+ struct rt_wqueue event;
+} *rt_condvar_t;
+
+void rt_condvar_init(rt_condvar_t cv, char *name);
+int rt_condvar_timedwait(rt_condvar_t cv, rt_mutex_t mtx, int suspend_flag,
+ rt_tick_t timeout);
+int rt_condvar_signal(rt_condvar_t cv);
+int rt_condvar_broadcast(rt_condvar_t cv);
+
+rt_inline void rt_condvar_detach(rt_condvar_t cv)
+{
+ RT_UNUSED(cv);
+ return ;
+}
+
+#endif /* __LWP_TERMINAL_CONDVAR_H__ */
diff --git a/components/drivers/include/ipc/pipe.h b/components/drivers/include/ipc/pipe.h
index 94ac10f635..fdba84a57e 100644
--- a/components/drivers/include/ipc/pipe.h
+++ b/components/drivers/include/ipc/pipe.h
@@ -12,6 +12,7 @@
#include <rtdef.h>
#include <rtconfig.h>
+#include "condvar.h"
/**
* Pipe Device
@@ -34,6 +35,7 @@ struct rt_pipe_device
int writer;
int reader;
+ struct rt_condvar waitfor_parter;
struct rt_mutex lock;
};
typedef struct rt_pipe_device rt_pipe_t;
diff --git a/components/drivers/include/ipc/waitqueue.h b/components/drivers/include/ipc/waitqueue.h
index 073300a72e..dcc01ceff9 100644
--- a/components/drivers/include/ipc/waitqueue.h
+++ b/components/drivers/include/ipc/waitqueue.h
@@ -49,6 +49,7 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int timeout);
int rt_wqueue_wait_killable(rt_wqueue_t *queue, int condition, int timeout);
int rt_wqueue_wait_interruptible(rt_wqueue_t *queue, int condition, int timeout);
void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key);
+void rt_wqueue_wakeup_all(rt_wqueue_t *queue, void *key);
#define DEFINE_WAIT_FUNC(name, function) \
struct rt_wqueue_node name = { \
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index 5da3c955d6..2445a65823 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -26,6 +26,7 @@
#include "ipc/completion.h"
#include "ipc/dataqueue.h"
#include "ipc/workqueue.h"
+#include "ipc/condvar.h"
#include "ipc/waitqueue.h"
#include "ipc/pipe.h"
#include "ipc/poll.h"
diff --git a/components/drivers/ipc/completion.c b/components/drivers/ipc/completion.c
index d74fcdc8d1..824f538129 100644
--- a/components/drivers/ipc/completion.c
+++ b/components/drivers/ipc/completion.c
@@ -134,7 +134,7 @@ RTM_EXPORT(rt_completion_wait);
*
* @param completion is a pointer to a completion object.
*/
-void rt_completion_done(struct rt_completion *completion)
+static int _completion_done(struct rt_completion *completion)
{
rt_base_t level;
rt_err_t error;
@@ -145,7 +145,7 @@ void rt_completion_done(struct rt_completion *completion)
if (RT_COMPLETION_FLAG(completion) == RT_COMPLETED)
{
rt_spin_unlock_irqrestore(&_completion_lock, level);
- return;
+ return -RT_EBUSY;
}
suspend_thread = RT_COMPLETION_THREAD(completion);
@@ -160,10 +160,38 @@ void rt_completion_done(struct rt_completion *completion)
LOG_D("%s: failed to resume thread", __func__);
}
}
+ else
+ {
+ /* no thread waiting */
+ error = -RT_EEMPTY;
+ }
completion->susp_thread_n_flag = RT_COMPLETION_NEW_STAT(RT_NULL, RT_COMPLETED);
rt_spin_unlock_irqrestore(&_completion_lock, level);
+
+ return error;
+}
+
+/**
+ * @brief This function indicates a completion has done.
+ *
+ * @param completion is a pointer to a completion object.
+ */
+void rt_completion_done(struct rt_completion *completion)
+{
+ _completion_done(completion);
}
RTM_EXPORT(rt_completion_done);
+/**
+ * @brief This function indicates a completion has done and wakeup the thread
+ *
+ * @param completion is a pointer to a completion object.
+ */
+rt_err_t rt_completion_wakeup(struct rt_completion *completion)
+{
+ return _completion_done(completion);
+}
+RTM_EXPORT(rt_completion_wakeup);
+
diff --git a/components/drivers/ipc/condvar.c b/components/drivers/ipc/condvar.c
new file mode 100644
index 0000000000..1eb42dc9ad
--- /dev/null
+++ b/components/drivers/ipc/condvar.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-20 Shell Support of condition variable
+ */
+#define DBG_TAG "ipc.condvar"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <rtdevice.h>
+#include <rtatomic.h>
+#include <rtthread.h>
+
+static struct rt_spinlock _local_cv_queue_lock = RT_SPINLOCK_INIT;
+
+#define CV_ASSERT_LOCKED(cv) \
+ RT_ASSERT(!(cv)->waiting_mtx || \
+ rt_mutex_get_owner((rt_mutex_t)(cv)->waiting_mtx) == \
+ rt_thread_self())
+
+void rt_condvar_init(rt_condvar_t cv, char *name)
+{
+#ifdef USING_RT_OBJECT
+ /* TODO: support rt object */
+ rt_object_init();
+#endif
+
+ rt_wqueue_init(&cv->event);
+ rt_atomic_store(&cv->waiters_cnt, 0);
+ rt_atomic_store(&cv->waiting_mtx, 0);
+}
+
+static int _waitq_inqueue(rt_wqueue_t *queue, struct rt_wqueue_node *node,
+ rt_tick_t timeout, int suspend_flag)
+{
+ rt_thread_t tcb = node->polling_thread;
+ rt_timer_t timer = &(tcb->thread_timer);
+ rt_err_t ret;
+
+ if (queue->flag != RT_WQ_FLAG_WAKEUP)
+ {
+ ret = rt_thread_suspend_with_flag(tcb, suspend_flag);
+ if (ret == RT_EOK)
+ {
+ rt_wqueue_add(queue, node);
+ if (timeout != RT_WAITING_FOREVER)
+ {
+ rt_timer_control(timer, RT_TIMER_CTRL_SET_TIME, &timeout);
+
+ rt_timer_start(timer);
+ }
+ }
+ }
+ else
+ {
+ ret = RT_EOK;
+ }
+
+ return ret;
+}
+
+#define INIT_WAITQ_NODE(node) \
+ { \
+ .polling_thread = rt_thread_self(), .key = 0, \
+ .wakeup = __wqueue_default_wake, .wqueue = &cv->event, \
+ .list = RT_LIST_OBJECT_INIT(node.list) \
+ }
+
+int rt_condvar_timedwait(rt_condvar_t cv, rt_mutex_t mtx, int suspend_flag,
+ rt_tick_t timeout)
+{
+ rt_err_t acq_mtx_succ, rc;
+ rt_atomic_t waiting_mtx;
+ struct rt_wqueue_node node = INIT_WAITQ_NODE(node);
+
+ /* not allowed in IRQ & critical section */
+ RT_DEBUG_SCHEDULER_AVAILABLE(1);
+ CV_ASSERT_LOCKED(cv);
+
+ /**
+ * for the worst case, this is racy with the following works to reset field
+ * before mutex is taken. The spinlock then comes to rescue.
+ */
+ rt_spin_lock(&_local_cv_queue_lock);
+ waiting_mtx = rt_atomic_load(&cv->waiting_mtx);
+ if (!waiting_mtx)
+ acq_mtx_succ = rt_atomic_compare_exchange_strong(
+ &cv->waiting_mtx, &waiting_mtx, (size_t)mtx);
+ else
+ acq_mtx_succ = 0;
+
+ rt_spin_unlock(&_local_cv_queue_lock);
+
+ if (acq_mtx_succ == 1 || waiting_mtx == (size_t)mtx)
+ {
+ rt_atomic_add(&cv->waiters_cnt, 1);
+
+ rt_enter_critical();
+
+ if (suspend_flag == RT_INTERRUPTIBLE)
+ rc = _waitq_inqueue(&cv->event, &node, timeout, RT_INTERRUPTIBLE);
+ else /* UNINTERRUPTIBLE is forbidden, since it's not safe for user space */
+ rc = _waitq_inqueue(&cv->event, &node, timeout, RT_KILLABLE);
+
+ acq_mtx_succ = rt_mutex_release(mtx);
+ RT_ASSERT(acq_mtx_succ == 0);
+ rt_exit_critical();
+
+ if (rc == RT_EOK)
+ {
+ rt_schedule();
+
+ rc = rt_get_errno();
+ rc = rc > 0 ? -rc : rc;
+ }
+ else
+ {
+ LOG_D("%s() failed to suspend", __func__);
+ }
+
+ rt_wqueue_remove(&node);
+
+ rt_spin_lock(&_local_cv_queue_lock);
+ if (rt_atomic_add(&cv->waiters_cnt, -1) == 1)
+ {
+ waiting_mtx = (size_t)mtx;
+ acq_mtx_succ = rt_atomic_compare_exchange_strong(&cv->waiting_mtx,
+ &waiting_mtx, 0);
+ RT_ASSERT(acq_mtx_succ == 1);
+ }
+ rt_spin_unlock(&_local_cv_queue_lock);
+
+ acq_mtx_succ = rt_mutex_take(mtx, RT_WAITING_FOREVER);
+ RT_ASSERT(acq_mtx_succ == 0);
+ }
+ else
+ {
+ LOG_D("%s: conflict waiting mutex", __func__);
+ rc = -EBUSY;
+ }
+
+ return rc;
+}
+
+/** Keep in mind that we always operating when cv.waiting_mtx is taken */
+
+int rt_condvar_signal(rt_condvar_t cv)
+{
+ CV_ASSERT_LOCKED(cv);
+
+ /* to avoid spurious wakeups */
+ if (rt_atomic_load(&cv->waiters_cnt) > 0)
+ rt_wqueue_wakeup(&cv->event, 0);
+
+ cv->event.flag = 0;
+ return 0;
+}
+
+int rt_condvar_broadcast(rt_condvar_t cv)
+{
+ CV_ASSERT_LOCKED(cv);
+
+ /* to avoid spurious wakeups */
+ if (rt_atomic_load(&cv->waiters_cnt) > 0)
+ rt_wqueue_wakeup_all(&cv->event, 0);
+
+ cv->event.flag = 0;
+ return 0;
+}
diff --git a/components/drivers/ipc/pipe.c b/components/drivers/ipc/pipe.c
index acd0c2def6..c39cd6bdc6 100644
--- a/components/drivers/ipc/pipe.c
+++ b/components/drivers/ipc/pipe.c
@@ -9,11 +9,13 @@
* 2017-11-08 JasonJiaJie fix memory leak issue when close a pipe.
* 2023-06-28 shell return POLLHUP when writer closed its channel on poll()
* fix flag test on pipe_fops_open()
+ * 2023-12-02 shell Make read pipe operation interruptable.
*/
#include <rthw.h>
#include <rtdevice.h>
#include <stdint.h>
#include <sys/errno.h>
+#include <ipc/condvar.h>
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
#include <unistd.h>
@@ -69,12 +71,12 @@ static int pipe_fops_open(struct dfs_file *fd)
if ((fd->flags & O_ACCMODE) == O_RDONLY)
{
- pipe->reader = 1;
+ pipe->reader += 1;
}
if ((fd->flags & O_ACCMODE) == O_WRONLY)
{
- pipe->writer = 1;
+ pipe->writer += 1;
}
if (fd->vnode->ref_count == 1)
{
@@ -86,6 +88,21 @@ static int pipe_fops_open(struct dfs_file *fd)
}
}
+ if ((fd->flags & O_ACCMODE) == O_RDONLY && !pipe->writer)
+ {
+ /* wait for partner */
+ rc = rt_condvar_timedwait(&pipe->waitfor_parter, &pipe->lock,
+ RT_INTERRUPTIBLE, RT_WAITING_FOREVER);
+ if (rc != 0)
+ {
+ pipe->reader--;
+ }
+ }
+ else if ((fd->flags & O_ACCMODE) == O_WRONLY)
+ {
+ rt_condvar_broadcast(&pipe->waitfor_parter);
+ }
+
__exit:
rt_mutex_release(&pipe->lock);
@@ -117,12 +134,12 @@ static int pipe_fops_close(struct dfs_file *fd)
if ((fd->flags & O_RDONLY) == O_RDONLY)
{
- pipe->reader = 0;
+ pipe->reader -= 1;
}
if ((fd->flags & O_WRONLY) == O_WRONLY)
{
- pipe->writer = 0;
+ pipe->writer -= 1;
while (!rt_list_isempty(&pipe->reader_queue.waiting_list))
{
rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
@@ -234,7 +251,8 @@ static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count)
rt_mutex_release(&pipe->lock);
rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
- rt_wqueue_wait(&pipe->reader_queue, 0, -1);
+ if (rt_wqueue_wait_interruptible(&pipe->reader_queue, 0, -1) == -RT_EINTR)
+ return -EINTR;
rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
}
}
@@ -309,7 +327,8 @@ static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t coun
rt_mutex_release(&pipe->lock);
rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
/* pipe full, waiting on suspended write list */
- rt_wqueue_wait(&pipe->writer_queue, 0, -1);
+ if (rt_wqueue_wait_interruptible(&pipe->writer_queue, 0, -1) == -RT_EINTR)
+ return -EINTR;
rt_mutex_take(&pipe->lock, -1);
}
rt_mutex_release(&pipe->lock);
@@ -611,6 +630,8 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
rt_mutex_init(&pipe->lock, name, RT_IPC_FLAG_FIFO);
rt_wqueue_init(&pipe->reader_queue);
rt_wqueue_init(&pipe->writer_queue);
+ rt_condvar_init(&pipe->waitfor_parter, "piwfp");
+
pipe->writer = 0;
pipe->reader = 0;
@@ -674,6 +695,7 @@ int rt_pipe_delete(const char *name)
pipe = (rt_pipe_t *)device;
+ rt_condvar_detach(&pipe->waitfor_parter);
rt_mutex_detach(&pipe->lock);
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
resource_id_put(&id_mgr, pipe->pipeno);
@@ -736,11 +758,6 @@ int pipe(int fildes[2])
pipe->is_named = RT_FALSE; /* unamed pipe */
pipe->pipeno = pipeno;
rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname);
- fildes[0] = open(dev_name, O_RDONLY, 0);
- if (fildes[0] < 0)
- {
- return -1;
- }
fildes[1] = open(dev_name, O_WRONLY, 0);
if (fildes[1] < 0)
@@ -749,6 +766,12 @@ int pipe(int fildes[2])
return -1;
}
+ fildes[0] = open(dev_name, O_RDONLY, 0);
+ if (fildes[0] < 0)
+ {
+ return -1;
+ }
+
return 0;
}
diff --git a/components/drivers/ipc/waitqueue.c b/components/drivers/ipc/waitqueue.c
index 03901a9ba3..75e14e5844 100644
--- a/components/drivers/ipc/waitqueue.c
+++ b/components/drivers/ipc/waitqueue.c
@@ -9,7 +9,11 @@
* to blocked thread.
* 2022-01-24 THEWON let rt_wqueue_wait return thread->error when using signal
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
+ * 2023-11-21 Shell Support wakeup_all
*/
+#define DBG_TAG "ipc.waitqueue"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
#include <stdint.h>
#include <rthw.h>
@@ -64,7 +68,8 @@ int __wqueue_default_wake(struct rt_wqueue_node *wait, void *key)
}
/**
- * @brief This function will wake up a pending thread on the specified waiting queue that meets the conditions.
+ * @brief This function will wake up a pending thread on the specified
+ * waiting queue that meets the conditions.
*
* @param queue is a pointer to the wait queue.
*
@@ -94,17 +99,89 @@ void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key)
entry = rt_list_entry(node, struct rt_wqueue_node, list);
if (entry->wakeup(entry, key) == 0)
{
- rt_thread_resume(entry->polling_thread);
- need_schedule = 1;
+ /**
+ * even though another thread may interrupt the thread and
+ * wakeup it meanwhile, we can asuume that condition is ready
+ */
+ entry->polling_thread->error = RT_EOK;
+ if (!rt_thread_resume(entry->polling_thread))
+ {
+ need_schedule = 1;
- rt_list_remove(&(entry->list));
- break;
+ rt_list_remove(&(entry->list));
+
+ break;
+ }
+ }
+ }
+ }
+ rt_spin_unlock_irqrestore(&(queue->spinlock), level);
+ if (need_schedule)
+ rt_schedule();
+
+ return;
+}
+
+/**
+ * @brief This function will wake up all pending thread on the specified
+ * waiting queue that meets the conditions.
+ *
+ * @param queue is a pointer to the wait queue.
+ *
+ * @param key is the wakeup conditions, but it is not effective now, because
+ * default wakeup function always return 0.
+ * If user wants to use it, user should define their own wakeup
+ * function.
+ */
+void rt_wqueue_wakeup_all(rt_wqueue_t *queue, void *key)
+{
+ rt_base_t level;
+ int need_schedule = 0;
+
+ rt_list_t *queue_list;
+ struct rt_list_node *node;
+ struct rt_wqueue_node *entry;
+
+ queue_list = &(queue->waiting_list);
+
+ level = rt_spin_lock_irqsave(&(queue->spinlock));
+ /* set wakeup flag in the queue */
+ queue->flag = RT_WQ_FLAG_WAKEUP;
+
+ if (!(rt_list_isempty(queue_list)))
+ {
+ for (node = queue_list->next; node != queue_list; )
+ {
+ entry = rt_list_entry(node, struct rt_wqueue_node, list);
+ if (entry->wakeup(entry, key) == 0)
+ {
+ /**
+ * even though another thread may interrupt the thread and
+ * wakeup it meanwhile, we can asuume that condition is ready
+ */
+ entry->polling_thread->error = RT_EOK;
+ if (!rt_thread_resume(entry->polling_thread))
+ {
+ need_schedule = 1;
+ }
+ else
+ {
+ /* wakeup happened too soon that waker hadn't slept */
+ LOG_D("%s: Thread resume failed", __func__);
+ }
+ node = node->next;
+ }
+ else
+ {
+ node = node->next;
}
}
}
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
if (need_schedule)
rt_schedule();
+
+ return;
}
/**
@@ -184,7 +261,7 @@ __exit_wakeup:
rt_wqueue_remove(&__wait);
- return tid->error;
+ return tid->error > 0 ? -tid->error : tid->error;
}
int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
diff --git a/components/drivers/ktime/inc/ktime.h b/components/drivers/ktime/inc/ktime.h
index 5fd5ffb763..44e2578bcf 100644
--- a/components/drivers/ktime/inc/ktime.h
+++ b/components/drivers/ktime/inc/ktime.h
@@ -136,6 +136,7 @@ rt_inline void rt_ktime_hrtimer_keep_errno(rt_ktime_hrtimer_t timer, rt_err_t er
RT_ASSERT(timer != RT_NULL);
timer->error = err;
+ rt_set_errno(-err);
}
/**
diff --git a/components/drivers/ofw/base.c b/components/drivers/ofw/base.c
index 8b081bc9d4..4578758a23 100644
--- a/components/drivers/ofw/base.c
+++ b/components/drivers/ofw/base.c
@@ -1109,17 +1109,20 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id)
if (tag && id >= 0)
{
- rt_list_for_each_entry(info, &_aliases_nodes, list)
+ if (!rt_list_isempty(&_aliases_nodes))
{
- if (rt_strncmp(info->tag, tag, info->tag_len))
+ rt_list_for_each_entry(info, &_aliases_nodes, list)
{
- continue;
- }
+ if (rt_strncmp(info->tag, tag, info->tag_len))
+ {
+ continue;
+ }
- if (info->id == id)
- {
- np = info->np;
- break;
+ if (info->id == id)
+ {
+ np = info->np;
+ break;
+ }
}
}
}
@@ -1130,18 +1133,20 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id)
int ofw_alias_node_id(struct rt_ofw_node *np)
{
int id;
- struct alias_info *info;
+ struct alias_info *info = RT_NULL;
if (np)
{
id = -1;
-
- rt_list_for_each_entry(info, &_aliases_nodes, list)
+ if (!rt_list_isempty(&_aliases_nodes))
{
- if (info->np == np)
+ rt_list_for_each_entry(info, &_aliases_nodes, list)
{
- id = info->id;
- break;
+ if (info->np == np)
+ {
+ id = info->id;
+ break;
+ }
}
}
}
@@ -1161,18 +1166,20 @@ int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag)
if (np && tag)
{
id = -1;
-
- rt_list_for_each_entry(info, &_aliases_nodes, list)
+ if (!rt_list_isempty(&_aliases_nodes))
{
- if (rt_strncmp(info->tag, tag, info->tag_len))
+ rt_list_for_each_entry(info, &_aliases_nodes, list)
{
- continue;
- }
+ if (rt_strncmp(info->tag, tag, info->tag_len))
+ {
+ continue;
+ }
- if (info->np == np)
- {
- id = info->id;
- break;
+ if (info->np == np)
+ {
+ id = info->id;
+ break;
+ }
}
}
}
@@ -1192,17 +1199,19 @@ int rt_ofw_get_alias_last_id(const char *tag)
if (tag)
{
id = -1;
-
- rt_list_for_each_entry(info, &_aliases_nodes, list)
+ if (!rt_list_isempty(&_aliases_nodes))
{
- if (rt_strncmp(info->tag, tag, info->tag_len))
+ rt_list_for_each_entry(info, &_aliases_nodes, list)
{
- continue;
- }
+ if (rt_strncmp(info->tag, tag, info->tag_len))
+ {
+ continue;
+ }
- if (info->id > id)
- {
- id = info->id;
+ if (info->id > id)
+ {
+ id = info->id;
+ }
}
}
}
@@ -1465,7 +1474,7 @@ static const char *ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const c
char *sf, split_field[64];
rt_size_t len = 0, max_ak = 0;
const char *str, *result = RT_NULL;
- RT_DECLARE_BITMAP(ak, sizeof(split_field));
+ RT_BITMAP_DECLARE(ak, sizeof(split_field));
struct rt_ofw_prop *prop;
/*
diff --git a/components/drivers/serial/SConscript b/components/drivers/serial/SConscript
index 2211134ef3..7ee41a4331 100644
--- a/components/drivers/serial/SConscript
+++ b/components/drivers/serial/SConscript
@@ -8,6 +8,9 @@ src = []
if not GetDepend(['RT_USING_SERIAL']):
Return('group')
+if GetDepend(['RT_USING_SMART']):
+ src += Glob('serial_tty.c')
+
if GetDepend(['RT_USING_SERIAL_V2']):
src += ['serial_v2.c']
else:
diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c
index 0382f3c856..8604c78db7 100644
--- a/components/drivers/serial/serial.c
+++ b/components/drivers/serial/serial.c
@@ -909,7 +909,7 @@ static rt_ssize_t rt_serial_write(struct rt_device *dev,
}
}
-#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_TTY)
+#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_SMART)
struct speed_baudrate_item
{
speed_t speed;
@@ -1058,7 +1058,7 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
}
break;
#ifdef RT_USING_POSIX_STDIO
-#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_TTY)
+#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_SMART)
case TCGETA:
{
struct termios *tio = (struct termios*)args;
@@ -1315,9 +1315,21 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
device->fops = &_serial_fops;
#endif
+#if defined(RT_USING_SMART)
+ rt_hw_serial_register_tty(serial);
+#endif
+
return ret;
}
+#if defined(RT_USING_SMART) && defined(LWP_DEBUG)
+static volatile int _early_input = 0;
+int lwp_startup_debug_request(void)
+{
+ return _early_input;
+}
+#endif
+
/* ISR for serial interrupt */
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{
@@ -1360,8 +1372,17 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
rt_spin_unlock_irqrestore(&(serial->spinlock), level);
}
- /* invoke callback */
- if (serial->parent.rx_indicate != RT_NULL)
+ /**
+ * Invoke callback.
+ * First try notify if any, and if notify is existed, rx_indicate()
+ * is not callback. This seperate the priority and makes the reuse
+ * of same serial device reasonable for RT console.
+ */
+ if (serial->rx_notify.notify)
+ {
+ serial->rx_notify.notify(serial->rx_notify.dev);
+ }
+ else if (serial->parent.rx_indicate != RT_NULL)
{
rt_size_t rx_length;
@@ -1376,10 +1397,9 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
serial->parent.rx_indicate(&serial->parent, rx_length);
}
}
- if (serial->rx_notify.notify)
- {
- serial->rx_notify.notify(serial->rx_notify.dev);
- }
+ #if defined(RT_USING_SMART) && defined(LWP_DEBUG)
+ _early_input = 1;
+ #endif
break;
}
case RT_SERIAL_EVENT_TX_DONE:
diff --git a/components/drivers/serial/serial_tty.c b/components/drivers/serial/serial_tty.c
new file mode 100644
index 0000000000..311a422dce
--- /dev/null
+++ b/components/drivers/serial/serial_tty.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-21 Shell init ver.
+ */
+
+#define DBG_TAG "drivers.serial"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <terminal/terminal.h>
+
+#define TTY_NAME_PREFIX "S" /* (S)erial */
+#define LWP_TTY_WORKQUEUE_PRIORITY 3
+
+struct serial_tty_context
+{
+ struct rt_serial_device *parent;
+ struct rt_device_notify backup_notify;
+ struct rt_work work;
+};
+
+static struct rt_workqueue *_ttyworkq; /* system work queue */
+
+static rt_atomic_t _device_id_counter = 0;
+
+static long get_dec_digits(rt_ubase_t val)
+{
+ long result = 1;
+ while (1)
+ {
+ if (val < 10)
+ return result;
+ if (val < 100)
+ return result + 1;
+ if (val < 1000)
+ return result + 2;
+ if (val < 10000)
+ return result + 3;
+ val /= 10000U;
+ result += 4;
+ }
+ return result;
+}
+
+static char *alloc_device_name(void)
+{
+ char *tty_dev_name;
+ unsigned int devid = rt_atomic_add(&_device_id_counter, 1);
+ long digits_len = (sizeof(TTY_NAME_PREFIX) - 1) /* raw prefix */
+ + get_dec_digits(devid) + 1; /* tailing \0 */
+
+ tty_dev_name = rt_malloc(digits_len);
+ if (tty_dev_name)
+ rt_sprintf(tty_dev_name, "%s%u", TTY_NAME_PREFIX, devid);
+ return tty_dev_name;
+}
+
+static void _tty_rx_notify(struct rt_device *device)
+{
+ lwp_tty_t tp;
+ struct serial_tty_context *softc;
+
+ tp = rt_container_of(device, struct lwp_tty, parent);
+ RT_ASSERT(tp);
+
+ softc = tty_softc(tp);
+
+ if (_ttyworkq)
+ rt_workqueue_submit_work(_ttyworkq, &softc->work, 0);
+}
+
+static void _tty_rx_worker(struct rt_work *work, void *data)
+{
+ char input;
+ rt_ssize_t readbytes;
+ lwp_tty_t tp = data;
+ struct serial_tty_context *softc;
+ struct rt_serial_device *serial;
+
+ tty_lock(tp);
+
+ while (1)
+ {
+ softc = tty_softc(tp);
+ serial = softc->parent;
+ readbytes = rt_device_read(&serial->parent, -1, &input, 1);
+ if (readbytes != 1)
+ {
+ break;
+ }
+
+ ttydisc_rint(tp, input, 0);
+ }
+
+ ttydisc_rint_done(tp);
+ tty_unlock(tp);
+}
+
+rt_inline void _setup_serial(struct rt_serial_device *serial, lwp_tty_t tp,
+ struct serial_tty_context *softc)
+{
+ struct rt_device_notify notify;
+
+ softc->backup_notify = serial->rx_notify;
+ notify.dev = &tp->parent;
+ notify.notify = _tty_rx_notify;
+
+ rt_device_init(&serial->parent);
+
+ rt_work_init(&softc->work, _tty_rx_worker, tp);
+ rt_device_control(&serial->parent, RT_DEVICE_CTRL_NOTIFY_SET, &notify);
+}
+
+rt_inline void _restore_serial(struct rt_serial_device *serial, lwp_tty_t tp,
+ struct serial_tty_context *softc)
+{
+ rt_device_control(&serial->parent, RT_DEVICE_CTRL_NOTIFY_SET, &softc->backup_notify);
+}
+
+static int _serial_isbusy(struct rt_serial_device *serial)
+{
+ rt_thread_t user_thread = rt_console_current_user();
+ rt_thread_t self_thread = rt_thread_self();
+
+ return rt_console_get_device() == &serial->parent &&
+ (user_thread != RT_NULL && user_thread != self_thread);
+}
+
+static void serial_tty_outwakeup(struct lwp_tty *tp)
+{
+ char out_char;
+ int len;
+ struct serial_tty_context *context = tty_softc(tp);
+ struct rt_serial_device *device;
+
+ if (!context || !context->parent)
+ {
+ LOG_E("%s: Data corruption", __func__);
+ return;
+ }
+
+ device = context->parent;
+
+ if (_serial_isbusy(device))
+ {
+ return ;
+ }
+
+ while ((len = ttydisc_getc(tp, &out_char, sizeof(out_char))) != 0)
+ {
+ device->ops->putc(device, out_char);
+
+ /* discard remaining if emergency output is happened */
+ if (_serial_isbusy(device))
+ {
+ break;
+ }
+ }
+}
+
+static int serial_tty_open(struct lwp_tty *tp)
+{
+ struct serial_tty_context *softc;
+ struct rt_serial_device *serial;
+ rt_err_t error;
+ int oflags;
+
+ softc = tty_softc(tp);
+ serial = softc->parent;
+
+ LOG_D("%s", __func__);
+
+ rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags);
+
+ error = rt_device_open(&serial->parent, oflags);
+
+ if (!error)
+ {
+ /**
+ * to avoid driver accesssing null data,
+ * these are setup only after tty is registered
+ */
+ _setup_serial(serial, tp, softc);
+ }
+ return error;
+}
+
+static void serial_tty_close(struct lwp_tty *tp)
+{
+ struct serial_tty_context *softc;
+ struct rt_serial_device *serial;
+ softc = tty_softc(tp);
+ serial = softc->parent;
+
+ LOG_D("%s", __func__);
+
+ _restore_serial(serial, tp, softc);
+ rt_device_close(&serial->parent);
+}
+
+static int serial_tty_ioctl(struct lwp_tty *tp, rt_ubase_t cmd, rt_caddr_t data,
+ struct rt_thread *td)
+{
+ int error;
+ switch (cmd)
+ {
+ default:
+ /**
+ * Note: for the most case, we don't let serial layer handle ioctl,
+ * for that they can't act properly regarding to the process
+ * management system, since it is unawared of that. So a ENOSYS is
+ * returned and caused the TTY layer to handle ioctl itself.
+ */
+ error = -ENOSYS;
+ break;
+ }
+ return error;
+}
+
+static struct lwp_ttydevsw serial_ttydevsw = {
+ .tsw_open = serial_tty_open,
+ .tsw_close = serial_tty_close,
+ .tsw_ioctl = serial_tty_ioctl,
+ .tsw_outwakeup = serial_tty_outwakeup,
+};
+
+rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial)
+{
+ rt_err_t rc;
+ lwp_tty_t tty;
+ char *dev_name;
+ struct serial_tty_context *softc;
+
+ if (serial->rx_notify.dev)
+ {
+ return -RT_EBUSY;
+ }
+
+ softc = rt_malloc(sizeof(struct serial_tty_context));
+ if (softc)
+ {
+ dev_name = alloc_device_name();
+ if (dev_name)
+ {
+ softc->parent = serial;
+ tty = lwp_tty_create(&serial_ttydevsw, softc);
+ if (tty)
+ {
+ rc = lwp_tty_register(tty, dev_name);
+
+ if (rc != RT_EOK)
+ {
+ rt_free(tty);
+ rt_free(softc);
+ }
+ }
+ else
+ {
+ rt_free(softc);
+ rc = -RT_ENOMEM;
+ }
+
+ rt_free(dev_name);
+ }
+ else
+ {
+ rt_free(softc);
+ rc = -RT_ENOMEM;
+ }
+ }
+ else
+ {
+ rc = -RT_ENOMEM;
+ }
+
+ return rc;
+}
+
+rt_err_t rt_hw_serial_unregister_tty(struct rt_serial_device *serial)
+{
+ rt_device_t tty_dev;
+ lwp_tty_t tp;
+ struct serial_tty_context *softc;
+
+ tty_dev = serial->rx_notify.dev;
+ tp = rt_container_of(tty_dev, struct lwp_tty, parent);
+
+ /* restore serial setting */
+ softc = tty_softc(tp);
+ serial->rx_notify = softc->backup_notify;
+
+ tty_rel_gone(tp);
+
+ /* device unregister? */
+ rt_device_destroy(&tp->parent);
+ /* resource free? */
+ lwp_tty_delete(tp);
+
+ return RT_EOK;
+}
+
+static int _tty_workqueue_init(void)
+{
+ if (_ttyworkq != RT_NULL)
+ return RT_EOK;
+
+ _ttyworkq = rt_workqueue_create("ttyworkq", RT_SYSTEM_WORKQUEUE_STACKSIZE,
+ LWP_TTY_WORKQUEUE_PRIORITY);
+ RT_ASSERT(_ttyworkq != RT_NULL);
+
+ return RT_EOK;
+}
+INIT_PREV_EXPORT(_tty_workqueue_init);
diff --git a/components/drivers/tty/SConscript b/components/drivers/tty/SConscript
deleted file mode 100644
index d972879b70..0000000000
--- a/components/drivers/tty/SConscript
+++ /dev/null
@@ -1,10 +0,0 @@
-from building import *
-
-# The set of source files associated with this SConscript file.
-src = Glob('*.c')
-cwd = GetCurrentDir()
-CPPPATH = [cwd + "/include"]
-
-group = DefineGroup('tty', src, depend = ['RT_USING_SMART', 'RT_USING_TTY'], CPPPATH = CPPPATH)
-
-Return('group')
diff --git a/components/drivers/tty/console.c b/components/drivers/tty/console.c
deleted file mode 100644
index a9c9b88731..0000000000
--- a/components/drivers/tty/console.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021.12.07 linzhenxing first version
- */
-#include <rtthread.h>
-#include <dfs_file.h>
-#include <dfs_fs.h>
-#include <tty.h>
-
-#define DBG_TAG "CONSOLE"
-#ifdef RT_TTY_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* RT_TTY_DEBUG */
-#include <rtdbg.h>
-
-#include <ipc/waitqueue.h>
-#include <ipc/ringbuffer.h>
-
-static struct tty_struct console_dev;
-static struct rt_ringbuffer console_rx_ringbuffer;
-static struct rt_wqueue console_rx_wqueue;
-static rt_thread_t console_rx_thread;
-static const size_t rb_bufsz = 0x1000;
-
-static void console_rx_work(void *parameter)
-{
- int len;
- char ch;
- int lens;
- static char buf[0x1000];
-
- struct tty_struct *console;
- console = &console_dev;
-
- while (1)
- {
- rt_wqueue_wait(&console_rx_wqueue, 0, RT_WAITING_FOREVER);
- lens = 0;
-
- while (lens < sizeof(buf))
- {
- len = rt_ringbuffer_get(&console_rx_ringbuffer, (void *)&ch, sizeof(ch));
- if (len == 0)
- {
- break;
- }
- lens += len;
- buf[lens-1] = ch;
- }
-
- if (lens && console->ldisc->ops->receive_buf)
- {
- console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens);
- }
- }
-}
-
-static int rx_thread_init(void)
-{
- void *rb_buffer;
- rt_thread_t thread;
-
- rb_buffer = rt_malloc(rb_bufsz);
- rt_ringbuffer_init(&console_rx_ringbuffer, rb_buffer, rb_bufsz);
- rt_wqueue_init(&console_rx_wqueue);
-
- thread = rt_thread_create("console_rx", console_rx_work, &console_dev, rb_bufsz, 10, 10);
- if (thread != RT_NULL)
- {
- rt_thread_startup(thread);
- console_rx_thread = thread;
- }
-
- return 0;
-}
-INIT_COMPONENT_EXPORT(rx_thread_init);
-
-static void console_rx_notify(struct rt_device *dev)
-{
- struct tty_struct *console = NULL;
- int len = 0;
- int lens = 0;
- char ch = 0;
-
- console = (struct tty_struct *)dev;
- RT_ASSERT(console != RT_NULL);
-
- while (1)
- {
- len = rt_device_read(console->io_dev, -1, &ch, 1);
- if (len == 0)
- {
- break;
- }
- lens += len;
- rt_ringbuffer_put(&console_rx_ringbuffer, (void *)&ch, sizeof(ch));
- if (lens > rb_bufsz)
- {
- break;
- }
- }
- if (console_rx_thread)
- rt_wqueue_wakeup(&console_rx_wqueue, 0);
-}
-
-struct tty_struct *console_tty_get(void)
-{
- return &console_dev;
-}
-
-static void iodev_close(struct tty_struct *console)
-{
- struct rt_device_notify rx_notify;
-
- rx_notify.notify = RT_NULL;
- rx_notify.dev = RT_NULL;
-
- /* clear notify */
- rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
- rt_device_close(console->io_dev);
-}
-
-static rt_err_t iodev_open(struct tty_struct *console)
-{
- rt_err_t ret = RT_EOK;
- struct rt_device_notify rx_notify;
- rt_uint16_t oflags = 0;
-
- rt_device_control(console->io_dev, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags);
-
- ret = rt_device_open(console->io_dev, oflags);
- if (ret != RT_EOK)
- {
- return -RT_ERROR;
- }
-
- rx_notify.notify = console_rx_notify;
- rx_notify.dev = (struct rt_device *)console;
- rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
- return RT_EOK;
-}
-
-struct rt_device *console_get_iodev(void)
-{
- return console_dev.io_dev;
-}
-
-struct rt_device *console_set_iodev(struct rt_device *iodev)
-{
- rt_base_t level = 0;
- struct rt_device *io_before = RT_NULL;
- struct tty_struct *console = RT_NULL;
-
- RT_ASSERT(iodev != RT_NULL);
-
- console = &console_dev;
-
- level = rt_spin_lock_irqsave(&console->spinlock);
-
- RT_ASSERT(console->init_flag >= TTY_INIT_FLAG_REGED);
-
- io_before = console->io_dev;
- if (iodev == io_before)
- {
- goto exit;
- }
-
- if (console->init_flag >= TTY_INIT_FLAG_INITED)
- {
- /* close old device */
- iodev_close(console);
- }
-
- console->io_dev = iodev;
- if (console->init_flag >= TTY_INIT_FLAG_INITED)
- {
- rt_err_t ret;
- /* open new device */
- ret = iodev_open(console);
- RT_ASSERT(ret == RT_EOK);
- }
-
-exit:
- rt_spin_unlock_irqrestore(&console->spinlock, level);
- return io_before;
-}
-
-/* RT-Thread Device Interface */
-/*
- * This function initializes console device.
- */
-static rt_err_t rt_console_init(struct rt_device *dev)
-{
- rt_base_t level = 0;
- rt_err_t result = RT_EOK;
- struct tty_struct *console = RT_NULL;
-
- RT_ASSERT(dev != RT_NULL);
-
- console = (struct tty_struct *)dev;
-
- level = rt_spin_lock_irqsave(&console->spinlock);
-
- RT_ASSERT(console->init_flag == TTY_INIT_FLAG_REGED);
-
- result = iodev_open(console);
- if (result != RT_EOK)
- {
- goto exit;
- }
-
- console->init_flag = TTY_INIT_FLAG_INITED;
-exit:
- rt_spin_unlock_irqrestore(&console->spinlock, level);
- return result;
-}
-
-static rt_err_t rt_console_open(struct rt_device *dev, rt_uint16_t oflag)
-{
- rt_err_t result = RT_EOK;
- struct tty_struct *console = RT_NULL;
-
- RT_ASSERT(dev != RT_NULL);
- console = (struct tty_struct *)dev;
- RT_ASSERT(console != RT_NULL);
- RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
- return result;
-}
-
-static rt_err_t rt_console_close(struct rt_device *dev)
-{
- rt_err_t result = RT_EOK;
- struct tty_struct *console = RT_NULL;
-
- console = (struct tty_struct *)dev;
- RT_ASSERT(console != RT_NULL);
- RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
- return result;
-}
-
-static rt_ssize_t rt_console_read(struct rt_device *dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
-{
- rt_size_t len = 0;
- return len;
-}
-
-static rt_ssize_t rt_console_write(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
-{
- rt_size_t len = 0;
- struct tty_struct *console = RT_NULL;
-
- console = (struct tty_struct *)dev;
- RT_ASSERT(console != RT_NULL);
- RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
-
- len = rt_device_write((struct rt_device *)console->io_dev, -1, buffer, size);
-
- return len;
-}
-
-static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args)
-{
- rt_size_t len = 0;
- struct tty_struct *console = RT_NULL;
-
- console = (struct tty_struct *)dev;
- RT_ASSERT(console != RT_NULL);
- RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
-
- len = rt_device_control((struct rt_device *)console->io_dev, cmd, args);
-
- return len;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops console_ops =
-{
- rt_console_init,
- rt_console_open,
- rt_console_close,
- rt_console_read,
- rt_console_write,
- rt_console_control,
-};
-#endif
-
-/*
- * console register
- */
-static struct dfs_file_ops con_fops;
-rt_err_t console_register(const char *name, struct rt_device *iodev)
-{
- rt_err_t ret = RT_EOK;
- struct rt_device *device = RT_NULL;
- struct tty_struct *console = &console_dev;
-
- RT_ASSERT(iodev != RT_NULL);
- RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE);
-
- tty_init(console, TTY_DRIVER_TYPE_CONSOLE, SERIAL_TYPE_NORMAL, iodev);
- console_ldata_init(console);
-
- device = &(console->parent);
- device->type = RT_Device_Class_Char;
-
-#ifdef RT_USING_DEVICE_OPS
- device->ops = &console_ops;
-#else
- device->init = rt_console_init;
- device->open = rt_console_open;
- device->close = rt_console_close;
- device->read = rt_console_read;
- device->write = rt_console_write;
- device->control = rt_console_control;
-#endif
-
- /* register a character device */
- ret = rt_device_register(device, name, 0);
- if (ret != RT_EOK)
- {
- LOG_E("console driver register fail\n");
- }
- else
- {
-#ifdef RT_USING_POSIX_DEVIO
- /* set fops */
- memcpy(&con_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
- device->fops = &con_fops;
-#endif
- }
-
- return ret;
-}
diff --git a/components/drivers/tty/include/console.h b/components/drivers/tty/include/console.h
deleted file mode 100644
index 653b31fade..0000000000
--- a/components/drivers/tty/include/console.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021.12.07 linzhenxing first version
- */
-#ifndef __CONSOLE_
-#define __CONSOLE_
-#include <rtthread.h>
-#include "tty.h"
-
-struct tty_struct *console_tty_get(void);
-struct rt_device *console_get_iodev(void);
-struct rt_device *console_set_iodev(struct rt_device *iodev);
-rt_err_t console_register(const char *name, struct rt_device *iodev);
-#endif
diff --git a/components/drivers/tty/include/tty.h b/components/drivers/tty/include/tty.h
deleted file mode 100644
index 79e30b6f51..0000000000
--- a/components/drivers/tty/include/tty.h
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021.12.07 linzhenxing first version
- */
-#ifndef __TTY_H__
-#define __TTY_H__
-#include <rthw.h>
-#include <rtthread.h>
-#include <tty_ldisc.h>
-#ifdef RT_USING_SMART
-#include <lwp.h>
-#endif
-#if defined(RT_USING_POSIX_TERMIOS)
-#include <poll.h>
-#include <termios.h>
-#endif
-
-#ifndef ENOIOCTLCMD
-#define ENOIOCTLCMD (515) /* No ioctl command */
-#endif
-
-#define current lwp_self()
-#define __DISABLED_CHAR '\0'
-
-struct tty_node
-{
- struct rt_lwp *lwp;
- struct tty_node *next;
-};
-
-void tty_initstack(struct tty_node *node);
-int tty_push(struct tty_node **head, struct rt_lwp *lwp);
-struct rt_lwp *tty_pop(struct tty_node **head, struct rt_lwp *target_lwp);
-/*
- * When a break, frame error, or parity error happens, these codes are
- * stuffed into the flags buffer.
- */
-#define TTY_NORMAL 0
-#define TTY_BREAK 1
-#define TTY_FRAME 2
-#define TTY_PARITY 3
-#define TTY_OVERRUN 4
-
-#define INTR_CHAR(tty) ((tty)->init_termios.c_cc[VINTR])
-#define QUIT_CHAR(tty) ((tty)->init_termios.c_cc[VQUIT])
-#define ERASE_CHAR(tty) ((tty)->init_termios.c_cc[VERASE])
-#define KILL_CHAR(tty) ((tty)->init_termios.c_cc[VKILL])
-#define EOF_CHAR(tty) ((tty)->init_termios.c_cc[VEOF])
-#define TIME_CHAR(tty) ((tty)->init_termios.c_cc[VTIME])
-#define MIN_CHAR(tty) ((tty)->init_termios.c_cc[VMIN])
-#define SWTC_CHAR(tty) ((tty)->init_termios.c_cc[VSWTC])
-#define START_CHAR(tty) ((tty)->init_termios.c_cc[VSTART])
-#define STOP_CHAR(tty) ((tty)->init_termios.c_cc[VSTOP])
-#define SUSP_CHAR(tty) ((tty)->init_termios.c_cc[VSUSP])
-#define EOL_CHAR(tty) ((tty)->init_termios.c_cc[VEOL])
-#define REPRINT_CHAR(tty) ((tty)->init_termios.c_cc[VREPRINT])
-#define DISCARD_CHAR(tty) ((tty)->init_termios.c_cc[VDISCARD])
-#define WERASE_CHAR(tty) ((tty)->init_termios.c_cc[VWERASE])
-#define LNEXT_CHAR(tty) ((tty)->init_termios.c_cc[VLNEXT])
-#define EOL2_CHAR(tty) ((tty)->init_termios.c_cc[VEOL2])
-
-#define _I_FLAG(tty,f) ((tty)->init_termios.c_iflag & (f))
-#define _O_FLAG(tty,f) ((tty)->init_termios.c_oflag & (f))
-#define _C_FLAG(tty,f) ((tty)->init_termios.c_cflag & (f))
-#define _L_FLAG(tty,f) ((tty)->init_termios.c_lflag & (f))
-
-#define I_IGNBRK(tty) _I_FLAG((tty),IGNBRK)
-#define I_BRKINT(tty) _I_FLAG((tty),BRKINT)
-#define I_IGNPAR(tty) _I_FLAG((tty),IGNPAR)
-#define I_PARMRK(tty) _I_FLAG((tty),PARMRK)
-#define I_INPCK(tty) _I_FLAG((tty),INPCK)
-#define I_ISTRIP(tty) _I_FLAG((tty),ISTRIP)
-#define I_INLCR(tty) _I_FLAG((tty),INLCR)
-#define I_IGNCR(tty) _I_FLAG((tty),IGNCR)
-#define I_ICRNL(tty) _I_FLAG((tty),ICRNL)
-#define I_IUCLC(tty) _I_FLAG((tty),IUCLC)
-#define I_IXON(tty) _I_FLAG((tty),IXON)
-#define I_IXANY(tty) _I_FLAG((tty),IXANY)
-#define I_IXOFF(tty) _I_FLAG((tty),IXOFF)
-#define I_IMAXBEL(tty) _I_FLAG((tty),IMAXBEL)
-#define I_IUTF8(tty) _I_FLAG((tty), IUTF8)
-
-#define O_OPOST(tty) _O_FLAG((tty),OPOST)
-#define O_OLCUC(tty) _O_FLAG((tty),OLCUC)
-#define O_ONLCR(tty) _O_FLAG((tty),ONLCR)
-#define O_OCRNL(tty) _O_FLAG((tty),OCRNL)
-#define O_ONOCR(tty) _O_FLAG((tty),ONOCR)
-#define O_ONLRET(tty) _O_FLAG((tty),ONLRET)
-#define O_OFILL(tty) _O_FLAG((tty),OFILL)
-#define O_OFDEL(tty) _O_FLAG((tty),OFDEL)
-#define O_NLDLY(tty) _O_FLAG((tty),NLDLY)
-#define O_CRDLY(tty) _O_FLAG((tty),CRDLY)
-#define O_TABDLY(tty) _O_FLAG((tty),TABDLY)
-#define O_BSDLY(tty) _O_FLAG((tty),BSDLY)
-#define O_VTDLY(tty) _O_FLAG((tty),VTDLY)
-#define O_FFDLY(tty) _O_FLAG((tty),FFDLY)
-
-#define C_BAUD(tty) _C_FLAG((tty),CBAUD)
-#define C_CSIZE(tty) _C_FLAG((tty),CSIZE)
-#define C_CSTOPB(tty) _C_FLAG((tty),CSTOPB)
-#define C_CREAD(tty) _C_FLAG((tty),CREAD)
-#define C_PARENB(tty) _C_FLAG((tty),PARENB)
-#define C_PARODD(tty) _C_FLAG((tty),PARODD)
-#define C_HUPCL(tty) _C_FLAG((tty),HUPCL)
-#define C_CLOCAL(tty) _C_FLAG((tty),CLOCAL)
-#define C_CIBAUD(tty) _C_FLAG((tty),CIBAUD)
-#define C_CRTSCTS(tty) _C_FLAG((tty),CRTSCTS)
-
-#define L_ISIG(tty) _L_FLAG((tty),ISIG)
-#define L_ICANON(tty) _L_FLAG((tty),ICANON)
-#define L_XCASE(tty) _L_FLAG((tty),XCASE)
-#define L_ECHO(tty) _L_FLAG((tty),ECHO)
-#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
-#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
-#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
-#define L_NOFLSH(tty) _L_FLAG((tty),NOFLSH)
-#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
-#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
-#define L_ECHOPRT(tty) _L_FLAG((tty),ECHOPRT)
-#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
-#define L_FLUSHO(tty) _L_FLAG((tty),FLUSHO)
-#define L_PENDIN(tty) _L_FLAG((tty),PENDIN)
-#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN)
-#define L_EXTPROC(tty) _L_FLAG((tty), EXTPROC)
-
-/*
- * Where all of the state associated with a tty is kept while the tty
- * is open. Since the termios state should be kept even if the tty
- * has been closed --- for things like the baud rate, etc --- it is
- * not stored here, but rather a pointer to the real state is stored
- * here. Possible the winsize structure should have the same
- * treatment, but (1) the default 80x24 is usually right and (2) it's
- * most often used by a windowing system, which will set the correct
- * size each time the window is created or resized anyway.
- * - TYT, 9/14/92
- */
-struct tty_struct
-{
- struct rt_device parent;
- int type;
- int subtype;
- int init_flag;
- int index; //for pty
- int pts_lock; //for pty
-
- struct tty_struct *other_struct; //for pty
-
- struct termios init_termios;
- struct winsize winsize;
- struct rt_mutex lock;
- pid_t pgrp;
- pid_t session;
- struct rt_lwp *foreground;
- struct tty_node *head;
-
- struct tty_ldisc *ldisc;
- void *disc_data;
- struct rt_device *io_dev;
-
- struct rt_wqueue wait_queue;
-
-#define RT_TTY_BUF 1024
- rt_list_t tty_drivers;
- struct rt_spinlock spinlock;
-};
-
-enum
-{
- TTY_INIT_FLAG_NONE = 0,
- TTY_INIT_FLAG_ALLOCED,
- TTY_INIT_FLAG_REGED,
- TTY_INIT_FLAG_INITED,
-};
-
-#define TTY_DRIVER_TYPE_SYSTEM 0x0001
-#define TTY_DRIVER_TYPE_CONSOLE 0x0002
-#define TTY_DRIVER_TYPE_SERIAL 0x0003
-#define TTY_DRIVER_TYPE_PTY 0x0004
-#define TTY_DRIVER_TYPE_SCC 0x0005 /* scc driver */
-#define TTY_DRIVER_TYPE_SYSCONS 0x0006
-
-/* tty magic number */
-#define TTY_MAGIC 0x5401
-
-/*
- * These bits are used in the flags field of the tty structure.
- *
- * So that interrupts won't be able to mess up the queues,
- * copy_to_cooked must be atomic with respect to itself, as must
- * tty->write. Thus, you must use the inline functions set_bit() and
- * clear_bit() to make things atomic.
- */
-#define TTY_THROTTLED 0
-#define TTY_IO_ERROR 1
-#define TTY_OTHER_CLOSED 2
-#define TTY_EXCLUSIVE 3
-#define TTY_DEBUG 4
-#define TTY_DO_WRITE_WAKEUP 5
-#define TTY_PUSH 6
-#define TTY_CLOSING 7
-#define TTY_DONT_FLIP 8
-#define TTY_HW_COOK_OUT 14
-#define TTY_HW_COOK_IN 15
-#define TTY_PTY_LOCK 16
-#define TTY_NO_WRITE_SPLIT 17
-
-#define NR_LDISCS 30
-
-/* line disciplines */
-#define N_TTY 0
-#define N_SLIP 1
-#define N_MOUSE 2
-#define N_PPP 3
-#define N_STRIP 4
-#define N_AX25 5
-#define N_X25 6 /* X.25 async */
-#define N_6PACK 7
-#define N_MASC 8 /* Reserved for Mobitex module <[email protected]> */
-#define N_R3964 9 /* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL 10 /* Reserved for Profibus */
-#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data */
- /* cards about SMS messages */
-#define N_HDLC 13 /* synchronous HDLC */
-#define N_SYNC_PPP 14 /* synchronous PPP */
-#define N_HCI 15 /* Bluetooth HCI UART */
-#define N_GIGASET_M101 16 /* Siemens Gigaset M101 serial DECT adapter */
-#define N_SLCAN 17 /* Serial / USB serial CAN Adaptors */
-#define N_PPS 18 /* Pulse per Second */
-#define N_V253 19 /* Codec control over voice modem */
-#define N_CAIF 20 /* CAIF protocol for talking to modems */
-#define N_GSM0710 21 /* GSM 0710 Mux */
-#define N_TI_WL 22 /* for TI's WL BT, FM, GPS combo chips */
-#define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */
-#define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */
-#define N_NCI 25 /* NFC NCI UART */
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-
-/* pty subtypes */
-#define PTY_TYPE_MASTER 0x0001
-#define PTY_TYPE_SLAVE 0x0002
-
-/* serial subtype definitions */
-#define SERIAL_TYPE_NORMAL 1
-
-#define max(a, b) ({\
- typeof(a) _a = a;\
- typeof(b) _b = b;\
- _a > _b ? _a : _b; })
-
-#define min(a, b) ({\
- typeof(a) _a = a;\
- typeof(b) _b = b;\
- _a < _b ? _a : _b; })
-
-void mutex_lock(rt_mutex_t mutex);
-void mutex_unlock(rt_mutex_t mutex);
-int __tty_check_change(struct tty_struct *tty, int sig);
-int tty_check_change(struct tty_struct *tty);
-
-rt_inline struct rt_wqueue *wait_queue_get(struct rt_lwp *lwp, struct tty_struct *tty)
-{
- if (lwp == RT_NULL)
- {
- return &tty->wait_queue;
- }
- return &lwp->wait_queue;
-}
-
-rt_inline struct rt_wqueue *wait_queue_current_get(struct rt_lwp *lwp, struct tty_struct *tty)
-{
- return wait_queue_get(lwp, tty);
-}
-
-rt_inline void tty_wakeup_check(struct tty_struct *tty)
-{
- struct rt_wqueue *wq = NULL;
-
- wq = wait_queue_current_get(tty->foreground, tty);
- rt_wqueue_wakeup(wq, (void*)POLLIN);
-}
-
-int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev);
-const struct dfs_file_ops *tty_get_fops(void);
-
-int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *arg);
-
-void console_ldata_init(struct tty_struct *tty);
-int n_tty_receive_buf(struct tty_struct *tty, char *cp, int count);
-
-#endif /*__TTY_H__*/
diff --git a/components/drivers/tty/include/tty_ldisc.h b/components/drivers/tty/include/tty_ldisc.h
deleted file mode 100644
index 9b95fd3591..0000000000
--- a/components/drivers/tty/include/tty_ldisc.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021.12.07 linzhenxing first version
- */
-#ifndef __TTY_LDISC_
-#define __TTY_LDISC_
-#include <rtthread.h>
-#include <dfs.h>
-#include <dfs_fs.h>
-#include <tty.h>
-#if defined(RT_USING_POSIX_TERMIOS)
-#include <termios.h>
-#endif
-struct tty_struct;
-
-struct tty_ldisc_ops
-{
- char *name;
- int num;
-
- int (*open) (struct dfs_file *fd);
- int (*close) (struct tty_struct *tty);
- int (*ioctl) (struct dfs_file *fd, int cmd, void *args);
- int (*read) (struct dfs_file *fd, void *buf, size_t count);
- int (*write) (struct dfs_file *fd, const void *buf, size_t count);
- int (*flush) (struct dfs_file *fd);
- int (*lseek) (struct dfs_file *fd, off_t offset);
- int (*getdents) (struct dfs_file *fd, struct dirent *dirp, uint32_t count);
-
- int (*poll) (struct dfs_file *fd, struct rt_pollreq *req);
- void (*set_termios) (struct tty_struct *tty, struct termios *old);
- int (*receive_buf) (struct tty_struct *tty,char *cp, int count);
-
- int refcount;
-};
-
-struct tty_ldisc
-{
- struct tty_ldisc_ops *ops;
- struct tty_struct *tty;
-};
-
-#define TTY_LDISC_MAGIC 0x5403
-
-int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
-void tty_ldisc_kill(struct tty_struct *tty);
-void tty_ldisc_init(struct tty_struct *tty);
-void tty_ldisc_release(struct tty_struct *tty);
-void n_tty_init(void);
-
-#endif // __TTY_LDISC_
diff --git a/components/drivers/tty/n_tty.c b/components/drivers/tty/n_tty.c
deleted file mode 100644
index bf1156ba38..0000000000
--- a/components/drivers/tty/n_tty.c
+++ /dev/null
@@ -1,2223 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021.12.07 linzhenxing first version
- */
-#include <stddef.h>
-#include <ctype.h>
-#include <tty.h>
-#include <lwp.h>
-#if defined(RT_USING_POSIX_TERMIOS)
-#include <termios.h>
-#endif
-#include <sys/errno.h>
-
-#define DBG_TAG "N_TTY"
-#ifdef RT_TTY_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* RT_TTY_DEBUG */
-#include <rtdbg.h>
-
-/* number of characters left in xmit buffer before select has we have room */
-#define WAKEUP_CHARS 256
-
-/*
- * This defines the low- and high-watermarks for throttling and
- * unthrottling the TTY driver. These watermarks are used for
- * controlling the space in the read buffer.
- */
-#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */
-#define TTY_THRESHOLD_UNTHROTTLE 128
-
-/*
- * Special byte codes used in the echo buffer to represent operations
- * or special handling of characters. Bytes in the echo buffer that
- * are not part of such special blocks are treated as normal character
- * codes.
- */
-#define ECHO_OP_START 0xff
-#define ECHO_OP_MOVE_BACK_COL 0x80
-#define ECHO_OP_SET_CANON_COL 0x81
-#define ECHO_OP_ERASE_TAB 0x82
-
-#define ECHO_COMMIT_WATERMARK 256
-#define ECHO_BLOCK 256
-#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32)
-
-static struct rt_spinlock _spinlock = RT_SPINLOCK_INIT;
-
-struct n_tty_data
-{
- /* producer-published */
- size_t read_head;
- size_t commit_head;
- size_t canon_head;
- size_t echo_head;
- size_t echo_commit;
- size_t echo_mark;
- unsigned long char_map[256];
-
- /* non-atomic */
- rt_bool_t no_room;
- /* must hold exclusive termios_rwsem to reset these */
- unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
- unsigned char push:1;
-
- /* shared by producer and consumer */
- char read_buf[RT_TTY_BUF];
- unsigned long read_flags[RT_TTY_BUF];
- unsigned char echo_buf[RT_TTY_BUF];
-
- /* consumer-published */
- size_t read_tail;
- size_t line_start;
-
- /* protected by output lock */
- unsigned int column;
- unsigned int canon_column;
- size_t echo_tail;
-
- rt_mutex_t atomic_read_lock;
- rt_mutex_t output_lock;
-};
-
-rt_inline int set_bit(int nr,int *addr)
-{
- int mask, retval;
- rt_base_t level;
-
- addr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- level = rt_spin_lock_irqsave(&_spinlock);
- retval = (mask & *addr) != 0;
- *addr |= mask;
- rt_spin_unlock_irqrestore(&_spinlock, level);
- return retval;
-}
-
-rt_inline int clear_bit(int nr, int *addr)
-{
- int mask, retval;
- rt_base_t level;
-
- addr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- level = rt_spin_lock_irqsave(&_spinlock);
- retval = (mask & *addr) != 0;
- *addr &= ~mask;
- rt_spin_unlock_irqrestore(&_spinlock, level);
- return retval;
-}
-
-rt_inline int test_bit(int nr, int *addr)
-{
- int mask;
-
- addr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- return ((mask & *addr) != 0);
-}
-
-rt_inline int test_and_clear_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- rt_base_t level;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- level = rt_spin_lock_irqsave(&_spinlock);
- retval = (mask & *a) != 0;
- *a &= ~mask;
- rt_spin_unlock_irqrestore(&_spinlock, level);
-
- return retval;
-}
-
-#ifdef __GNUC__
-rt_inline unsigned long __ffs(unsigned long word)
-{
- return __builtin_ffsl(word);
-}
-#else
-rt_inline unsigned long __ffs(unsigned long word)
-{
- int num = 0;
-
-#if BITS_PER_LONG == 64
- if ((word & 0xffffffff) == 0)
- {
- num += 32;
- word >>= 32;
- }
-#endif
- if ((word & 0xffff) == 0)
- {
- num += 16;
- word >>= 16;
- }
- if ((word & 0xff) == 0)
- {
- num += 8;
- word >>= 8;
- }
- if ((word & 0xf) == 0)
- {
- num += 4;
- word >>= 4;
- }
- if ((word & 0x3) == 0)
- {
- num += 2;
- word >>= 2;
- }
- if ((word & 0x1) == 0)
- {
- num += 1;
- }
-
- return num;
-}
-#endif
-
-#define BITS_PER_LONG 32
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-
-/*
- * Find the next set bit in a memory region.
- */
-rt_inline unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p = addr + BITOP_WORD(offset);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- {
- return size;
- }
-
- size -= result;
- offset %= BITS_PER_LONG;
- if (offset)
- {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < BITS_PER_LONG)
- {
- goto found_first;
- }
-
- if (tmp)
- {
- goto found_middle;
- }
-
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
-
- while (size & ~(BITS_PER_LONG-1))
- {
- if ((tmp = *(p++)))
- {
- goto found_middle;
- }
-
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
-
- if (!size)
- {
- return result;
- }
-
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (BITS_PER_LONG - size));
- if (tmp == 0UL) /* Are any bits set? */
- {
- return result + size; /* Nope. */
- }
-
-found_middle:
- return result + __ffs(tmp);
-}
-
-rt_inline void tty_sigaddset(lwp_sigset_t *set, int _sig)
-{
- unsigned long sig = _sig - 1;
-
- if (_LWP_NSIG_WORDS == 1)
- {
- set->sig[0] |= 1UL << sig;
- }
- else
- {
- set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW);
- }
-}
-
-rt_inline size_t read_cnt(struct n_tty_data *ldata)
-{
- return ldata->read_head - ldata->read_tail;
-}
-
-rt_inline char read_buf(struct n_tty_data *ldata, size_t i)
-{
- return ldata->read_buf[i & (RT_TTY_BUF - 1)];
-}
-
-rt_inline char *read_buf_addr(struct n_tty_data *ldata, size_t i)
-{
- return &ldata->read_buf[i & (RT_TTY_BUF - 1)];
-}
-
-rt_inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i)
-{
- return ldata->echo_buf[i & (RT_TTY_BUF - 1)];
-}
-
-rt_inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i)
-{
- return &ldata->echo_buf[i & (RT_TTY_BUF - 1)];
-}
-
-/**
- * put_tty_queue - add character to tty
- * @c: character
- * @ldata: n_tty data
- *
- * Add a character to the tty read_buf queue.
- *
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
- */
-rt_inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
-{
- *read_buf_addr(ldata, ldata->read_head) = c;
- ldata->read_head++;
-}
-
-/**
- * reset_buffer_flags - reset buffer state
- * @tty: terminal to reset
- *
- * Reset the read buffer counters and clear the flags.
- * Called from n_tty_open() and n_tty_flush_buffer().
- *
- * Locking: caller holds exclusive termios_rwsem
- * (or locking is not required)
- */
-
-static void reset_buffer_flags(struct n_tty_data *ldata)
-{
- ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
- ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
- ldata->commit_head = 0;
- ldata->echo_mark = 0;
- ldata->line_start = 0;
-
- ldata->erasing = 0;
- rt_memset(ldata->read_flags, 0, RT_TTY_BUF);
- ldata->push = 0;
-}
-
-/**
- * add_echo_byte - add a byte to the echo buffer
- * @c: unicode byte to echo
- * @ldata: n_tty data
- *
- * Add a character or operation byte to the echo buffer.
- */
-
-rt_inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
-{
- *echo_buf_addr(ldata, ldata->echo_head++) = c;
-}
-
-/**
- * echo_move_back_col - add operation to move back a column
- * @ldata: n_tty data
- *
- * Add an operation to the echo buffer to move back one column.
- */
-
-static void echo_move_back_col(struct n_tty_data *ldata)
-{
- add_echo_byte(ECHO_OP_START, ldata);
- add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
-}
-
-/**
- * echo_set_canon_col - add operation to set the canon column
- * @ldata: n_tty data
- *
- * Add an operation to the echo buffer to set the canon column
- * to the current column.
- */
-
-static void echo_set_canon_col(struct n_tty_data *ldata)
-{
- add_echo_byte(ECHO_OP_START, ldata);
- add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
-}
-
-/**
- * echo_erase_tab - add operation to erase a tab
- * @num_chars: number of character columns already used
- * @after_tab: true if num_chars starts after a previous tab
- * @ldata: n_tty data
- *
- * Add an operation to the echo buffer to erase a tab.
- *
- * Called by the eraser function, which knows how many character
- * columns have been used since either a previous tab or the start
- * of input. This information will be used later, along with
- * canon column (if applicable), to go back the correct number
- * of columns.
- */
-
-static void echo_erase_tab(unsigned int num_chars, int after_tab,
- struct n_tty_data *ldata)
-{
- add_echo_byte(ECHO_OP_START, ldata);
- add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
-
- /* We only need to know this modulo 8 (tab spacing) */
- num_chars &= 7;
-
- /* Set the high bit as a flag if num_chars is after a previous tab */
- if (after_tab)
- {
- num_chars |= 0x80;
- }
-
- add_echo_byte(num_chars, ldata);
-}
-
-/**
- * echo_char_raw - echo a character raw
- * @c: unicode byte to echo
- * @tty: terminal device
- *
- * Echo user input back onto the screen. This must be called only when
- * L_ECHO(tty) is true. Called from the driver receive_buf path.
- *
- * This variant does not treat control characters specially.
- */
-
-static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
-{
- if (c == ECHO_OP_START)
- {
- add_echo_byte(ECHO_OP_START, ldata);
- add_echo_byte(ECHO_OP_START, ldata);
- }
- else
- {
- add_echo_byte(c, ldata);
- }
-}
-
-/**
- * echo_char - echo a character
- * @c: unicode byte to echo
- * @tty: terminal device
- *
- * Echo user input back onto the screen. This must be called only when
- * L_ECHO(tty) is true. Called from the driver receive_buf path.
- *
- * This variant tags control characters to be echoed as "^X"
- * (where X is the letter representing the control char).
- */
-
-static void echo_char(unsigned char c, struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (c == ECHO_OP_START)
- {
- add_echo_byte(ECHO_OP_START, ldata);
- add_echo_byte(ECHO_OP_START, ldata);
- }
- else
- {
- if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
- {
- add_echo_byte(ECHO_OP_START, ldata);
- }
- add_echo_byte(c, ldata);
- }
-}
-
-/**
- * finish_erasing - complete erase
- * @ldata: n_tty data
- */
-
-rt_inline void finish_erasing(struct n_tty_data *ldata)
-{
- if (ldata->erasing)
- {
- echo_char_raw('/', ldata);
- ldata->erasing = 0;
- }
-}
-
-/**
- * is_utf8_continuation - utf8 multibyte check
- * @c: byte to check
- *
- * Returns true if the utf8 character 'c' is a multibyte continuation
- * character. We use this to correctly compute the on screen size
- * of the character when printing
- */
-
-rt_inline int is_utf8_continuation(unsigned char c)
-{
- return (c & 0xc0) == 0x80;
-}
-
-/**
- * is_continuation - multibyte check
- * @c: byte to check
- *
- * Returns true if the utf8 character 'c' is a multibyte continuation
- * character and the terminal is in unicode mode.
- */
-
-rt_inline int is_continuation(unsigned char c, struct tty_struct *tty)
-{
- return I_IUTF8(tty) && is_utf8_continuation(c);
-}
-
-/**
- * eraser - handle erase function
- * @c: character input
- * @tty: terminal device
- *
- * Perform erase and necessary output when an erase character is
- * present in the stream from the driver layer. Handles the complexities
- * of UTF-8 multibyte symbols.
- *
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
- */
-
-static void eraser(unsigned char c, struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
- enum { KERASE, WERASE, KILL } kill_type;
- size_t head = 0;
- size_t cnt = 0;
- int seen_alnums = 0;
-
- if (ldata->read_head == ldata->canon_head)
- {
- /* process_output('\a', tty); */ /* what do you think? */
- return;
- }
-
- if (c == ERASE_CHAR(tty))
- {
- kill_type = KERASE;
- }
- else if (c == WERASE_CHAR(tty))
- {
- kill_type = WERASE;
- }
- else
- {
- if (!L_ECHO(tty))
- {
- ldata->read_head = ldata->canon_head;
- return;
- }
-
- if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty))
- {
- ldata->read_head = ldata->canon_head;
- finish_erasing(ldata);
- echo_char(KILL_CHAR(tty), tty);
- /* Add a newline if ECHOK is on and ECHOKE is off. */
- if (L_ECHOK(tty))
- {
- echo_char_raw('\n', ldata);
- }
- return;
- }
- kill_type = KILL;
- }
-
- seen_alnums = 0;
- while (ldata->read_head != ldata->canon_head)
- {
- head = ldata->read_head;
-
- /* erase a single possibly multibyte character */
- do
- {
- head--;
- c = read_buf(ldata, head);
- } while (is_continuation(c, tty) && head != ldata->canon_head);
-
- /* do not partially erase */
- if (is_continuation(c, tty))
- {
- break;
- }
-
- if (kill_type == WERASE)
- {
- /* Equivalent to BSD's ALTWERASE. */
- if (isalnum(c) || c == '_')
- {
- seen_alnums++;
- }
- else if (seen_alnums)
- {
- break;
- }
- }
- cnt = ldata->read_head - head;
- ldata->read_head = head;
- if (L_ECHO(tty))
- {
- if (L_ECHOPRT(tty))
- {
- if (!ldata->erasing)
- {
- echo_char_raw('\\', ldata);
- ldata->erasing = 1;
- }
- /* if cnt > 1, output a multi-byte character */
- echo_char(c, tty);
- while (--cnt > 0)
- {
- head++;
- echo_char_raw(read_buf(ldata, head), ldata);
- echo_move_back_col(ldata);
- }
- }
- else if (kill_type == KERASE && !L_ECHOE(tty))
- {
- echo_char(ERASE_CHAR(tty), tty);
- }
- else if (c == '\t')
- {
- unsigned int num_chars = 0;
- int after_tab = 0;
- size_t tail = ldata->read_head;
-
- /*
- * Count the columns used for characters
- * since the start of input or after a
- * previous tab.
- * This info is used to go back the correct
- * number of columns.
- */
- while (tail != ldata->canon_head)
- {
- tail--;
- c = read_buf(ldata, tail);
- if (c == '\t')
- {
- after_tab = 1;
- break;
- }
- else if (iscntrl(c))
- {
- if (L_ECHOCTL(tty))
- {
- num_chars += 2;
- }
- }
- else if (!is_continuation(c, tty))
- {
- num_chars++;
- }
- }
- echo_erase_tab(num_chars, after_tab, ldata);
- }
- else
- {
- if (iscntrl(c) && L_ECHOCTL(tty))
- {
- echo_char_raw('\b', ldata);
- echo_char_raw(' ', ldata);
- echo_char_raw('\b', ldata);
- }
- if (!iscntrl(c) || L_ECHOCTL(tty))
- {
- echo_char_raw('\b', ldata);
- echo_char_raw(' ', ldata);
- echo_char_raw('\b', ldata);
- }
- }
- }
- if (kill_type == KERASE)
- {
- break;
- }
- }
- if (ldata->read_head == ldata->canon_head && L_ECHO(tty))
- {
- finish_erasing(ldata);
- }
-}
-
-/**
- * isig - handle the ISIG optio
- * @sig: signal
- * @tty: terminal
- *
- * Called when a signal is being sent due to terminal input.
- * Called from the driver receive_buf path so serialized.
- *
- * Performs input and output flush if !NOFLSH. In this context, the echo
- * buffer is 'output'. The signal is processed first to alert any current
- * readers or writers to discontinue and exit their i/o loops.
- *
- * Locking: ctrl_lock
- */
-
-static void __isig(int sig, struct tty_struct *tty)
-{
- struct rt_lwp *lwp = tty->foreground;
- struct tty_ldisc *ld = RT_NULL;
- struct termios old_termios;
- struct termios *new_termios = get_old_termios();
-
- if (lwp)
- {
- if (sig == SIGTSTP)
- {
- struct rt_lwp *old_lwp;
-
- rt_memcpy(&old_termios, &(tty->init_termios), sizeof(struct termios));
- tty->init_termios = *new_termios;
- ld = tty->ldisc;
- if (ld != RT_NULL)
- {
- if (ld->ops->set_termios)
- {
- ld->ops->set_termios(tty, &old_termios);
- }
- }
- lwp_signal_kill(lwp, SIGTTOU, SI_USER, 0);
- old_lwp = tty_pop(&tty->head, RT_NULL);
- tty->foreground = old_lwp;
- }
- else
- {
- lwp_signal_kill(lwp, sig, SI_USER, 0);
- }
- }
-}
-
-static void isig(int sig, struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (L_NOFLSH(tty))
- {
- /* signal only */
- __isig(sig, tty);
-
- }
- else
- { /* signal and flush */
- __isig(sig, tty);
-
- /* clear echo buffer */
- ldata->echo_head = ldata->echo_tail = 0;
- ldata->echo_mark = ldata->echo_commit = 0;
-
- /* clear input buffer */
- reset_buffer_flags(tty->disc_data);
- }
-}
-
-/**
- * do_output_char - output one character
- * @c: character (or partial unicode symbol)
- * @tty: terminal device
- * @space: space available in tty driver write buffer
- *
- * This is a helper function that handles one output character
- * (including special characters like TAB, CR, LF, etc.),
- * doing OPOST processing and putting the results in the
- * tty driver's write buffer.
- *
- * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY
- * and NLDLY. They simply aren't relevant in the world today.
- * If you ever need them, add them here.
- *
- * Returns the number of bytes of buffer space used or -1 if
- * no space left.
- *
- * Locking: should be called under the output_lock to protect
- * the column state and space left in the buffer
- */
-
-static int do_output_char(unsigned char c, struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
- int spaces = 0;
- char *ch = RT_NULL;
-
- switch (c)
- {
- case '\n':
- if (O_ONLRET(tty))
- {
- ldata->column = 0;
- }
-
- if (O_ONLCR(tty))
- {
- ldata->canon_column = ldata->column = 0;
- ch = "\r\n";
- rt_device_write((rt_device_t)tty, -1, ch, 2);
- return 2;
- }
- ldata->canon_column = ldata->column;
- break;
- case '\r':
- if (O_ONOCR(tty) && ldata->column == 0)
- {
- return 0;
- }
-
- if (O_OCRNL(tty))
- {
- c = '\n';
- if (O_ONLRET(tty))
- {
- ldata->canon_column = ldata->column = 0;
- }
- break;
- }
- ldata->canon_column = ldata->column = 0;
- break;
- case '\t':
- spaces = 8 - (ldata->column & 7);
- if (O_TABDLY(tty) == XTABS)
- {
- ldata->column += spaces;
- ch = " ";
- rt_device_write((rt_device_t)tty, -1, &ch, spaces);
- return spaces;
- }
- ldata->column += spaces;
- break;
- case '\b':
- if (ldata->column > 0)
- {
- ldata->column--;
- }
- ch = "\b \b";
- rt_device_write((rt_device_t)tty, -1, ch, strlen(ch));
- return 1;
- default:
- if (!iscntrl(c))
- {
- if (O_OLCUC(tty))
- {
- c = toupper(c);
- }
-
- if (!is_continuation(c, tty))
- {
- ldata->column++;
- }
- }
- break;
- }
-
- rt_device_write((rt_device_t)tty, -1, &c, 1);
- return 1;
-}
-
-/**
- * process_output - output post processor
- * @c: character (or partial unicode symbol)
- * @tty: terminal device
- *
- * Output one character with OPOST processing.
- * Returns -1 when the output device is full and the character
- * must be retried.
- *
- * Locking: output_lock to protect column state and space left
- * (also, this is called from n_tty_write under the
- * tty layer write lock)
- */
-
-static int process_output(unsigned char c, struct tty_struct *tty)
-{
- int retval = 0;
-
- retval = do_output_char(c, tty);
- if (retval < 0)
- {
- return -1;
- }
- else
- {
- return 0;
- }
-}
-
-/**
- * process_output_block - block post processor
- * @tty: terminal device
- * @buf: character buffer
- * @nr: number of bytes to output
- *
- * Output a block of characters with OPOST processing.
- * Returns the number of characters output.
- *
- * This path is used to speed up block console writes, among other
- * things when processing blocks of output data. It handles only
- * the simple cases normally found and helps to generate blocks of
- * symbols for the console driver and thus improve performance.
- *
- * Locking: output_lock to protect column state and space left
- * (also, this is called from n_tty_write under the
- * tty layer write lock)
- */
-
-static ssize_t process_output_block(struct tty_struct *tty,
- const char *buf, unsigned int nr)
-{
- struct n_tty_data *ldata = tty->disc_data;
- int i = 0;
- ssize_t size = 0;
- const char *cp = RT_NULL;
-
- for (i = 0, cp = buf; i < nr; i++, cp++)
- {
- char c = *cp;
-
- switch (c)
- {
- case '\n':
- if (O_ONLRET(tty))
- {
- ldata->column = 0;
- }
-
- if (O_ONLCR(tty))
- {
- goto break_out;
- }
- ldata->canon_column = ldata->column;
- break;
- case '\r':
- if (O_ONOCR(tty) && ldata->column == 0)
- {
- goto break_out;
- }
-
- if (O_OCRNL(tty))
- {
- goto break_out;
- }
-
- ldata->canon_column = ldata->column = 0;
- break;
- case '\t':
- goto break_out;
- case '\b':
- if (ldata->column > 0)
- {
- ldata->column--;
- }
- break;
- default:
- if (!iscntrl(c))
- {
- if (O_OLCUC(tty))
- {
- goto break_out;
- }
-
- if (!is_continuation(c, tty))
- {
- ldata->column++;
- }
- }
- break;
- }
- }
-break_out:
- size = rt_device_write((rt_device_t)tty, -1, buf, i);
- return size;
-}
-
-static size_t __process_echoes(struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
- size_t tail = 0;
- unsigned char c = 0;
- char ch = 0;
- unsigned char num_chars = 0, num_bs = 0;
-
- tail = ldata->echo_tail;
- while (ldata->echo_commit != tail)
- {
- c = echo_buf(ldata, tail);
- if (c == ECHO_OP_START)
- {
- unsigned char op = 0;
-
- /*
- * If the buffer byte is the start of a multi-byte
- * operation, get the next byte, which is either the
- * op code or a control character value.
- */
- op = echo_buf(ldata, tail + 1);
-
- switch (op)
- {
- case ECHO_OP_ERASE_TAB:
- num_chars = echo_buf(ldata, tail + 2);
-
- /*
- * Determine how many columns to go back
- * in order to erase the tab.
- * This depends on the number of columns
- * used by other characters within the tab
- * area. If this (modulo 8) count is from
- * the start of input rather than from a
- * previous tab, we offset by canon column.
- * Otherwise, tab spacing is normal.
- */
- if (!(num_chars & 0x80))
- {
- num_chars += ldata->canon_column;
- }
- num_bs = 8 - (num_chars & 7);
-
- while (num_bs--)
- {
- ch = '\b';
- rt_device_write((rt_device_t)tty, -1, &ch, 1);
- if (ldata->column > 0)
- {
- ldata->column--;
- }
- }
- tail += 3;
- break;
-
- case ECHO_OP_SET_CANON_COL:
- ldata->canon_column = ldata->column;
- tail += 2;
- break;
-
- case ECHO_OP_MOVE_BACK_COL:
- if (ldata->column > 0)
- {
- ldata->column--;
- }
- tail += 2;
- break;
-
- case ECHO_OP_START:
- ch = ECHO_OP_START;
- rt_device_write((rt_device_t)tty, -1, &ch, 1);
- ldata->column++;
- tail += 2;
- break;
-
- default:
- /*
- * If the op is not a special byte code,
- * it is a ctrl char tagged to be echoed
- * as "^X" (where X is the letter
- * representing the control char).
- * Note that we must ensure there is
- * enough space for the whole ctrl pair.
- *
- */
- ch = '^';
- rt_device_write((rt_device_t)tty, -1, &ch, 1);
- ch = op ^ 0100;
- rt_device_write((rt_device_t)tty, -1, &ch, 1);
- ldata->column += 2;
- tail += 2;
- }
- }
- else
- {
- if (O_OPOST(tty))
- {
- int retval = do_output_char(c, tty);
- if (retval < 0)
- {
- break;
- }
- }
- else
- {
- rt_device_write((rt_device_t)tty, -1, &c, 1);
- }
- tail += 1;
- }
- }
-
- /* If the echo buffer is nearly full (so that the possibility exists
- * of echo overrun before the next commit), then discard enough
- * data at the tail to prevent a subsequent overrun */
- while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK)
- {
- if (echo_buf(ldata, tail) == ECHO_OP_START)
- {
- if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB)
- {
- tail += 3;
- }
- else
- {
- tail += 2;
- }
- }
- else
- {
- tail++;
- }
- }
-
- ldata->echo_tail = tail;
- return 0;
-}
-
-static void commit_echoes(struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
- size_t nr = 0, old = 0;
- size_t head = 0;
-
- head = ldata->echo_head;
- ldata->echo_mark = head;
- old = ldata->echo_commit - ldata->echo_tail;
-
- /* Process committed echoes if the accumulated # of bytes
- * is over the threshold (and try again each time another
- * block is accumulated) */
- nr = head - ldata->echo_tail;
- if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK))
- {
- return;
- }
-
- ldata->echo_commit = head;
- __process_echoes(tty);
-}
-
-static void process_echoes(struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (ldata->echo_mark == ldata->echo_tail)
- {
- return;
- }
-
- ldata->echo_commit = ldata->echo_mark;
- __process_echoes(tty);
-}
-
-/* NB: echo_mark and echo_head should be equivalent here */
-static void flush_echoes(struct tty_struct *tty)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
- ldata->echo_commit == ldata->echo_head)
- {
- return;
- }
-
- ldata->echo_commit = ldata->echo_head;
- __process_echoes(tty);
-}
-/**
- * n_tty_set_termios - termios data changed
- * @tty: terminal
- * @old: previous data
- *
- * Called by the tty layer when the user changes termios flags so
- * that the line discipline can plan ahead. This function cannot sleep
- * and is protected from re-entry by the tty layer. The user is
- * guaranteed that this function will not be re-entered or in progress
- * when the ldisc is closed.
- *
- * Locking: Caller holds tty->termios_rwsem
- */
-
-static void n_tty_set_termios(struct tty_struct *tty, struct termios *old)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (!old || (old->c_lflag ^ tty->init_termios.c_lflag) & (ICANON | EXTPROC))
- {
- rt_memset(ldata->read_flags, 0, RT_TTY_BUF);
- ldata->line_start = ldata->read_tail;
- if (!L_ICANON(tty) || !read_cnt(ldata))
- {
- ldata->canon_head = ldata->read_tail;
- ldata->push = 0;
- }
- else
- {
- set_bit((ldata->read_head - 1) & (RT_TTY_BUF - 1),(int *)ldata->read_flags);
- ldata->canon_head = ldata->read_head;
- ldata->push = 1;
- }
- ldata->commit_head = ldata->read_head;
- ldata->erasing = 0;
- ldata->lnext = 0;
- }
-
- ldata->icanon = (L_ICANON(tty) != 0);
-
- if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
- I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
- I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
- I_PARMRK(tty))
- {
- rt_memset(ldata->char_map, 0, 256);
- if (I_IGNCR(tty) || I_ICRNL(tty))
- {
- set_bit('\r', (int *)ldata->char_map);
- }
-
- if (I_INLCR(tty))
- {
- set_bit('\n', (int *)ldata->char_map);
- }
-
- if (L_ICANON(tty))
- {
- set_bit(ERASE_CHAR(tty), (int *)ldata->char_map);
- set_bit(KILL_CHAR(tty),(int *) ldata->char_map);
- set_bit(EOF_CHAR(tty), (int *)ldata->char_map);
- set_bit('\n',(int *) ldata->char_map);
- set_bit(EOL_CHAR(tty),(int *) ldata->char_map);
- if (L_IEXTEN(tty))
- {
- set_bit(WERASE_CHAR(tty), (int *)ldata->char_map);
- set_bit(LNEXT_CHAR(tty), (int *)ldata->char_map);
- set_bit(EOL2_CHAR(tty), (int *)ldata->char_map);
- if (L_ECHO(tty))
- {
- set_bit(REPRINT_CHAR(tty),
- (int *)ldata->char_map);
- }
- }
- }
- if (I_IXON(tty))
- {
- set_bit(START_CHAR(tty), (int *)ldata->char_map);
- set_bit(STOP_CHAR(tty), (int *)ldata->char_map);
- }
- if (L_ISIG(tty))
- {
- set_bit(INTR_CHAR(tty), (int *)ldata->char_map);
- set_bit(QUIT_CHAR(tty), (int *)ldata->char_map);
- set_bit(SUSP_CHAR(tty), (int *)ldata->char_map);
- }
- clear_bit(__DISABLED_CHAR, (int *)ldata->char_map);
- ldata->raw = 0;
- ldata->real_raw = 0;
- }
- else
- {
- ldata->raw = 1;
- if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
- (I_IGNPAR(tty) || !I_INPCK(tty))/* &&
- (tty->driver->flags & TTY_DRIVER_REAL_RAW)*/)
- {
- ldata->real_raw = 1;
- }
- else
- {
- ldata->real_raw = 0;
- }
- }
-}
-
-void console_ldata_init(struct tty_struct *tty)
-{
- struct n_tty_data *ldata = RT_NULL;
-
- ldata = rt_malloc(sizeof(struct n_tty_data));
- if (ldata == RT_NULL)
- {
- LOG_E("console_ldata_init ldata malloc fail");
- return;
- }
- tty->disc_data = ldata;
- reset_buffer_flags(ldata);
- ldata->column = 0;
- ldata->canon_column = 0;
- ldata->no_room = 0;
- ldata->lnext = 0;
- n_tty_set_termios(tty, RT_NULL);
- return;
-}
-
-static int n_tty_open(struct dfs_file *fd)
-{
- int ret = 0;
- struct n_tty_data *ldata = RT_NULL;
- struct tty_struct *tty = (struct tty_struct*)fd->vnode->data;
-
- ldata = rt_malloc(sizeof(struct n_tty_data));
- if (ldata == RT_NULL)
- {
- LOG_E("n_tty_open ldata malloc fail");
- return -1;
- }
-
- ldata->atomic_read_lock = rt_mutex_create("atomic_read_lock",RT_IPC_FLAG_FIFO);
- if(ldata->atomic_read_lock == RT_NULL)
- {
- LOG_E("n_tty_open atomic_read_lock create fail");
- return -1;
- }
-
- ldata->output_lock = rt_mutex_create("output_lock",RT_IPC_FLAG_FIFO);
- if(ldata->output_lock == RT_NULL)
- {
- LOG_E("n_tty_open output_lock create fail");
- return -1;
- }
-
- tty->disc_data = ldata;
- reset_buffer_flags(ldata);
- ldata->column = 0;
- ldata->canon_column = 0;
- ldata->lnext = 0;
- n_tty_set_termios(tty, RT_NULL);
- return ret;
-}
-
-rt_inline int input_available_p(struct tty_struct *tty, int poll)
-{
- struct n_tty_data *ldata = tty->disc_data;
- int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
-
- if (ldata->icanon && !L_EXTPROC(tty))
- {
- return ldata->canon_head != ldata->read_tail;
- }
- else
- {
- return ldata->commit_head - ldata->read_tail >= amt;
- }
-}
-
-/**
- * copy_from_read_buf - copy read data directly
- * @tty: terminal device
- * @b: user data
- * @nr: size of data
- *
- * Helper function to speed up n_tty_read. It is only called when
- * ICANON is off; it copies characters straight from the tty queue to
- * user space directly. It can be profitably called twice; once to
- * drain the space from the tail pointer to the (physical) end of the
- * buffer, and once to drain the space from the (physical) beginning of
- * the buffer to head pointer.
- *
- * Called under the ldata->atomic_read_lock sem
- *
- * n_tty_read()/consumer path:
- * caller holds non-exclusive termios_rwsem
- * read_tail published
- */
-
-static int copy_from_read_buf(struct tty_struct *tty,char *b,size_t nr)
-{
- struct n_tty_data *ldata = tty->disc_data;
- size_t n = 0;
- rt_bool_t is_eof = 0;
- size_t head = ldata->commit_head;
- size_t tail = ldata->read_tail & (RT_TTY_BUF - 1);
-
- n = min(head - ldata->read_tail, RT_TTY_BUF - tail);
- n = min(nr, n);
- if (n)
- {
- const char *from = read_buf_addr(ldata, tail);
- memcpy(b, from, n);
- is_eof = n == 1 && *from == EOF_CHAR(tty);
- ldata->read_tail += n;
- /* Turn single EOF into zero-length read */
- if (L_EXTPROC(tty) && ldata->icanon && is_eof &&
- (head == ldata->read_tail))
- {
- n = 0;
- }
-
- }
- return n;
-}
-
-/**
- * canon_copy_from_read_buf - copy read data in canonical mode
- * @tty: terminal device
- * @b: user data
- * @nr: size of data
- *
- * Helper function for n_tty_read. It is only called when ICANON is on;
- * it copies one line of input up to and including the line-delimiting
- * character into the user-space buffer.
- *
- * NB: When termios is changed from non-canonical to canonical mode and
- * the read buffer contains data, n_tty_set_termios() simulates an EOF
- * push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer.
- * This causes data already processed as input to be immediately available
- * as input although a newline has not been received.
- *
- * Called under the atomic_read_lock mutex
- *
- * n_tty_read()/consumer path:
- * caller holds non-exclusive termios_rwsem
- * read_tail published
- */
-
-static int canon_copy_from_read_buf(struct tty_struct *tty, char *b, size_t nr)
-{
- struct n_tty_data *ldata = tty->disc_data;
- size_t n = 0, size = 0, more = 0, c = 0;
- size_t eol = 0;
- size_t tail = 0;
- int found = 0;
-
- /* N.B. avoid overrun if nr == 0 */
- if (nr == 0)
- {
- return 0;
- }
-
- n = min(nr + 1, ldata->canon_head - ldata->read_tail);
-
- tail = ldata->read_tail & (RT_TTY_BUF - 1);
- size = min(tail + n, RT_TTY_BUF);
-
- eol = find_next_bit(ldata->read_flags, size, tail);
- more = n - (size - tail);
- if (eol == RT_TTY_BUF && more)
- {
- /* scan wrapped without finding set bit */
- eol = find_next_bit(ldata->read_flags, more, 0);
- found = eol != more;
- }
- else
- {
- found = eol != size;
- }
-
- n = eol - tail;
- if (n > RT_TTY_BUF)
- {
- n += RT_TTY_BUF;
- }
- c = n + found;
-
- if (!found || read_buf(ldata, eol) != __DISABLED_CHAR)
- {
- c = min(nr, c);
- n = c;
- }
-
- size_t buf_size = RT_TTY_BUF - tail;
- const void *from = read_buf_addr(ldata, tail);
- size_t temp_n = n;
- if (n > buf_size)
- {
- memcpy(b, from, buf_size);
- b += buf_size;
- temp_n -= buf_size;
- from = ldata->read_buf;
- }
- memcpy(b, from, temp_n);
-
- if (found)
- {
- clear_bit(eol, (int *)ldata->read_flags);
- }
- ldata->read_tail = ldata->read_tail + c;
-
- if (found)
- {
- if (!ldata->push)
- {
- ldata->line_start = ldata->read_tail;
- }
- else
- {
- ldata->push = 0;
- }
- }
- return n;
-}
-
-
-static int n_tty_close(struct tty_struct *tty)
-{
- int ret = 0;
- struct n_tty_data *ldata = RT_NULL;
- struct tty_struct *o_tty = RT_NULL;
-
- RT_ASSERT(tty != RT_NULL);
- if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
- {
- o_tty = tty->other_struct;
- }
- else
- {
- o_tty = tty;
- }
-
- ldata = o_tty->disc_data;
- rt_free(ldata);
- o_tty->disc_data = RT_NULL;
- return ret;
-}
-
-static int n_tty_ioctl(struct dfs_file *fd, int cmd, void *args)
-{
- int ret = 0;
- struct tty_struct *real_tty = RT_NULL;
- struct tty_struct *tty = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
- if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
- {
- real_tty = tty->other_struct;
- }
- else
- {
- real_tty = tty;
- }
-
- switch(cmd)
- {
-
- default:
- ret = n_tty_ioctl_extend(real_tty, cmd, args);
- if (ret != -ENOIOCTLCMD)
- {
- return ret;
- }
- }
-
- ret = rt_device_control((rt_device_t)real_tty, cmd, args);
- if (ret != -ENOIOCTLCMD)
- {
- return ret;
- }
- return ret;
-}
-
-static void
-n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
-{
- isig(signal, tty);
- if (L_ECHO(tty))
- {
- echo_char(c, tty);
- commit_echoes(tty);
- }
- else
- {
- process_echoes(tty);
- }
- return;
-}
-
-/**
- * n_tty_receive_char - perform processing
- * @tty: terminal device
- * @c: character
- *
- * Process an individual character of input received from the driver.
- * This is serialized with respect to itself by the rules for the
- * driver above.
- *
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
- * publishes canon_head if canonical mode is active
- *
- * Returns 1 if LNEXT was received, else returns 0
- */
-
-static int n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (I_IXON(tty))
- {
- if (c == START_CHAR(tty)) /*ctrl + p realize missing*/
- {
- process_echoes(tty);
- return 0;
- }
- if (c == STOP_CHAR(tty)) /*ctrl + s realize missing*/
- {
- return 0;
- }
- }
-
- if (L_ISIG(tty))
- {
- if (c == INTR_CHAR(tty)) /*ctrl + c realize missing*/
- {
- n_tty_receive_signal_char(tty, SIGINT, c);
- return 0;
- }
- else if (c == QUIT_CHAR(tty)) /*ctrl + d realize missing*/
- {
- n_tty_receive_signal_char(tty, SIGQUIT, c);
- return 0;
- }
- else if (c == SUSP_CHAR(tty)) /*ctrl + z realize missing*/
- {
- n_tty_receive_signal_char(tty, SIGTSTP, c);
- return 0;
- }
- }
-
- if (c == '\r')
- {
- if (I_IGNCR(tty))
- {
- return 0;
- }
-
- if (I_ICRNL(tty))
- {
- c = '\n';
- }
- }
- else if (c == '\n' && I_INLCR(tty))
- {
- c = '\r';
- }
-
- if (ldata->icanon)
- {
- if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
- (c == WERASE_CHAR(tty) && L_IEXTEN(tty)))
- {
- eraser(c, tty);
- commit_echoes(tty);
- return 0;
- }
- if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty))
- {
- ldata->lnext = 1;
- if (L_ECHO(tty))
- {
- finish_erasing(ldata);
- if (L_ECHOCTL(tty))
- {
- echo_char_raw('^', ldata);
- echo_char_raw('\b', ldata);
- commit_echoes(tty);
- }
- }
- return 1;
- }
- if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty))
- {
- size_t tail = ldata->canon_head;
-
- finish_erasing(ldata);
- echo_char(c, tty);
- echo_char_raw('\n', ldata);
- while (tail != ldata->read_head)
- {
- echo_char(read_buf(ldata, tail), tty);
- tail++;
- }
- commit_echoes(tty);
- return 0;
- }
- if (c == '\n')
- {
- if (L_ECHO(tty) || L_ECHONL(tty))
- {
- echo_char_raw('\n', ldata);
- commit_echoes(tty);
- }
- goto handle_newline;
- }
- if (c == EOF_CHAR(tty))
- {
- c = __DISABLED_CHAR;
- goto handle_newline;
- }
- if ((c == EOL_CHAR(tty)) ||
- (c == EOL2_CHAR(tty) && L_IEXTEN(tty)))
- {
- /*
- * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
- */
- if (L_ECHO(tty))
- {
- /* Record the column of first canon char. */
- if (ldata->canon_head == ldata->read_head)
- {
- echo_set_canon_col(ldata);
- }
-
- echo_char(c, tty);
- commit_echoes(tty);
- }
- /*
- * XXX does PARMRK doubling happen for
- * EOL_CHAR and EOL2_CHAR?
- */
- if (c == (unsigned char) '\377' && I_PARMRK(tty))
- {
- put_tty_queue(c, ldata);
- }
-
-handle_newline:
- set_bit(ldata->read_head & (RT_TTY_BUF - 1), (int *)ldata->read_flags);
- put_tty_queue(c, ldata);
- ldata->canon_head = ldata->read_head;
- tty_wakeup_check(tty);
- return 0;
- }
- }
-
- if (L_ECHO(tty))
- {
- finish_erasing(ldata);
- if (c == '\n')
- {
- echo_char_raw('\n', ldata);
- }
- else
- {
- /* Record the column of first canon char. */
- if (ldata->canon_head == ldata->read_head)
- {
- echo_set_canon_col(ldata);
- }
- echo_char(c, tty);
- }
- commit_echoes(tty);
- }
-
- /* PARMRK doubling check */
- if (c == (unsigned char) '\377' && I_PARMRK(tty))
- {
- put_tty_queue(c, ldata);
- }
-
- put_tty_queue(c, ldata);
- return 0;
-}
-
-rt_inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (L_ECHO(tty))
- {
- finish_erasing(ldata);
- /* Record the column of first canon char. */
- if (ldata->canon_head == ldata->read_head)
- {
- echo_set_canon_col(ldata);
- }
-
- echo_char(c, tty);
- commit_echoes(tty);
- }
- /* PARMRK doubling check */
- if (c == (unsigned char) '\377' && I_PARMRK(tty))
- {
- put_tty_queue(c, ldata);
- }
-
- put_tty_queue(c, ldata);
-}
-
-static void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
-{
- n_tty_receive_char_inline(tty, c);
-}
-
-static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- ldata->lnext = 0;
- if (flag == TTY_NORMAL)
- {
- if (I_ISTRIP(tty))
- {
- c &= 0x7f;
- }
-
- if (I_IUCLC(tty) && L_IEXTEN(tty))
- {
- c = tolower(c);
- }
-
- n_tty_receive_char(tty, c);
- }
- else
- {
- //n_tty_receive_char_flagged(tty, c, flag);
- }
-
-}
-
-static void n_tty_receive_buf_real_raw(struct tty_struct *tty, char *cp, int count)
-{
- struct n_tty_data *ldata = tty->disc_data;
- size_t n = 0, head = 0;
-
- head = ldata->read_head & (RT_TTY_BUF - 1);
- n = min(count, RT_TTY_BUF - head);
- rt_memcpy(read_buf_addr(ldata, head), cp, n);
- ldata->read_head += n;
- cp += n;
- count -= n;
-
- head = ldata->read_head & (RT_TTY_BUF - 1);
- n = min(count, RT_TTY_BUF - head);
- rt_memcpy(read_buf_addr(ldata, head), cp, n);
- ldata->read_head += n;
-}
-
-static void n_tty_receive_buf_raw(struct tty_struct *tty, char *cp, int count)
-{
- struct n_tty_data *ldata = tty->disc_data;
- char flag = TTY_NORMAL;
-
- while (count--)
- {
- if (flag == TTY_NORMAL)
- {
- put_tty_queue(*cp++, ldata);
- }
- }
-}
-
-static void n_tty_receive_buf_standard(struct tty_struct *tty, char *cp, int count)
-{
- struct n_tty_data *ldata = tty->disc_data;
- char flag = TTY_NORMAL;
-
- while (count--)
- {
- char c = *cp++;
-
- if (I_ISTRIP(tty))
- {
- c &= 0x7f;
- }
-
- if (I_IUCLC(tty) && L_IEXTEN(tty))
- {
- c = tolower(c);
- }
-
- if (L_EXTPROC(tty))
- {
- put_tty_queue(c, ldata);
- continue;
- }
-
- if (!test_bit(c, (int *)ldata->char_map))
- {
- n_tty_receive_char_inline(tty, c);
- }
- else if (n_tty_receive_char_special(tty, c) && count)
- {
- n_tty_receive_char_lnext(tty, *cp++, flag);
- count--;
- }
- }
-}
-
-rt_inline void n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c)
-{
- struct n_tty_data *ldata = tty->disc_data;
-
- if (L_ECHO(tty))
- {
- finish_erasing(ldata);
- /* Record the column of first canon char. */
- if (ldata->canon_head == ldata->read_head)
- {
- echo_set_canon_col(ldata);
- }
-
- echo_char(c, tty);
- commit_echoes(tty);
- }
- put_tty_queue(c, ldata);
-}
-
-static void n_tty_receive_buf_fast(struct tty_struct *tty, char *cp, int count)
-{
- struct n_tty_data *ldata = tty->disc_data;
- char flag = TTY_NORMAL;
-
- while (count--)
- {
- unsigned char c = *cp++;
-
- if (!test_bit(c, (int *)ldata->char_map))
- {
- n_tty_receive_char_fast(tty, c);
- }
- else if (n_tty_receive_char_special(tty, c) && count)
- {
- n_tty_receive_char_lnext(tty, *cp++, flag);
- count--;
- }
- }
-}
-
-static void __receive_buf(struct tty_struct *tty, char *cp, int count)
-{
- struct n_tty_data *ldata = tty->disc_data;
- rt_bool_t preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty));
-
- if (ldata->real_raw)
- {
- n_tty_receive_buf_real_raw(tty, cp, count);
- }
-
- else if (ldata->raw || (L_EXTPROC(tty) && !preops))
- {
- n_tty_receive_buf_raw(tty, cp, count);
- }
- else
- {
- if (!preops && !I_PARMRK(tty))
- {
- n_tty_receive_buf_fast(tty, cp, count);
- }
- else
- {
- n_tty_receive_buf_standard(tty, cp, count);
- }
- flush_echoes(tty);
- }
-
- if (ldata->icanon && !L_EXTPROC(tty))
- return;
-
- /* publish read_head to consumer */
- ldata->commit_head = ldata->read_head;
-
- if (read_cnt(ldata))
- {
- tty_wakeup_check(tty);
- }
-}
-
-int n_tty_receive_buf(struct tty_struct *tty,char *cp, int count)
-{
- int size = 0;
- struct n_tty_data *ldata = tty->disc_data;
- int room = 0, n = 0, rcvd = 0, overflow = 0;
-
- size = count;
- while(1)
- {
- size_t tail = ldata->read_tail;
-
- room = RT_TTY_BUF - (ldata->read_head - tail);
-
- if (I_PARMRK(tty))
- {
- room = (room +2)/3;
- }
- room--;
- if (room <= 0)
- {
- overflow = ldata->icanon && ldata->canon_head == tail;
- if (overflow && room < 0)
- {
- ldata->read_head--;
- }
-
- room = overflow;
- }
- else
- {
- overflow = 0;
- }
-
- n = min(size, room);
-
- if (!n)
- {
- break;
- }
-
- if (!overflow)
- {
- __receive_buf(tty, cp, n);
- }
-
- cp += n;
- size -= n;
- rcvd += n;
- }
- return count - size;
-}
-
-/**
- * job_control - check job control
- * @tty: tty
- * @file: file handle
- *
- * Perform job control management checks on this file/tty descriptor
- * and if appropriate send any needed signals and return a negative
- * error code if action should be taken.
- *
- * Locking: redirected write test is safe
- * current->signal->tty check is safe
- * ctrl_lock to safely reference tty->pgrp
- */
-
-static int job_control(struct tty_struct *tty)
-{
- return __tty_check_change(tty, SIGTTIN);
-}
-
-static struct rt_wqueue *_wait_queue_current_get(struct tty_struct *tty)
-{
- struct rt_lwp *lwp;
-
- lwp = lwp_self();
- if (!lwp || !lwp->tty)
- lwp = RT_NULL;
-
- return wait_queue_get(lwp, tty);
-}
-
-static int n_tty_read(struct dfs_file *fd, void *buf, size_t count)
-{
- rt_base_t level = 0;
- char *b = (char *)buf;
- struct tty_struct *tty = RT_NULL;
- struct rt_wqueue *wq = RT_NULL;
- int wait_ret = 0;
- int retval = 0;
- int c = 0;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
- c = job_control(tty);
- if (c < 0)
- {
- return c;
- }
-
- struct n_tty_data *ldata = tty->disc_data;
-
- wq = _wait_queue_current_get(tty);
-
- while(count)
- {
- if ((!input_available_p(tty, 0)))
- {
- if (fd->flags & O_NONBLOCK)
- {
- retval = -EAGAIN;
- break;
- }
-
- wait_ret = rt_wqueue_wait_interruptible(wq, 0, RT_WAITING_FOREVER);
-
- if (wait_ret != 0)
- {
- break;
- }
- }
-
- level = rt_spin_lock_irqsave(&tty->spinlock);
- if (ldata->icanon && !L_EXTPROC(tty))
- {
- retval = canon_copy_from_read_buf(tty, b, count);
- }
- else
- {
- retval = copy_from_read_buf(tty, b, count);
- }
- rt_spin_unlock_irqrestore(&tty->spinlock, level);
-
- if (retval >= 1)
- {
- break;
- }
- }
-
- return retval;
-}
-
-static int n_tty_write(struct dfs_file *fd, const void *buf, size_t count)
-{
- int retval = 0;
- char *b = (char *)buf;
- int c = 0;
- struct tty_struct *tty = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
- retval = tty_check_change(tty);
- if (retval)
- {
- return retval;
- }
-
- process_echoes(tty);
- retval = count;
- while(1)
- {
- if (O_OPOST(tty))
- {
- while (count > 0)
- {
- ssize_t num = process_output_block(tty, b, count);
- if (num < 0)
- {
- if (num == -EAGAIN)
- {
- break;
- }
-
- retval = num;
- goto break_out;
- }
- b += num;
- count -= num;
- if (count == 0)
- {
- break;
- }
-
- c = *b;
- if (process_output(c, tty) < 0)
- {
- break;
- }
-
- b++;
- count--;
- }
- retval -= count;
- }
- else
- {
- while (count > 0)
- {
- c = rt_device_write((rt_device_t)tty, -1, b, count);
- if (c < 0)
- {
- retval = c;
- goto break_out;
- }
- b += c;
- count -= c;
- }
- retval -= count;
- }
-
- if (!count)
- {
- break;
- }
- if (fd->flags & O_NONBLOCK)
- {
- break;
- }
- }
-break_out:
- return retval;
-}
-
-static int n_tty_flush(struct dfs_file *fd)
-{
- return 0;
-}
-
-static int n_tty_lseek(struct dfs_file *fd, off_t offset)
-{
- return 0;
-}
-
-static int n_tty_getdents(struct dfs_file *fd, struct dirent *dirp, uint32_t count)
-{
- return 0;
-}
-
-static int n_tty_poll(struct dfs_file *fd, struct rt_pollreq *req)
-{
- rt_base_t level = 0;
- int mask = POLLOUT;
- struct tty_struct *tty = RT_NULL;
- struct rt_wqueue *wq = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
-
- RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED);
-
- wq = _wait_queue_current_get(tty);
- rt_poll_add(wq, req);
-
- level = rt_spin_lock_irqsave(&tty->spinlock);
- if (input_available_p(tty, 1))
- {
- mask |= POLLIN;
- }
- rt_spin_unlock_irqrestore(&tty->spinlock, level);
-
- return mask;
-}
-
-struct tty_ldisc_ops n_tty_ops = {
- "n_tty",
- 0,
- n_tty_open,
- n_tty_close,
- n_tty_ioctl,
- n_tty_read,
- n_tty_write,
- n_tty_flush,
- n_tty_lseek,
- n_tty_getdents,
- n_tty_poll,
- n_tty_set_termios,
- n_tty_receive_buf,
- 0,
-};
diff --git a/components/drivers/tty/pty.c b/components/drivers/tty/pty.c
deleted file mode 100644
index b6cbda5574..0000000000
--- a/components/drivers/tty/pty.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021.12.07 linzhenxing first version
- */
-#include <rtthread.h>
-#include <tty.h>
-#include <tty_ldisc.h>
-
-#define DBG_TAG "PTY"
-#ifdef RT_TTY_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* RT_TTY_DEBUG */
-#include <rtdbg.h>
-
-#define PTY_PTS_SIZE 10
-static struct tty_struct ptm_dev;
-static struct tty_struct pts_devs[PTY_PTS_SIZE];
-static int pts_index = 0;
-
-static int pts_register(struct tty_struct *ptmx, struct tty_struct *pts, int pts_index);
-
-/* check free pts device */
-static struct tty_struct *find_freepts(void)
-{
- for(int i = 0; i < PTY_PTS_SIZE; i++)
- {
- if (pts_devs[i].init_flag == TTY_INIT_FLAG_NONE)
- {
- pts_devs[i].init_flag = TTY_INIT_FLAG_ALLOCED;
- return &pts_devs[i];
- }
- }
- return RT_NULL;
-}
-
-/* Set the lock flag on a pty */
-static int pty_set_lock(struct tty_struct *tty, int *arg)
-{
- int val = *arg;
-
- if (val)
- {
- tty->pts_lock = val;
- }
- else
- {
- tty->pts_lock = val;
- }
- return 0;
-}
-
-static int pty_get_lock(struct tty_struct *tty, int *arg)
-{
- *arg = tty->pts_lock;
- return 0;
-}
-
-static int pty_get_index(struct tty_struct *tty, int *arg)
-{
- *arg = tty->index;
- return 0;
-}
-/* RT-Thread Device Interface */
-/*
- * This function initializes console device.
- */
-static rt_err_t pty_device_init(struct rt_device *dev)
-{
- rt_err_t result = RT_EOK;
- struct tty_struct *tty = RT_NULL;
-
- RT_ASSERT(dev != RT_NULL);
- tty = (struct tty_struct *)dev;
-
- RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_REGED);
- tty->init_flag = TTY_INIT_FLAG_INITED;
-
- return result;
-}
-
-static rt_err_t pty_device_open(struct rt_device *dev, rt_uint16_t oflag)
-{
- rt_err_t result = RT_EOK;
- return result;
-}
-
-static rt_err_t pty_device_close(struct rt_device *dev)
-{
- rt_err_t result = RT_EOK;
- struct tty_struct *tty = (struct tty_struct*)dev;
- //struct tty_struct *to = RT_NULL;
-
- if (tty->subtype == PTY_TYPE_MASTER)
- {
- // to = tty->other_struct;
- // to->init_flag = TTY_INIT_FLAG_NONE;
- // to->other_struct = RT_NULL;
- // to->foreground = RT_NULL;
- // to->index = -1;
- // tty_ldisc_kill(to);
- // tty->other_struct = RT_NULL;
- }
- else
- {
- // to = tty->other_struct;
- // to->other_struct = RT_NULL;
- // tty->init_flag = TTY_INIT_FLAG_NONE;
- // tty->other_struct = RT_NULL;
- // tty->foreground = RT_NULL;
- // tty->index = -1;
- // tty->other_struct = RT_NULL;
- // tty_ldisc_kill(tty);
- }
-
- return result;
-}
-
-static rt_ssize_t pty_device_read(struct rt_device *dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
-{
- rt_size_t len = 0;
-
- return len;
-}
-
-static rt_ssize_t pty_device_write(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
-{
- rt_size_t len = 0;
- rt_base_t level = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_struct *to = RT_NULL;
-
- tty = (struct tty_struct *)dev;
- RT_ASSERT(tty != RT_NULL);
- RT_ASSERT(tty->init_flag == TTY_INIT_FLAG_INITED);
- to = tty->other_struct;
-
- level = rt_spin_lock_irqsave(&tty->spinlock);
- if (to->ldisc->ops->receive_buf)
- {
- len = to->ldisc->ops->receive_buf(to, (char *)buffer, size);
- }
- rt_spin_unlock_irqrestore(&tty->spinlock, level);
-
- return len;
-}
-
-static rt_err_t pty_device_control(rt_device_t dev, int cmd, void *args)
-{
- struct tty_struct *tty = (struct tty_struct *)dev;
-
- switch (cmd)
- {
- case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
- return pty_set_lock(tty, (int *)args);
- case TIOCGPTLCK: /* Get PT Lock status */
- return pty_get_lock(tty, (int *)args);
- case TIOCGPTN: /* Get PT Number */
- return pty_get_index(tty, (int *)args);
- }
-
- return -ENOIOCTLCMD;
-}
-
-static int ptmx_open(struct dfs_file *fd)
-{
- int ret = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_struct *pts = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
-
- pts = find_freepts();
- if (pts == RT_NULL)
- {
- LOG_E("No free PTS device found.\n");
- return -1;
- }
- ret = pts_register(tty, pts, pts_index);
- if (ret < 0)
- {
- LOG_E("pts register fail\n");
- rt_free(pts);
- return -1;
- }
- pts_index++;
- tty->other_struct = pts;
-
- ld = tty->ldisc;
- if (ld->ops->open)
- {
- ret = ld->ops->open(fd);
- }
-
- rt_device_t device = (rt_device_t)fd->vnode->data;
- if(fd->vnode->ref_count == 1)
- {
- ret = rt_device_open(device, fd->flags);
- }
-
- return ret;
-}
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops pty_device_ops =
-{
- pty_device_init,
- pty_device_open,
- pty_device_close,
- pty_device_read,
- pty_device_write,
- pty_device_control,
-};
-#endif /* RT_USING_DEVICE_OPS */
-
-static struct dfs_file_ops pts_fops;
-static struct dfs_file_ops ptmx_fops;
-static int pts_register(struct tty_struct *ptmx, struct tty_struct *pts, int pts_index)
-{
- char name[20];
- rt_err_t ret = RT_EOK;
- struct rt_device *device = RT_NULL;
-
- RT_ASSERT(ptmx!=RT_NULL);
-
- if (pts->init_flag != TTY_INIT_FLAG_ALLOCED)
- {
- LOG_E("pts%d has been registered\n", pts_index);
- ret = (-RT_EBUSY);
- }
- else
- {
- tty_init(pts, TTY_DRIVER_TYPE_PTY, PTY_TYPE_SLAVE, NULL);
- pts->index = pts_index;
- pts->pts_lock = 1;
- pts->other_struct = ptmx;
-
- device = &pts->parent;
- device->type = RT_Device_Class_Char;
-#ifdef RT_USING_DEVICE_OPS
- device->ops = &pty_device_ops;
-#else
- device->init = pty_device_init;
- device->open = pty_device_open;
- device->close = pty_device_close;
- device->read = pty_device_read;
- device->write = pty_device_write;
- device->control = pty_device_control;
-#endif /* RT_USING_DEVICE_OPS */
-
- rt_snprintf(name, sizeof(name), "pts%d", pts_index);
- ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
- if (ret != RT_EOK)
- {
- LOG_E("pts%d register failed\n", pts_index);
- ret = -RT_EIO;
- }
- else
- {
-#ifdef RT_USING_POSIX_DEVIO
- /* set fops */
- memcpy(&pts_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
- device->fops = &pts_fops;
-#endif
- }
- }
-
- return ret;
-}
-
-static int ptmx_register(void)
-{
- rt_err_t ret = RT_EOK;
- struct rt_device *device = RT_NULL;
- struct tty_struct *ptmx = &ptm_dev;
-
- RT_ASSERT(ptmx->init_flag == TTY_INIT_FLAG_NONE);
-
- tty_init(ptmx, TTY_DRIVER_TYPE_PTY, PTY_TYPE_MASTER, NULL);
-
- device = &(ptmx->parent);
- device->type = RT_Device_Class_Char;
-
-#ifdef RT_USING_DEVICE_OPS
- device->ops = &pty_device_ops;
-#else
- device->init = pty_device_init;
- device->open = pty_device_open;
- device->close = pty_device_close;
- device->read = pty_device_read;
- device->write = pty_device_write;
- device->control = pty_device_control;
-#endif /* RT_USING_DEVICE_OPS */
-
- ret = rt_device_register(device, "ptmx", RT_DEVICE_FLAG_RDWR);
- if (ret != RT_EOK)
- {
- LOG_E("ptmx register fail\n");
- ret = -RT_EIO;
- }
- else
- {
-#ifdef RT_USING_POSIX_DEVIO
- /* set fops */
- memcpy(&ptmx_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
- ptmx_fops.open = ptmx_open;
- device->fops = &ptmx_fops;
-#endif
- }
-
- return ret;
-}
-INIT_DEVICE_EXPORT(ptmx_register);
diff --git a/components/drivers/tty/tty.c b/components/drivers/tty/tty.c
deleted file mode 100644
index 075b177d5c..0000000000
--- a/components/drivers/tty/tty.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-12-07 linzhenxing first version
- * 2023-06-26 WangXiaoyao fix bug on foreground app switch
- */
-#include <dfs_file.h>
-#include <dfs_fs.h>
-#include <lwp.h>
-#include <rtdevice.h>
-#include <rtthread.h>
-#include <tty.h>
-#include <tty_ldisc.h>
-#include <shell.h>
-
-#if defined(RT_USING_POSIX_DEVIO)
-#include <termios.h>
-#endif
-
-#define DBG_TAG "TTY"
-#ifdef RT_TTY_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* RT_TTY_DEBUG */
-#include <rtdbg.h>
-
-const struct termios tty_std_termios = { /* for the benefit of tty drivers */
- .c_iflag = IMAXBEL | IUCLC | INLCR | ICRNL | IGNPAR,
- .c_oflag = OPOST,
- .c_cflag = B38400 | CS8 | CREAD | HUPCL,
- .c_lflag = ISIG | ECHOE | TOSTOP | NOFLSH,
- RT_NULL,/* .c_line = N_TTY, */
- .c_cc = INIT_C_CC,
- .__c_ispeed = 38400,
- .__c_ospeed = 38400
-};
-
-void tty_initstack(struct tty_node *node)
-{
- node->lwp = RT_NULL;
- node->next = RT_NULL;
-}
-
-static struct tty_node tty_node_cache = { RT_NULL, RT_NULL };
-
-static struct tty_node *_tty_node_alloc(void)
-{
- struct tty_node *node = tty_node_cache.next;
-
- if (node == RT_NULL)
- {
- node = rt_calloc(1, sizeof(struct tty_node));
- }
- else
- {
- tty_node_cache.next = node->next;
- }
-
- return node;
-}
-
-static void _tty_node_free(struct tty_node *node)
-{
- node->next = tty_node_cache.next;
- tty_node_cache.next = node;
-}
-
-int tty_push(struct tty_node **head, struct rt_lwp *lwp)
-{
- struct tty_node *node = _tty_node_alloc();
-
- if (!node)
- {
- return -1;
- }
-
- node->lwp = lwp;
- node->next = *head;
- *head = node;
-
- return 0;
-}
-
-struct rt_lwp *tty_pop(struct tty_node **head, struct rt_lwp *target_lwp)
-{
- struct tty_node *node;
- struct rt_lwp *lwp = RT_NULL;
-
- if (!head || !*head)
- {
- return RT_NULL;
- }
-
- node = *head;
-
- if (target_lwp != RT_NULL && node->lwp != target_lwp)
- {
- struct tty_node *prev = RT_NULL;
-
- while (node != RT_NULL && node->lwp != target_lwp)
- {
- prev = node;
- node = node->next;
- }
-
- if (node != RT_NULL)
- {
- /* prev is impossible equ RT_NULL */
- prev->next = node->next;
- lwp = target_lwp;
- _tty_node_free(node);
- }
- }
- else
- {
- lwp = (*head)->lwp;
- *head = (*head)->next;
- node->lwp = RT_NULL;
- _tty_node_free(node);
- }
-
- return lwp;
-}
-
-/**
- * tty_check_change - check for POSIX terminal changes
- * @tty: tty to check
- *
- * If we try to write to, or set the state of, a terminal and we're
- * not in the foreground, send a SIGTTOU. If the signal is blocked or
- * ignored, go ahead and perform the operation. (POSIX 7.2)
- *
- * Locking: ctrl_lock
- */
-
-int __tty_check_change(struct tty_struct *tty, int sig)
-{
- pid_t pgrp = 0, tty_pgrp = 0;
- int ret = 0;
- struct rt_lwp *lwp;
-
- lwp = lwp_self();
-
- if (lwp == RT_NULL)
- {
- return 0;
- }
-
- if (lwp->tty != tty)
- {
- return 0;
- }
-
- pgrp = lwp->__pgrp;
- tty_pgrp = tty->pgrp;
-
- if (tty_pgrp && (pgrp != tty->pgrp))
- {
- lwp_signal_kill(lwp, sig, SI_USER, 0);
- }
-
- if (!tty_pgrp)
- {
- LOG_D("sig=%d, tty->pgrp == -1!\n", sig);
- }
- return ret;
-}
-
-int tty_check_change(struct tty_struct *tty)
-{
- return __tty_check_change(tty, SIGTTOU);
-}
-
-static int tty_open(struct dfs_file *fd)
-{
- int ret = 0;
- int noctty = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
-
- ld = tty->ldisc;
- if (ld->ops->open)
- {
- ret = ld->ops->open(fd);
- }
- noctty = (fd->flags & O_NOCTTY);
-
- rt_device_t device = (rt_device_t)fd->vnode->data;
- if (fd->vnode->ref_count == 1)
- {
- ret = rt_device_open(device, fd->flags);
- }
- if (current == RT_NULL) //kernel mode not lwp
- {
- return ret;
- }
-
- if (!noctty &&
- current->leader &&
- !current->tty &&
- tty->session == -1)
- {
- current->tty = tty;
- current->tty_old_pgrp = 0;
- tty->session = current->session;
- tty->pgrp = current->__pgrp;
- tty->foreground = current;
- }
-
- return ret;
-}
-
-static int tty_close(struct dfs_file *fd)
-{
- int ret = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
- ld = tty->ldisc;
- if (ld->ops->close)
- {
- //ld->ops->close(tty);
- }
- if (fd->vnode->ref_count == 1)
- {
- ret = rt_device_close((rt_device_t)tty);
- }
- return ret;
-}
-
-static int tiocsctty(struct tty_struct *tty, int arg)
-{
- if (current->leader &&
- (current->session == tty->session))
- {
- return 0;
- }
-
- /*
- * The process must be a session leader and
- * not have a controlling tty already.
- */
- if (!current->leader || current->tty)
- {
- return -EPERM;
- }
-
- if (tty->session > 0)
- {
- LOG_E("this tty have control process\n");
-
- }
- current->tty = tty;
- current->tty_old_pgrp = 0;
- tty->session = current->session;
- tty->pgrp = current->__pgrp;
- tty->foreground = current;
- if (tty->type == TTY_DRIVER_TYPE_PTY)
- {
- tty->other_struct->foreground = current;
- }
- return 0;
-}
-
-static int tiocswinsz(struct tty_struct *tty, struct winsize *p_winsize)
-{
- rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row);
- return 0;
-}
-
-static int tiocgwinsz(struct tty_struct *tty, struct winsize *p_winsize)
-{
- if(rt_thread_self() != rt_thread_find(FINSH_THREAD_NAME))
- {
- /* only can be used in tshell thread; otherwise, return default size */
- p_winsize->ws_col = 80;
- p_winsize->ws_row = 24;
- }
- else
- {
- #define _TIO_BUFLEN 20
- char _tio_buf[_TIO_BUFLEN];
- unsigned char cnt1, cnt2, cnt3, i;
- char row_s[4], col_s[4];
- char *p;
-
- rt_memset(_tio_buf, 0, _TIO_BUFLEN);
-
- /* send the command to terminal for getting the window size of the terminal */
- rt_kprintf("\033[18t");
-
- /* waiting for the response from the terminal */
- i = 0;
- while(i < _TIO_BUFLEN)
- {
- _tio_buf[i] = finsh_getchar();
- if(_tio_buf[i] != 't')
- {
- i ++;
- }
- else
- {
- break;
- }
- }
- if(i == _TIO_BUFLEN)
- {
- /* buffer overloaded, and return default size */
- p_winsize->ws_col = 80;
- p_winsize->ws_row = 24;
- return 0;
- }
-
- /* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */
- rt_memset(row_s,0,4);
- rt_memset(col_s,0,4);
- cnt1 = 0;
- while(cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';')
- {
- cnt1++;
- }
- cnt2 = ++cnt1;
- while(cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';')
- {
- cnt2++;
- }
- p = row_s;
- while(cnt1 < cnt2)
- {
- *p++ = _tio_buf[cnt1++];
- }
- p = col_s;
- cnt2++;
- cnt3 = rt_strlen(_tio_buf) - 1;
- while(cnt2 < cnt3)
- {
- *p++ = _tio_buf[cnt2++];
- }
-
- /* load the window size date */
- p_winsize->ws_col = atoi(col_s);
- p_winsize->ws_row = atoi(row_s);
- #undef _TIO_BUFLEN
- }
-
- p_winsize->ws_xpixel = 0;/* unused */
- p_winsize->ws_ypixel = 0;/* unused */
-
- return 0;
-}
-
-static int tty_ioctl(struct dfs_file *fd, int cmd, void *args)
-{
- int ret = 0;
- void *p = (void *)args;
- struct tty_struct *tty = RT_NULL;
- struct tty_struct *real_tty = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
-
- if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
- {
- real_tty = tty->other_struct;
- }
- else
- {
- real_tty = tty;
- }
-
- switch (cmd)
- {
- case TIOCSCTTY:
- return tiocsctty(real_tty, 1);
- case TIOCGWINSZ:
- return tiocgwinsz(real_tty, p);
- case TIOCSWINSZ:
- return tiocswinsz(real_tty, p);
- }
-
- ld = tty->ldisc;
- if (ld->ops->ioctl)
- {
- ret = ld->ops->ioctl(fd, cmd, args);
- }
- return ret;
-}
-
-#ifdef RT_USING_DFS_V2
-static ssize_t tty_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
-#else
-static ssize_t tty_read(struct dfs_file *fd, void *buf, size_t count)
-#endif
-{
- int ret = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
-
- ld = tty->ldisc;
- if (ld && ld->ops->read)
- {
- ret = ld->ops->read(fd, buf, count);
- }
- return ret;
-}
-
-#ifdef RT_USING_DFS_V2
-static ssize_t tty_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
-#else
-static ssize_t tty_write(struct dfs_file *fd, const void *buf, size_t count )
-#endif
-{
- int ret = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
-
- ld = tty->ldisc;
- if (ld && ld->ops->write)
- {
- ret = ld->ops->write(fd, buf, count);
- }
-
- return ret;
-}
-
-static int tty_poll(struct dfs_file *fd, struct rt_pollreq *req)
-{
- int ret = 0;
- struct tty_struct *tty = RT_NULL;
- struct tty_ldisc *ld = RT_NULL;
-
- tty = (struct tty_struct *)fd->vnode->data;
- RT_ASSERT(tty != RT_NULL);
- ld = tty->ldisc;
- if (ld->ops->poll)
- {
- ret = ld->ops->poll(fd, req);
- }
- return ret;
-}
-
-static const struct dfs_file_ops tty_fops =
-{
- .open = tty_open,
- .close = tty_close,
- .ioctl = tty_ioctl,
- .read = tty_read,
- .write = tty_write,
- .poll = tty_poll,
-};
-
-const struct dfs_file_ops *tty_get_fops(void)
-{
- return &tty_fops;
-}
-
-int tty_init(struct tty_struct *tty, int type, int subtype, struct rt_device *iodev)
-{
- if (tty)
- {
- struct tty_node *node = NULL;
-
- node = rt_calloc(1, sizeof(struct tty_node));
- if (node)
- {
- tty->type = type;
- tty->subtype = subtype;
- tty->io_dev = iodev;
-
- tty->head = node;
- tty_initstack(tty->head);
-
- tty->pgrp = -1;
- tty->session = -1;
- tty->foreground = RT_NULL;
-
- rt_mutex_init(&tty->lock, "ttyLock", RT_IPC_FLAG_PRIO);
- rt_wqueue_init(&tty->wait_queue);
- rt_spin_lock_init(&tty->spinlock);
-
- tty_ldisc_init(tty);
- tty->init_termios = tty_std_termios;
- tty->init_flag = TTY_INIT_FLAG_REGED;
- }
- }
-
- return 0;
-}
diff --git a/components/drivers/tty/tty_ioctl.c b/components/drivers/tty/tty_ioctl.c
deleted file mode 100644
index 92206266c3..0000000000
--- a/components/drivers/tty/tty_ioctl.c
+++ /dev/null
@@ -1,122 +0,0 @@
-#include <stddef.h>
-#include <rtthread.h>
-#include <tty.h>
-#if defined(RT_USING_POSIX_DEVIO)
-#include <termios.h>
-#endif
-
-#define DBG_TAG "TTY_IOCTL"
-#ifdef RT_TTY_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* RT_TTY_DEBUG */
-#include <rtdbg.h>
-
-/*
- * Internal flag options for termios setting behavior
- */
-#define TERMIOS_FLUSH 1
-#define TERMIOS_WAIT 2
-#define TERMIOS_TERMIO 4
-#define TERMIOS_OLD 8
-
-/**
- * set_termios - set termios values for a tty
- * @tty: terminal device
- * @arg: user data
- * @opt: option information
- *
- * Helper function to prepare termios data and run necessary other
- * functions before using tty_set_termios to do the actual changes.
- *
- * Locking:
- * Called functions take ldisc and termios_rwsem locks
- */
-
-static int set_termios(struct tty_struct *tty, void *arg, int opt)
-{
- struct termios old_termios;
- struct tty_ldisc *ld = RT_NULL;
- struct termios *new_termios = (struct termios *)arg;
- rt_base_t level = 0;
- int retval = tty_check_change(tty);
-
- if (retval)
- {
- return retval;
- }
-
- memcpy(&old_termios, &(tty->init_termios), sizeof(struct termios));
- level = rt_spin_lock_irqsave(&tty->spinlock);
- tty->init_termios = *new_termios;
- rt_spin_unlock_irqrestore(&tty->spinlock, level);
- ld = tty->ldisc;
- if (ld != NULL)
- {
- if (ld->ops->set_termios)
- {
- ld->ops->set_termios(tty, &old_termios);
- }
- }
- return 0;
-}
-
-int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *args)
-{
- int ret = 0;
- void *p = (void *)args;
- struct tty_struct *real_tty = RT_NULL;
-
- if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
- {
- real_tty = tty->other_struct;
- }
- else
- {
- real_tty = tty;
- }
-
- switch(cmd)
- {
- case TCGETS:
- case TCGETA:
- {
- struct termios *tio = (struct termios *)p;
- if (tio == RT_NULL)
- {
- return -RT_EINVAL;
- }
-
- memcpy(tio, &real_tty->init_termios, sizeof(real_tty->init_termios));
- return ret;
- }
- case TCSETSF:
- {
- return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
- }
- case TCSETSW:
- {
- return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
- }
- case TCSETS:
- {
- return set_termios(real_tty, p, TERMIOS_OLD);
- }
- case TCSETAF:
- {
- return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
- }
- case TCSETAW:
- {
- return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
- }
- case TCSETA:
- {
- return set_termios(real_tty, p, TERMIOS_TERMIO);
- }
- default:
- break;
- }
- return -ENOIOCTLCMD;
-}
diff --git a/components/drivers/tty/tty_ldisc.c b/components/drivers/tty/tty_ldisc.c
deleted file mode 100644
index f2aef64bcc..0000000000
--- a/components/drivers/tty/tty_ldisc.c
+++ /dev/null
@@ -1,178 +0,0 @@
-#include <tty.h>
-#include <tty_ldisc.h>
-
-#define DBG_TAG "TTY_LDISC"
-#ifdef RT_TTY_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* RT_TTY_DEBUG */
-#include <rtdbg.h>
-
-extern struct tty_ldisc_ops n_tty_ops;
-static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS] = {
- &n_tty_ops, /* N_TTY = 0 */
-};
-
-static struct rt_spinlock _spinlock = RT_SPINLOCK_INIT;
-
-static struct tty_ldisc_ops *get_ldops(int disc)
-{
- struct tty_ldisc_ops *ldops = RT_NULL;
- rt_base_t level = 0;
- level = rt_spin_lock_irqsave(&_spinlock);
- ldops = tty_ldiscs[disc];
- if (ldops)
- {
- ldops->refcount++;
- }
- rt_spin_unlock_irqrestore(&_spinlock, level);
- return ldops;
-}
-
-static void put_ldops(struct tty_ldisc_ops *ldops)
-{
- rt_base_t level = 0;
-
- level = rt_spin_lock_irqsave(&_spinlock);
- ldops->refcount--;
- rt_spin_unlock_irqrestore(&_spinlock, level);
-}
-
-static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
-{
- struct tty_ldisc *ld = RT_NULL;
- struct tty_ldisc_ops *ldops = RT_NULL;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- {
- return RT_NULL;
- }
-
- ldops = get_ldops(disc);
- if (ldops == RT_NULL)
- {
- LOG_E("tty ldisc get error\n");
- return RT_NULL;
- }
-
- ld = rt_malloc(sizeof(struct tty_ldisc));
- if (ld == RT_NULL)
- {
- ldops->refcount--;
- return RT_NULL;
- }
-
- ld->ops = ldops;
- ld->tty = tty;
-
- return ld;
-}
-
-/**
- * tty_ldisc_put - release the ldisc
- *
- * Complement of tty_ldisc_get().
- */
-static void tty_ldisc_put(struct tty_ldisc *ld)
-{
- if (ld)
- {
- put_ldops(ld->ops);
- rt_free(ld);
- }
-}
-
-/**
- * tty_ldisc_close - close a line discipline
- * @tty: tty we are opening the ldisc on
- * @ld: discipline to close
- *
- * A helper close method. Also a convenient debugging and check
- * point.
- */
-static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
-{
- if (ld && ld->ops->close)
- {
- ld->ops->close(tty);
- }
-}
-
-/**
- * tty_ldisc_kill - teardown ldisc
- * @tty: tty being released
- *
- * Perform final close of the ldisc and reset tty->ldisc
- */
-void tty_ldisc_kill(struct tty_struct *tty)
-{
- if (tty && tty->ldisc)
- {
- /*
- * Now kill off the ldisc
- */
- tty_ldisc_close(tty, tty->ldisc);
- tty_ldisc_put(tty->ldisc);
- /* Force an oops if we mess this up */
- tty->ldisc = NULL;
- }
-}
-
-int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
-{
- int ret = 0;
- rt_base_t level = 0;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- {
- return -EINVAL;
- }
-
- level = rt_spin_lock_irqsave(&_spinlock);
- tty_ldiscs[disc] = new_ldisc;
- new_ldisc->num = disc;
- new_ldisc->refcount = 0;
- rt_spin_unlock_irqrestore(&_spinlock, level);
-
- return ret;
-}
-
-/**
- * tty_ldisc_release - release line discipline
- * @tty: tty being shut down (or one end of pty pair)
- *
- * Called during the final close of a tty or a pty pair in order to shut
- * down the line discpline layer. On exit, each tty's ldisc is NULL.
- */
-
-void tty_ldisc_release(struct tty_struct *tty)
-{
- struct tty_struct *o_tty = tty->other_struct;
-
- /*
- * Shutdown this line discipline. As this is the final close,
- * it does not race with the set_ldisc code path.
- */
- tty_ldisc_kill(tty);
- if (o_tty)
- {
- tty_ldisc_kill(o_tty);
- }
-}
-
-/**
- * tty_ldisc_init - ldisc setup for new tty
- * @tty: tty being allocated
- *
- * Set up the line discipline objects for a newly allocated tty. Note that
- * the tty structure is not completely set up when this call is made.
- */
-
-void tty_ldisc_init(struct tty_struct *tty)
-{
- if (tty)
- {
- tty->ldisc = tty_ldisc_get(tty, N_TTY);
- }
-}