BIOS.I386.Keyboard.Mod 19 KB

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