tty.c 1.5 KB

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