BIOS.AMD64.Keyboard.Mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE Keyboard; (** AUTHOR "pjm"; PURPOSE "PC keyboard driver"; *)
  3. (* temporary Native-based version *)
  4. IMPORT SYSTEM, Machine, KernelLog, Modules, Kernel, Objects, Inputs, Commands, Files;
  5. CONST
  6. (* do not change these values, as they are used in the keyboard tables from Native *)
  7. ScrollLock = 0; NumLock = 1; CapsLock = 2; LAlt = 3; RAlt = 4;
  8. LCtrl = 5; RCtrl = 6; LShift = 7; RShift = 8; GreyEsc = 9;
  9. Resetting = 10; SetTypematic = 11; SendingLEDs = 12;
  10. LMeta = 13; RMeta = 14;
  11. DeadKey = 0;
  12. TraceKeys = FALSE;
  13. TYPE
  14. Keyboard = OBJECT
  15. VAR last: Inputs.KeyboardMsg;
  16. PROCEDURE HandleInterrupt;
  17. VAR m: SET; i: LONGINT; msg: Inputs.KeyboardMsg; k: INTEGER; c: CHAR;
  18. BEGIN {EXCLUSIVE}
  19. SYSTEM.PORTIN(060H, c); (* get scan code *)
  20. SYSTEM.PORTIN(061H, SYSTEM.VAL(CHAR, m));
  21. INCL(m, 7); SYSTEM.PORTOUT(061H, SYSTEM.VAL(CHAR, m));
  22. EXCL(m, 7); SYSTEM.PORTOUT(061H, SYSTEM.VAL(CHAR, m)); (* ack *)
  23. IF TraceKeys THEN KernelLog.Hex(ORD(c), -3) END;
  24. k := MapScanCode(c, msg.keysym);
  25. IF k >= 0 THEN msg.ch := CHR(k) ELSE msg.ch := 0X END;
  26. IF TraceKeys & (msg.keysym # Inputs.KsNil) THEN
  27. KernelLog.Hex(msg.keysym, 9); KernelLog.Ln
  28. END;
  29. (*msg.key := CHR(ORD(c) MOD 80H);*)
  30. msg.flags := {};
  31. FOR i := LAlt TO RShift DO
  32. IF i IN flags THEN INCL(msg.flags, mapflag[i]) END
  33. END;
  34. FOR i := LMeta TO RMeta DO
  35. IF i IN flags THEN INCL(msg.flags, i-LMeta+Inputs.LeftMeta) END
  36. END;
  37. IF c >= 80X THEN INCL(msg.flags, Inputs.Release) END;
  38. IF (msg.flags # last.flags) OR (msg.ch # 0X) OR (msg.keysym # Inputs.KsNil) THEN
  39. last := msg; Inputs.keyboard.Handle(msg)
  40. END
  41. END HandleInterrupt;
  42. PROCEDURE &Init*;
  43. BEGIN
  44. last.ch := 0X; (*last.key := 0X;*) last.flags := {0..31};
  45. Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+1)
  46. END Init;
  47. PROCEDURE Finalize;
  48. BEGIN
  49. Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0+1)
  50. END Finalize;
  51. END Keyboard;
  52. VAR
  53. dkey: SHORTINT;
  54. lastport: LONGINT;
  55. lastvalue: SYSTEM.BYTE;
  56. keyval: INTEGER;
  57. table: ADDRESS;
  58. flags: SET;
  59. keytable: POINTER TO ARRAY OF CHAR;
  60. keyboard: Keyboard;
  61. mapflag: ARRAY RShift+1 OF SHORTINT;
  62. (* ---- Keyboard Driver ---- *)
  63. (* Translation table format:
  64. table = { scancode unshifted-code shifted-code flags } 0FFX .
  65. scancode = <scancode byte from keyboard, bit 7 set for "grey" extended keys>
  66. unshifted-code = <CHAR produced by this scancode, without shift>
  67. shifted-code = <CHAR produced by this scancode, with shift>
  68. flags = <bit-mapped flag byte indicating special behaviour>
  69. flag bit function
  70. 0 01 DeadKey: Set dead key flag according to translated key code (1-7)
  71. 1 02 NumLock: if set, the state of NumLock will reverse the action of shift (for num keypad) *** no longer ***
  72. 2 04 CapsLock: if set, the state of CapsLock will reverse the action of shift (for alpha keys)
  73. 3 08 LAlt: \ the state of these two flags in the table and the current state of the two...
  74. 4 10 RAlt: / ...Alt keys must match exactly, otherwise the search is continued.
  75. 5 20 \
  76. 6 40 > dead key number (0-7), must match current dead key flag
  77. 7 80 /
  78. The table is scanned sequentially (speed not critical). Ctrl-Break, Ctrl-F10 and Ctrl-Alt-Del
  79. are always defined and are not in the table. The control keys are also always defined. *)
  80. (* TableUS - US keyboard translation table (dead keys: ^=1, '=2, `=3, ~=4, "=5) *)
  81. PROCEDURE TableUS(): ADDRESS;
  82. CODE {SYSTEM.AMD64}
  83. LEA RAX, [RIP + L2 - L1];
  84. L1:
  85. LEAVE
  86. RET
  87. L2:
  88. ; alphabet
  89. DB 1EH, 'a', 'A', 4H, 30H, 'b', 'B', 4H, 2EH, 'c', 'C', 4H, 20H, 'd', 'D', 4H
  90. DB 12H, 'e', 'E', 4H, 21H, 'f', 'F', 4H, 22H, 'g', 'G', 4H, 23H, 'h', 'H', 4H
  91. DB 17H, 'i', 'I', 4H, 24H, 'j', 'J', 4H, 25H, 'k', 'K', 4H, 26H, 'l', 'L', 4H
  92. DB 32H, 'm', 'M', 4H, 31H, 'n', 'N', 4H, 18H, 'o', 'O', 4H, 19H, 'p', 'P', 4H
  93. DB 10H, 'q', 'Q', 4H, 13H, 'r', 'R', 4H, 1FH, 's', 'S', 4H, 14H, 't', 'T', 4H
  94. DB 16H, 'u', 'U', 4H, 2FH, 'v', 'V', 4H, 11H, 'w', 'W', 4H, 2DH, 'x', 'X', 4H
  95. DB 15H, 'y', 'Y', 4H, 2CH, 'z', 'Z', 4H
  96. ; Oberon accents (LAlt & RAlt)
  97. ; DB 1EH, 'ä', 'Ä', 0CH, 12H, 'ë', 0FFH, 0CH, 18H, 'ö', 'Ö', 0CH, 16H, 'ü', 'Ü', 0CH
  98. ; DB 17H, 'ï', 0FFH, 0CH, 1FH, 'ß', 0FFH, 0CH, 2EH, 'ç', 0FFH, 0CH, 31H, 'ñ', 0FFH, 0CH
  99. ; DB 1EH, 'ä', 'Ä', 14H, 12H, 'ë', 0FFH, 14H, 18H, 'ö', 'Ö', 14H, 16H, 'ü', 'Ü', 14H
  100. ; DB 17H, 'ï', 0FFH, 14H, 1FH, 'ß', 0FFH, 14H, 2EH, 'ç', 0FFH, 14H, 31H, 'ñ', 0FFH, 14H
  101. ; ; dead keys (LAlt & RAlt)
  102. ; DB 07H, 0FFH, 1H, 9H, 28H, 2H, 5H, 9H, 29H, 3H, 4H, 9H,
  103. ; DB 07H, 0FFH, 1H, 11H, 28H, 2H, 5H, 11H, 29H, 3H, 4H, 11H,
  104. ; ; following keys
  105. ; DB 1EH, 'â', 0FFH, 20H, 12H, 'ê', 0FFH, 20H, 17H, 'î', 0FFH, 20H, 18H, 'ô', 0FFH, 20H
  106. ; DB 16H, 'û', 0FFH, 20H, 1EH, 'à', 0FFH, 60H, 12H, 'è', 0FFH, 60H, 17H, 'ì', 0FFH, 60H
  107. ; DB 18H, 'ò', 0FFH, 60H, 16H, 'ù', 0FFH, 60H, 1EH, 'á', 0FFH, 40H, 12H, 'é', 0FFH, 40H
  108. ; DB 1EH, 'ä', 'Ä', 0A4H, 12H, 'ë', 0FFH, 0A0H, 17H, 'ï', 0FFH, 0A0H, 18H, 'ö', 'Ö', 0A4H
  109. ; DB 16H, 'ü', 'Ü', 0A4H, 31H, 'ñ', 0FFH, 80H
  110. DB 1EH, 83H, 80H, 0CH, 12H, 91H, 0FFH, 0CH, 18H, 84H, 81H, 0CH, 16H, 85H, 82H, 0CH
  111. DB 17H, 92H, 0FFH, 0CH, 1FH, 96H, 0FFH, 0CH, 2EH, 93H, 0FFH, 0CH, 31H, 95H, 0FFH, 0CH
  112. DB 1EH, 83H, 80H, 14H, 12H, 91H, 0FFH, 14H, 18H, 84H, 81H, 14H, 16H, 85H, 82H, 14H
  113. DB 17H, 92H, 0FFH, 14H, 1FH, 96H, 0FFH, 14H, 2EH, 93H, 0FFH, 14H, 31H, 95H, 0FFH, 14H
  114. ; dead keys (LAlt & RAlt)
  115. DB 07H, 0FFH, 1H, 9H, 28H, 2H, 5H, 9H, 29H, 3H, 4H, 9H,
  116. DB 07H, 0FFH, 1H, 11H, 28H, 2H, 5H, 11H, 29H, 3H, 4H, 11H,
  117. ; following keys
  118. DB 1EH, 86H, 0FFH, 20H, 12H, 87H, 0FFH, 20H, 17H, 88H, 0FFH, 20H, 18H, 89H, 0FFH, 20H
  119. DB 16H, 8AH, 0FFH, 20H, 1EH, 8BH, 0FFH, 60H, 12H, 8CH, 0FFH, 60H, 17H, 8DH, 0FFH, 60H
  120. DB 18H, 8EH, 0FFH, 60H, 16H, 8FH, 0FFH, 60H, 1EH, 94H, 0FFH, 40H, 12H, 90H, 0FFH, 40H
  121. DB 1EH, 83H, 80H, 0A4H, 12H, 91H, 0FFH, 0A0H, 17H, 92H, 0FFH, 0A0H, 18H, 84H, 81H, 0A4H
  122. DB 16H, 85H, 82H, 0A4H, 31H, 95H, 0FFH, 80H
  123. DB 1EH, 'a', 'A', 0CH, 12H, 'e', 0FFH, 0CH, 18H, 'o', 'O', 0CH, 16H, 'u', 'U', 0CH
  124. DB 17H, 'i', 0FFH, 0CH, 1FH, 's', 0FFH, 0CH, 2EH, 'c', 0FFH, 0CH, 31H, 'n', 0FFH, 0CH
  125. DB 1EH, 'a', 'A', 14H, 12H, 'e', 0FFH, 14H, 18H, 'o', 'O', 14H, 16H, 'u', 'U', 14H
  126. DB 17H, 'i', 0FFH, 14H, 1FH, 's', 0FFH, 14H, 2EH, 'c', 0FFH, 14H, 31H, 'n', 0FFH, 14H
  127. ; dead keys (LAlt & RAlt)
  128. DB 07H, 0FFH, 1H, 9H, 28H, 2H, 5H, 9H, 29H, 3H, 4H, 9H,
  129. DB 07H, 0FFH, 1H, 11H, 28H, 2H, 5H, 11H, 29H, 3H, 4H, 11H,
  130. ; following keys
  131. DB 1EH, 'a', 0FFH, 20H, 12H, 'e', 0FFH, 20H, 17H, 'i', 0FFH, 20H, 18H, 'o', 0FFH, 20H
  132. DB 16H, 'u', 0FFH, 20H, 1EH, 'a', 0FFH, 60H, 12H, 'e', 0FFH, 60H, 17H, 'i', 0FFH, 60H
  133. DB 18H, 'o', 0FFH, 60H, 16H, 'u', 0FFH, 60H, 1EH, 'a', 0FFH, 40H, 12H, 'e', 0FFH, 40H
  134. DB 1EH, 'a', 'A', 0A4H, 12H, 'e', 0FFH, 0A0H, 17H, 'i', 0FFH, 0A0H, 18H, 'o', 'O', 0A4H
  135. DB 16H, 'u', 'U', 0A4H, 31H, 'n', 0FFH, 80H
  136. ; numbers at top
  137. DB 0BH, '0', ')', 0H, 02H, '1', '!', 0H, 03H, '2', '@', 0H, 04H, '3', '#', 0H
  138. DB 05H, '4', '$', 0H, 06H, '5', '%', 0H, 07H, '6', '^', 0H, 08H, '7', '&', 0H
  139. DB 09H, '8', '*', 0H, 0AH, '9', '(', 0H
  140. ; symbol keys
  141. DB 28H, 27H, 22H, 0H, 33H, ',', '<', 0H, 0CH, '-', '_', 0H, 34H, '.', '>', 0H
  142. DB 35H, '/', '?', 0H, 27H, ';', ':', 0H, 0DH, '=', '+', 0H, 1AH, '[', '{', 0H
  143. DB 2BH, '\', '|', 0H, 1BH, ']', '}', 0H, 29H, '`', '~', 0H
  144. ; control keys
  145. DB 0EH, 7FH, 7FH, 0H ; backspace
  146. DB 0FH, 09H, 09H, 0H ; tab
  147. DB 1CH, 0DH, 0DH, 0H ; enter
  148. DB 39H, 20H, 20H, 0H ; space
  149. DB 01H, 1BH, 1BH, 0H ; esc
  150. ; keypad
  151. DB 4FH, 0A9H, '1', 2H ; end/1
  152. DB 50H, 0C2H, '2', 2H ; down/2
  153. DB 51H, 0A3H, '3', 2H ; pgdn/3
  154. DB 4BH, 0C4H, '4', 2H ; left/4
  155. DB 4CH, 0FFH, '5', 2H ; center/5
  156. DB 4DH, 0C3H, '6', 2H ; right/6
  157. DB 47H, 0A8H, '7', 2H ; home/7
  158. DB 48H, 0C1H, '8', 2H ; up/8
  159. DB 49H, 0A2H, '9', 2H ; pgup/9
  160. DB 52H, 0A0H, '0', 2H ; insert/0
  161. DB 53H, 0A1H, 2EH, 2H ; del/.
  162. ; grey keys
  163. DB 4AH, '-', '-', 0H ; grey -
  164. DB 4EH, '+', '+', 0H ; grey +
  165. DB 0B5H, '/', '/', 0H ; grey /
  166. DB 37H, '*', '*', 0H ; grey *
  167. DB 0D0H, 0C2H, 0C2H, 0H ; grey down
  168. DB 0CBH, 0C4H, 0C4H, 0H ; grey left
  169. DB 0CDH, 0C3H, 0C3H, 0H ; grey right
  170. DB 0C8H, 0C1H, 0C1H, 0H ; grey up
  171. DB 09CH, 0DH, 0DH, 0H ; grey enter
  172. DB 0D2H, 0A0H, 0A0H, 0H ; grey ins
  173. DB 0D3H, 0A1H, 0A1H, 0H ; grey del
  174. DB 0C9H, 0A2H, 0A2H, 0H ; grey pgup
  175. DB 0D1H, 0A3H, 0A3H, 0H ; grey pgdn
  176. DB 0C7H, 0A8H, 0A8H, 0H ; grey home
  177. DB 0CFH, 0A9H, 0A9H, 0H ; grey end
  178. ; function keys
  179. DB 3BH, 0A4H, 0FFH, 0H ; F1
  180. DB 3CH, 0A5H, 0FFH, 0H ; F2
  181. DB 3DH, 0A6H, 0FFH, 0H ; F3
  182. DB 3EH, 0A7H, 0FFH, 0H ; F4
  183. DB 3FH, 0F5H, 0FFH, 0H ; F5
  184. DB 40H, 0F6H, 0FFH, 0H ; F6
  185. DB 41H, 0F7H, 0FFH, 0H ; F7
  186. DB 42H, 0F8H, 0FFH, 0H ; F8
  187. DB 43H, 0F9H, 0FFH, 0H ; F9
  188. DB 44H, 0FAH, 0FFH, 0H ; F10
  189. DB 57H, 0FBH, 0FFH, 0H ; F11
  190. DB 58H, 0FCH, 0FFH, 0H ; F12
  191. DB 0FFH
  192. END TableUS;
  193. PROCEDURE TableFromFile(name: ARRAY OF CHAR): ADDRESS;
  194. VAR f: Files.File; r: Files.Rider; len: LONGINT;
  195. BEGIN
  196. KernelLog.String("Keyboard: "); KernelLog.String(name);
  197. f := Files.Old(name);
  198. IF f # NIL THEN
  199. len := f.Length();
  200. IF len MOD 4 = 0 THEN
  201. NEW(keytable, len+1);
  202. f.Set(r, 0); f.ReadBytes(r, keytable^, 0, len);
  203. IF r.res = 0 THEN
  204. KernelLog.String(" loaded."); KernelLog.Ln;
  205. keytable[len] := 0FFX;
  206. RETURN ADDRESSOF(keytable[0])
  207. ELSE
  208. KernelLog.String(" res="); KernelLog.Int(r.res, 1)
  209. END
  210. ELSE
  211. KernelLog.String(" len="); KernelLog.Int(len, 1)
  212. END
  213. ELSE
  214. KernelLog.String(" not found.")
  215. END;
  216. KernelLog.Ln;
  217. RETURN TableUS()
  218. END TableFromFile;
  219. (* Translate - Translate scan code "c" to key. *)
  220. PROCEDURE Translate(flags: SET; c: CHAR): INTEGER;
  221. CONST
  222. Alt = {LAlt, RAlt}; Ctrl = {LCtrl, RCtrl}; Shift = {LShift, RShift};
  223. VAR a: ADDRESS; s1: CHAR; s: SET; k: INTEGER; dkn: SHORTINT;
  224. BEGIN {EXCLUSIVE}
  225. IF (c = 46X) & (flags * Ctrl # {}) THEN RETURN -2 END; (* Ctrl-Break - break *)
  226. IF (c = 44X) & (flags * Ctrl # {}) THEN RETURN 0FFH END; (* Ctrl-F10 - exit *)
  227. IF (c = 53X) & (flags * Ctrl # {}) & (flags * Alt # {}) THEN RETURN 0A1H END; (* Ctrl-Alt-Del - Del *)
  228. IF GreyEsc IN flags THEN c := CHR(ORD(c)+80H) END;
  229. a := table;
  230. LOOP
  231. SYSTEM.GET(a, s1);
  232. IF s1 = 0FFX THEN (* end of table, unmapped key *)
  233. k := -1; dkey := 0; EXIT
  234. ELSIF s1 = c THEN (* found scan code in table *)
  235. SYSTEM.GET(a+3, SYSTEM.VAL(CHAR, s)); (* flags from table *)
  236. dkn := SHORT(SHORT(SYSTEM.VAL(LONGINT, LSH(s * {5..7}, -5))));
  237. s := s * {DeadKey, NumLock, CapsLock, LAlt, RAlt, LCtrl, RCtrl}; k := 0;
  238. IF ((s * Alt = flags * Alt) OR (NumLock IN s) OR (s1 > 03BX)) & (dkn = dkey) THEN (* Alt & dead keys match exactly *)
  239. IF flags * Shift # {} THEN INCL(s, LShift) END; (* check if shift pressed *)
  240. (* handle CapsLock *)
  241. IF (CapsLock IN s) & (CapsLock IN flags) THEN s := s / {LShift} END;
  242. (* handle NumLock *)
  243. IF NumLock IN s THEN
  244. IF NumLock IN flags THEN s := s + {LShift} ELSE s := s - {LShift} END
  245. END;
  246. (* get key code *)
  247. IF LShift IN s THEN SYSTEM.GET(a+2, SYSTEM.VAL(CHAR, k)) (* shifted value *)
  248. ELSE SYSTEM.GET(a+1, SYSTEM.VAL(CHAR, k)) (* unshifted value *)
  249. END;
  250. IF (DeadKey IN s) & (k <= 7) THEN (* dead key *)
  251. dkey := SHORT(k); k := -1 (* set new dead key state *)
  252. ELSIF k = 0FFH THEN (* unmapped key *)
  253. k := -1; dkey := 0 (* reset dead key state *)
  254. ELSE (* mapped key *)
  255. IF flags * Ctrl # {} THEN
  256. IF ((k >= 64) & (k <= 95)) OR ((k >= 97) & (k <= 122)) THEN
  257. k := SHORT(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, k) * {0..4})) (* control *)
  258. ELSIF k = 13 THEN (* Ctrl-Enter *)
  259. k := 10
  260. END
  261. END;
  262. IF flags * Alt # {} THEN (* Alt-keypad *)
  263. IF (k >= ORD('0')) & (k <= ORD('9')) & (NumLock IN s) THEN (* keypad num *)
  264. IF keyval = -1 THEN keyval := k-ORD('0')
  265. ELSE keyval := (10*keyval + (k-ORD('0'))) MOD 1000
  266. END;
  267. k := -1
  268. END
  269. END;
  270. dkey := 0 (* reset dead key state *)
  271. END;
  272. EXIT
  273. END
  274. END;
  275. INC(a, 4)
  276. END; (* LOOP *)
  277. RETURN k
  278. END Translate;
  279. (* Wait - Wait for keyboard serial port to acknowledge byte. *)
  280. PROCEDURE Wait;
  281. VAR t: Kernel.MilliTimer; s: SET;
  282. BEGIN
  283. Kernel.SetTimer(t, 20); (* wait up to 17 ms *)
  284. REPEAT
  285. SYSTEM.PORTIN(64H, SYSTEM.VAL(CHAR, s))
  286. UNTIL ~(1 IN s) OR Kernel.Expired(t)
  287. END Wait;
  288. (* SendByte - Send a byte to the keyboard. *)
  289. PROCEDURE SendByte(port: LONGINT; value: SYSTEM.BYTE);
  290. BEGIN
  291. Wait; SYSTEM.PORTOUT(port, SYSTEM.VAL(CHAR, value));
  292. lastport := port; lastvalue := value
  293. END SendByte;
  294. (* ShiftKey - Handle shift keys. *)
  295. PROCEDURE ShiftKey(left, right: SHORTINT; in: BOOLEAN);
  296. BEGIN
  297. IF in THEN
  298. IF GreyEsc IN flags THEN INCL(flags, right)
  299. ELSE INCL(flags, left)
  300. END
  301. ELSE
  302. IF GreyEsc IN flags THEN EXCL(flags, right)
  303. ELSE EXCL(flags, left)
  304. END
  305. END
  306. END ShiftKey;
  307. (* LedKey - Handle "lock" keys. *)
  308. PROCEDURE LedKey(VAR flags: SET; lock: SHORTINT; c: CHAR;
  309. VAR k: INTEGER);
  310. BEGIN
  311. IF flags * {LAlt, RAlt, LCtrl, RCtrl, LShift, RShift} = {} THEN
  312. flags := flags / {lock}
  313. ELSE
  314. k := Translate(flags, c)
  315. END
  316. END LedKey;
  317. (* MapScanCode - Map a scan code "c" to a key code. *)
  318. PROCEDURE MapScanCode(c: CHAR; VAR keysym: LONGINT): INTEGER;
  319. VAR k: INTEGER; oldleds: SET;
  320. BEGIN
  321. SendByte(64H, 0ADX); Wait; (* disable keyboard *)
  322. k := -1; oldleds := flags * {ScrollLock, NumLock, CapsLock};
  323. keysym := Inputs.KsNil; (* no key *)
  324. IF c = 0X THEN (* overrun, ignore *)
  325. ELSIF c = 0FAX THEN (* keyboard ack *)
  326. IF Resetting IN flags THEN
  327. EXCL(flags, Resetting); INCL(flags, SendingLEDs);
  328. SendByte(60H, 0EDX) (* set keyboard LEDs *)
  329. ELSIF SendingLEDs IN flags THEN
  330. SendByte(60H, SYSTEM.VAL(CHAR, oldleds));
  331. EXCL(flags, SendingLEDs)
  332. ELSIF SetTypematic IN flags THEN
  333. EXCL(flags, SetTypematic); INCL(flags, Resetting);
  334. SendByte(60H, 020X) (* 30Hz, 500 ms *)
  335. ELSE (* assume ack was for something else *)
  336. END
  337. ELSIF c = 0FEX THEN (* keyboard resend *)
  338. SendByte(lastport, lastvalue)
  339. ELSIF c = 038X THEN (* Alt make *)
  340. ShiftKey(LAlt, RAlt, TRUE); keysym := Inputs.KsAltL
  341. ELSIF c = 01DX THEN (* Ctrl make *)
  342. ShiftKey(LCtrl, RCtrl, TRUE); keysym := Inputs.KsControlL
  343. ELSIF c = 02AX THEN (* LShift make *)
  344. IF ~(GreyEsc IN flags) THEN
  345. INCL(flags, LShift); keysym := Inputs.KsShiftL
  346. END
  347. ELSIF c = 036X THEN (* RShift make *)
  348. IF ~(GreyEsc IN flags) THEN
  349. INCL(flags, RShift); keysym := Inputs.KsShiftR
  350. END
  351. ELSIF c = 05BX THEN (* LMeta make *)
  352. INCL(flags, LMeta); keysym := Inputs.KsMetaL
  353. ELSIF c = 05CX THEN (* RMeta make *)
  354. INCL(flags, RMeta); keysym := Inputs.KsMetaR
  355. ELSIF c = 03AX THEN (* Caps make *)
  356. LedKey(flags, CapsLock, c, k)
  357. ELSIF c = 046X THEN (* Scroll make *)
  358. LedKey(flags, ScrollLock, c, k);
  359. IF k = -2 THEN keysym := Inputs.KsBreak END (* Break *)
  360. ELSIF c = 045X THEN (* Num make *)
  361. LedKey(flags, NumLock, c, k)
  362. ELSIF c = 0B8X THEN (* Alt break *)
  363. ShiftKey(LAlt, RAlt, FALSE); keysym := Inputs.KsAltL;
  364. IF (keyval >= 0) & (keyval < 255) THEN k := keyval END; (* exclude 255 - reboot *)
  365. keyval := -1
  366. ELSIF c = 09DX THEN (* Ctrl break *)
  367. ShiftKey(LCtrl, RCtrl, FALSE); keysym := Inputs.KsControlL
  368. ELSIF c = 0AAX THEN (* LShift break *)
  369. IF ~(GreyEsc IN flags) THEN
  370. EXCL(flags, LShift); keysym := Inputs.KsShiftL
  371. END
  372. ELSIF c = 0B6X THEN (* RShift break *)
  373. IF ~(GreyEsc IN flags) THEN
  374. EXCL(flags, RShift); keysym := Inputs.KsShiftR
  375. END
  376. ELSIF c = 0DBX THEN (* LMeta break *)
  377. EXCL(flags, LMeta); keysym := Inputs.KsMetaL
  378. ELSIF c = 0DCX THEN (* RMeta break *)
  379. EXCL(flags, RMeta); keysym := Inputs.KsMetaR
  380. ELSIF c = 05DX THEN (* Menu make *)
  381. keysym := Inputs.KsMenu (* Windows menu *)
  382. ELSIF c < 080X THEN (* Other make *)
  383. k := Translate(flags, c);
  384. IF c = 0EX THEN keysym := Inputs.KsBackSpace (* backspace *)
  385. ELSIF c = 0FX THEN keysym := Inputs.KsTab (* tab *)
  386. ELSIF c = 1CX THEN keysym := Inputs.KsReturn (* enter *)
  387. ELSIF c = 01X THEN keysym := Inputs.KsEscape (* esc *)
  388. ELSIF c = 3DX THEN keysym := Inputs.KsF3 (* f3 *)
  389. ELSIF c = 4AX THEN keysym := Inputs.KsKPSubtract (* kp - *)
  390. ELSIF c = 4EX THEN keysym := Inputs.KsKPAdd (* kp + *)
  391. ELSIF c = 0B5X THEN keysym := Inputs.KsKPDivide (* kp / *)
  392. ELSIF c = 37X THEN keysym := Inputs.KsKPMultiply (* kp * *)
  393. ELSIF k >= 0 THEN keysym := KeySym(CHR(k))
  394. ELSE (* skip *)
  395. END
  396. ELSE (* ignore *)
  397. END;
  398. IF c = 0E0X THEN INCL(flags, GreyEsc) ELSE EXCL(flags, GreyEsc) END;
  399. IF flags * {ScrollLock, NumLock, CapsLock} # oldleds THEN
  400. INCL(flags, SendingLEDs);
  401. SendByte(60H, 0EDX) (* set keyboard LEDs *)
  402. END;
  403. SendByte(64H, 0AEX); (* enable keyboard *)
  404. (* now do additional mappings *)
  405. RETURN k
  406. END MapScanCode;
  407. (* Map Oberon character code to X11 keysym (/usr/include/X11/keysymdef.h). *)
  408. PROCEDURE KeySym(ch: CHAR): LONGINT;
  409. VAR x: LONGINT;
  410. BEGIN
  411. IF (ch >= 1X) & (ch <= 7EX) THEN x := ORD(ch) (* ascii *)
  412. ELSIF ch = 0A0X THEN x := Inputs.KsInsert (* insert *)
  413. ELSIF ch = 0A1X THEN x := Inputs.KsDelete (* delete *)
  414. ELSIF ch = 0A8X THEN x := Inputs.KsHome (* home *)
  415. ELSIF ch = 0A9X THEN x := Inputs.KsEnd (* end *)
  416. ELSIF ch = 0A2X THEN x := Inputs.KsPageUp (* pgup *)
  417. ELSIF ch = 0A3X THEN x := Inputs.KsPageDown (* pgdn *)
  418. ELSIF ch = 0C4X THEN x := Inputs.KsLeft (* left *)
  419. ELSIF ch = 0C1X THEN x := Inputs.KsUp (* up *)
  420. ELSIF ch = 0C3X THEN x := Inputs.KsRight (* right *)
  421. ELSIF ch = 0C2X THEN x := Inputs.KsDown (* down *)
  422. ELSIF ch = 0A4X THEN x := Inputs.KsF1 (* f1 *)
  423. ELSIF ch = 0A5X THEN x := Inputs.KsF2 (* f2 *)
  424. (*ELSIF ch = 0xxX THEN x := Inputs.KsF3*) (* f3 *)
  425. ELSIF ch = 0A7X THEN x := Inputs.KsF4 (* f4 *)
  426. ELSIF ch = 0F5X THEN x := Inputs.KsF5 (* f5 *)
  427. ELSIF ch = 0F6X THEN x := Inputs.KsF6 (* f6 *)
  428. ELSIF ch = 0F7X THEN x := Inputs.KsF7 (* f7 *)
  429. ELSIF ch = 0F8X THEN x := Inputs.KsF8 (* f8 *)
  430. ELSIF ch = 0F9X THEN x := Inputs.KsF9 (* f9 *)
  431. ELSIF ch = 0FAX THEN x := Inputs.KsF10 (* f10 *)
  432. ELSIF ch = 0FBX THEN x := Inputs.KsF11 (* f11 *)
  433. ELSIF ch = 0FCX THEN x := Inputs.KsF12 (* f12 *)
  434. ELSE x := 0
  435. END;
  436. RETURN x
  437. END KeySym;
  438. (* InitKeyboard - Initialise the keyboard. *)
  439. PROCEDURE InitKeyboard;
  440. VAR s: SET; c: CHAR; i: SHORTINT; k: ARRAY 32 OF CHAR;
  441. BEGIN
  442. keyval := -1; dkey := 0;
  443. mapflag[LAlt] := Inputs.LeftAlt; mapflag[RAlt] := Inputs.RightAlt;
  444. mapflag[LCtrl] := Inputs.LeftCtrl; mapflag[RCtrl] := Inputs.RightCtrl;
  445. mapflag[LShift] := Inputs.LeftShift; mapflag[RShift] := Inputs.RightShift;
  446. (* Get table *)
  447. Machine.GetConfig("Keyboard", k);
  448. i := 0; WHILE (k[i] # 0X) & (k[i] # '.') DO INC(i) END;
  449. IF k[i] = '.' THEN table := TableFromFile(k)
  450. ELSE table := TableUS()
  451. END;
  452. (* Get compatibility option *)
  453. flags := {};
  454. NEW(keyboard);
  455. (* clear the keyboard's internal buffer *)
  456. i := 8;
  457. LOOP
  458. SYSTEM.PORTIN(64H, SYSTEM.VAL(CHAR, s));
  459. IF ~(0 IN s) OR (i = 0) THEN EXIT END;
  460. SYSTEM.PORTIN(60H, c); (* read byte *)
  461. SYSTEM.PORTIN(61H, SYSTEM.VAL(CHAR, s));
  462. INCL(s, 7); SYSTEM.PORTOUT(61H, SYSTEM.VAL(CHAR, s));
  463. EXCL(s, 7); SYSTEM.PORTOUT(61H, SYSTEM.VAL(CHAR, s)); (* ack *)
  464. DEC(i)
  465. END;
  466. flags := {SetTypematic};
  467. Machine.GetConfig("NumLock", k);
  468. IF k[0] = '1' THEN INCL(flags, NumLock) END;
  469. SendByte(60H, 0F3X) (* settypedel, will cause Ack from keyboard *)
  470. END InitKeyboard;
  471. PROCEDURE SetLayout*(context : Commands.Context); (** KeyboardLayoutFile ~ *)
  472. VAR layoutFilename : ARRAY 256 OF CHAR;
  473. BEGIN {EXCLUSIVE}
  474. IF (keyboard # NIL) THEN
  475. context.arg.GetString(layoutFilename);
  476. table := TableFromFile(layoutFilename);
  477. ELSE
  478. context.error.String("Keyboard: No keyboard found."); context.error.Ln;
  479. END;
  480. END SetLayout;
  481. PROCEDURE Install*;
  482. END Install;
  483. PROCEDURE Cleanup;
  484. BEGIN
  485. IF (keyboard # NIL) & (Modules.shutdown = Modules.None) THEN
  486. keyboard.Finalize; keyboard := NIL
  487. END
  488. END Cleanup;
  489. BEGIN
  490. InitKeyboard;
  491. Modules.InstallTermHandler(Cleanup)
  492. END Keyboard.
  493. (*
  494. 19.08.1999 pjm Split from Aos.Input
  495. 20.09.2006 Added SetLayout (staubesv)
  496. *)
  497. Keyboard.Install ~
  498. Keyboard.SetLayout KeyCH.Bin ~
  499. Keyboard.SetLayout KeyUS.Bin ~
  500. System.Free Keyboard ~