#include #include #include #include #include #include #include #include #include #include #include #include #include #define STDIN_BUFSIZE 4096 static char stdin_buffer[STDIN_BUFSIZE]; static off_t p_rpos, p_wpos; static wait_queue_t __wait_queue, *wait_queue = &__wait_queue; void dev_stdin_write(char c) { bool intr_flag; if (c != '\0') { local_intr_save(intr_flag); { stdin_buffer[p_wpos % STDIN_BUFSIZE] = c; if (p_wpos - p_rpos < STDIN_BUFSIZE) { p_wpos ++; } if (!wait_queue_empty(wait_queue)) { wakeup_queue(wait_queue, WT_KBD, 1); } } local_intr_restore(intr_flag); } } static int dev_stdin_read(char *buf, size_t len) { int ret = 0; bool intr_flag; local_intr_save(intr_flag); { for (; ret < len; ret ++, p_rpos ++) { try_again: if (p_rpos < p_wpos) { *buf ++ = stdin_buffer[p_rpos % STDIN_BUFSIZE]; } else { wait_t __wait, *wait = &__wait; wait_current_set(wait_queue, wait, WT_KBD); local_intr_restore(intr_flag); schedule(); local_intr_save(intr_flag); wait_current_del(wait_queue, wait); if (wait->wakeup_flags == WT_KBD) { goto try_again; } break; } } } local_intr_restore(intr_flag); return ret; } static int stdin_open(struct device *dev, uint32_t open_flags) { if (open_flags != O_RDONLY) { return -E_INVAL; } return 0; } static int stdin_close(struct device *dev) { return 0; } static int stdin_io(struct device *dev, struct iobuf *iob, bool write) { if (!write) { int ret; if ((ret = dev_stdin_read(iob->io_base, iob->io_resid)) > 0) { iob->io_resid -= ret; } return ret; } return -E_INVAL; } static int stdin_ioctl(struct device *dev, int op, void *data) { return -E_INVAL; } static void stdin_device_init(struct device *dev) { dev->d_blocks = 0; dev->d_blocksize = 1; dev->d_open = stdin_open; dev->d_close = stdin_close; dev->d_io = stdin_io; dev->d_ioctl = stdin_ioctl; p_rpos = p_wpos = 0; wait_queue_init(wait_queue); } void dev_init_stdin(void) { struct inode *node; if ((node = dev_create_inode()) == NULL) { panic("stdin: dev_create_node.\n"); } stdin_device_init(vop_info(node, device)); int ret; if ((ret = vfs_add_dev("stdin", node, 0)) != 0) { panic("stdin: vfs_add_dev: %e.\n", ret); } }