BIOS.Keyboard.Mod 20 KB

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