keyboard.g 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. # This file is part of asmc, a bootstrapping OS with minimal seed
  2. # Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
  3. # https://gitlab.com/giomasce/asmc
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. # This simple keyboard driver is inspired by pc_kbd.c in iPXE
  15. $kbd_status
  16. const KBD_SHIFT 1
  17. const KBD_CTRL 2
  18. const KBD_CAPS 4
  19. fun kbd_get_scancode 0 {
  20. if 0x64 inb 0x01 & ! {
  21. 0 ret ;
  22. }
  23. $scan
  24. @scan 0x60 inb = ;
  25. if scan 0x2a == scan 0x36 == || {
  26. @kbd_status kbd_status KBD_SHIFT | = ;
  27. }
  28. if scan 0xaa == scan 0xb6 == || {
  29. @kbd_status kbd_status KBD_SHIFT ~ & = ;
  30. }
  31. if scan 0x1d == {
  32. @kbd_status kbd_status KBD_CTRL | = ;
  33. }
  34. if scan 0x9d == {
  35. @kbd_status kbd_status KBD_CTRL ~ & = ;
  36. }
  37. if scan 0x3a == {
  38. @kbd_status kbd_status KBD_CAPS ^ = ;
  39. }
  40. if scan 0x80 & {
  41. 0 ret ;
  42. }
  43. scan ret ;
  44. }
  45. fun kbd_maybe_getc 0 {
  46. $scan
  47. @scan kbd_get_scancode = ;
  48. if scan 0 == {
  49. 0 ret ;
  50. }
  51. if scan 0x54 >= {
  52. 0 ret ;
  53. }
  54. # Convert scan code to character
  55. $c
  56. if kbd_status KBD_SHIFT & ! {
  57. @c "\0\01234567890-=\0\tqwertyuiop[]\n\0asdfghjkl;\'`\0\\zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0\0789-456+1230." scan + **c = ;
  58. } else {
  59. @c "\0\0!@#$%^&*()_+\0\tQWERTYUIOP{}\n\0ASDFGHJKL:\"~\0|ZXCVBNM<>?\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0789-456+1230." scan + **c = ;
  60. }
  61. # Fix some characters that cannot be represented into a string
  62. if scan 0x01 == {
  63. @c 0x1b = ;
  64. }
  65. if scan 0x0e == {
  66. @c 0x08 = ;
  67. }
  68. # If caps lock is on, invert lower and upper case
  69. if kbd_status KBD_CAPS & {
  70. if 'A' c <= c 'Z' <= && 'a' c <= c 'z' <= && || {
  71. @c c 'A' ^ 'a' ^ = ;
  72. }
  73. }
  74. c ret ;
  75. }
  76. fun kbd_getc 0 {
  77. while 1 {
  78. $c
  79. @c kbd_maybe_getc = ;
  80. if c {
  81. c ret ;
  82. }
  83. }
  84. }
  85. # Take input from either serial or keyboard
  86. fun input_getc 0 {
  87. while 1 {
  88. $c
  89. @c kbd_maybe_getc = ;
  90. if c { c ret ; }
  91. @c serial_maybe_read = ;
  92. if c { c ret ; }
  93. }
  94. }