1706f2543Smrg/* 2706f2543Smrg * Copyright � 1999 Keith Packard 3706f2543Smrg * XKB integration � 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com> 4706f2543Smrg * 5706f2543Smrg * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c: 6706f2543Smrg * Copyright � 1990,91 by Thomas Roell, Dinkelscherben, Germany. 7706f2543Smrg * Copyright � 1994-2001 by The XFree86 Project, Inc. 8706f2543Smrg * 9706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 10706f2543Smrg * copy of this software and associated documentation files (the "Software"), 11706f2543Smrg * to deal in the Software without restriction, including without limitation 12706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 14706f2543Smrg * Software is furnished to do so, subject to the following conditions: 15706f2543Smrg * 16706f2543Smrg * The above copyright notice and this permission notice shall be included in 17706f2543Smrg * all copies or substantial portions of the Software. 18706f2543Smrg * 19706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 26706f2543Smrg * 27706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 28706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 29706f2543Smrg * the sale, use or other dealings in this Software without prior written 30706f2543Smrg * authorization from the copyright holder(s) and author(s). 31706f2543Smrg */ 32706f2543Smrg 33706f2543Smrg#ifdef HAVE_CONFIG_H 34706f2543Smrg#include <kdrive-config.h> 35706f2543Smrg#endif 36706f2543Smrg#include "kdrive.h" 37706f2543Smrg#include <linux/keyboard.h> 38706f2543Smrg#include <linux/kd.h> 39706f2543Smrg#define XK_PUBLISHING 40706f2543Smrg#include <X11/keysym.h> 41706f2543Smrg#include <termios.h> 42706f2543Smrg#include <sys/ioctl.h> 43706f2543Smrg 44706f2543Smrgextern int LinuxConsoleFd; 45706f2543Smrg 46706f2543Smrgstatic const KeySym linux_to_x[256] = { 47706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 48706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 49706f2543Smrg XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, 50706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 51706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 52706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 53706f2543Smrg NoSymbol, NoSymbol, NoSymbol, XK_Escape, 54706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 55706f2543Smrg XK_space, XK_exclam, XK_quotedbl, XK_numbersign, 56706f2543Smrg XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, 57706f2543Smrg XK_parenleft, XK_parenright, XK_asterisk, XK_plus, 58706f2543Smrg XK_comma, XK_minus, XK_period, XK_slash, 59706f2543Smrg XK_0, XK_1, XK_2, XK_3, 60706f2543Smrg XK_4, XK_5, XK_6, XK_7, 61706f2543Smrg XK_8, XK_9, XK_colon, XK_semicolon, 62706f2543Smrg XK_less, XK_equal, XK_greater, XK_question, 63706f2543Smrg XK_at, XK_A, XK_B, XK_C, 64706f2543Smrg XK_D, XK_E, XK_F, XK_G, 65706f2543Smrg XK_H, XK_I, XK_J, XK_K, 66706f2543Smrg XK_L, XK_M, XK_N, XK_O, 67706f2543Smrg XK_P, XK_Q, XK_R, XK_S, 68706f2543Smrg XK_T, XK_U, XK_V, XK_W, 69706f2543Smrg XK_X, XK_Y, XK_Z, XK_bracketleft, 70706f2543Smrg XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, 71706f2543Smrg XK_grave, XK_a, XK_b, XK_c, 72706f2543Smrg XK_d, XK_e, XK_f, XK_g, 73706f2543Smrg XK_h, XK_i, XK_j, XK_k, 74706f2543Smrg XK_l, XK_m, XK_n, XK_o, 75706f2543Smrg XK_p, XK_q, XK_r, XK_s, 76706f2543Smrg XK_t, XK_u, XK_v, XK_w, 77706f2543Smrg XK_x, XK_y, XK_z, XK_braceleft, 78706f2543Smrg XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, 79706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 80706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 81706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 82706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 83706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 84706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 85706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 86706f2543Smrg NoSymbol, NoSymbol, NoSymbol, NoSymbol, 87706f2543Smrg XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, 88706f2543Smrg XK_currency, XK_yen, XK_brokenbar, XK_section, 89706f2543Smrg XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, 90706f2543Smrg XK_notsign, XK_hyphen, XK_registered, XK_macron, 91706f2543Smrg XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, 92706f2543Smrg XK_acute, XK_mu, XK_paragraph, XK_periodcentered, 93706f2543Smrg XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, 94706f2543Smrg XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, 95706f2543Smrg XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, 96706f2543Smrg XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, 97706f2543Smrg XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, 98706f2543Smrg XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, 99706f2543Smrg XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, 100706f2543Smrg XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, 101706f2543Smrg XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, 102706f2543Smrg XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, 103706f2543Smrg XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, 104706f2543Smrg XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, 105706f2543Smrg XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, 106706f2543Smrg XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, 107706f2543Smrg XK_eth, XK_ntilde, XK_ograve, XK_oacute, 108706f2543Smrg XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, 109706f2543Smrg XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, 110706f2543Smrg XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis 111706f2543Smrg}; 112706f2543Smrg 113706f2543Smrg/* 114706f2543Smrg * Getting a keycode from scancode 115706f2543Smrg * 116706f2543Smrg * With XKB 117706f2543Smrg * -------- 118706f2543Smrg * 119706f2543Smrg * We have to enqueue keyboard events using standard X keycodes which correspond 120706f2543Smrg * to AT scancode + 8; this means that we need to translate the Linux scancode 121706f2543Smrg * provided by the kernel to an AT scancode -- this translation is not linear 122706f2543Smrg * and requires that we use a LUT. 123706f2543Smrg * 124706f2543Smrg * 125706f2543Smrg * Without XKB 126706f2543Smrg * ----------- 127706f2543Smrg * 128706f2543Smrg * We can use custom keycodes, which makes things simpler; we define our custom 129706f2543Smrg * keycodes as Linux scancodes + KD_KEY_OFFSET 130706f2543Smrg*/ 131706f2543Smrg 132706f2543Smrg/* 133706f2543Smrg This LUT translates AT scancodes into Linux ones -- the keymap we create 134706f2543Smrg for the core X keyboard protocol has to be AT-scancode based so that it 135706f2543Smrg corresponds to the Xkb keymap. 136706f2543Smrg*/ 137706f2543Smrg#if 0 138706f2543Smrgstatic unsigned char at2lnx[] = 139706f2543Smrg{ 140706f2543Smrg 0x0, /* no valid scancode */ 141706f2543Smrg 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ 142706f2543Smrg 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ 143706f2543Smrg 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ 144706f2543Smrg 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ 145706f2543Smrg 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ 146706f2543Smrg 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ 147706f2543Smrg 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ 148706f2543Smrg 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ 149706f2543Smrg 0x11, /* KEY_W */ 0x12, /* KEY_E */ 150706f2543Smrg 0x13, /* KEY_R */ 0x14, /* KEY_T */ 151706f2543Smrg 0x15, /* KEY_Y */ 0x16, /* KEY_U */ 152706f2543Smrg 0x17, /* KEY_I */ 0x18, /* KEY_O */ 153706f2543Smrg 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ 154706f2543Smrg 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ 155706f2543Smrg 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ 156706f2543Smrg 0x1f, /* KEY_S */ 0x20, /* KEY_D */ 157706f2543Smrg 0x21, /* KEY_F */ 0x22, /* KEY_G */ 158706f2543Smrg 0x23, /* KEY_H */ 0x24, /* KEY_J */ 159706f2543Smrg 0x25, /* KEY_K */ 0x26, /* KEY_L */ 160706f2543Smrg 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ 161706f2543Smrg 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ 162706f2543Smrg 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ 163706f2543Smrg 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ 164706f2543Smrg 0x2f, /* KEY_V */ 0x30, /* KEY_B */ 165706f2543Smrg 0x31, /* KEY_N */ 0x32, /* KEY_M */ 166706f2543Smrg 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ 167706f2543Smrg 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ 168706f2543Smrg 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ 169706f2543Smrg 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ 170706f2543Smrg 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ 171706f2543Smrg 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ 172706f2543Smrg 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ 173706f2543Smrg 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ 174706f2543Smrg 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ 175706f2543Smrg 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ 176706f2543Smrg 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ 177706f2543Smrg 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ 178706f2543Smrg 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ 179706f2543Smrg 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ 180706f2543Smrg 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ 181706f2543Smrg 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ 182706f2543Smrg 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ 183706f2543Smrg 0x00, /* 0x55 */ 0x56, /* KEY_Less */ 184706f2543Smrg 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ 185706f2543Smrg 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ 186706f2543Smrg 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ 187706f2543Smrg 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ 188706f2543Smrg 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ 189706f2543Smrg 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ 190706f2543Smrg 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ 191706f2543Smrg 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ 192706f2543Smrg 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ 193706f2543Smrg 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ 194706f2543Smrg 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ 195706f2543Smrg 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ 196706f2543Smrg 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ 197706f2543Smrg 0x00, /* 0x71 */ 0x00, /* 0x72 */ 198706f2543Smrg 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ 199706f2543Smrg 0x00, /* 0x75 */ 0x00, /* 0x76 */ 200706f2543Smrg 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ 201706f2543Smrg 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ 202706f2543Smrg 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ 203706f2543Smrg 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ 204706f2543Smrg 0x00, /* 0x7f */ 205706f2543Smrg}; 206706f2543Smrg 207706f2543Smrg#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0])) 208706f2543Smrg#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0 209706f2543Smrg 210706f2543Smrgstatic unsigned char tbl[KD_MAX_WIDTH] = 211706f2543Smrg{ 212706f2543Smrg 0, 213706f2543Smrg 1 << KG_SHIFT, 214706f2543Smrg (1 << KG_ALTGR), 215706f2543Smrg (1 << KG_ALTGR) | (1 << KG_SHIFT) 216706f2543Smrg}; 217706f2543Smrg#endif 218706f2543Smrg 219706f2543Smrgstatic void 220706f2543SmrgreadKernelMapping(KdKeyboardInfo *ki) 221706f2543Smrg{ 222706f2543Smrg#if 0 223706f2543Smrg KeySym *k; 224706f2543Smrg int i, j; 225706f2543Smrg struct kbentry kbe; 226706f2543Smrg int minKeyCode, maxKeyCode; 227706f2543Smrg int row; 228706f2543Smrg int fd; 229706f2543Smrg 230706f2543Smrg if (!ki) 231706f2543Smrg return; 232706f2543Smrg 233706f2543Smrg fd = LinuxConsoleFd; 234706f2543Smrg 235706f2543Smrg minKeyCode = NR_KEYS; 236706f2543Smrg maxKeyCode = 0; 237706f2543Smrg row = 0; 238706f2543Smrg ki->keySyms.mapWidth = KD_MAX_WIDTH; 239706f2543Smrg for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i) 240706f2543Smrg { 241706f2543Smrg kbe.kb_index = LNX_KEY_INDEX(i); 242706f2543Smrg 243706f2543Smrg k = ki->keySyms.map + row * ki->keySyms.mapWidth; 244706f2543Smrg 245706f2543Smrg for (j = 0; j < ki->keySyms.mapWidth; ++j) 246706f2543Smrg { 247706f2543Smrg unsigned short kval; 248706f2543Smrg 249706f2543Smrg k[j] = NoSymbol; 250706f2543Smrg 251706f2543Smrg kbe.kb_table = tbl[j]; 252706f2543Smrg kbe.kb_value = 0; 253706f2543Smrg if (ioctl(fd, KDGKBENT, &kbe)) 254706f2543Smrg continue; 255706f2543Smrg 256706f2543Smrg kval = KVAL(kbe.kb_value); 257706f2543Smrg switch (KTYP(kbe.kb_value)) 258706f2543Smrg { 259706f2543Smrg case KT_LATIN: 260706f2543Smrg case KT_LETTER: 261706f2543Smrg k[j] = linux_to_x[kval]; 262706f2543Smrg break; 263706f2543Smrg 264706f2543Smrg case KT_FN: 265706f2543Smrg if (kval <= 19) 266706f2543Smrg k[j] = XK_F1 + kval; 267706f2543Smrg else switch (kbe.kb_value) 268706f2543Smrg { 269706f2543Smrg case K_FIND: 270706f2543Smrg k[j] = XK_Home; /* or XK_Find */ 271706f2543Smrg break; 272706f2543Smrg case K_INSERT: 273706f2543Smrg k[j] = XK_Insert; 274706f2543Smrg break; 275706f2543Smrg case K_REMOVE: 276706f2543Smrg k[j] = XK_Delete; 277706f2543Smrg break; 278706f2543Smrg case K_SELECT: 279706f2543Smrg k[j] = XK_End; /* or XK_Select */ 280706f2543Smrg break; 281706f2543Smrg case K_PGUP: 282706f2543Smrg k[j] = XK_Prior; 283706f2543Smrg break; 284706f2543Smrg case K_PGDN: 285706f2543Smrg k[j] = XK_Next; 286706f2543Smrg break; 287706f2543Smrg case K_HELP: 288706f2543Smrg k[j] = XK_Help; 289706f2543Smrg break; 290706f2543Smrg case K_DO: 291706f2543Smrg k[j] = XK_Execute; 292706f2543Smrg break; 293706f2543Smrg case K_PAUSE: 294706f2543Smrg k[j] = XK_Pause; 295706f2543Smrg break; 296706f2543Smrg case K_MACRO: 297706f2543Smrg k[j] = XK_Menu; 298706f2543Smrg break; 299706f2543Smrg default: 300706f2543Smrg break; 301706f2543Smrg } 302706f2543Smrg break; 303706f2543Smrg 304706f2543Smrg case KT_SPEC: 305706f2543Smrg switch (kbe.kb_value) 306706f2543Smrg { 307706f2543Smrg case K_ENTER: 308706f2543Smrg k[j] = XK_Return; 309706f2543Smrg break; 310706f2543Smrg case K_BREAK: 311706f2543Smrg k[j] = XK_Break; 312706f2543Smrg break; 313706f2543Smrg case K_CAPS: 314706f2543Smrg k[j] = XK_Caps_Lock; 315706f2543Smrg break; 316706f2543Smrg case K_NUM: 317706f2543Smrg k[j] = XK_Num_Lock; 318706f2543Smrg break; 319706f2543Smrg case K_HOLD: 320706f2543Smrg k[j] = XK_Scroll_Lock; 321706f2543Smrg break; 322706f2543Smrg case K_COMPOSE: 323706f2543Smrg k[j] = XK_Multi_key; 324706f2543Smrg break; 325706f2543Smrg default: 326706f2543Smrg break; 327706f2543Smrg } 328706f2543Smrg break; 329706f2543Smrg 330706f2543Smrg case KT_PAD: 331706f2543Smrg switch (kbe.kb_value) 332706f2543Smrg { 333706f2543Smrg case K_PPLUS: 334706f2543Smrg k[j] = XK_KP_Add; 335706f2543Smrg break; 336706f2543Smrg case K_PMINUS: 337706f2543Smrg k[j] = XK_KP_Subtract; 338706f2543Smrg break; 339706f2543Smrg case K_PSTAR: 340706f2543Smrg k[j] = XK_KP_Multiply; 341706f2543Smrg break; 342706f2543Smrg case K_PSLASH: 343706f2543Smrg k[j] = XK_KP_Divide; 344706f2543Smrg break; 345706f2543Smrg case K_PENTER: 346706f2543Smrg k[j] = XK_KP_Enter; 347706f2543Smrg break; 348706f2543Smrg case K_PCOMMA: 349706f2543Smrg k[j] = XK_KP_Separator; 350706f2543Smrg break; 351706f2543Smrg case K_PDOT: 352706f2543Smrg k[j] = XK_KP_Decimal; 353706f2543Smrg break; 354706f2543Smrg case K_PPLUSMINUS: 355706f2543Smrg k[j] = XK_KP_Subtract; 356706f2543Smrg break; 357706f2543Smrg default: 358706f2543Smrg if (kval <= 9) 359706f2543Smrg k[j] = XK_KP_0 + kval; 360706f2543Smrg break; 361706f2543Smrg } 362706f2543Smrg break; 363706f2543Smrg 364706f2543Smrg /* 365706f2543Smrg * KT_DEAD keys are for accelerated diacritical creation. 366706f2543Smrg */ 367706f2543Smrg case KT_DEAD: 368706f2543Smrg switch (kbe.kb_value) 369706f2543Smrg { 370706f2543Smrg case K_DGRAVE: 371706f2543Smrg k[j] = XK_dead_grave; 372706f2543Smrg break; 373706f2543Smrg case K_DACUTE: 374706f2543Smrg k[j] = XK_dead_acute; 375706f2543Smrg break; 376706f2543Smrg case K_DCIRCM: 377706f2543Smrg k[j] = XK_dead_circumflex; 378706f2543Smrg break; 379706f2543Smrg case K_DTILDE: 380706f2543Smrg k[j] = XK_dead_tilde; 381706f2543Smrg break; 382706f2543Smrg case K_DDIERE: 383706f2543Smrg k[j] = XK_dead_diaeresis; 384706f2543Smrg break; 385706f2543Smrg } 386706f2543Smrg break; 387706f2543Smrg 388706f2543Smrg case KT_CUR: 389706f2543Smrg switch (kbe.kb_value) 390706f2543Smrg { 391706f2543Smrg case K_DOWN: 392706f2543Smrg k[j] = XK_Down; 393706f2543Smrg break; 394706f2543Smrg case K_LEFT: 395706f2543Smrg k[j] = XK_Left; 396706f2543Smrg break; 397706f2543Smrg case K_RIGHT: 398706f2543Smrg k[j] = XK_Right; 399706f2543Smrg break; 400706f2543Smrg case K_UP: 401706f2543Smrg k[j] = XK_Up; 402706f2543Smrg break; 403706f2543Smrg } 404706f2543Smrg break; 405706f2543Smrg 406706f2543Smrg case KT_SHIFT: 407706f2543Smrg switch (kbe.kb_value) 408706f2543Smrg { 409706f2543Smrg case K_ALTGR: 410706f2543Smrg k[j] = XK_Mode_switch; 411706f2543Smrg break; 412706f2543Smrg case K_ALT: 413706f2543Smrg k[j] = (kbe.kb_index == 0x64 ? 414706f2543Smrg XK_Alt_R : XK_Alt_L); 415706f2543Smrg break; 416706f2543Smrg case K_CTRL: 417706f2543Smrg k[j] = (kbe.kb_index == 0x61 ? 418706f2543Smrg XK_Control_R : XK_Control_L); 419706f2543Smrg break; 420706f2543Smrg case K_CTRLL: 421706f2543Smrg k[j] = XK_Control_L; 422706f2543Smrg break; 423706f2543Smrg case K_CTRLR: 424706f2543Smrg k[j] = XK_Control_R; 425706f2543Smrg break; 426706f2543Smrg case K_SHIFT: 427706f2543Smrg k[j] = (kbe.kb_index == 0x36 ? 428706f2543Smrg XK_Shift_R : XK_Shift_L); 429706f2543Smrg break; 430706f2543Smrg case K_SHIFTL: 431706f2543Smrg k[j] = XK_Shift_L; 432706f2543Smrg break; 433706f2543Smrg case K_SHIFTR: 434706f2543Smrg k[j] = XK_Shift_R; 435706f2543Smrg break; 436706f2543Smrg default: 437706f2543Smrg break; 438706f2543Smrg } 439706f2543Smrg break; 440706f2543Smrg 441706f2543Smrg /* 442706f2543Smrg * KT_ASCII keys accumulate a 3 digit decimal number that gets 443706f2543Smrg * emitted when the shift state changes. We can't emulate that. 444706f2543Smrg */ 445706f2543Smrg case KT_ASCII: 446706f2543Smrg break; 447706f2543Smrg 448706f2543Smrg case KT_LOCK: 449706f2543Smrg if (kbe.kb_value == K_SHIFTLOCK) 450706f2543Smrg k[j] = XK_Shift_Lock; 451706f2543Smrg break; 452706f2543Smrg 453706f2543Smrg#ifdef KT_X 454706f2543Smrg case KT_X: 455706f2543Smrg /* depends on new keyboard symbols in file linux/keyboard.h */ 456706f2543Smrg if(kbe.kb_value == K_XMENU) k[j] = XK_Menu; 457706f2543Smrg if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone; 458706f2543Smrg break; 459706f2543Smrg#endif 460706f2543Smrg#ifdef KT_XF 461706f2543Smrg case KT_XF: 462706f2543Smrg /* special linux keysyms which map directly to XF86 keysyms */ 463706f2543Smrg k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00; 464706f2543Smrg break; 465706f2543Smrg#endif 466706f2543Smrg 467706f2543Smrg default: 468706f2543Smrg break; 469706f2543Smrg } 470706f2543Smrg if (i < minKeyCode) 471706f2543Smrg minKeyCode = i; 472706f2543Smrg if (i > maxKeyCode) 473706f2543Smrg maxKeyCode = i; 474706f2543Smrg } 475706f2543Smrg 476706f2543Smrg if (minKeyCode == NR_KEYS) 477706f2543Smrg continue; 478706f2543Smrg 479706f2543Smrg if (k[3] == k[2]) k[3] = NoSymbol; 480706f2543Smrg if (k[2] == k[1]) k[2] = NoSymbol; 481706f2543Smrg if (k[1] == k[0]) k[1] = NoSymbol; 482706f2543Smrg if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; 483706f2543Smrg if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol; 484706f2543Smrg row++; 485706f2543Smrg } 486706f2543Smrg ki->minScanCode = minKeyCode; 487706f2543Smrg ki->maxScanCode = maxKeyCode; 488706f2543Smrg#endif 489706f2543Smrg} 490706f2543Smrg 491706f2543Smrg/* 492706f2543Smrg * We need these to handle extended scancodes correctly (I could just use the 493706f2543Smrg * numbers below, but this makes the code more readable 494706f2543Smrg */ 495706f2543Smrg 496706f2543Smrg/* The prefix codes */ 497706f2543Smrg#define KEY_Prefix0 /* special 0x60 */ 96 498706f2543Smrg#define KEY_Prefix1 /* special 0x61 */ 97 499706f2543Smrg 500706f2543Smrg/* The raw scancodes */ 501706f2543Smrg#define KEY_Enter /* Enter 0x1c */ 28 502706f2543Smrg#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29 503706f2543Smrg#define KEY_Slash /* / (Slash) ? 0x35 */ 53 504706f2543Smrg#define KEY_KP_Multiply /* * 0x37 */ 55 505706f2543Smrg#define KEY_Alt /* Alt(left) 0x38 */ 56 506706f2543Smrg#define KEY_F3 /* F3 0x3d */ 61 507706f2543Smrg#define KEY_F4 /* F4 0x3e */ 62 508706f2543Smrg#define KEY_F5 /* F5 0x3f */ 63 509706f2543Smrg#define KEY_F6 /* F6 0x40 */ 64 510706f2543Smrg#define KEY_F7 /* F7 0x41 */ 65 511706f2543Smrg#define KEY_ScrollLock /* ScrollLock 0x46 */ 70 512706f2543Smrg#define KEY_KP_7 /* 7 Home 0x47 */ 71 513706f2543Smrg#define KEY_KP_8 /* 8 Up 0x48 */ 72 514706f2543Smrg#define KEY_KP_9 /* 9 PgUp 0x49 */ 73 515706f2543Smrg#define KEY_KP_Minus /* - (Minus) 0x4a */ 74 516706f2543Smrg#define KEY_KP_4 /* 4 Left 0x4b */ 75 517706f2543Smrg#define KEY_KP_5 /* 5 0x4c */ 76 518706f2543Smrg#define KEY_KP_6 /* 6 Right 0x4d */ 77 519706f2543Smrg#define KEY_KP_Plus /* + (Plus) 0x4e */ 78 520706f2543Smrg#define KEY_KP_1 /* 1 End 0x4f */ 79 521706f2543Smrg#define KEY_KP_2 /* 2 Down 0x50 */ 80 522706f2543Smrg#define KEY_KP_3 /* 3 PgDown 0x51 */ 81 523706f2543Smrg#define KEY_KP_0 /* 0 Insert 0x52 */ 82 524706f2543Smrg#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83 525706f2543Smrg#define KEY_Home /* Home 0x59 */ 89 526706f2543Smrg#define KEY_Up /* Up 0x5a */ 90 527706f2543Smrg#define KEY_PgUp /* PgUp 0x5b */ 91 528706f2543Smrg#define KEY_Left /* Left 0x5c */ 92 529706f2543Smrg#define KEY_Begin /* Begin 0x5d */ 93 530706f2543Smrg#define KEY_Right /* Right 0x5e */ 94 531706f2543Smrg#define KEY_End /* End 0x5f */ 95 532706f2543Smrg#define KEY_Down /* Down 0x60 */ 96 533706f2543Smrg#define KEY_PgDown /* PgDown 0x61 */ 97 534706f2543Smrg#define KEY_Insert /* Insert 0x62 */ 98 535706f2543Smrg#define KEY_Delete /* Delete 0x63 */ 99 536706f2543Smrg#define KEY_KP_Enter /* Enter 0x64 */ 100 537706f2543Smrg#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101 538706f2543Smrg#define KEY_Pause /* Pause 0x66 */ 102 539706f2543Smrg#define KEY_Print /* Print 0x67 */ 103 540706f2543Smrg#define KEY_KP_Divide /* Divide 0x68 */ 104 541706f2543Smrg#define KEY_AltLang /* AtlLang(right) 0x69 */ 105 542706f2543Smrg#define KEY_Break /* Break 0x6a */ 106 543706f2543Smrg#define KEY_LMeta /* Left Meta 0x6b */ 107 544706f2543Smrg#define KEY_RMeta /* Right Meta 0x6c */ 108 545706f2543Smrg#define KEY_Menu /* Menu 0x6d */ 109 546706f2543Smrg#define KEY_F13 /* F13 0x6e */ 110 547706f2543Smrg#define KEY_F14 /* F14 0x6f */ 111 548706f2543Smrg#define KEY_F15 /* F15 0x70 */ 112 549706f2543Smrg#define KEY_F16 /* F16 0x71 */ 113 550706f2543Smrg#define KEY_F17 /* F17 0x72 */ 114 551706f2543Smrg#define KEY_KP_DEC /* KP_DEC 0x73 */ 115 552706f2543Smrg 553706f2543Smrgstatic void 554706f2543SmrgLinuxKeyboardRead (int fd, void *closure) 555706f2543Smrg{ 556706f2543Smrg unsigned char buf[256], *b; 557706f2543Smrg int n; 558706f2543Smrg unsigned char prefix = 0, scancode = 0; 559706f2543Smrg 560706f2543Smrg while ((n = read (fd, buf, sizeof (buf))) > 0) { 561706f2543Smrg b = buf; 562706f2543Smrg while (n--) { 563706f2543Smrg /* 564706f2543Smrg * With xkb we use RAW mode for reading the console, which allows us 565706f2543Smrg * process extended scancodes. 566706f2543Smrg * 567706f2543Smrg * See if this is a prefix extending the following keycode 568706f2543Smrg */ 569706f2543Smrg if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0)) 570706f2543Smrg { 571706f2543Smrg prefix = KEY_Prefix0; 572706f2543Smrg /* swallow this up */ 573706f2543Smrg b++; 574706f2543Smrg continue; 575706f2543Smrg } 576706f2543Smrg else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1)) 577706f2543Smrg { 578706f2543Smrg prefix = KEY_Prefix1; 579706f2543Smrg /* swallow this up */ 580706f2543Smrg b++; 581706f2543Smrg continue; 582706f2543Smrg } 583706f2543Smrg scancode = b[0] & 0x7f; 584706f2543Smrg 585706f2543Smrg switch (prefix) { 586706f2543Smrg /* from xf86Events.c */ 587706f2543Smrg case KEY_Prefix0: 588706f2543Smrg { 589706f2543Smrg switch (scancode) { 590706f2543Smrg case KEY_KP_7: 591706f2543Smrg scancode = KEY_Home; break; /* curs home */ 592706f2543Smrg case KEY_KP_8: 593706f2543Smrg scancode = KEY_Up; break; /* curs up */ 594706f2543Smrg case KEY_KP_9: 595706f2543Smrg scancode = KEY_PgUp; break; /* curs pgup */ 596706f2543Smrg case KEY_KP_4: 597706f2543Smrg scancode = KEY_Left; break; /* curs left */ 598706f2543Smrg case KEY_KP_5: 599706f2543Smrg scancode = KEY_Begin; break; /* curs begin */ 600706f2543Smrg case KEY_KP_6: 601706f2543Smrg scancode = KEY_Right; break; /* curs right */ 602706f2543Smrg case KEY_KP_1: 603706f2543Smrg scancode = KEY_End; break; /* curs end */ 604706f2543Smrg case KEY_KP_2: 605706f2543Smrg scancode = KEY_Down; break; /* curs down */ 606706f2543Smrg case KEY_KP_3: 607706f2543Smrg scancode = KEY_PgDown; break; /* curs pgdown */ 608706f2543Smrg case KEY_KP_0: 609706f2543Smrg scancode = KEY_Insert; break; /* curs insert */ 610706f2543Smrg case KEY_KP_Decimal: 611706f2543Smrg scancode = KEY_Delete; break; /* curs delete */ 612706f2543Smrg case KEY_Enter: 613706f2543Smrg scancode = KEY_KP_Enter; break; /* keypad enter */ 614706f2543Smrg case KEY_LCtrl: 615706f2543Smrg scancode = KEY_RCtrl; break; /* right ctrl */ 616706f2543Smrg case KEY_KP_Multiply: 617706f2543Smrg scancode = KEY_Print; break; /* print */ 618706f2543Smrg case KEY_Slash: 619706f2543Smrg scancode = KEY_KP_Divide; break; /* keyp divide */ 620706f2543Smrg case KEY_Alt: 621706f2543Smrg scancode = KEY_AltLang; break; /* right alt */ 622706f2543Smrg case KEY_ScrollLock: 623706f2543Smrg scancode = KEY_Break; break; /* curs break */ 624706f2543Smrg case 0x5b: 625706f2543Smrg scancode = KEY_LMeta; break; 626706f2543Smrg case 0x5c: 627706f2543Smrg scancode = KEY_RMeta; break; 628706f2543Smrg case 0x5d: 629706f2543Smrg scancode = KEY_Menu; break; 630706f2543Smrg case KEY_F3: 631706f2543Smrg scancode = KEY_F13; break; 632706f2543Smrg case KEY_F4: 633706f2543Smrg scancode = KEY_F14; break; 634706f2543Smrg case KEY_F5: 635706f2543Smrg scancode = KEY_F15; break; 636706f2543Smrg case KEY_F6: 637706f2543Smrg scancode = KEY_F16; break; 638706f2543Smrg case KEY_F7: 639706f2543Smrg scancode = KEY_F17; break; 640706f2543Smrg case KEY_KP_Plus: 641706f2543Smrg scancode = KEY_KP_DEC; break; 642706f2543Smrg /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */ 643706f2543Smrg case 0x2A: 644706f2543Smrg case 0x36: 645706f2543Smrg b++; 646706f2543Smrg prefix = 0; 647706f2543Smrg continue; 648706f2543Smrg default: 649706f2543Smrg /* 650706f2543Smrg * "Internet" keyboards are generating lots of new 651706f2543Smrg * codes. Let them pass. There is little consistency 652706f2543Smrg * between them, so don't bother with symbolic names at 653706f2543Smrg * this level. 654706f2543Smrg */ 655706f2543Smrg scancode += 0x78; 656706f2543Smrg } 657706f2543Smrg break; 658706f2543Smrg } 659706f2543Smrg 660706f2543Smrg case KEY_Prefix1: 661706f2543Smrg { 662706f2543Smrg /* we do no handle these */ 663706f2543Smrg b++; 664706f2543Smrg prefix = 0; 665706f2543Smrg continue; 666706f2543Smrg } 667706f2543Smrg 668706f2543Smrg default: /* should not happen*/ 669706f2543Smrg case 0: /* do nothing */ 670706f2543Smrg ; 671706f2543Smrg } 672706f2543Smrg 673706f2543Smrg prefix = 0; 674706f2543Smrg KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80); 675706f2543Smrg b++; 676706f2543Smrg } 677706f2543Smrg } 678706f2543Smrg} 679706f2543Smrg 680706f2543Smrgstatic int LinuxKbdTrans; 681706f2543Smrgstatic struct termios LinuxTermios; 682706f2543Smrg 683706f2543Smrgstatic Status 684706f2543SmrgLinuxKeyboardEnable (KdKeyboardInfo *ki) 685706f2543Smrg{ 686706f2543Smrg struct termios nTty; 687706f2543Smrg unsigned char buf[256]; 688706f2543Smrg int n; 689706f2543Smrg int fd; 690706f2543Smrg 691706f2543Smrg if (!ki) 692706f2543Smrg return !Success; 693706f2543Smrg 694706f2543Smrg fd = LinuxConsoleFd; 695706f2543Smrg ki->driverPrivate = (void *) (intptr_t) fd; 696706f2543Smrg 697706f2543Smrg ioctl (fd, KDGKBMODE, &LinuxKbdTrans); 698706f2543Smrg tcgetattr (fd, &LinuxTermios); 699706f2543Smrg ioctl(fd, KDSKBMODE, K_RAW); 700706f2543Smrg nTty = LinuxTermios; 701706f2543Smrg nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); 702706f2543Smrg nTty.c_oflag = 0; 703706f2543Smrg nTty.c_cflag = CREAD | CS8; 704706f2543Smrg nTty.c_lflag = 0; 705706f2543Smrg nTty.c_cc[VTIME]=0; 706706f2543Smrg nTty.c_cc[VMIN]=1; 707706f2543Smrg cfsetispeed(&nTty, 9600); 708706f2543Smrg cfsetospeed(&nTty, 9600); 709706f2543Smrg tcsetattr(fd, TCSANOW, &nTty); 710706f2543Smrg /* 711706f2543Smrg * Flush any pending keystrokes 712706f2543Smrg */ 713706f2543Smrg while ((n = read (fd, buf, sizeof (buf))) > 0) 714706f2543Smrg ; 715706f2543Smrg KdRegisterFd (fd, LinuxKeyboardRead, ki); 716706f2543Smrg return Success; 717706f2543Smrg} 718706f2543Smrg 719706f2543Smrgstatic void 720706f2543SmrgLinuxKeyboardDisable (KdKeyboardInfo *ki) 721706f2543Smrg{ 722706f2543Smrg int fd; 723706f2543Smrg 724706f2543Smrg if (!ki) 725706f2543Smrg return; 726706f2543Smrg 727706f2543Smrg fd = (int) (intptr_t) ki->driverPrivate; 728706f2543Smrg 729706f2543Smrg KdUnregisterFd(ki, fd, FALSE); 730706f2543Smrg ioctl(fd, KDSKBMODE, LinuxKbdTrans); 731706f2543Smrg tcsetattr(fd, TCSANOW, &LinuxTermios); 732706f2543Smrg} 733706f2543Smrg 734706f2543Smrgstatic Status 735706f2543SmrgLinuxKeyboardInit (KdKeyboardInfo *ki) 736706f2543Smrg{ 737706f2543Smrg if (!ki) 738706f2543Smrg return !Success; 739706f2543Smrg 740706f2543Smrg free(ki->path); 741706f2543Smrg ki->path = strdup("console"); 742706f2543Smrg free(ki->name); 743706f2543Smrg ki->name = strdup("Linux console keyboard"); 744706f2543Smrg 745706f2543Smrg readKernelMapping (ki); 746706f2543Smrg 747706f2543Smrg return Success; 748706f2543Smrg} 749706f2543Smrg 750706f2543Smrgstatic void 751706f2543SmrgLinuxKeyboardLeds (KdKeyboardInfo *ki, int leds) 752706f2543Smrg{ 753706f2543Smrg if (!ki) 754706f2543Smrg return; 755706f2543Smrg 756706f2543Smrg ioctl ((int)(intptr_t)ki->driverPrivate, KDSETLED, leds & 7); 757706f2543Smrg} 758706f2543Smrg 759706f2543SmrgKdKeyboardDriver LinuxKeyboardDriver = { 760706f2543Smrg "keyboard", 761706f2543Smrg .Init = LinuxKeyboardInit, 762706f2543Smrg .Enable = LinuxKeyboardEnable, 763706f2543Smrg .Leds = LinuxKeyboardLeds, 764706f2543Smrg .Disable = LinuxKeyboardDisable, 765706f2543Smrg}; 766