tty.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include <kernel/hw/serial.h>
  2. #include <kernel/process.hpp>
  3. #include <kernel/stdio.hpp>
  4. #include <kernel/tty.hpp>
  5. #include <kernel/vga.hpp>
  6. #include <types/stdint.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. while (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. *buf = this->buf.get();
  28. --buf_size;
  29. --n;
  30. if (*(buf++) == '\n')
  31. break;
  32. }
  33. return orig_n - n;
  34. }
  35. vga_tty::vga_tty()
  36. {
  37. snprintf(this->name, sizeof(this->name), "ttyVGA");
  38. }
  39. serial_tty::serial_tty(int id)
  40. : id(id)
  41. {
  42. snprintf(this->name, sizeof(this->name), "ttyS%x", (int)id);
  43. }
  44. void serial_tty::putchar(char c)
  45. {
  46. serial_send_data(id, c);
  47. }
  48. void vga_tty::putchar(char c)
  49. {
  50. static struct vga_char vc = { .c = '\0', .color = VGA_CHAR_COLOR_WHITE };
  51. vc.c = c;
  52. vga_put_char(&vc);
  53. }
  54. void vga_tty::recvchar(char c)
  55. {
  56. // TODO: keyboard scan code
  57. buf.put(c);
  58. }
  59. void serial_tty::recvchar(char c)
  60. {
  61. switch (c) {
  62. case '\r':
  63. buf.put('\n');
  64. if (echo) {
  65. serial_send_data(PORT_SERIAL0, '\r');
  66. serial_send_data(PORT_SERIAL0, '\n');
  67. }
  68. this->blocklist.notify();
  69. break;
  70. // ^?: backspace
  71. case 0x7f:
  72. if (!buf.empty() && buf.back() != '\n')
  73. buf.pop();
  74. if (echo) {
  75. serial_send_data(PORT_SERIAL0, 0x08);
  76. serial_send_data(PORT_SERIAL0, '\x1b');
  77. serial_send_data(PORT_SERIAL0, '[');
  78. serial_send_data(PORT_SERIAL0, 'K');
  79. }
  80. break;
  81. // ^U: clear the line
  82. case 0x15:
  83. while (!buf.empty() && buf.back() != '\n')
  84. buf.pop();
  85. if (echo) {
  86. serial_send_data(PORT_SERIAL0, '\r');
  87. serial_send_data(PORT_SERIAL0, '\x1b');
  88. serial_send_data(PORT_SERIAL0, '[');
  89. serial_send_data(PORT_SERIAL0, '2');
  90. serial_send_data(PORT_SERIAL0, 'K');
  91. }
  92. break;
  93. default:
  94. buf.put(c);
  95. if (echo)
  96. serial_send_data(PORT_SERIAL0, c);
  97. break;
  98. }
  99. }