tty.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <kernel/hw/serial.h>
  2. #include <kernel/process.hpp>
  3. #include <kernel/tty.hpp>
  4. #include <kernel/vga.hpp>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. tty::tty()
  8. : buf(BUFFER_SIZE)
  9. {
  10. }
  11. void tty::print(const char* str)
  12. {
  13. while (*str != '\0')
  14. this->putchar(*(str++));
  15. }
  16. size_t tty::read(char* buf, size_t buf_size, size_t n)
  17. {
  18. size_t orig_n = n;
  19. while (buf_size && n) {
  20. if (this->buf.empty()) {
  21. current_thread->attr.ready = 0;
  22. current_thread->attr.wait = 1;
  23. this->blocklist.subscribe(current_thread);
  24. schedule();
  25. this->blocklist.unsubscribe(current_thread);
  26. }
  27. if (this->buf.empty())
  28. break;
  29. *buf = this->buf.get();
  30. --buf_size;
  31. --n;
  32. if (*(buf++) == '\n')
  33. break;
  34. }
  35. return orig_n - n;
  36. }
  37. vga_tty::vga_tty()
  38. {
  39. snprintf(this->name, sizeof(this->name), "ttyVGA");
  40. }
  41. serial_tty::serial_tty(int id)
  42. : id(id)
  43. {
  44. snprintf(this->name, sizeof(this->name), "ttyS%x", (int)id);
  45. }
  46. void serial_tty::putchar(char c)
  47. {
  48. serial_send_data(id, c);
  49. }
  50. void vga_tty::putchar(char c)
  51. {
  52. static struct vga_char vc = { .c = '\0', .color = VGA_CHAR_COLOR_WHITE };
  53. vc.c = c;
  54. vga_put_char(&vc);
  55. }
  56. void vga_tty::recvchar(char c)
  57. {
  58. // TODO: keyboard scan code
  59. buf.put(c);
  60. }
  61. void serial_tty::recvchar(char c)
  62. {
  63. switch (c) {
  64. case '\r':
  65. buf.put('\n');
  66. if (echo) {
  67. serial_send_data(PORT_SERIAL0, '\r');
  68. serial_send_data(PORT_SERIAL0, '\n');
  69. }
  70. this->blocklist.notify();
  71. break;
  72. // ^?: backspace
  73. case 0x7f:
  74. if (!buf.empty() && buf.back() != '\n') {
  75. buf.pop();
  76. if (echo) {
  77. serial_send_data(PORT_SERIAL0, 0x08);
  78. serial_send_data(PORT_SERIAL0, '\x1b');
  79. serial_send_data(PORT_SERIAL0, '[');
  80. serial_send_data(PORT_SERIAL0, 'K');
  81. }
  82. }
  83. break;
  84. // ^U: clear the line
  85. case 0x15:
  86. while (!buf.empty() && buf.back() != '\n') {
  87. buf.pop();
  88. if (echo) {
  89. // clear the line
  90. // serial_send_data(PORT_SERIAL0, '\r');
  91. // serial_send_data(PORT_SERIAL0, '\x1b');
  92. // serial_send_data(PORT_SERIAL0, '[');
  93. // serial_send_data(PORT_SERIAL0, '2');
  94. // serial_send_data(PORT_SERIAL0, 'K');
  95. serial_send_data(PORT_SERIAL0, 0x08);
  96. serial_send_data(PORT_SERIAL0, '\x1b');
  97. serial_send_data(PORT_SERIAL0, '[');
  98. serial_send_data(PORT_SERIAL0, 'K');
  99. }
  100. }
  101. break;
  102. // ^C: SIGINT
  103. case 0x03:
  104. console->print("sigint");
  105. break;
  106. // ^D: EOF
  107. case 0x04:
  108. this->blocklist.notify();
  109. break;
  110. // ^Z: SIGSTOP
  111. case 0x1a:
  112. console->print("sigstop");
  113. break;
  114. default:
  115. buf.put(c);
  116. if (echo)
  117. serial_send_data(PORT_SERIAL0, c);
  118. break;
  119. }
  120. }