^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <termios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "chan_user.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <os.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <um_malloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct tty_chan {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) char *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) int raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct termios tt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct tty_chan *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (*str != ':') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) "a device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *data = ((struct tty_chan) { .dev = str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .raw = opts->raw });
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int tty_open(int input, int output, int primary, void *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) char **dev_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct tty_chan *data = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int fd, err, mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (input && output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) mode = O_RDWR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) else if (input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) mode = O_RDONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) else if (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) mode = O_WRONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) fd = open(data->dev, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (data->raw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) CATCH_EINTR(err = tcgetattr(fd, &data->tt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) err = raw(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *dev_out = data->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) const struct chan_ops tty_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .type = "tty",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .init = tty_chan_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .open = tty_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .close = generic_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .read = generic_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .write = generic_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .console_write = generic_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .window_size = generic_window_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .free = generic_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .winch = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };