| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /*
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-12-15 tyx first implementation
- */
- #include <rtdevice.h>
- #include <string.h>
- #include <vconsole.h>
- #include <finsh.h>
- #define PRINT rt_kprintf
- #define VC_EVENT_RECV (0x1 << 0)
- #define VC_EVENT_EXIT (0x1 << 1)
- int libc_stdio_set_console(const char* device_name, int mode);
- int libc_stdio_get_console(void);
- static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer,
- rt_size_t size);
- static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer,
- rt_size_t size);
- #ifdef RT_USING_POSIX
- #include <dfs_posix.h>
- #include <dfs_poll.h>
- static rt_err_t fops_rx_ind(rt_device_t dev, rt_size_t size)
- {
- rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN);
- return RT_EOK;
- }
- /* fops for vc */
- static int _fops_open(struct dfs_fd *fd)
- {
- rt_err_t ret = 0;
- rt_uint16_t flags = 0;
- rt_device_t device;
- device = (rt_device_t)fd->data;
- RT_ASSERT(device != RT_NULL);
- switch (fd->flags & O_ACCMODE)
- {
- case O_RDONLY:
- flags = RT_DEVICE_FLAG_RDONLY;
- break;
- case O_WRONLY:
- flags = RT_DEVICE_FLAG_WRONLY;
- break;
- case O_RDWR:
- flags = RT_DEVICE_FLAG_RDWR;
- break;
- default:
- break;
- }
- if ((fd->flags & O_ACCMODE) != O_WRONLY)
- rt_device_set_rx_indicate(device, fops_rx_ind);
- ret = rt_device_open(device, flags);
- if (ret == RT_EOK) return 0;
- return ret;
- }
- static int _fops_close(struct dfs_fd *fd)
- {
- rt_device_t device;
- device = (rt_device_t)fd->data;
- rt_device_set_rx_indicate(device, RT_NULL);
- rt_device_close(device);
- return 0;
- }
- static int _fops_ioctl(struct dfs_fd *fd, int cmd, void *args)
- {
- rt_device_t device;
- device = (rt_device_t)fd->data;
- switch (cmd)
- {
- case FIONREAD:
- break;
- case FIONWRITE:
- break;
- }
- return rt_device_control(device, cmd, args);
- }
- static int _fops_read(struct dfs_fd *fd, void *buf, size_t count)
- {
- int size = 0;
- rt_device_t device;
- device = (rt_device_t)fd->data;
- do
- {
- size = rt_device_read(device, -1, buf, count);
- if (size <= 0)
- {
- if (fd->flags & O_NONBLOCK)
- {
- size = -EAGAIN;
- break;
- }
- rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER);
- }
- }while (size <= 0);
- return size;
- }
- static int _fops_write(struct dfs_fd *fd, const void *buf, size_t count)
- {
- rt_device_t device;
- device = (rt_device_t)fd->data;
- return rt_device_write(device, -1, buf, count);
- }
- static int _fops_poll(struct dfs_fd *fd, struct rt_pollreq *req)
- {
- int mask = 0;
- int flags = 0;
- rt_device_t device;
- vconsole_t vc;
- device = (rt_device_t)fd->data;
- RT_ASSERT(device != RT_NULL);
- vc = (vconsole_t)device;
- /* only support POLLIN */
- flags = fd->flags & O_ACCMODE;
- if (flags == O_RDONLY || flags == O_RDWR)
- {
- rt_poll_add(&(device->wait_queue), req);
- if (rt_ringbuffer_data_len(&vc->ring_buff) > 0)
- mask |= POLLIN;
- }
- return mask;
- }
- const static struct dfs_file_ops _vc_fops =
- {
- _fops_open,
- _fops_close,
- _fops_ioctl,
- _fops_read,
- _fops_write,
- RT_NULL, /* flush */
- RT_NULL, /* lseek */
- RT_NULL, /* getdents */
- _fops_poll,
- };
- #endif
- static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer,
- rt_size_t size)
- {
- vconsole_t vc = (vconsole_t)dev;
- rt_size_t len;
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_take(&vc->mutex);
- #else
- rt_enter_critical();
- #endif
- len = rt_ringbuffer_get(&vc->ring_buff, buffer, size);
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_release(&vc->mutex);
- #else
- rt_exit_critical();
- #endif
- return len;
- }
- static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer,
- rt_size_t size)
- {
- vconsole_t vc = (vconsole_t)dev;
- rt_size_t len, w_len;
- rt_uint8_t *bstr;
- const rt_uint8_t *str = buffer;
- int index = 0, lf = 0;
- int i;
- w_len = 0;
- bstr = vc->cache;
- for (i = 0; i < size && index < vc->cache_size; i++)
- {
- if(str[i] == '\n')
- {
- bstr[index++] = '\r';
- lf ++;
- }
- bstr[index++] = str[i];
- if (index >= vc->cache_size - 1)
- {
- len = vc->output(dev, vc->cache, vc->cache_size);
- index = 0;
- w_len += len;
- }
- }
- if (index > 0)
- {
- len = vc->output(dev, vc->cache, index);
- w_len += len;
- }
- if (w_len > lf)
- w_len -= lf;
- return w_len;
- }
- #ifdef RT_USING_DEVICE_OPS
- const static struct rt_device_ops _vc_ops =
- {
- RT_NULL,
- RT_NULL,
- RT_NULL,
- _read,
- _write,
- RT_NULL
- };
- #endif
- rt_device_t vconsole_create(const char *name, vc_output_t out)
- {
- vconsole_t vc;
- int ret;
- rt_device_t vc_dev;
- if (out == RT_NULL)
- {
- return RT_NULL;
- }
- /* create virtual console device */
- vc = rt_calloc(1, sizeof(struct vconsole) +
- VCONSOLE_CACHE_SIZE +
- VCONSOLE_POOL_SIZE);
- if (vc == RT_NULL)
- {
- return RT_NULL;
- }
- vc->magic = VCONSOLE_MAGIC_NUM;
- vc->output = out;
- vc->cache_size = VCONSOLE_CACHE_SIZE;
- vc->ring_size = VCONSOLE_POOL_SIZE;
- rt_ringbuffer_init(&vc->ring_buff, vc->ring_pool, vc->ring_size);
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_init(&vc->mutex, name, RT_IPC_FLAG_FIFO);
- #endif
- /* init virtual console device */
- vc_dev = &vc->parent;
- vc_dev->type = RT_Device_Class_Char;
- #ifdef RT_USING_DEVICE_OPS
- vc_dev->ops = &_vc_ops;
- #else
- vc_dev->init = RT_NULL;
- vc_dev->open = RT_NULL;
- vc_dev->close = RT_NULL;
- vc_dev->read = _read;
- vc_dev->write = _write;
- vc_dev->control = RT_NULL;
- #endif
- vc_dev->user_data = RT_NULL;
- /* register virtual console device */
- ret = rt_device_register(vc_dev, name,
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
- if (ret != RT_EOK)
- {
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_detach(&vc->mutex);
- #endif
- rt_free(vc);
- return RT_NULL;
- }
- #ifdef RT_USING_POSIX
- /* set fops */
- vc_dev->fops = &_vc_fops;
- #endif
- return vc_dev;
- }
- rt_device_t vconsole_switch(rt_device_t device)
- {
- rt_device_t old_dev;
- if (device == RT_NULL)
- return RT_NULL;
- old_dev = rt_console_get_device();
- rt_console_set_device(device->parent.name);
- #ifdef RT_USING_POSIX
- {
- int fd, flags;
- fd = libc_stdio_get_console();
- flags = ioctl(fd, F_GETFL, 0);
- ioctl(fd, F_SETFL, (void *)(flags | O_NONBLOCK));
- libc_stdio_set_console(device->parent.name, O_RDWR);
- rt_wqueue_wakeup(&(old_dev->wait_queue), (void*)POLLERR);
- rt_thread_mdelay(20);
- }
- #else
- finsh_set_device(device->parent.name);
- #endif
- return old_dev;
- }
- rt_err_t vconsole_delete(rt_device_t device)
- {
- vconsole_t vc = (vconsole_t)device;
- if (vc == RT_NULL)
- {
- return -RT_EINVAL;
- }
- if (device == rt_console_get_device())
- {
- return -RT_EBUSY;
- }
- if (vc->magic != VCONSOLE_MAGIC_NUM)
- {
- return -RT_ERROR;
- }
- rt_device_unregister(device);
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_detach(&vc->mutex);
- #endif
- rt_free(vc);
- return RT_EOK;
- }
- rt_size_t vconsole_input(rt_device_t device, const rt_uint8_t *buff, rt_size_t size)
- {
- rt_size_t len;
- vconsole_t vc = (vconsole_t)device;
- RT_ASSERT(vc != RT_NULL);
- RT_ASSERT(vc->magic == VCONSOLE_MAGIC_NUM);
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_take(&vc->mutex);
- #else
- rt_enter_critical();
- #endif
- len = rt_ringbuffer_put(&vc->ring_buff, buff, size);
- #ifdef VCONSOLE_USING_MUTEX
- rt_mutex_release(&vc->mutex);
- #else
- rt_exit_critical();
- #endif
- if (len > 0 && device->rx_indicate)
- {
- device->rx_indicate(device, len);
- }
- return len;
- }
|