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