1*dbddf429SAlex Dewar // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 3e99525f9SJeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include <errno.h> 7e99525f9SJeff Dike #include <fcntl.h> 8e99525f9SJeff Dike #include <termios.h> 91da177e4SLinus Torvalds #include "chan_user.h" 1037185b33SAl Viro #include <os.h> 1137185b33SAl Viro #include <um_malloc.h> 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds struct tty_chan { 141da177e4SLinus Torvalds char *dev; 151da177e4SLinus Torvalds int raw; 161da177e4SLinus Torvalds struct termios tt; 171da177e4SLinus Torvalds }; 181da177e4SLinus Torvalds 195e7672ecSJeff Dike static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) 201da177e4SLinus Torvalds { 211da177e4SLinus Torvalds struct tty_chan *data; 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds if (*str != ':') { 24e99525f9SJeff Dike printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify " 251da177e4SLinus Torvalds "a device\n"); 26108ffa8cSJeff Dike return NULL; 271da177e4SLinus Torvalds } 281da177e4SLinus Torvalds str++; 291da177e4SLinus Torvalds 3043f5b308SJeff Dike data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); 311da177e4SLinus Torvalds if (data == NULL) 32108ffa8cSJeff Dike return NULL; 331da177e4SLinus Torvalds *data = ((struct tty_chan) { .dev = str, 341da177e4SLinus Torvalds .raw = opts->raw }); 351da177e4SLinus Torvalds 36108ffa8cSJeff Dike return data; 371da177e4SLinus Torvalds } 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds static int tty_open(int input, int output, int primary, void *d, 401da177e4SLinus Torvalds char **dev_out) 411da177e4SLinus Torvalds { 421da177e4SLinus Torvalds struct tty_chan *data = d; 43e99525f9SJeff Dike int fd, err, mode = 0; 441da177e4SLinus Torvalds 45e99525f9SJeff Dike if (input && output) 46e99525f9SJeff Dike mode = O_RDWR; 47e99525f9SJeff Dike else if (input) 48e99525f9SJeff Dike mode = O_RDONLY; 49e99525f9SJeff Dike else if (output) 50e99525f9SJeff Dike mode = O_WRONLY; 51e99525f9SJeff Dike 52e99525f9SJeff Dike fd = open(data->dev, mode); 53108ffa8cSJeff Dike if (fd < 0) 54e99525f9SJeff Dike return -errno; 55108ffa8cSJeff Dike 561da177e4SLinus Torvalds if (data->raw) { 571da177e4SLinus Torvalds CATCH_EINTR(err = tcgetattr(fd, &data->tt)); 581da177e4SLinus Torvalds if (err) 59108ffa8cSJeff Dike return err; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds err = raw(fd); 621da177e4SLinus Torvalds if (err) 63108ffa8cSJeff Dike return err; 641da177e4SLinus Torvalds } 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds *dev_out = data->dev; 67108ffa8cSJeff Dike return fd; 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 705e7672ecSJeff Dike const struct chan_ops tty_ops = { 711da177e4SLinus Torvalds .type = "tty", 721da177e4SLinus Torvalds .init = tty_chan_init, 731da177e4SLinus Torvalds .open = tty_open, 741da177e4SLinus Torvalds .close = generic_close, 751da177e4SLinus Torvalds .read = generic_read, 761da177e4SLinus Torvalds .write = generic_write, 77fd9bc53bSPaolo 'Blaisorblade' Giarrusso .console_write = generic_console_write, 781da177e4SLinus Torvalds .window_size = generic_window_size, 791da177e4SLinus Torvalds .free = generic_free, 801da177e4SLinus Torvalds .winch = 0, 811da177e4SLinus Torvalds }; 82