11da177e4SLinus Torvalds /* 2e99525f9SJeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 31da177e4SLinus Torvalds * Licensed under the GPL 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" 10e99525f9SJeff Dike #include "kern_constants.h" 111da177e4SLinus Torvalds #include "os.h" 12c13e5690SPaolo 'Blaisorblade' Giarrusso #include "um_malloc.h" 13e99525f9SJeff Dike #include "user.h" 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds struct tty_chan { 161da177e4SLinus Torvalds char *dev; 171da177e4SLinus Torvalds int raw; 181da177e4SLinus Torvalds struct termios tt; 191da177e4SLinus Torvalds }; 201da177e4SLinus Torvalds 215e7672ecSJeff Dike static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) 221da177e4SLinus Torvalds { 231da177e4SLinus Torvalds struct tty_chan *data; 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds if (*str != ':') { 26e99525f9SJeff Dike printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify " 271da177e4SLinus Torvalds "a device\n"); 28108ffa8cSJeff Dike return NULL; 291da177e4SLinus Torvalds } 301da177e4SLinus Torvalds str++; 311da177e4SLinus Torvalds 32*43f5b308SJeff Dike data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); 331da177e4SLinus Torvalds if (data == NULL) 34108ffa8cSJeff Dike return NULL; 351da177e4SLinus Torvalds *data = ((struct tty_chan) { .dev = str, 361da177e4SLinus Torvalds .raw = opts->raw }); 371da177e4SLinus Torvalds 38108ffa8cSJeff Dike return data; 391da177e4SLinus Torvalds } 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds static int tty_open(int input, int output, int primary, void *d, 421da177e4SLinus Torvalds char **dev_out) 431da177e4SLinus Torvalds { 441da177e4SLinus Torvalds struct tty_chan *data = d; 45e99525f9SJeff Dike int fd, err, mode = 0; 461da177e4SLinus Torvalds 47e99525f9SJeff Dike if (input && output) 48e99525f9SJeff Dike mode = O_RDWR; 49e99525f9SJeff Dike else if (input) 50e99525f9SJeff Dike mode = O_RDONLY; 51e99525f9SJeff Dike else if (output) 52e99525f9SJeff Dike mode = O_WRONLY; 53e99525f9SJeff Dike 54e99525f9SJeff Dike fd = open(data->dev, mode); 55108ffa8cSJeff Dike if (fd < 0) 56e99525f9SJeff Dike return -errno; 57108ffa8cSJeff Dike 581da177e4SLinus Torvalds if (data->raw) { 591da177e4SLinus Torvalds CATCH_EINTR(err = tcgetattr(fd, &data->tt)); 601da177e4SLinus Torvalds if (err) 61108ffa8cSJeff Dike return err; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds err = raw(fd); 641da177e4SLinus Torvalds if (err) 65108ffa8cSJeff Dike return err; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds *dev_out = data->dev; 69108ffa8cSJeff Dike return fd; 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds 725e7672ecSJeff Dike const struct chan_ops tty_ops = { 731da177e4SLinus Torvalds .type = "tty", 741da177e4SLinus Torvalds .init = tty_chan_init, 751da177e4SLinus Torvalds .open = tty_open, 761da177e4SLinus Torvalds .close = generic_close, 771da177e4SLinus Torvalds .read = generic_read, 781da177e4SLinus Torvalds .write = generic_write, 79fd9bc53bSPaolo 'Blaisorblade' Giarrusso .console_write = generic_console_write, 801da177e4SLinus Torvalds .window_size = generic_window_size, 811da177e4SLinus Torvalds .free = generic_free, 821da177e4SLinus Torvalds .winch = 0, 831da177e4SLinus Torvalds }; 84