SDL_wscons_kbd.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #include <dev/wscons/wsksymvar.h>
  20. #include <dev/wscons/wsksymdef.h>
  21. #include "SDL_scancode.h"
  22. #include "SDL_events.h"
  23. #include "SDL_keyboard.h"
  24. #include "SDL_wscons.h"
  25. #include "SDL_log.h"
  26. #include <sys/time.h>
  27. #include <dev/wscons/wsconsio.h>
  28. #include <dev/wscons/wsdisplay_usl_io.h>
  29. #include <termios.h>
  30. #include <fcntl.h>
  31. #include <sys/ioctl.h>
  32. #include <sys/param.h>
  33. #include <unistd.h>
  34. #include "../../events/SDL_events_c.h"
  35. #ifdef __NetBSD__
  36. #define KS_GROUP_Ascii KS_GROUP_Plain
  37. #define KS_Cmd_ScrollBack KS_Cmd_ScrollFastUp
  38. #define KS_Cmd_ScrollFwd KS_Cmd_ScrollFastDown
  39. #endif
  40. #define RETIFIOCTLERR(x) if (x == -1) { free(input); input = NULL; return NULL;}
  41. typedef struct SDL_WSCONS_mouse_input_data SDL_WSCONS_mouse_input_data;
  42. extern SDL_WSCONS_mouse_input_data* SDL_WSCONS_Init_Mouse();
  43. extern void updateMouse(SDL_WSCONS_mouse_input_data* input);
  44. extern void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data* input);
  45. /* Conversion table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c */
  46. static const unsigned char latin1_to_upper[256] = {
  47. /* 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f */
  48. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
  49. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
  50. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
  51. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
  55. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
  56. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
  57. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
  58. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
  59. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
  60. 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 6 */
  61. 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 6 */
  62. 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 7 */
  63. 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
  65. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
  69. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
  71. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
  74. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
  75. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
  76. 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* e */
  77. 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* e */
  78. 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* f */
  79. 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* f */
  80. };
  81. /* Compose table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c */
  82. static struct SDL_wscons_compose_tab_s {
  83. keysym_t elem[2];
  84. keysym_t result;
  85. } compose_tab[] = {
  86. { { KS_plus, KS_plus }, KS_numbersign },
  87. { { KS_a, KS_a }, KS_at },
  88. { { KS_parenleft, KS_parenleft }, KS_bracketleft },
  89. { { KS_slash, KS_slash }, KS_backslash },
  90. { { KS_parenright, KS_parenright }, KS_bracketright },
  91. { { KS_parenleft, KS_minus }, KS_braceleft },
  92. { { KS_slash, KS_minus }, KS_bar },
  93. { { KS_parenright, KS_minus }, KS_braceright },
  94. { { KS_exclam, KS_exclam }, KS_exclamdown },
  95. { { KS_c, KS_slash }, KS_cent },
  96. { { KS_l, KS_minus }, KS_sterling },
  97. { { KS_y, KS_minus }, KS_yen },
  98. { { KS_s, KS_o }, KS_section },
  99. { { KS_x, KS_o }, KS_currency },
  100. { { KS_c, KS_o }, KS_copyright },
  101. { { KS_less, KS_less }, KS_guillemotleft },
  102. { { KS_greater, KS_greater }, KS_guillemotright },
  103. { { KS_question, KS_question }, KS_questiondown },
  104. { { KS_dead_acute, KS_space }, KS_apostrophe },
  105. { { KS_dead_grave, KS_space }, KS_grave },
  106. { { KS_dead_tilde, KS_space }, KS_asciitilde },
  107. { { KS_dead_circumflex, KS_space }, KS_asciicircum },
  108. { { KS_dead_diaeresis, KS_space }, KS_quotedbl },
  109. { { KS_dead_cedilla, KS_space }, KS_comma },
  110. { { KS_dead_circumflex, KS_A }, KS_Acircumflex },
  111. { { KS_dead_diaeresis, KS_A }, KS_Adiaeresis },
  112. { { KS_dead_grave, KS_A }, KS_Agrave },
  113. { { KS_dead_abovering, KS_A }, KS_Aring },
  114. { { KS_dead_tilde, KS_A }, KS_Atilde },
  115. { { KS_dead_cedilla, KS_C }, KS_Ccedilla },
  116. { { KS_dead_acute, KS_E }, KS_Eacute },
  117. { { KS_dead_circumflex, KS_E }, KS_Ecircumflex },
  118. { { KS_dead_diaeresis, KS_E }, KS_Ediaeresis },
  119. { { KS_dead_grave, KS_E }, KS_Egrave },
  120. { { KS_dead_acute, KS_I }, KS_Iacute },
  121. { { KS_dead_circumflex, KS_I }, KS_Icircumflex },
  122. { { KS_dead_diaeresis, KS_I }, KS_Idiaeresis },
  123. { { KS_dead_grave, KS_I }, KS_Igrave },
  124. { { KS_dead_tilde, KS_N }, KS_Ntilde },
  125. { { KS_dead_acute, KS_O }, KS_Oacute },
  126. { { KS_dead_circumflex, KS_O }, KS_Ocircumflex },
  127. { { KS_dead_diaeresis, KS_O }, KS_Odiaeresis },
  128. { { KS_dead_grave, KS_O }, KS_Ograve },
  129. { { KS_dead_tilde, KS_O }, KS_Otilde },
  130. { { KS_dead_acute, KS_U }, KS_Uacute },
  131. { { KS_dead_circumflex, KS_U }, KS_Ucircumflex },
  132. { { KS_dead_diaeresis, KS_U }, KS_Udiaeresis },
  133. { { KS_dead_grave, KS_U }, KS_Ugrave },
  134. { { KS_dead_acute, KS_Y }, KS_Yacute },
  135. { { KS_dead_acute, KS_a }, KS_aacute },
  136. { { KS_dead_circumflex, KS_a }, KS_acircumflex },
  137. { { KS_dead_diaeresis, KS_a }, KS_adiaeresis },
  138. { { KS_dead_grave, KS_a }, KS_agrave },
  139. { { KS_dead_abovering, KS_a }, KS_aring },
  140. { { KS_dead_tilde, KS_a }, KS_atilde },
  141. { { KS_dead_cedilla, KS_c }, KS_ccedilla },
  142. { { KS_dead_acute, KS_e }, KS_eacute },
  143. { { KS_dead_circumflex, KS_e }, KS_ecircumflex },
  144. { { KS_dead_diaeresis, KS_e }, KS_ediaeresis },
  145. { { KS_dead_grave, KS_e }, KS_egrave },
  146. { { KS_dead_acute, KS_i }, KS_iacute },
  147. { { KS_dead_circumflex, KS_i }, KS_icircumflex },
  148. { { KS_dead_diaeresis, KS_i }, KS_idiaeresis },
  149. { { KS_dead_grave, KS_i }, KS_igrave },
  150. { { KS_dead_tilde, KS_n }, KS_ntilde },
  151. { { KS_dead_acute, KS_o }, KS_oacute },
  152. { { KS_dead_circumflex, KS_o }, KS_ocircumflex },
  153. { { KS_dead_diaeresis, KS_o }, KS_odiaeresis },
  154. { { KS_dead_grave, KS_o }, KS_ograve },
  155. { { KS_dead_tilde, KS_o }, KS_otilde },
  156. { { KS_dead_acute, KS_u }, KS_uacute },
  157. { { KS_dead_circumflex, KS_u }, KS_ucircumflex },
  158. { { KS_dead_diaeresis, KS_u }, KS_udiaeresis },
  159. { { KS_dead_grave, KS_u }, KS_ugrave },
  160. { { KS_dead_acute, KS_y }, KS_yacute },
  161. { { KS_dead_diaeresis, KS_y }, KS_ydiaeresis },
  162. { { KS_quotedbl, KS_A }, KS_Adiaeresis },
  163. { { KS_quotedbl, KS_E }, KS_Ediaeresis },
  164. { { KS_quotedbl, KS_I }, KS_Idiaeresis },
  165. { { KS_quotedbl, KS_O }, KS_Odiaeresis },
  166. { { KS_quotedbl, KS_U }, KS_Udiaeresis },
  167. { { KS_quotedbl, KS_a }, KS_adiaeresis },
  168. { { KS_quotedbl, KS_e }, KS_ediaeresis },
  169. { { KS_quotedbl, KS_i }, KS_idiaeresis },
  170. { { KS_quotedbl, KS_o }, KS_odiaeresis },
  171. { { KS_quotedbl, KS_u }, KS_udiaeresis },
  172. { { KS_quotedbl, KS_y }, KS_ydiaeresis },
  173. { { KS_acute, KS_A }, KS_Aacute },
  174. { { KS_asciicircum, KS_A }, KS_Acircumflex },
  175. { { KS_grave, KS_A }, KS_Agrave },
  176. { { KS_asterisk, KS_A }, KS_Aring },
  177. { { KS_asciitilde, KS_A }, KS_Atilde },
  178. { { KS_cedilla, KS_C }, KS_Ccedilla },
  179. { { KS_acute, KS_E }, KS_Eacute },
  180. { { KS_asciicircum, KS_E }, KS_Ecircumflex },
  181. { { KS_grave, KS_E }, KS_Egrave },
  182. { { KS_acute, KS_I }, KS_Iacute },
  183. { { KS_asciicircum, KS_I }, KS_Icircumflex },
  184. { { KS_grave, KS_I }, KS_Igrave },
  185. { { KS_asciitilde, KS_N }, KS_Ntilde },
  186. { { KS_acute, KS_O }, KS_Oacute },
  187. { { KS_asciicircum, KS_O }, KS_Ocircumflex },
  188. { { KS_grave, KS_O }, KS_Ograve },
  189. { { KS_asciitilde, KS_O }, KS_Otilde },
  190. { { KS_acute, KS_U }, KS_Uacute },
  191. { { KS_asciicircum, KS_U }, KS_Ucircumflex },
  192. { { KS_grave, KS_U }, KS_Ugrave },
  193. { { KS_acute, KS_Y }, KS_Yacute },
  194. { { KS_acute, KS_a }, KS_aacute },
  195. { { KS_asciicircum, KS_a }, KS_acircumflex },
  196. { { KS_grave, KS_a }, KS_agrave },
  197. { { KS_asterisk, KS_a }, KS_aring },
  198. { { KS_asciitilde, KS_a }, KS_atilde },
  199. { { KS_cedilla, KS_c }, KS_ccedilla },
  200. { { KS_acute, KS_e }, KS_eacute },
  201. { { KS_asciicircum, KS_e }, KS_ecircumflex },
  202. { { KS_grave, KS_e }, KS_egrave },
  203. { { KS_acute, KS_i }, KS_iacute },
  204. { { KS_asciicircum, KS_i }, KS_icircumflex },
  205. { { KS_grave, KS_i }, KS_igrave },
  206. { { KS_asciitilde, KS_n }, KS_ntilde },
  207. { { KS_acute, KS_o }, KS_oacute },
  208. { { KS_asciicircum, KS_o }, KS_ocircumflex },
  209. { { KS_grave, KS_o }, KS_ograve },
  210. { { KS_asciitilde, KS_o }, KS_otilde },
  211. { { KS_acute, KS_u }, KS_uacute },
  212. { { KS_asciicircum, KS_u }, KS_ucircumflex },
  213. { { KS_grave, KS_u }, KS_ugrave },
  214. { { KS_acute, KS_y }, KS_yacute },
  215. #ifndef __NetBSD__
  216. { { KS_dead_caron, KS_space }, KS_L2_caron },
  217. { { KS_dead_caron, KS_S }, KS_L2_Scaron },
  218. { { KS_dead_caron, KS_Z }, KS_L2_Zcaron },
  219. { { KS_dead_caron, KS_s }, KS_L2_scaron },
  220. { { KS_dead_caron, KS_z }, KS_L2_zcaron }
  221. #endif
  222. };
  223. static keysym_t ksym_upcase(keysym_t ksym)
  224. {
  225. if (ksym >= KS_f1 && ksym <= KS_f20)
  226. return(KS_F1 - KS_f1 + ksym);
  227. if (KS_GROUP(ksym) == KS_GROUP_Ascii && ksym <= 0xff &&
  228. latin1_to_upper[ksym] != 0x00)
  229. return(latin1_to_upper[ksym]);
  230. return(ksym);
  231. }
  232. static struct wscons_keycode_to_SDL {
  233. keysym_t sourcekey;
  234. SDL_Scancode targetKey;
  235. } conversion_table[] = {
  236. {KS_Menu, SDL_SCANCODE_APPLICATION},
  237. {KS_Up, SDL_SCANCODE_UP},
  238. {KS_Down, SDL_SCANCODE_DOWN},
  239. {KS_Left, SDL_SCANCODE_LEFT},
  240. {KS_Right, SDL_SCANCODE_RIGHT},
  241. {KS_Hold_Screen, SDL_SCANCODE_SCROLLLOCK},
  242. {KS_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR},
  243. {KS_Caps_Lock, SDL_SCANCODE_CAPSLOCK},
  244. {KS_BackSpace, SDL_SCANCODE_BACKSPACE},
  245. {KS_space, SDL_SCANCODE_SPACE},
  246. {KS_Delete, SDL_SCANCODE_BACKSPACE},
  247. {KS_Home, SDL_SCANCODE_HOME},
  248. {KS_End, SDL_SCANCODE_END},
  249. {KS_Pause, SDL_SCANCODE_PAUSE},
  250. {KS_Print_Screen, SDL_SCANCODE_PRINTSCREEN},
  251. {KS_Insert, SDL_SCANCODE_INSERT},
  252. {KS_Escape, SDL_SCANCODE_ESCAPE},
  253. {KS_Return, SDL_SCANCODE_RETURN},
  254. {KS_Linefeed, SDL_SCANCODE_RETURN},
  255. {KS_KP_Delete, SDL_SCANCODE_DELETE},
  256. {KS_KP_Insert, SDL_SCANCODE_INSERT},
  257. {KS_Control_L, SDL_SCANCODE_LCTRL},
  258. {KS_Control_R, SDL_SCANCODE_RCTRL},
  259. {KS_Shift_L, SDL_SCANCODE_LSHIFT},
  260. {KS_Shift_R, SDL_SCANCODE_RSHIFT},
  261. {KS_Alt_L, SDL_SCANCODE_LALT},
  262. {KS_Alt_R, SDL_SCANCODE_RALT},
  263. {KS_grave, SDL_SCANCODE_GRAVE},
  264. {KS_KP_0, SDL_SCANCODE_KP_0},
  265. {KS_KP_1, SDL_SCANCODE_KP_1},
  266. {KS_KP_2, SDL_SCANCODE_KP_2},
  267. {KS_KP_3, SDL_SCANCODE_KP_3},
  268. {KS_KP_4, SDL_SCANCODE_KP_4},
  269. {KS_KP_5, SDL_SCANCODE_KP_5},
  270. {KS_KP_6, SDL_SCANCODE_KP_6},
  271. {KS_KP_7, SDL_SCANCODE_KP_7},
  272. {KS_KP_8, SDL_SCANCODE_KP_8},
  273. {KS_KP_9, SDL_SCANCODE_KP_9},
  274. {KS_KP_Enter, SDL_SCANCODE_KP_ENTER},
  275. {KS_KP_Multiply, SDL_SCANCODE_KP_MULTIPLY},
  276. {KS_KP_Add, SDL_SCANCODE_KP_PLUS},
  277. {KS_KP_Subtract, SDL_SCANCODE_KP_MINUS},
  278. {KS_KP_Divide, SDL_SCANCODE_KP_DIVIDE},
  279. {KS_KP_Up, SDL_SCANCODE_UP},
  280. {KS_KP_Down, SDL_SCANCODE_DOWN},
  281. {KS_KP_Left, SDL_SCANCODE_LEFT},
  282. {KS_KP_Right, SDL_SCANCODE_RIGHT},
  283. {KS_KP_Equal, SDL_SCANCODE_KP_EQUALS},
  284. {KS_f1, SDL_SCANCODE_F1},
  285. {KS_f2, SDL_SCANCODE_F2},
  286. {KS_f3, SDL_SCANCODE_F3},
  287. {KS_f4, SDL_SCANCODE_F4},
  288. {KS_f5, SDL_SCANCODE_F5},
  289. {KS_f6, SDL_SCANCODE_F6},
  290. {KS_f7, SDL_SCANCODE_F7},
  291. {KS_f8, SDL_SCANCODE_F8},
  292. {KS_f9, SDL_SCANCODE_F9},
  293. {KS_f10, SDL_SCANCODE_F10},
  294. {KS_f11, SDL_SCANCODE_F11},
  295. {KS_f12, SDL_SCANCODE_F12},
  296. {KS_f13, SDL_SCANCODE_F13},
  297. {KS_f14, SDL_SCANCODE_F14},
  298. {KS_f15, SDL_SCANCODE_F15},
  299. {KS_f16, SDL_SCANCODE_F16},
  300. {KS_f17, SDL_SCANCODE_F17},
  301. {KS_f18, SDL_SCANCODE_F18},
  302. {KS_f19, SDL_SCANCODE_F19},
  303. {KS_f20, SDL_SCANCODE_F20},
  304. #if !defined(__NetBSD__)
  305. {KS_f21, SDL_SCANCODE_F21},
  306. {KS_f22, SDL_SCANCODE_F22},
  307. {KS_f23, SDL_SCANCODE_F23},
  308. {KS_f24, SDL_SCANCODE_F24},
  309. #endif
  310. {KS_Meta_L, SDL_SCANCODE_LGUI},
  311. {KS_Meta_R, SDL_SCANCODE_RGUI},
  312. {KS_Zenkaku_Hankaku, SDL_SCANCODE_LANG5},
  313. {KS_Hiragana_Katakana, SDL_SCANCODE_INTERNATIONAL2},
  314. {KS_yen, SDL_SCANCODE_INTERNATIONAL3},
  315. {KS_Henkan, SDL_SCANCODE_INTERNATIONAL4},
  316. {KS_Muhenkan, SDL_SCANCODE_INTERNATIONAL5},
  317. {KS_KP_Prior, SDL_SCANCODE_PRIOR},
  318. {KS_a, SDL_SCANCODE_A},
  319. {KS_b, SDL_SCANCODE_B},
  320. {KS_c, SDL_SCANCODE_C},
  321. {KS_d, SDL_SCANCODE_D},
  322. {KS_e, SDL_SCANCODE_E},
  323. {KS_f, SDL_SCANCODE_F},
  324. {KS_g, SDL_SCANCODE_G},
  325. {KS_h, SDL_SCANCODE_H},
  326. {KS_i, SDL_SCANCODE_I},
  327. {KS_j, SDL_SCANCODE_J},
  328. {KS_k, SDL_SCANCODE_K},
  329. {KS_l, SDL_SCANCODE_L},
  330. {KS_m, SDL_SCANCODE_M},
  331. {KS_n, SDL_SCANCODE_N},
  332. {KS_o, SDL_SCANCODE_O},
  333. {KS_p, SDL_SCANCODE_P},
  334. {KS_q, SDL_SCANCODE_Q},
  335. {KS_r, SDL_SCANCODE_R},
  336. {KS_s, SDL_SCANCODE_S},
  337. {KS_t, SDL_SCANCODE_T},
  338. {KS_u, SDL_SCANCODE_U},
  339. {KS_v, SDL_SCANCODE_V},
  340. {KS_w, SDL_SCANCODE_W},
  341. {KS_x, SDL_SCANCODE_X},
  342. {KS_y, SDL_SCANCODE_Y},
  343. {KS_z, SDL_SCANCODE_Z},
  344. {KS_0, SDL_SCANCODE_0},
  345. {KS_1, SDL_SCANCODE_1},
  346. {KS_2, SDL_SCANCODE_2},
  347. {KS_3, SDL_SCANCODE_3},
  348. {KS_4, SDL_SCANCODE_4},
  349. {KS_5, SDL_SCANCODE_5},
  350. {KS_6, SDL_SCANCODE_6},
  351. {KS_7, SDL_SCANCODE_7},
  352. {KS_8, SDL_SCANCODE_8},
  353. {KS_9, SDL_SCANCODE_9},
  354. {KS_minus, SDL_SCANCODE_MINUS},
  355. {KS_equal, SDL_SCANCODE_EQUALS},
  356. {KS_Tab, SDL_SCANCODE_TAB},
  357. {KS_KP_Tab, SDL_SCANCODE_KP_TAB},
  358. {KS_apostrophe, SDL_SCANCODE_APOSTROPHE},
  359. {KS_bracketleft, SDL_SCANCODE_LEFTBRACKET},
  360. {KS_bracketright, SDL_SCANCODE_RIGHTBRACKET},
  361. {KS_semicolon, SDL_SCANCODE_SEMICOLON},
  362. {KS_comma, SDL_SCANCODE_COMMA},
  363. {KS_period, SDL_SCANCODE_PERIOD},
  364. {KS_slash, SDL_SCANCODE_SLASH},
  365. {KS_backslash, SDL_SCANCODE_BACKSLASH}
  366. };
  367. typedef struct {
  368. int fd;
  369. struct wskbd_map_data keymap;
  370. int ledstate;
  371. int origledstate;
  372. int shiftstate[4];
  373. int shiftheldstate[8];
  374. int lockheldstate[5];
  375. kbd_t encoding;
  376. char text[128];
  377. unsigned int text_len;
  378. keysym_t composebuffer[2];
  379. unsigned char composelen;
  380. } SDL_WSCONS_input_data;
  381. static SDL_WSCONS_input_data* inputs[4] = {NULL, NULL, NULL, NULL};
  382. static SDL_WSCONS_mouse_input_data* mouseInputData = NULL;
  383. #define IS_CONTROL_HELD (input->shiftstate[2] > 0)
  384. #define IS_ALT_HELD (input->shiftstate[1] > 0)
  385. #define IS_SHIFT_HELD ((input->shiftstate[0] > 0) || (input->ledstate & (1 << 5)))
  386. #define IS_ALTGR_MODE ((input->ledstate & (1 << 4)) || (input->shiftstate[3] > 0))
  387. #define IS_NUMLOCK_ON (input->ledstate & LED_NUM)
  388. #define IS_SCROLLLOCK_ON (input->ledstate & LED_SCR)
  389. #define IS_CAPSLOCK_ON (input->ledstate & LED_CAP)
  390. static SDL_WSCONS_input_data* SDL_WSCONS_Init_Keyboard(const char* dev)
  391. {
  392. #ifdef WSKBDIO_SETVERSION
  393. int version = WSKBDIO_EVENT_VERSION;
  394. #endif
  395. SDL_WSCONS_input_data* input = (SDL_WSCONS_input_data*)SDL_calloc(1, sizeof(SDL_WSCONS_input_data));
  396. if (!input) {
  397. return input;
  398. }
  399. input->fd = open(dev,O_RDWR | O_NONBLOCK);
  400. if (input->fd == -1) {
  401. free(input);
  402. input = NULL;
  403. return NULL;
  404. }
  405. input->keymap.map = SDL_calloc(sizeof(struct wscons_keymap), KS_NUMKEYCODES);
  406. if (input->keymap.map == NULL) {
  407. free(input);
  408. return NULL;
  409. }
  410. input->keymap.maplen = KS_NUMKEYCODES;
  411. RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETMAP, &input->keymap));
  412. RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETLEDS, &input->ledstate));
  413. input->origledstate = input->ledstate;
  414. RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETENCODING, &input->encoding));
  415. #ifdef WSKBDIO_SETVERSION
  416. RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_SETVERSION, &version));
  417. #endif
  418. return input;
  419. }
  420. void SDL_WSCONS_Init()
  421. {
  422. inputs[0] = SDL_WSCONS_Init_Keyboard("/dev/wskbd0");
  423. inputs[1] = SDL_WSCONS_Init_Keyboard("/dev/wskbd1");
  424. inputs[2] = SDL_WSCONS_Init_Keyboard("/dev/wskbd2");
  425. inputs[3] = SDL_WSCONS_Init_Keyboard("/dev/wskbd3");
  426. mouseInputData = SDL_WSCONS_Init_Mouse();
  427. return;
  428. }
  429. void SDL_WSCONS_Quit()
  430. {
  431. int i = 0;
  432. SDL_WSCONS_input_data* input = NULL;
  433. SDL_WSCONS_Quit_Mouse(mouseInputData);
  434. mouseInputData = NULL;
  435. for (i = 0; i < 4; i++) {
  436. input = inputs[i];
  437. if (input) {
  438. if (input->fd != -1 && input->fd != 0) {
  439. ioctl(input->fd,WSKBDIO_SETLEDS, &input->origledstate);
  440. close(input->fd);
  441. input->fd = -1;
  442. }
  443. free(input);
  444. input = NULL;
  445. }
  446. inputs[i] = NULL;
  447. }
  448. }
  449. static void put_queue(SDL_WSCONS_input_data *kbd, uint c)
  450. {
  451. /* c is already part of a UTF-8 sequence and safe to add as a character */
  452. if (kbd->text_len < (sizeof(kbd->text)-1)) {
  453. kbd->text[kbd->text_len++] = (char)(c);
  454. }
  455. }
  456. static void put_utf8(SDL_WSCONS_input_data* input, uint c)
  457. {
  458. if (c < 0x80)
  459. /* 0******* */
  460. put_queue(input, c);
  461. else if (c < 0x800) {
  462. /* 110***** 10****** */
  463. put_queue(input, 0xc0 | (c >> 6));
  464. put_queue(input, 0x80 | (c & 0x3f));
  465. } else if (c < 0x10000) {
  466. if (c >= 0xD800 && c <= 0xF500)
  467. return;
  468. if (c == 0xFFFF)
  469. return;
  470. /* 1110**** 10****** 10****** */
  471. put_queue(input, 0xe0 | (c >> 12));
  472. put_queue(input, 0x80 | ((c >> 6) & 0x3f));
  473. put_queue(input, 0x80 | (c & 0x3f));
  474. } else if (c < 0x110000) {
  475. /* 11110*** 10****** 10****** 10****** */
  476. put_queue(input, 0xf0 | (c >> 18));
  477. put_queue(input, 0x80 | ((c >> 12) & 0x3f));
  478. put_queue(input, 0x80 | ((c >> 6) & 0x3f));
  479. put_queue(input, 0x80 | (c & 0x3f));
  480. }
  481. }
  482. static void Translate_to_text(SDL_WSCONS_input_data* input, keysym_t ksym)
  483. {
  484. if (KS_GROUP(ksym) == KS_GROUP_Keypad) {
  485. if (isprint(ksym & 0xFF)) ksym &= 0xFF;
  486. }
  487. switch(ksym) {
  488. case KS_Escape:
  489. case KS_Delete:
  490. case KS_BackSpace:
  491. case KS_Return:
  492. case KS_Linefeed:
  493. /* All of these are unprintable characters. Ignore them */
  494. break;
  495. default:
  496. put_utf8(input, ksym);
  497. break;
  498. }
  499. if (input->text_len > 0) {
  500. input->text[input->text_len] = '\0';
  501. SDL_SendKeyboardText(input->text);
  502. /*memset(input->text, 0, sizeof(input->text));*/
  503. input->text_len = 0;
  504. input->text[0] = 0;
  505. }
  506. }
  507. static void Translate_to_keycode(SDL_WSCONS_input_data* input, int type, keysym_t ksym)
  508. {
  509. struct wscons_keymap keyDesc = input->keymap.map[ksym];
  510. keysym_t* group = &keyDesc.group1[KS_GROUP(keyDesc.group1[0]) == KS_GROUP_Keypad && IS_NUMLOCK_ON ? !IS_SHIFT_HELD : 0];
  511. int i = 0;
  512. /* Check command first, then group[0]*/
  513. switch (keyDesc.command) {
  514. case KS_Cmd_ScrollBack: {
  515. SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP);
  516. return;
  517. }
  518. case KS_Cmd_ScrollFwd: {
  519. SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN);
  520. return;
  521. }
  522. }
  523. for (i = 0; i < sizeof(conversion_table) / sizeof(struct wscons_keycode_to_SDL); i++) {
  524. if (conversion_table[i].sourcekey == group[0]) {
  525. SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey);
  526. return;
  527. }
  528. }
  529. SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN);
  530. }
  531. static void updateKeyboard(SDL_WSCONS_input_data* input)
  532. {
  533. struct wscons_event events[64];
  534. int type;
  535. int n,i,gindex,acc_i;
  536. keysym_t *group;
  537. keysym_t ksym, result;
  538. if (!input) return;
  539. if ((n = read(input->fd, events, sizeof(events))) > 0) {
  540. n /= sizeof(struct wscons_event);
  541. for (i = 0; i < n; i++) {
  542. type = events[i].type;
  543. switch(type) {
  544. case WSCONS_EVENT_KEY_DOWN: {
  545. switch (input->keymap.map[events[i].value].group1[0]) {
  546. case KS_Hold_Screen: {
  547. if (input->lockheldstate[0] >= 1) break;
  548. input->ledstate ^= LED_SCR;
  549. ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
  550. input->lockheldstate[0] = 1;
  551. break;
  552. }
  553. case KS_Num_Lock: {
  554. if (input->lockheldstate[1] >= 1) break;
  555. input->ledstate ^= LED_NUM;
  556. ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
  557. input->lockheldstate[1] = 1;
  558. break;
  559. }
  560. case KS_Caps_Lock: {
  561. if (input->lockheldstate[2] >= 1) break;
  562. input->ledstate ^= LED_CAP;
  563. ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
  564. input->lockheldstate[2] = 1;
  565. break;
  566. }
  567. #ifndef __NetBSD__
  568. case KS_Mode_Lock: {
  569. if (input->lockheldstate[3] >= 1) break;
  570. input->ledstate ^= 1 << 4;
  571. ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
  572. input->lockheldstate[3] = 1;
  573. break;
  574. }
  575. #endif
  576. case KS_Shift_Lock: {
  577. if (input->lockheldstate[4] >= 1) break;
  578. input->ledstate ^= 1 << 5;
  579. ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
  580. input->lockheldstate[4] = 1;
  581. break;
  582. }
  583. case KS_Shift_L: {
  584. if (input->shiftheldstate[0]) break;
  585. input->shiftstate[0]++;
  586. input->shiftheldstate[0] = 1;
  587. break;
  588. }
  589. case KS_Shift_R: {
  590. if (input->shiftheldstate[1]) break;
  591. input->shiftstate[0]++;
  592. input->shiftheldstate[1] = 1;
  593. break;
  594. }
  595. case KS_Alt_L: {
  596. if (input->shiftheldstate[2]) break;
  597. input->shiftstate[1]++;
  598. input->shiftheldstate[2] = 1;
  599. break;
  600. }
  601. case KS_Alt_R: {
  602. if (input->shiftheldstate[3]) break;
  603. input->shiftstate[1]++;
  604. input->shiftheldstate[3] = 1;
  605. break;
  606. }
  607. case KS_Control_L: {
  608. if (input->shiftheldstate[4]) break;
  609. input->shiftstate[2]++;
  610. input->shiftheldstate[4] = 1;
  611. break;
  612. }
  613. case KS_Control_R: {
  614. if (input->shiftheldstate[5]) break;
  615. input->shiftstate[2]++;
  616. input->shiftheldstate[5] = 1;
  617. break;
  618. }
  619. case KS_Mode_switch: {
  620. if (input->shiftheldstate[6]) break;
  621. input->shiftstate[3]++;
  622. input->shiftheldstate[6] = 1;
  623. break;
  624. }
  625. }
  626. }
  627. break;
  628. case WSCONS_EVENT_KEY_UP: {
  629. switch(input->keymap.map[events[i].value].group1[0]) {
  630. case KS_Hold_Screen: {
  631. if (input->lockheldstate[0]) input->lockheldstate[0] = 0;
  632. }
  633. break;
  634. case KS_Num_Lock: {
  635. if (input->lockheldstate[1]) input->lockheldstate[1] = 0;
  636. }
  637. break;
  638. case KS_Caps_Lock: {
  639. if (input->lockheldstate[2]) input->lockheldstate[2] = 0;
  640. }
  641. break;
  642. #ifndef __NetBSD__
  643. case KS_Mode_Lock: {
  644. if (input->lockheldstate[3]) input->lockheldstate[3] = 0;
  645. }
  646. break;
  647. #endif
  648. case KS_Shift_Lock: {
  649. if (input->lockheldstate[4]) input->lockheldstate[4] = 0;
  650. }
  651. break;
  652. case KS_Shift_L: {
  653. input->shiftheldstate[0] = 0;
  654. if (input->shiftstate[0]) input->shiftstate[0]--;
  655. break;
  656. }
  657. case KS_Shift_R: {
  658. input->shiftheldstate[1] = 0;
  659. if (input->shiftstate[0]) input->shiftstate[0]--;
  660. break;
  661. }
  662. case KS_Alt_L: {
  663. input->shiftheldstate[2] = 0;
  664. if (input->shiftstate[1]) input->shiftstate[1]--;
  665. break;
  666. }
  667. case KS_Alt_R: {
  668. input->shiftheldstate[3] = 0;
  669. if (input->shiftstate[1]) input->shiftstate[1]--;
  670. break;
  671. }
  672. case KS_Control_L: {
  673. input->shiftheldstate[4] = 0;
  674. if (input->shiftstate[2]) input->shiftstate[2]--;
  675. break;
  676. }
  677. case KS_Control_R: {
  678. input->shiftheldstate[5] = 0;
  679. if (input->shiftstate[2]) input->shiftstate[2]--;
  680. break;
  681. }
  682. case KS_Mode_switch: {
  683. input->shiftheldstate[6] = 0;
  684. if (input->shiftstate[3]) input->shiftstate[3]--;
  685. break;
  686. }
  687. }
  688. }
  689. break;
  690. case WSCONS_EVENT_ALL_KEYS_UP:
  691. for (i = 0; i < SDL_NUM_SCANCODES; i++) {
  692. SDL_SendKeyboardKey(SDL_RELEASED, i);
  693. }
  694. break;
  695. }
  696. Translate_to_keycode(input, type, events[i].value);
  697. if (type == WSCONS_EVENT_KEY_UP) continue;
  698. if (IS_ALTGR_MODE && !IS_CONTROL_HELD)
  699. group = &input->keymap.map[events[i].value].group2[0];
  700. else
  701. group = &input->keymap.map[events[i].value].group1[0];
  702. if (IS_NUMLOCK_ON && KS_GROUP(group[1]) == KS_GROUP_Keypad) {
  703. gindex = !IS_SHIFT_HELD;
  704. ksym = group[gindex];
  705. } else {
  706. if (IS_CAPSLOCK_ON && !IS_SHIFT_HELD) {
  707. gindex = 0;
  708. ksym = ksym_upcase(group[0]);
  709. } else {
  710. gindex = IS_SHIFT_HELD;
  711. ksym = group[gindex];
  712. }
  713. }
  714. result = KS_voidSymbol;
  715. switch (KS_GROUP(ksym)) {
  716. case KS_GROUP_Ascii:
  717. case KS_GROUP_Keypad:
  718. case KS_GROUP_Function:
  719. result = ksym;
  720. break;
  721. case KS_GROUP_Mod:
  722. if (ksym == KS_Multi_key) {
  723. input->ledstate |= WSKBD_LED_COMPOSE;
  724. ioctl(input->fd,WSKBDIO_SETLEDS, &input->ledstate);
  725. input->composelen = 2;
  726. input->composebuffer[0] = input->composebuffer[1] = 0;
  727. }
  728. break;
  729. case KS_GROUP_Dead:
  730. if (input->composelen == 0) {
  731. input->ledstate |= WSKBD_LED_COMPOSE;
  732. ioctl(input->fd,WSKBDIO_SETLEDS, &input->ledstate);
  733. input->composelen = 1;
  734. input->composebuffer[0] = ksym;
  735. input->composebuffer[1] = 0;
  736. } else result = ksym;
  737. break;
  738. }
  739. if (result == KS_voidSymbol) continue;
  740. if (input->composelen > 0) {
  741. if (input->composelen == 2 && group == &input->keymap.map[events[i].value].group2[0]) {
  742. if (input->keymap.map[events[i].value].group2[gindex] == input->keymap.map[events[i].value].group1[gindex]) {
  743. input->composelen = 0;
  744. input->composebuffer[0] = input->composebuffer[1] = 0;
  745. }
  746. }
  747. if (input->composelen != 0) {
  748. input->composebuffer[2 - input->composelen] = result;
  749. if (--input->composelen == 0) {
  750. result = KS_voidSymbol;
  751. input->ledstate &= ~WSKBD_LED_COMPOSE;
  752. ioctl(input->fd,WSKBDIO_SETLEDS, &input->ledstate);
  753. for (acc_i = 0; acc_i < SDL_arraysize(compose_tab); acc_i++) {
  754. if ((compose_tab[acc_i].elem[0] == input->composebuffer[0]
  755. && compose_tab[acc_i].elem[1] == input->composebuffer[1])
  756. || (compose_tab[acc_i].elem[0] == input->composebuffer[1]
  757. && compose_tab[acc_i].elem[1] == input->composebuffer[0])) {
  758. result = compose_tab[acc_i].result;
  759. break;
  760. }
  761. }
  762. } else continue;
  763. }
  764. }
  765. if (KS_GROUP(result) == KS_GROUP_Ascii) {
  766. if (IS_CONTROL_HELD) {
  767. if ((result >= KS_at && result <= KS_z) || result == KS_space)
  768. result = result & 0x1f;
  769. else if (result == KS_2)
  770. result = 0x00;
  771. else if (result >= KS_3 && result <= KS_7)
  772. result = KS_Escape + (result - KS_3);
  773. else if (result == KS_8)
  774. result = KS_Delete;
  775. }
  776. if (IS_ALT_HELD) {
  777. if (input->encoding & KB_METAESC) {
  778. Translate_to_keycode(input, WSCONS_EVENT_KEY_DOWN, KS_Escape);
  779. Translate_to_text(input, result);
  780. continue;
  781. } else result |= 0x80;
  782. }
  783. }
  784. Translate_to_text(input,result);
  785. continue;
  786. }
  787. }
  788. }
  789. void SDL_WSCONS_PumpEvents()
  790. {
  791. int i = 0;
  792. for (i = 0; i < 4; i++)
  793. updateKeyboard(inputs[i]);
  794. if (mouseInputData != NULL) updateMouse(mouseInputData);
  795. }