SDL_wscons_kbd.c 33 KB

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