tty.c 1.5 KB

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