keyboard.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. *
  3. * Copyright © 1999 Keith Packard
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and its
  6. * documentation for any purpose is hereby granted without fee, provided that
  7. * the above copyright notice appear in all copies and that both that
  8. * copyright notice and this permission notice appear in supporting
  9. * documentation, and that the name of Keith Packard not be used in
  10. * advertising or publicity pertaining to distribution of the software without
  11. * specific, written prior permission. Keith Packard makes no
  12. * representations about the suitability of this software for any purpose. It
  13. * is provided "as is" without express or implied warranty.
  14. *
  15. * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17. * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  20. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. * PERFORMANCE OF THIS SOFTWARE.
  22. */
  23. #ifdef HAVE_CONFIG_H
  24. #include <kdrive-config.h>
  25. #endif
  26. #include "kdrive.h"
  27. #include "kkeymap.h"
  28. #include <linux/keyboard.h>
  29. #include <linux/kd.h>
  30. #define XK_PUBLISHING
  31. #include <X11/keysym.h>
  32. #include <termios.h>
  33. #include <sys/ioctl.h>
  34. extern int LinuxConsoleFd;
  35. static const KeySym linux_to_x[256] = {
  36. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  37. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  38. XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
  39. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  40. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  41. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  42. NoSymbol, NoSymbol, NoSymbol, XK_Escape,
  43. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  44. XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
  45. XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
  46. XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
  47. XK_comma, XK_minus, XK_period, XK_slash,
  48. XK_0, XK_1, XK_2, XK_3,
  49. XK_4, XK_5, XK_6, XK_7,
  50. XK_8, XK_9, XK_colon, XK_semicolon,
  51. XK_less, XK_equal, XK_greater, XK_question,
  52. XK_at, XK_A, XK_B, XK_C,
  53. XK_D, XK_E, XK_F, XK_G,
  54. XK_H, XK_I, XK_J, XK_K,
  55. XK_L, XK_M, XK_N, XK_O,
  56. XK_P, XK_Q, XK_R, XK_S,
  57. XK_T, XK_U, XK_V, XK_W,
  58. XK_X, XK_Y, XK_Z, XK_bracketleft,
  59. XK_backslash, XK_bracketright, XK_asciicircum, XK_underscore,
  60. XK_grave, XK_a, XK_b, XK_c,
  61. XK_d, XK_e, XK_f, XK_g,
  62. XK_h, XK_i, XK_j, XK_k,
  63. XK_l, XK_m, XK_n, XK_o,
  64. XK_p, XK_q, XK_r, XK_s,
  65. XK_t, XK_u, XK_v, XK_w,
  66. XK_x, XK_y, XK_z, XK_braceleft,
  67. XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace,
  68. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  69. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  70. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  71. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  72. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  73. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  74. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  75. NoSymbol, NoSymbol, NoSymbol, NoSymbol,
  76. XK_nobreakspace, XK_exclamdown, XK_cent, XK_sterling,
  77. XK_currency, XK_yen, XK_brokenbar, XK_section,
  78. XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
  79. XK_notsign, XK_hyphen, XK_registered, XK_macron,
  80. XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior,
  81. XK_acute, XK_mu, XK_paragraph, XK_periodcentered,
  82. XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright,
  83. XK_onequarter, XK_onehalf, XK_threequarters, XK_questiondown,
  84. XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde,
  85. XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla,
  86. XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
  87. XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
  88. XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
  89. XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply,
  90. XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex,
  91. XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp,
  92. XK_agrave, XK_aacute, XK_acircumflex, XK_atilde,
  93. XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla,
  94. XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
  95. XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis,
  96. XK_eth, XK_ntilde, XK_ograve, XK_oacute,
  97. XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division,
  98. XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex,
  99. XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis
  100. };
  101. static unsigned char tbl[KD_MAX_WIDTH] = {
  102. 0,
  103. 1 << KG_SHIFT,
  104. (1 << KG_ALTGR),
  105. (1 << KG_ALTGR) | (1 << KG_SHIFT)
  106. };
  107. static void readKernelMapping(void)
  108. {
  109. KeySym *k;
  110. int i, j;
  111. struct kbentry kbe;
  112. int minKeyCode, maxKeyCode;
  113. int row;
  114. minKeyCode = NR_KEYS;
  115. maxKeyCode = 0;
  116. row = 0;
  117. for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i) {
  118. kbe.kb_index = i;
  119. k = kdKeymap + row * KD_MAX_WIDTH;
  120. for (j = 0; j < KD_MAX_WIDTH; ++j) {
  121. unsigned short kval;
  122. k[j] = NoSymbol;
  123. kbe.kb_table = tbl[j];
  124. kbe.kb_value = 0;
  125. if (ioctl(LinuxConsoleFd, KDGKBENT, &kbe))
  126. continue;
  127. kval = KVAL(kbe.kb_value);
  128. switch (KTYP(kbe.kb_value)) {
  129. case KT_LATIN:
  130. case KT_LETTER:
  131. k[j] = linux_to_x[kval];
  132. break;
  133. case KT_FN:
  134. if (kval <= 19)
  135. k[j] = XK_F1 + kval;
  136. else
  137. switch (kbe.kb_value) {
  138. case K_FIND:
  139. k[j] = XK_Home; /* or XK_Find */
  140. break;
  141. case K_INSERT:
  142. k[j] = XK_Insert;
  143. break;
  144. case K_REMOVE:
  145. k[j] = XK_Delete;
  146. break;
  147. case K_SELECT:
  148. k[j] = XK_End; /* or XK_Select */
  149. break;
  150. case K_PGUP:
  151. k[j] = XK_Prior;
  152. break;
  153. case K_PGDN:
  154. k[j] = XK_Next;
  155. break;
  156. case K_HELP:
  157. k[j] = XK_Help;
  158. break;
  159. case K_DO:
  160. k[j] = XK_Execute;
  161. break;
  162. case K_PAUSE:
  163. k[j] = XK_Pause;
  164. break;
  165. case K_MACRO:
  166. k[j] = XK_Menu;
  167. break;
  168. default:
  169. break;
  170. }
  171. break;
  172. case KT_SPEC:
  173. switch (kbe.kb_value) {
  174. case K_ENTER:
  175. k[j] = XK_Return;
  176. break;
  177. case K_BREAK:
  178. k[j] = XK_Break;
  179. break;
  180. case K_CAPS:
  181. k[j] = XK_Caps_Lock;
  182. break;
  183. case K_NUM:
  184. k[j] = XK_Num_Lock;
  185. break;
  186. case K_HOLD:
  187. k[j] = XK_Scroll_Lock;
  188. break;
  189. case K_COMPOSE:
  190. k[j] = XK_Multi_key;
  191. break;
  192. default:
  193. break;
  194. }
  195. break;
  196. case KT_PAD:
  197. switch (kbe.kb_value) {
  198. case K_PPLUS:
  199. k[j] = XK_KP_Add;
  200. break;
  201. case K_PMINUS:
  202. k[j] = XK_KP_Subtract;
  203. break;
  204. case K_PSTAR:
  205. k[j] = XK_KP_Multiply;
  206. break;
  207. case K_PSLASH:
  208. k[j] = XK_KP_Divide;
  209. break;
  210. case K_PENTER:
  211. k[j] = XK_KP_Enter;
  212. break;
  213. case K_PCOMMA:
  214. k[j] = XK_KP_Separator;
  215. break;
  216. case K_PDOT:
  217. k[j] = XK_KP_Decimal;
  218. break;
  219. case K_PPLUSMINUS:
  220. k[j] = XK_KP_Subtract;
  221. break;
  222. default:
  223. if (kval <= 9)
  224. k[j] = XK_KP_0 + kval;
  225. break;
  226. }
  227. break;
  228. /*
  229. * KT_DEAD keys are for accelerated diacritical creation.
  230. */
  231. case KT_DEAD:
  232. switch (kbe.kb_value) {
  233. case K_DGRAVE:
  234. k[j] = XK_dead_grave;
  235. break;
  236. case K_DACUTE:
  237. k[j] = XK_dead_acute;
  238. break;
  239. case K_DCIRCM:
  240. k[j] = XK_dead_circumflex;
  241. break;
  242. case K_DTILDE:
  243. k[j] = XK_dead_tilde;
  244. break;
  245. case K_DDIERE:
  246. k[j] = XK_dead_diaeresis;
  247. break;
  248. }
  249. break;
  250. case KT_CUR:
  251. switch (kbe.kb_value) {
  252. case K_DOWN:
  253. k[j] = XK_Down;
  254. break;
  255. case K_LEFT:
  256. k[j] = XK_Left;
  257. break;
  258. case K_RIGHT:
  259. k[j] = XK_Right;
  260. break;
  261. case K_UP:
  262. k[j] = XK_Up;
  263. break;
  264. }
  265. break;
  266. case KT_SHIFT:
  267. switch (kbe.kb_value) {
  268. case K_ALTGR:
  269. k[j] = XK_Mode_switch;
  270. break;
  271. case K_ALT:
  272. k[j] = (kbe.kb_index == 0x64 ?
  273. XK_Alt_R : XK_Alt_L);
  274. break;
  275. case K_CTRL:
  276. k[j] = (kbe.kb_index == 0x61 ?
  277. XK_Control_R : XK_Control_L);
  278. break;
  279. case K_CTRLL:
  280. k[j] = XK_Control_L;
  281. break;
  282. case K_CTRLR:
  283. k[j] = XK_Control_R;
  284. break;
  285. case K_SHIFT:
  286. k[j] = (kbe.kb_index == 0x36 ?
  287. XK_Shift_R : XK_Shift_L);
  288. break;
  289. case K_SHIFTL:
  290. k[j] = XK_Shift_L;
  291. break;
  292. case K_SHIFTR:
  293. k[j] = XK_Shift_R;
  294. break;
  295. default:
  296. break;
  297. }
  298. break;
  299. /*
  300. * KT_ASCII keys accumulate a 3 digit decimal number that gets
  301. * emitted when the shift state changes. We can't emulate that.
  302. */
  303. case KT_ASCII:
  304. break;
  305. case KT_LOCK:
  306. if (kbe.kb_value == K_SHIFTLOCK)
  307. k[j] = XK_Shift_Lock;
  308. break;
  309. #ifdef KT_X
  310. case KT_X:
  311. /* depends on new keyboard symbols in file linux/keyboard.h */
  312. if (kbe.kb_value == K_XMENU)
  313. k[j] = XK_Menu;
  314. if (kbe.kb_value == K_XTELEPHONE)
  315. k[j] = XK_telephone;
  316. break;
  317. #endif
  318. #ifdef KT_XF
  319. case KT_XF:
  320. /* special linux keysyms which map directly to XF86 keysyms */
  321. k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00;
  322. break;
  323. #endif
  324. default:
  325. break;
  326. }
  327. if (i < minKeyCode)
  328. minKeyCode = i;
  329. if (i > maxKeyCode)
  330. maxKeyCode = i;
  331. }
  332. if (minKeyCode == NR_KEYS)
  333. continue;
  334. if (k[3] == k[2])
  335. k[3] = NoSymbol;
  336. if (k[2] == k[1])
  337. k[2] = NoSymbol;
  338. if (k[1] == k[0])
  339. k[1] = NoSymbol;
  340. if (k[0] == k[2] && k[1] == k[3])
  341. k[2] = k[3] = NoSymbol;
  342. if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol)
  343. k[3] = NoSymbol;
  344. row++;
  345. }
  346. kdMinScanCode = minKeyCode;
  347. kdMaxScanCode = maxKeyCode;
  348. }
  349. static void LinuxKeyboardLoad(void)
  350. {
  351. readKernelMapping();
  352. }
  353. static void LinuxKeyboardRead(int fd, void *closure)
  354. {
  355. unsigned char buf[256], *b;
  356. int n;
  357. while ((n = read(fd, buf, sizeof(buf))) > 0) {
  358. b = buf;
  359. while (n--) {
  360. KdEnqueueKeyboardEvent(b[0] & 0x7f, b[0] & 0x80);
  361. b++;
  362. }
  363. }
  364. }
  365. static int LinuxKbdTrans;
  366. static struct termios LinuxTermios;
  367. static int LinuxKbdType;
  368. static int LinuxKeyboardEnable(int fd, void *closure)
  369. {
  370. struct termios nTty;
  371. unsigned char buf[256];
  372. int n;
  373. ioctl(fd, KDGKBMODE, &LinuxKbdTrans);
  374. tcgetattr(fd, &LinuxTermios);
  375. ioctl(fd, KDSKBMODE, K_MEDIUMRAW);
  376. nTty = LinuxTermios;
  377. nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
  378. nTty.c_oflag = 0;
  379. nTty.c_cflag = CREAD | CS8;
  380. nTty.c_lflag = 0;
  381. nTty.c_cc[VTIME] = 0;
  382. nTty.c_cc[VMIN] = 1;
  383. cfsetispeed(&nTty, 9600);
  384. cfsetospeed(&nTty, 9600);
  385. tcsetattr(fd, TCSANOW, &nTty);
  386. /*
  387. * Flush any pending keystrokes
  388. */
  389. while ((n = read(fd, buf, sizeof(buf))) > 0) ;
  390. return fd;
  391. }
  392. static void LinuxKeyboardDisable(int fd, void *closure)
  393. {
  394. ioctl(LinuxConsoleFd, KDSKBMODE, LinuxKbdTrans);
  395. tcsetattr(LinuxConsoleFd, TCSANOW, &LinuxTermios);
  396. }
  397. static int LinuxKeyboardInit(void)
  398. {
  399. if (!LinuxKbdType)
  400. LinuxKbdType = KdAllocInputType();
  401. KdRegisterFd(LinuxKbdType, LinuxConsoleFd, LinuxKeyboardRead, 0);
  402. LinuxKeyboardEnable(LinuxConsoleFd, 0);
  403. KdRegisterFdEnableDisable(LinuxConsoleFd,
  404. LinuxKeyboardEnable, LinuxKeyboardDisable);
  405. return 1;
  406. }
  407. static void LinuxKeyboardFini(void)
  408. {
  409. LinuxKeyboardDisable(LinuxConsoleFd, 0);
  410. KdUnregisterFds(LinuxKbdType, FALSE);
  411. }
  412. static void LinuxKeyboardLeds(int leds)
  413. {
  414. ioctl(LinuxConsoleFd, KDSETLED, leds & 7);
  415. }
  416. static void LinuxKeyboardBell(int volume, int pitch, int duration)
  417. {
  418. if (volume && pitch) {
  419. ioctl(LinuxConsoleFd, KDMKTONE,
  420. ((1193190 / pitch) & 0xffff) |
  421. (((unsigned long)duration * volume / 50) << 16));
  422. }
  423. }
  424. const KdKeyboardFuncs LinuxKeyboardFuncs = {
  425. LinuxKeyboardLoad,
  426. LinuxKeyboardInit,
  427. LinuxKeyboardLeds,
  428. LinuxKeyboardBell,
  429. LinuxKeyboardFini,
  430. 3,
  431. };