123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-12-07 Shell init ver.
- */
- #define DBG_TAG "lwp.tty"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include "tty_config.h"
- #include "tty_internal.h"
- #include "bsd_porting.h"
- #include "terminal.h"
- #include <fcntl.h>
- static struct dfs_file_ops ptm_fops;
- static int ptm_fops_open(struct dfs_file *file)
- {
- int rc;
- rt_uint32_t oflags = file->flags;
- rt_thread_t cur_thr = rt_thread_self();
- if (file->vnode && file->vnode->data)
- {
- /**
- * Filter out illegal flags
- */
- if ((oflags & ~(O_RDWR | O_NOCTTY | O_CLOEXEC | O_LARGEFILE)) == 0)
- {
- rc = pts_alloc(FFLAGS(oflags & O_ACCMODE), cur_thr, file);
- /* detached operation from devfs */
- if (rc == 0)
- file->vnode->fops = &ptm_fops;
- }
- else
- {
- rc = -EINVAL;
- }
- }
- else
- {
- rc = -EINVAL;
- }
- return rc;
- }
- static int ptm_fops_close(struct dfs_file *file)
- {
- int rc;
- lwp_tty_t tp;
- rt_device_t device;
- if (file->data)
- {
- device = (rt_device_t)file->data;
- tp = rt_container_of(device, struct lwp_tty, parent);
- rc = bsd_ptsdev_methods.fo_close(tp, rt_thread_self());
- }
- else
- {
- rc = -EINVAL;
- }
- return rc;
- }
- static ssize_t ptm_fops_read(struct dfs_file *file, void *buf, size_t count,
- off_t *pos)
- {
- ssize_t rc = 0;
- int error;
- struct uio uio;
- struct iovec iov;
- rt_device_t device;
- struct lwp_tty *tp;
- int oflags = file->flags;
- if (file->data)
- {
- device = (rt_device_t)file->data;
- tp = rt_container_of(device, struct lwp_tty, parent);
- /* setup uio parameters */
- iov.iov_base = (void *)buf;
- iov.iov_len = count;
- uio.uio_offset = file->fpos;
- uio.uio_resid = count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_rw = UIO_READ;
- rc = count;
- error =
- bsd_ptsdev_methods.fo_read(tp, &uio, 0, oflags, rt_thread_self());
- rc -= uio.uio_resid;
- if (error)
- {
- rc = error;
- }
- /* reset file context */
- file->fpos = uio.uio_offset;
- }
- return rc;
- }
- static ssize_t ptm_fops_write(struct dfs_file *file, const void *buf,
- size_t count, off_t *pos)
- {
- ssize_t rc = 0;
- int error;
- struct uio uio;
- struct iovec iov;
- rt_device_t device;
- struct lwp_tty *tp;
- int oflags = file->flags;
- if (file->data)
- {
- device = (rt_device_t)file->data;
- tp = rt_container_of(device, struct lwp_tty, parent);
- /* setup uio parameters */
- iov.iov_base = (void *)buf;
- iov.iov_len = count;
- uio.uio_offset = file->fpos;
- uio.uio_resid = count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_rw = UIO_WRITE;
- rc = count;
- error =
- bsd_ptsdev_methods.fo_write(tp, &uio, 0, oflags, rt_thread_self());
- if (error)
- {
- rc = error;
- }
- else
- {
- rc -= uio.uio_resid;
- }
- /* reset file context */
- file->fpos = uio.uio_offset;
- }
- return rc;
- }
- static int ptm_fops_ioctl(struct dfs_file *file, int cmd, void *arg)
- {
- int rc;
- lwp_tty_t tp;
- rt_device_t device;
- rt_ubase_t cmd_normal = (unsigned int)cmd;
- if (file->data)
- {
- device = (rt_device_t)file->data;
- tp = rt_container_of(device, struct lwp_tty, parent);
- switch (cmd_normal)
- {
- case TIOCSPTLCK:
- {
- int is_lock;
- if (lwp_get_from_user(&is_lock, arg, sizeof(int)) != sizeof(int))
- return -EFAULT;
- pts_set_lock(tp, is_lock);
- rc = 0;
- }
- break;
- case TIOCGPTLCK:
- {
- int is_lock = pts_is_locked(tp);
- if (lwp_put_to_user(arg, &is_lock, sizeof(int)) != sizeof(int))
- return -EFAULT;
- rc = 0;
- }
- break;
- case TIOCGPKT:
- {
- int pktmode = pts_get_pktmode(tp);
- if (lwp_put_to_user(arg, &pktmode, sizeof(int)) != sizeof(int))
- return -EFAULT;
- rc = 0;
- }
- break;
- default:
- rc = bsd_ptsdev_methods.fo_ioctl(
- tp, cmd_normal, arg, 0, FFLAGS(file->flags), rt_thread_self());
- break;
- }
- }
- else
- {
- rc = -EINVAL;
- }
- return rc;
- }
- static int ptm_fops_flush(struct dfs_file *file)
- {
- return -EINVAL;
- }
- static off_t ptm_fops_lseek(struct dfs_file *file, off_t offset, int wherece)
- {
- return -EINVAL;
- }
- static int ptm_fops_truncate(struct dfs_file *file, off_t offset)
- {
- return -EINVAL;
- }
- static int ptm_fops_poll(struct dfs_file *file, struct rt_pollreq *req)
- {
- int rc;
- rt_device_t device;
- struct lwp_tty *tp;
- if (file->data)
- {
- device = (rt_device_t)file->data;
- tp = rt_container_of(device, struct lwp_tty, parent);
- rc = bsd_ptsdev_methods.fo_poll(tp, req, 0, rt_thread_self());
- }
- else
- {
- rc = -1;
- }
- return rc;
- }
- static int ptm_fops_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap)
- {
- return -EINVAL;
- }
- static int ptm_fops_lock(struct dfs_file *file, struct file_lock *flock)
- {
- return -EINVAL;
- }
- static int ptm_fops_flock(struct dfs_file *file, int operation, struct file_lock *flock)
- {
- return -EINVAL;
- }
- static struct dfs_file_ops ptm_fops = {
- .open = ptm_fops_open,
- .close = ptm_fops_close,
- .ioctl = ptm_fops_ioctl,
- .read = ptm_fops_read,
- .write = ptm_fops_write,
- .flush = ptm_fops_flush,
- .lseek = ptm_fops_lseek,
- .truncate = ptm_fops_truncate,
- .poll = ptm_fops_poll,
- .mmap = ptm_fops_mmap,
- .lock = ptm_fops_lock,
- .flock = ptm_fops_flock,
- };
- rt_err_t lwp_ptmx_init(rt_device_t ptmx_device, const char *root_path)
- {
- char *device_name;
- int root_len;
- const char *dev_rel_path;
- rt_err_t rc;
- root_len = strlen(root_path);
- dev_rel_path = "/ptmx";
- device_name = rt_malloc(root_len + sizeof("/ptmx"));
- if (device_name)
- {
- /* Register device */
- sprintf(device_name, "%s%s", root_path, dev_rel_path);
- rt_device_register(ptmx_device, device_name, 0);
- /* Setup fops */
- ptmx_device->fops = &ptm_fops;
- rt_free(device_name);
- rc = RT_EOK;
- }
- else
- {
- rc = -RT_ENOMEM;
- }
- return rc;
- }
- /* system level ptmx */
- static struct rt_device sysptmx;
- static struct dfs_file_ops sysptmx_file_ops;
- static rt_err_t sysptmx_readlink(struct rt_device *dev, char *buf, int len)
- {
- int rc = 0;
- /* TODO: support multi-root ? */
- strncpy(buf, "pts/ptmx", len);
- return rc;
- }
- static int _sys_ptmx_init(void)
- {
- rt_err_t rc;
- rt_device_t sysptmx_rtdev = &sysptmx;
- /* setup system level device */
- sysptmx_rtdev->type = RT_Device_Class_Char;
- sysptmx_rtdev->ops = RT_NULL;
- rc = rt_device_register(sysptmx_rtdev, "ptmx", RT_DEVICE_FLAG_DYNAMIC);
- if (rc == RT_EOK)
- {
- sysptmx_rtdev->readlink = &sysptmx_readlink;
- sysptmx_rtdev->fops = &sysptmx_file_ops;
- }
- return rc;
- }
- INIT_DEVICE_EXPORT(_sys_ptmx_init);
|