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