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
tty_chan_init(char * str,int device,const struct chan_opts * opts)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
tty_open(int input,int output,int primary,void * d,char ** dev_out)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