kbd.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2012-2018 K. Lange
  5. *
  6. * General-purpose keyboard conversion library.
  7. *
  8. * This provides similar functionality to xkb:
  9. * - It provides mappings for keyboards from locales
  10. * - It translates incoming key presses to key names
  11. * - It translates incoming keys to escape sequences
  12. */
  13. #include <stdio.h>
  14. #include <toaru/kbd.h>
  15. #define DEBUG_SCANCODES 0
  16. #define KEY_UP_MASK 0x80
  17. #define KEY_CODE_MASK 0x7F
  18. #define KEY_CTRL_MASK 0x40
  19. #define norm 0x01
  20. #define spec 0x02
  21. #define func 0x03
  22. #define SET_UNSET(a,b,c) (a) = (c) ? ((a) | (b)) : ((a) & ~(b))
  23. char key_method[] = {
  24. /* 00 */ 0, spec, norm, norm, norm, norm, norm, norm,
  25. /* 08 */ norm, norm, norm, norm, norm, norm, norm, norm,
  26. /* 10 */ norm, norm, norm, norm, norm, norm, norm, norm,
  27. /* 18 */ norm, norm, norm, norm, norm, spec, norm, norm,
  28. /* 20 */ norm, norm, norm, norm, norm, norm, norm, norm,
  29. /* 28 */ norm, norm, spec, norm, norm, norm, norm, norm,
  30. /* 30 */ norm, norm, norm, norm, norm, norm, spec, norm,
  31. /* 38 */ spec, norm, spec, func, func, func, func, func,
  32. /* 40 */ func, func, func, func, func, spec, spec, spec,
  33. /* 48 */ spec, spec, spec, spec, spec, spec, spec, spec,
  34. /* 50 */ spec, spec, spec, spec, spec, spec, spec, func,
  35. /* 58 */ func, spec, spec, spec, spec, spec, spec, spec,
  36. /* 60 */ spec, spec, spec, spec, spec, spec, spec, spec,
  37. /* 68 */ spec, spec, spec, spec, spec, spec, spec, spec,
  38. /* 70 */ spec, spec, spec, spec, spec, spec, spec, spec,
  39. /* 78 */ spec, spec, spec, spec, spec, spec, spec, spec,
  40. };
  41. char kbd_us[128] = {
  42. 0, 27,
  43. '1','2','3','4','5','6','7','8','9','0',
  44. '-','=','\b',
  45. '\t', /* tab */
  46. 'q','w','e','r','t','y','u','i','o','p','[',']','\n',
  47. 0, /* control */
  48. 'a','s','d','f','g','h','j','k','l',';','\'', '`',
  49. 0, /* left shift */
  50. '\\','z','x','c','v','b','n','m',',','.','/',
  51. 0, /* right shift */
  52. '*',
  53. 0, /* alt */
  54. ' ', /* space */
  55. 0, /* caps lock */
  56. 0, /* F1 [59] */
  57. 0, 0, 0, 0, 0, 0, 0, 0,
  58. 0, /* ... F10 */
  59. 0, /* 69 num lock */
  60. 0, /* scroll lock */
  61. 0, /* home */
  62. 0, /* up */
  63. 0, /* page up */
  64. '-',
  65. 0, /* left arrow */
  66. 0,
  67. 0, /* right arrow */
  68. '+',
  69. 0, /* 79 end */
  70. 0, /* down */
  71. 0, /* page down */
  72. 0, /* insert */
  73. 0, /* delete */
  74. 0, 0, 0,
  75. 0, /* F11 */
  76. 0, /* F12 */
  77. 0, /* everything else */
  78. };
  79. char kbd_us_l2[128] = {
  80. 0, 27,
  81. '!','@','#','$','%','^','&','*','(',')',
  82. '_','+','\b',
  83. '\t', /* tab */
  84. 'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',
  85. 0, /* control */
  86. 'A','S','D','F','G','H','J','K','L',':','"', '~',
  87. 0, /* left shift */
  88. '|','Z','X','C','V','B','N','M','<','>','?',
  89. 0, /* right shift */
  90. '*',
  91. 0, /* alt */
  92. ' ', /* space */
  93. 0, /* caps lock */
  94. 0, /* F1 [59] */
  95. 0, 0, 0, 0, 0, 0, 0, 0,
  96. 0, /* ... F10 */
  97. 0, /* 69 num lock */
  98. 0, /* scroll lock */
  99. 0, /* home */
  100. 0, /* up */
  101. 0, /* page up */
  102. '-',
  103. 0, /* left arrow */
  104. 0,
  105. 0, /* right arrow */
  106. '+',
  107. 0, /* 79 end */
  108. 0, /* down */
  109. 0, /* page down */
  110. 0, /* insert */
  111. 0, /* delete */
  112. 0, 0, 0,
  113. 0, /* F11 */
  114. 0, /* F12 */
  115. 0, /* everything else */
  116. };
  117. /*
  118. * Converts from incoming terminal keys to kbd_keys
  119. */
  120. kbd_key_t kbd_key(key_event_state_t * state, unsigned char c) {
  121. switch (state->kbd_state) {
  122. case KBD_NORMAL:
  123. switch (c) {
  124. case 0x1b:
  125. state->kbd_state = KBD_ESC_A;
  126. return KEY_NONE;
  127. default:
  128. return c;
  129. }
  130. case KBD_ESC_A:
  131. switch (c) {
  132. case 0x5b:
  133. state->kbd_state = KBD_ESC_B;
  134. return KEY_NONE;
  135. case 'O':
  136. state->kbd_state = KBD_ESC_O;
  137. return KEY_NONE;
  138. default:
  139. state->kbd_state = KBD_NORMAL;
  140. return c;
  141. }
  142. case KBD_ESC_O:
  143. switch (c) {
  144. case 0x41:
  145. state->kbd_state = KBD_NORMAL;
  146. return KEY_ARROW_UP;
  147. case 0x42:
  148. state->kbd_state = KBD_NORMAL;
  149. return KEY_ARROW_DOWN;
  150. case 0x43:
  151. state->kbd_state = KBD_NORMAL;
  152. return KEY_ARROW_RIGHT;
  153. case 0x44:
  154. state->kbd_state = KBD_NORMAL;
  155. return KEY_ARROW_LEFT;
  156. case 'H':
  157. state->kbd_state = KBD_NORMAL;
  158. return KEY_HOME;
  159. case 'F':
  160. state->kbd_state = KBD_NORMAL;
  161. return KEY_END;
  162. default:
  163. state->kbd_state = KBD_NORMAL;
  164. return c;
  165. }
  166. case KBD_ESC_B:
  167. switch (c) {
  168. case 0x41:
  169. state->kbd_state = KBD_NORMAL;
  170. return KEY_ARROW_UP;
  171. case 0x42:
  172. state->kbd_state = KBD_NORMAL;
  173. return KEY_ARROW_DOWN;
  174. case 0x43:
  175. state->kbd_state = KBD_NORMAL;
  176. return KEY_ARROW_RIGHT;
  177. case 0x44:
  178. state->kbd_state = KBD_NORMAL;
  179. return KEY_ARROW_LEFT;
  180. case 'H':
  181. state->kbd_state = KBD_NORMAL;
  182. return KEY_HOME;
  183. case 'F':
  184. state->kbd_state = KBD_NORMAL;
  185. return KEY_END;
  186. case '1':
  187. case '2':
  188. case '3':
  189. case '4':
  190. case '5':
  191. case '6':
  192. state->kbd_esc_buf = c;
  193. state->kbd_state = KBD_ESC_EXT;
  194. return KEY_NONE;
  195. default:
  196. state->kbd_state = KBD_NORMAL;
  197. return c;
  198. }
  199. case KBD_ESC_EXT:
  200. switch (c) {
  201. case '~':
  202. switch (state->kbd_esc_buf) {
  203. case '2':
  204. state->kbd_state = KBD_NORMAL;
  205. return KEY_INSERT;
  206. case '3':
  207. state->kbd_state = KBD_NORMAL;
  208. return KEY_DEL;
  209. case '5':
  210. state->kbd_state = KBD_NORMAL;
  211. return KEY_PAGE_UP;
  212. case '6':
  213. state->kbd_state = KBD_NORMAL;
  214. return KEY_PAGE_DOWN;
  215. default:
  216. return c;
  217. }
  218. case 'A':
  219. switch (state->kbd_esc_buf) {
  220. case '2':
  221. state->kbd_state = KBD_NORMAL;
  222. return KEY_SHIFT_ARROW_UP;
  223. case '5':
  224. state->kbd_state = KBD_NORMAL;
  225. return KEY_CTRL_ARROW_UP;
  226. /* Other modifier states? */
  227. default:
  228. return c;
  229. }
  230. case 'B':
  231. switch (state->kbd_esc_buf) {
  232. case '2':
  233. state->kbd_state = KBD_NORMAL;
  234. return KEY_SHIFT_ARROW_DOWN;
  235. case '5':
  236. state->kbd_state = KBD_NORMAL;
  237. return KEY_CTRL_ARROW_DOWN;
  238. /* Other modifier states? */
  239. default:
  240. return c;
  241. }
  242. case 'C':
  243. switch (state->kbd_esc_buf) {
  244. case '2':
  245. state->kbd_state = KBD_NORMAL;
  246. return KEY_SHIFT_ARROW_RIGHT;
  247. case '5':
  248. state->kbd_state = KBD_NORMAL;
  249. return KEY_CTRL_ARROW_RIGHT;
  250. /* Other modifier states? */
  251. default:
  252. return c;
  253. }
  254. case 'D':
  255. switch (state->kbd_esc_buf) {
  256. case '2':
  257. state->kbd_state = KBD_NORMAL;
  258. return KEY_SHIFT_ARROW_LEFT;
  259. case '5':
  260. state->kbd_state = KBD_NORMAL;
  261. return KEY_CTRL_ARROW_LEFT;
  262. /* Other modifier states? */
  263. default:
  264. return c;
  265. }
  266. case ';':
  267. /* We don't produce multiple-argument escapes ourself, but
  268. * we should handle them anyway because other terminals
  269. * definitely do make them... */
  270. state->kbd_state = KBD_ESC_B;
  271. return KEY_NONE;
  272. default:
  273. return c;
  274. }
  275. default:
  276. return KEY_BAD_STATE;
  277. }
  278. return KEY_BAD_STATE;
  279. }
  280. int kbd_scancode(key_event_state_t * state, unsigned char c, key_event_t * event) {
  281. /* Convert scancodes to a series of keys */
  282. event->keycode = 0;
  283. event->action = 0;
  284. event->modifiers = 0;
  285. event->key = 0;
  286. #if DEBUG_SCANCODES
  287. fprintf(stderr, "[%d] %d\n", state->kbd_s_state, (int)c);
  288. #endif
  289. event->modifiers |= state->kl_ctrl ? KEY_MOD_LEFT_CTRL : 0;
  290. event->modifiers |= state->kl_shift ? KEY_MOD_LEFT_SHIFT : 0;
  291. event->modifiers |= state->kl_alt ? KEY_MOD_LEFT_ALT : 0;
  292. event->modifiers |= state->kl_super ? KEY_MOD_LEFT_SUPER : 0;
  293. event->modifiers |= state->kr_ctrl ? KEY_MOD_RIGHT_CTRL : 0;
  294. event->modifiers |= state->kr_shift ? KEY_MOD_RIGHT_SHIFT : 0;
  295. event->modifiers |= state->kr_alt ? KEY_MOD_RIGHT_ALT : 0;
  296. event->modifiers |= state->kr_super ? KEY_MOD_RIGHT_SUPER : 0;
  297. if (!state->kbd_s_state) {
  298. if (c == 0xE0) {
  299. state->kbd_s_state = 1;
  300. /* Literally nothing */
  301. return 0;
  302. }
  303. if (c & KEY_UP_MASK) {
  304. c ^= KEY_UP_MASK;
  305. event->action = KEY_ACTION_UP;
  306. } else {
  307. event->action = KEY_ACTION_DOWN;
  308. }
  309. int down = (event->action == KEY_ACTION_DOWN);
  310. switch (key_method[c]) {
  311. case norm:
  312. {
  313. event->keycode = kbd_us[c];
  314. if (state->k_ctrl) {
  315. int s = kbd_us[c];
  316. if (s >= 'a' && s <= 'z') s -= 'a' - 'A';
  317. if (s == '-') s = '_';
  318. if (s == '`') s = '@';
  319. int out = (int)(s - KEY_CTRL_MASK);
  320. if (out < 0 || out > 0x1F) {
  321. event->key = kbd_us[c];
  322. } else {
  323. event->key = out;
  324. }
  325. } else {
  326. event->key = state->k_shift ? kbd_us_l2[c] : kbd_us[c];
  327. }
  328. }
  329. break;
  330. case spec:
  331. switch (c) {
  332. case 0x01:
  333. event->key = '\033';
  334. event->keycode = KEY_ESCAPE;
  335. break;
  336. case 0x1D:
  337. state->k_ctrl = down;
  338. state->kl_ctrl = down;
  339. event->keycode = KEY_LEFT_CTRL;
  340. SET_UNSET(event->modifiers, KEY_MOD_LEFT_CTRL, down);
  341. break;
  342. case 0x2A:
  343. state->k_shift = down;
  344. state->kl_shift = down;
  345. event->keycode = KEY_LEFT_SHIFT;
  346. SET_UNSET(event->modifiers, KEY_MOD_LEFT_SHIFT, down);
  347. break;
  348. case 0x36:
  349. state->k_shift = down;
  350. state->kr_shift = down;
  351. event->keycode = KEY_RIGHT_SHIFT;
  352. SET_UNSET(event->modifiers, KEY_MOD_RIGHT_SHIFT, down);
  353. break;
  354. case 0x38:
  355. state->k_alt = down;
  356. state->kl_alt = down;
  357. event->keycode = KEY_LEFT_ALT;
  358. SET_UNSET(event->modifiers, KEY_MOD_LEFT_ALT, down);
  359. break;
  360. case KEY_SCANCODE_NUM_0:
  361. event->keycode = KEY_NUM_0;
  362. event->key = '0';
  363. break;
  364. case KEY_SCANCODE_NUM_1:
  365. event->keycode = KEY_NUM_1;
  366. event->key = '1';
  367. break;
  368. case KEY_SCANCODE_NUM_2:
  369. event->keycode = KEY_NUM_2;
  370. event->key = '2';
  371. break;
  372. case KEY_SCANCODE_NUM_3:
  373. event->keycode = KEY_NUM_3;
  374. event->key = '3';
  375. break;
  376. case KEY_SCANCODE_NUM_4:
  377. event->keycode = KEY_NUM_4;
  378. event->key = '4';
  379. break;
  380. case KEY_SCANCODE_NUM_5:
  381. event->keycode = KEY_NUM_5;
  382. event->key = '5';
  383. break;
  384. case KEY_SCANCODE_NUM_6:
  385. event->keycode = KEY_NUM_6;
  386. event->key = '6';
  387. break;
  388. case KEY_SCANCODE_NUM_7:
  389. event->keycode = KEY_NUM_7;
  390. event->key = '7';
  391. break;
  392. case KEY_SCANCODE_NUM_8:
  393. event->keycode = KEY_NUM_8;
  394. event->key = '8';
  395. break;
  396. case KEY_SCANCODE_NUM_9:
  397. event->keycode = KEY_NUM_9;
  398. event->key = '9';
  399. break;
  400. case KEY_SCANCODE_NUM_DOT:
  401. event->keycode = KEY_NUM_DOT;
  402. event->key = '.';
  403. break;
  404. case KEY_SCANCODE_NUM_MIN:
  405. event->keycode = KEY_NUM_MINUS;
  406. event->key = '-';
  407. break;
  408. case KEY_SCANCODE_NUM_ADD:
  409. event->keycode = KEY_NUM_PLUS;
  410. event->key = '+';
  411. break;
  412. default:
  413. break;
  414. }
  415. break;
  416. case func:
  417. switch (c) {
  418. case KEY_SCANCODE_F1:
  419. event->keycode = KEY_F1;
  420. break;
  421. case KEY_SCANCODE_F2:
  422. event->keycode = KEY_F2;
  423. break;
  424. case KEY_SCANCODE_F3:
  425. event->keycode = KEY_F3;
  426. break;
  427. case KEY_SCANCODE_F4:
  428. event->keycode = KEY_F4;
  429. break;
  430. case KEY_SCANCODE_F5:
  431. event->keycode = KEY_F5;
  432. break;
  433. case KEY_SCANCODE_F6:
  434. event->keycode = KEY_F6;
  435. break;
  436. case KEY_SCANCODE_F7:
  437. event->keycode = KEY_F7;
  438. break;
  439. case KEY_SCANCODE_F8:
  440. event->keycode = KEY_F8;
  441. break;
  442. case KEY_SCANCODE_F9:
  443. event->keycode = KEY_F9;
  444. break;
  445. case KEY_SCANCODE_F10:
  446. event->keycode = KEY_F10;
  447. break;
  448. case KEY_SCANCODE_F11:
  449. event->keycode = KEY_F11;
  450. break;
  451. case KEY_SCANCODE_F12:
  452. event->keycode = KEY_F12;
  453. break;
  454. }
  455. break;
  456. default:
  457. break;
  458. }
  459. if (event->key) {
  460. return down;
  461. }
  462. return 0;
  463. } else if (state->kbd_s_state == 1) {
  464. if (c & KEY_UP_MASK) {
  465. c ^= KEY_UP_MASK;
  466. event->action = KEY_ACTION_UP;
  467. } else {
  468. event->action = KEY_ACTION_DOWN;
  469. }
  470. int down = (event->action == KEY_ACTION_DOWN);
  471. switch (c) {
  472. case 0x5B:
  473. state->k_super = down;
  474. state->kl_super = down;
  475. event->keycode = KEY_LEFT_SUPER;
  476. SET_UNSET(event->modifiers, KEY_MOD_LEFT_SUPER, down);
  477. break;
  478. case 0x5C:
  479. state->k_super = down;
  480. state->kr_super = down;
  481. event->keycode = KEY_RIGHT_SUPER;
  482. SET_UNSET(event->modifiers, KEY_MOD_RIGHT_SUPER, down);
  483. break;
  484. case 0x1D:
  485. state->kr_ctrl = down;
  486. state->k_ctrl = down;
  487. event->keycode = KEY_RIGHT_CTRL;
  488. SET_UNSET(event->modifiers, KEY_MOD_RIGHT_CTRL, down);
  489. break;
  490. case 0x38:
  491. state->kr_alt = down;
  492. state->k_alt = down;
  493. event->keycode = KEY_RIGHT_ALT;
  494. SET_UNSET(event->modifiers, KEY_MOD_RIGHT_ALT, down);
  495. break;
  496. case 0x48:
  497. event->keycode = KEY_ARROW_UP;
  498. break;
  499. case 0x4D:
  500. event->keycode = KEY_ARROW_RIGHT;
  501. break;
  502. case 0x47:
  503. event->keycode = KEY_HOME;
  504. break;
  505. case 0x49:
  506. event->keycode = KEY_PAGE_UP;
  507. break;
  508. case 0x4B:
  509. event->keycode = KEY_ARROW_LEFT;
  510. break;
  511. case 0x4F:
  512. event->keycode = KEY_END;
  513. break;
  514. case 0x50:
  515. event->keycode = KEY_ARROW_DOWN;
  516. break;
  517. case 0x51:
  518. event->keycode = KEY_PAGE_DOWN;
  519. break;
  520. case 0x52:
  521. event->keycode = KEY_INSERT;
  522. break;
  523. case 0x53:
  524. event->keycode = KEY_DEL;
  525. break;
  526. case 0x35:
  527. event->keycode = KEY_NUM_DIV;
  528. event->key = '/';
  529. break;
  530. case 0x1C:
  531. event->keycode = KEY_NUM_ENTER;
  532. event->key = '\n';
  533. break;
  534. default:
  535. break;
  536. }
  537. state->kbd_s_state = 0;
  538. return 0;
  539. }
  540. return 0;
  541. }