/* maybe called when keymap is undefined, so that shiftkey release is seen */ static void compute_shiftstate(void) { int i, j, k, sym, val; shift_state = 0; for (i = 0; i < SIZE(k_down); i++) k_down[i] = 0; for (i = 0; i < SIZE(key_down); i++) if (key_down[i]) { /* skip this word if not a single bit on */ k = i * BITS_PER_LONG; for (j = 0; j < BITS_PER_LONG; j++, k++) if (test_bit(k, key_down)) { sym = plain_map[k]; if (KTYP(sym) == KT_SHIFT) { val = KVAL(sym); if (val == KVAL(K_CAPSSHIFT)) val = KVAL(K_SHIFT); k_down[val]++; shift_state |= (1 << val); } } } #ifdef DBG2 printf("compute shift_state=%ld\r\n", shift_state); #endif }
static void do_shift(unsigned char value, char up_flag) { int old_state = shift_state; if (rep) return; /* Mimic typewriter: a CapsShift key acts like Shift but undoes CapsLock */ if (value == KVAL(K_CAPSSHIFT)) { value = KVAL(K_SHIFT); if (!up_flag) clr_vc_kbd_led(kbd, VC_CAPSLOCK); } if (up_flag) { /* handle the case that two shift or control keys are depressed simultaneously */ if (k_down[value]) k_down[value]--; } else k_down[value]++; if (k_down[value]) shift_state |= (1 << value); else shift_state &= ~ (1 << value); /* kludge, no joke... */ if (up_flag && shift_state != old_state && npadch != -1) { put_queue(npadch & 0xff); npadch = -1; } }
/* * Fetch one entry from the kernel keymap. */ bool CLinuxInputDevice::GetKeymapEntry(KeymapEntry& entry) { int code = entry.code; unsigned short value; //DFBInputDeviceKeyIdentifier identifier; if (m_vt_fd < 0) return false; // to support '+' and '/' with Boxee's remote control we do something ugly like this for now if (KVAL(code) == 98) { code = K(KTYP(code),53); } /* fetch the base level */ value = KeyboardGetSymbol(KeyboardReadValue(K_NORMTAB, code)); //printf("base=%d typ=%d code %d\n", KVAL(value), KTYP(value), code); /* write base level symbol to entry */ entry.base = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_BASE); /* fetch the shifted base level */ value = KeyboardGetSymbol(KeyboardReadValue(K_SHIFTTAB, entry.code)); //printf("shift=%d\n", value); /* write shifted base level symbol to entry */ entry.shift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_SHIFT); // to support '+' and '/' with Boxee's remote control we could do ugly something like this for now if (KVAL(code) == 78) { //code = K(KTYP(code),13); //entry.code = K(KTYP(code),13); entry.base = K(KTYP(code),43); } /* fetch the alternative level */ value = KeyboardGetSymbol(KeyboardReadValue(K_ALTTAB, entry.code)); //printf("alt=%d\n", value); /* write alternative level symbol to entry */ entry.alt = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT); /* fetch the shifted alternative level */ value = KeyboardGetSymbol(KeyboardReadValue(K_ALTSHIFTTAB, entry.code)); //printf("altshift=%d\n", value); /* write shifted alternative level symbol to entry */ entry.altShift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT_SHIFT); return true; }
static int do_constant_key(struct lk_ctx *ctx, int i, unsigned short key) { int typ, val; unsigned int j; typ = KTYP(key); val = KVAL(key); if ((typ == KT_LATIN || typ == KT_LETTER) && ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'))) { unsigned short defs[16]; defs[0] = K(KT_LETTER, val); defs[1] = K(KT_LETTER, val ^ 32); defs[2] = defs[0]; defs[3] = defs[1]; for (j = 4; j < 8; j++) defs[j] = K(KT_LATIN, val & ~96); for (j = 8; j < 16; j++) defs[j] = K(KT_META, KVAL(defs[j - 8])); for (j = 0; j < ctx->keymap->total; j++) { if (!lk_map_exists(ctx, j)) continue; if (j > 0 && lk_key_exists(ctx, j, i)) continue; if (lk_add_key(ctx, j, i, defs[j % 16]) < 0) return -1; } } else { /* do this also for keys like Escape, as promised in the man page */ for (j = 1; j < ctx->keymap->total; j++) { if (!lk_map_exists(ctx, j)) continue; if (lk_key_exists(ctx, j, i)) continue; if (lk_add_key(ctx, j, i, key) < 0) return -1; } } return 0; }
static int print_keysym(int *key, int state, int *lockers, int socket) { static int modifier = 0; int code; int type; int value; code = key[modifier]; type = KTYP(code); value = KVAL(code); if (type >= syms_size) { code = code ^ 0xf000; if (code < 0) return dprintf(socket, "<(null)>"); if (code < 0x80) return dprintf(socket, "%s", iso646_syms[code]); return dprintf(socket, "[%#04x]", code); } if (type == KT_LETTER) type = KT_LATIN; if (type < syms_size && value < syms[type].size) { if (type == KT_SHIFT) return shift_handler(value, state, &modifier); if (type == KT_LOCK) return lock_handler(value, state, &modifier, lockers); if (state) return dprintf(socket, "%s", syms[type].table[value]); } if (type == KT_META && value < syms[0].size) return dprintf(socket, "<Meta_%s>", syms[0].table[value]); if (state) return dprintf(socket, "[%#04x]", code); return 1; }
static DFBInputDeviceKeyIdentifier keyboard_get_identifier( int code, unsigned short value ) { unsigned char type = KTYP(value); unsigned char index = KVAL(value); if (type == KT_PAD) { if (index <= 9) return DIKI_KP_0 + index; switch (value) { case K_PSLASH: return DIKI_KP_DIV; case K_PSTAR: return DIKI_KP_MULT; case K_PMINUS: return DIKI_KP_MINUS; case K_PPLUS: return DIKI_KP_PLUS; case K_PENTER: return DIKI_KP_ENTER; case K_PCOMMA: case K_PDOT: return DIKI_KP_DECIMAL; } } /* Looks like a hack, but don't know a better way yet. */ switch (code) { case 12: return DIKI_MINUS_SIGN; case 13: return DIKI_EQUALS_SIGN; case 26: return DIKI_BRACKET_LEFT; case 27: return DIKI_BRACKET_RIGHT; case 39: return DIKI_SEMICOLON; case 40: return DIKI_QUOTE_RIGHT; case 41: return DIKI_QUOTE_LEFT; case 43: return DIKI_BACKSLASH; case 51: return DIKI_COMMA; case 52: return DIKI_PERIOD; case 53: return DIKI_SLASH; case 54: return DIKI_SHIFT_R; case 97: return DIKI_CONTROL_R; case 100: return DIKI_ALT_R; default: ; } /* special keys not in the map, hack? */ if (code == 124) /* keypad equal key */ return DIKI_KP_EQUAL; if (code == 125) /* left windows key */ return DIKI_META_L; if (code == 126) /* right windows key */ return DIKI_META_R; if (code == 127) /* context menu key */ return DIKI_SUPER_R; return DIKI_UNKNOWN; }
int lk_add_key(struct lk_ctx *ctx, unsigned int k_table, unsigned int k_index, int keycode) { struct lk_array *map; unsigned int code = keycode + 1; if (keycode == CODE_FOR_UNKNOWN_KSYM) { /* is safer not to be silent in this case, * it can be caused by coding errors as well. */ ERR(ctx, _("lk_add_key called with bad keycode %d"), keycode); return -1; } if (!k_index && keycode == K_NOSUCHMAP) return 0; map = lk_array_get_ptr(ctx->keymap, k_table); if (!map) { if (ctx->keywords & LK_KEYWORD_KEYMAPS) { ERR(ctx, _("adding map %d violates explicit keymaps line"), k_table); return -1; } if (lk_add_map(ctx, k_table) < 0) return -1; } if ((ctx->keywords & LK_KEYWORD_ALTISMETA) && keycode == K_HOLE && lk_key_exists(ctx, k_table, k_index)) return 0; map = lk_array_get_ptr(ctx->keymap, k_table); if (lk_array_set(map, k_index, &code) < 0) { ERR(ctx, _("unable to set key %d for table %d"), k_index, k_table); return -1; } if (ctx->keywords & LK_KEYWORD_ALTISMETA) { unsigned int alttable = k_table | M_ALT; int type = KTYP(keycode); int val = KVAL(keycode); if (alttable != k_table && lk_map_exists(ctx, alttable) && !lk_key_exists(ctx, alttable, k_index) && (type == KT_LATIN || type == KT_LETTER) && val < 128) { if (lk_add_key(ctx, alttable, k_index, K(KT_META, val)) < 0) return -1; } } return 0; }
/* * Generate ebcdic -> ascii translation table from kbd_data. */ void kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc) { unsigned short *keymap, keysym; int i, j, k; memset(ebcasc, ' ', 256); for (i = 0; i < ARRAY_SIZE(key_maps); i++) { keymap = kbd->key_maps[i]; if (!keymap) continue; for (j = 0; j < NR_KEYS; j++) { keysym = keymap[j]; k = ((i & 1) << 7) + j; if (KTYP(keysym) == (KT_LATIN | 0xf0) || KTYP(keysym) == (KT_LETTER | 0xf0)) ebcasc[k] = KVAL(keysym); else if (KTYP(keysym) == (KT_DEAD | 0xf0)) ebcasc[k] = ret_diacr[KVAL(keysym)]; } } }
/* * Generate ascii -> ebcdic translation table from kbd_data. */ void kbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc) { unsigned short *keymap, keysym; int i, j, k; memset(ascebc, 0x40, 256); for (i = 0; i < ARRAY_SIZE(key_maps); i++) { keymap = kbd->key_maps[i]; if (!keymap) continue; for (j = 0; j < NR_KEYS; j++) { k = ((i & 1) << 7) + j; keysym = keymap[j]; if (KTYP(keysym) == (KT_LATIN | 0xf0) || KTYP(keysym) == (KT_LETTER | 0xf0)) ascebc[KVAL(keysym)] = k; else if (KTYP(keysym) == (KT_DEAD | 0xf0)) ascebc[ret_diacr[KVAL(keysym)]] = k; } } }
dword TranslateUnicode(dword keycode) { int m = 0; if(modkeys & KMOD_SHIFT) m |= (1<<KG_SHIFT); if(modkeys & KMOD_CTRL) m |= (1<<KG_CTRL); if(modkeys & KMOD_LALT) m |= (1<<KG_ALT); if(modkeys & KMOD_RALT) m |= (1<<KG_ALTGR); //CAPS changes shift meaning in both directions if((modkeys & KMOD_CAPS) && KTYP(kmap[m][keycode]) == KT_LETTER ) m ^= (1<<KG_SHIFT); //num pad handling stays same so far if((modkeys & KMOD_NUM) && KTYP(kmap[m][keycode]) == KT_PAD ) return KVAL(kmap[m][keycode]); else return KVAL(kmap[m][keycode]); }
/* called after returning from RAW mode or when changing consoles - recompute k_down[] and shift_state from key_down[] */ void compute_shiftstate(void) { int i, j, k, sym, val; shift_state = 0; for(i=0; i < SIZE(k_down); i++) k_down[i] = 0; for(i=0; i < SIZE(key_down); i++) if(key_down[i]) { /* skip this word if not a single bit on */ k = (i<<5); for(j=0; j<32; j++,k++) if(test_bit(k, key_down)) { sym = key_map[0][k]; if(KTYP(sym) == KT_SHIFT) { val = KVAL(sym); k_down[val]++; shift_state |= (1<<val); } } } }
unsigned short keypad_keysym_redirect(unsigned short keysym) { if (applic_keypad || KTYP(keysym) != KT_PAD || KVAL(keysym) >= NR_PAD) return keysym; #define KL(val) K(KT_LATIN, val) static const unsigned short num_map[] = { KL('0'), KL('1'), KL('2'), KL('3'), KL('4'), KL('5'), KL('6'), KL('7'), KL('8'), KL('9'), KL('+'), KL('-'), KL('*'), KL('/'), K_ENTER, KL(','), KL('.'), KL('?'), KL('('), KL(')'), KL('#') }; static const unsigned short fn_map[] = { K_INSERT, K_SELECT, K_DOWN, K_PGDN, K_LEFT, K_P5, K_RIGHT, K_FIND, K_UP, K_PGUP, KL('+'), KL('-'), KL('*'), KL('/'), K_ENTER, K_REMOVE, K_REMOVE, KL('?'), KL('('), KL(')'), KL('#') }; if (lock_state & K_NUMLOCK) return num_map[keysym - K_P0]; return fn_map[keysym - K_P0]; }
u_char vmklnx_map_key(u_char value, u_char keytype) { u_char map_value = KEYBOARD_INVALID_VALUE; /* function keys */ if (keytype == KT_FN) { switch (value) { case KVAL(K_FIND): map_value = VMK_INPUT_KEY_HOME; break; case KVAL(K_PGUP): map_value = VMK_INPUT_KEY_PAGEUP; break; case KVAL(K_SELECT): map_value = VMK_INPUT_KEY_END; break; case KVAL(K_PGDN): map_value = VMK_INPUT_KEY_PAGEDOWN; break; case KVAL(K_INSERT): map_value = VMK_INPUT_KEY_INSERT; break; case KVAL(K_REMOVE): map_value = VMK_INPUT_KEY_DELETE; break; default: if ((char)value >= KVAL(K_F1) && value <= KVAL(K_F12)) { map_value = value - K_F1 + VMK_INPUT_KEY_F1; } else { vmk_InputPutsQueue(func_table[value]); } break; } } /* cursor */ if (keytype == KT_CUR) { switch (value) { case KVAL(K_UP): map_value = VMK_INPUT_KEY_UP; break; case KVAL(K_LEFT): map_value = VMK_INPUT_KEY_LEFT; break; case KVAL(K_RIGHT): map_value = VMK_INPUT_KEY_RIGHT; break; case KVAL(K_DOWN): map_value = VMK_INPUT_KEY_DOWN; break; default: printk("Unknown cursor key\n"); break; } } /* console */ if (keytype == KT_CONS) { if ((char)value >= KVAL(K_F1) && value <= KVAL(K_F12)) { map_value = value - K_F1 + VMK_INPUT_KEY_ALT_F1; } } if (map_value != KEYBOARD_INVALID_VALUE) { vmk_InputPutQueue(map_value); } return map_value; }
int s_video_helper_kbd_update (s_video_input_data_t *keybd) { int i; int led = 0; int pressed; int scancode; int bytesread; unsigned char buf; int map = 0; s_keyboard_flag_t keycode_flag; bytesread = read(s_video_helper_keybd.fd, &buf, 1); for (i = 0; i < bytesread; i++) { scancode = buf & 0x7f; pressed = (buf & 0x80) ? EVENT_TYPE_KEYBOARD_RELEASED : EVENT_TYPE_KEYBOARD_PRESSED; keybd->keybd.state = pressed; keybd->keybd.scancode = scancode; keybd->keybd.button = s_video_helper_keybd_keycode_[scancode][KEYCODE_PLAIN]; keybd->keybd.keycode = s_video_helper_keybd_keycode_[scancode][KEYCODE_PLAIN]; keycode_flag = xynth_server->window->event->keybd->flag; switch (keybd->keybd.button) { case KEYBOARD_BUTTON_LEFTSHIFT: case KEYBOARD_BUTTON_RIGHTSHIFT: case KEYBOARD_BUTTON_LEFTCONTROL: case KEYBOARD_BUTTON_RIGHTCONTROL: case KEYBOARD_BUTTON_ALT: case KEYBOARD_BUTTON_ALTGR: case KEYBOARD_BUTTON_CAPS_LOCK: goto keycode_plain; default: break; } if (keycode_flag & KEYBOARD_FLAG_SHIFT) { keybd->keybd.button = s_video_helper_keybd_keycode_[scancode][KEYCODE_SHIFT]; map |= (1 << KG_SHIFT); } if (keycode_flag & KEYBOARD_FLAG_CTRL) { map |= (1 << KG_CTRL); } if (keycode_flag & KEYBOARD_FLAG_LEFTALT) { map |= (1 << KG_ALT); } if (keycode_flag & KEYBOARD_FLAG_ALTGR) { keybd->keybd.button = s_video_helper_keybd_keycode_[scancode][KEYCODE_ALTGR]; map |= (1 << KG_ALTGR); } keycode_plain: if (KTYP(s_video_helper_keybd_keymap[map][scancode]) == KT_LETTER) { if (keycode_flag & KEYBOARD_FLAG_CAPSLOCK) { map ^= (1 << KG_SHIFT); } } if (KTYP(s_video_helper_keybd_keymap[map][scancode]) == KT_PAD) { if (keycode_flag & KEYBOARD_FLAG_NUMLOCK) { keybd->keybd.ascii = KVAL(s_video_helper_keybd_keymap[map][scancode]); } } else { keybd->keybd.ascii = KVAL(s_video_helper_keybd_keymap[map][scancode]); } ioctl(s_video_helper_keybd.fd, KDGETLED, &led); if (keycode_flag & KEYBOARD_FLAG_CAPSLOCK) { led |= LED_CAP; } else { led &= ~LED_CAP; } if (keycode_flag & KEYBOARD_FLAG_NUMLOCK) { led |= LED_NUM; } else { led &= ~LED_NUM; } ioctl(s_video_helper_keybd.fd, KDSETLED, led); } return 0; }
int CLinuxInputDevice::KeyboardGetSymbol(unsigned short value) { unsigned char type = KTYP(value); unsigned char index = KVAL(value); switch (type) { case KT_FN: if (index < 15) return XBMCK_F1 + index; break; case KT_LETTER: case KT_LATIN: switch (index) { case 0x1c: return XBMCK_PRINT; case 0x7f: return XBMCK_BACKSPACE; case 0xa4: return XBMCK_EURO; /* euro currency sign */ default: return index; } break; /* case KT_DEAD: switch (value) { case K_DGRAVE: return DIKS_DEAD_GRAVE; case K_DACUTE: return DIKS_DEAD_ACUTE; case K_DCIRCM: return DIKS_DEAD_CIRCUMFLEX; case K_DTILDE: return DIKS_DEAD_TILDE; case K_DDIERE: return DIKS_DEAD_DIAERESIS; case K_DCEDIL: return DIKS_DEAD_CEDILLA; default: break; } break; case KT_PAD: if (index <= 9 && level != DIKSI_BASE) return (DFBInputDeviceKeySymbol) (DIKS_0 + index); break; */ } return XBMCK_UNKNOWN; }
/* this logic is pulled from kbd_keycode() in drivers/tty/vt/keyboard.c in the Linux kernel source */ static void SDL_EVDEV_do_text_input(unsigned short keycode) { char shift_state; int locks_state; struct kbentry kbe; unsigned char type; char text[2] = { 0 }; if (_this->console_fd < 0) return; shift_state = TIOCL_GETSHIFTSTATE; if (ioctl(_this->console_fd, TIOCLINUX, &shift_state) < 0) { /* TODO: error */ return; } kbe.kb_table = shift_state; kbe.kb_index = keycode; if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) { /* TODO: error */ return; } type = KTYP(kbe.kb_value); if (type < 0xf0) { /* * FIXME: keysyms with a type below 0xf0 represent a unicode character * which requires special handling due to dead characters, diacritics, * etc. For perfect input a proper way to deal with such characters * should be implemented. * * For reference, the only place I was able to find out about this * special 0xf0 value was in an unused? couple of patches listed below. * * http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-keyboard.diff * http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-console.diff */ return; } type -= 0xf0; /* if type is KT_LETTER then it can be affected by Caps Lock */ if (type == KT_LETTER) { type = KT_LATIN; if (ioctl(_this->console_fd, KDGKBLED, &locks_state) < 0) { /* TODO: error */ return; } if (locks_state & K_CAPSLOCK) { kbe.kb_table = shift_state ^ (1 << KG_SHIFT); if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) { /* TODO: error */ return; } } } /* TODO: convert values >= 0x80 from ISO-8859-1? to UTF-8 */ if (type != KT_LATIN || KVAL(kbe.kb_value) >= 0x80) return; *text = KVAL(kbe.kb_value); SDL_SendKeyboardText(text); }
static void do_pad(unsigned char value, char up_flag) { static const char pad_chars[] = "0123456789+-*/\015,.?()"; /*static const char app_map[] = "pqrstuvwxylSRQMnnmPQ"; */ #ifdef DBG2 printf("do_pad: %d\r\n", value); #endif if (up_flag) return; /* no action, if this is a key release */ #if 0 /* kludge... shift forces cursor/number keys */ if ( /*vc_kbd_mode(kbd,VC_APPLIC) */ applic_mode && !k_down[KG_SHIFT]) { if (value < sizeof(app_map)) applkey(app_map[value], 1); return; } #endif switch (value) { case KVAL(K_PPLUS): put_acqueue('+'); return; case KVAL(K_PMINUS): put_acqueue('-'); return; case KVAL(K_PSLASH): put_acqueue('/'); return; case KVAL(K_PSTAR): put_acqueue('*'); return; } if ((!scan_numlock_state /*vc_kbd_led(kbd,VC_NUMLOCK) */ && !(shift_state & ((1 << KG_SHIFT) | (1 << KG_SHIFTL) | (1 << KG_SHIFTR)))) || (scan_numlock_state && (shift_state & ((1 << KG_CTRL) | (1 << KG_CTRLL) | (1 << KG_CTRLR))))) { switch (value) { case KVAL(K_PCOMMA): case KVAL(K_PDOT): do_fn(KVAL(K_REMOVE), 0); return; case KVAL(K_P0): do_fn(KVAL(K_INSERT), 0); return; case KVAL(K_P1): do_fn(KVAL(K_SELECT), 0); return; case KVAL(K_P2): do_cur(KVAL(K_DOWN), 0); return; case KVAL(K_P3): do_fn(KVAL(K_PGDN), 0); return; case KVAL(K_P4): do_cur(KVAL(K_LEFT), 0); return; case KVAL(K_P6): do_cur(KVAL(K_RIGHT), 0); return; case KVAL(K_P7): do_fn(KVAL(K_FIND), 0); return; case KVAL(K_P8): do_cur(KVAL(K_UP), 0); return; case KVAL(K_P9): do_fn(KVAL(K_PGUP), 0); return; case KVAL(K_P5): applkey('G', /*vc_kbd_mode(kbd, VC_APPLIC) */ applic_mode); return; } } if (value < sizeof(pad_chars)) /*put_fqueue(pad_chars[value]); */ put_queue(pad_chars[value]); #if 0 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) put_queue(10); #endif }
static void do_pad(unsigned char value, char up_flag) { static const char *pad_chars = "0123456789+-*/\015,.?"; static const char *app_map = "pqrstuvwxylSRQMnn?"; if (up_flag) return; /* no action, if this is a key release */ /* kludge... shift forces cursor/number keys */ if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) { applkey(app_map[value], 1); return; } if (!vc_kbd_led(kbd,VC_NUMLOCK)) switch (value) { case KVAL(K_PCOMMA): case KVAL(K_PDOT): do_fn(KVAL(K_REMOVE), 0); return; case KVAL(K_P0): do_fn(KVAL(K_INSERT), 0); return; case KVAL(K_P1): do_fn(KVAL(K_SELECT), 0); return; case KVAL(K_P2): do_cur(KVAL(K_DOWN), 0); return; case KVAL(K_P3): do_fn(KVAL(K_PGDN), 0); return; case KVAL(K_P4): do_cur(KVAL(K_LEFT), 0); return; case KVAL(K_P6): do_cur(KVAL(K_RIGHT), 0); return; case KVAL(K_P7): do_fn(KVAL(K_FIND), 0); return; case KVAL(K_P8): do_cur(KVAL(K_UP), 0); return; case KVAL(K_P9): do_fn(KVAL(K_PGUP), 0); return; case KVAL(K_P5): applkey('G', vc_kbd_mode(kbd, VC_APPLIC)); return; } put_queue(pad_chars[value]); if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) put_queue(10); }
/* Keyboard support */ static int kbd_getc(void) { unsigned char dt, brk, val; unsigned code; loop: while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ; dt = kbd_inb(KBD_DATA_REG); brk = dt & 0x80; /* brk == 1 on key release */ dt = dt & 0x7f; /* keycode */ if (console_global_data.shfts) code = shift_map[dt]; else if (console_global_data.ctls) code = ctrl_map[dt]; else code = plain_map[dt]; val = KVAL(code); switch (KTYP(code) & 0x0f) { case KT_LATIN: if (brk) break; if (console_global_data.alts) val |= 0x80; if (val == 0x7f) /* map delete to backspace */ val = '\b'; return val; case KT_LETTER: if (brk) break; if (console_global_data.caps) val -= 'a'-'A'; return val; case KT_SPEC: if (brk) break; if (val == KVAL(K_CAPS)) console_global_data.caps = !console_global_data.caps; else if (val == KVAL(K_ENTER)) { enter: /* Wait for key up */ while (1) { while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ; dt = kbd_inb(KBD_DATA_REG); if (dt & 0x80) /* key up */ break; } return 10; } break; case KT_PAD: if (brk) break; if (val < 10) return val; if (val == KVAL(K_PENTER)) goto enter; break; case KT_SHIFT: switch (val) { case KG_SHIFT: case KG_SHIFTL: case KG_SHIFTR: console_global_data.shfts = brk ? 0 : 1; break; case KG_ALT: case KG_ALTGR: console_global_data.alts = brk ? 0 : 1; break; case KG_CTRL: case KG_CTRLL: case KG_CTRLR: console_global_data.ctls = brk ? 0 : 1; break; } break; case KT_LOCK: switch (val) { case KG_SHIFT: case KG_SHIFTL: case KG_SHIFTR: if (brk) console_global_data.shfts = !console_global_data.shfts; break; case KG_ALT: case KG_ALTGR: if (brk) console_global_data.alts = !console_global_data.alts; break; case KG_CTRL: case KG_CTRLL: case KG_CTRLR: if (brk) console_global_data.ctls = !console_global_data.ctls; break; } break; } /* if (brk) return (0); */ /* Ignore initial 'key up' codes */ goto loop; }
static uint8_t process_keyboard(inode_t* inode, struct tty_context* tio, int fd, int* pos) { keyboard_t k; if(sys_read(fd, &k, sizeof(keyboard_t)) == 0) { errno = EIO; return 0; } switch(k.vkey) { case KEY_LEFTALT: tty_keys = !!(k.down) ? tty_keys | K_ALT : tty_keys & ~K_ALT; return 0; case KEY_RIGHTALT: tty_keys = !!(k.down) ? tty_keys | K_ALTGR : tty_keys & ~K_ALTGR; return 0; case KEY_LEFTSHIFT: case KEY_RIGHTSHIFT: tty_keys = !!(k.down) ? tty_keys | K_SHIFT : tty_keys & ~K_SHIFT; return 0; case KEY_LEFTCTRL: case KEY_RIGHTCTRL: tty_keys = !!(k.down) ? tty_keys | K_CTRL : tty_keys & ~K_CTRL; return 0; case KEY_CAPSLOCK: tty_capslock = !(k.down) ? tty_capslock : !tty_capslock; return 0; default: break; } if(!k.down) return 0; int16_t key; uint8_t ch; switch(tty_keys) { #define _(x, y) \ case x : { key = tty_keymap.y[k.vkey] & 0x0FFF; break; } _(0, plain); _(K_SHIFT, shift); _(K_ALTGR, altgr); _(K_SHIFT | K_ALTGR, shift_altgr); _(K_CTRL, ctrl); _(K_SHIFT | K_CTRL, shift_ctrl); _(K_ALTGR | K_CTRL, altgr_ctrl); _(K_ALTGR | K_SHIFT | K_CTRL, altgr_shift_ctrl); _(K_ALT, alt); _(K_SHIFT | K_ALT, shift_alt); _(K_ALTGR | K_ALT, altgr_alt); _(K_ALTGR | K_SHIFT | K_ALT, altgr_shift_alt); _(K_CTRL | K_ALT, ctrl_alt); _(K_SHIFT | K_CTRL | K_ALT, shift_ctrl_alt); _(K_ALTGR | K_CTRL | K_ALT, altgr_ctrl_alt); _(K_ALTGR | K_SHIFT | K_CTRL | K_ALT, altgr_shift_ctrl_alt); default: key = 0; break; #undef _ } ch = KVAL(key); switch(KTYP(key)) { case KT_LATIN: case KT_LETTER: if(tty_capslock) { if(tty_keys & K_SHIFT) ch += ch >= 'A' && ch <= 'z' ? 32 : 0; else ch -= ch >= 'a' && ch <= 'Z' ? 32 : 0; } case KT_ASCII: break; case KT_SPEC: case KT_PAD: if(!__kmap[KTYP(key)] || !__kmap[KTYP(key)][KVAL(key)]) return 0; ch = __kmap[KTYP(key)][KVAL(key)][0]; break; default: if(!__kmap[KTYP(key)] || !__kmap[KTYP(key)][KVAL(key)]) return 0; fifo_write(&tio->in, __kmap[KTYP(key)][KVAL(key)], strlen(__kmap[KTYP(key)][KVAL(key)])); *pos = *pos + strlen(__kmap[KTYP(key)][KVAL(key)]); if(tio->ios.c_lflag & ECHO) tty_output_write(inode, __kmap[KTYP(key)][KVAL(key)], 0, strlen(__kmap[KTYP(key)][KVAL(key)])); return 0; } return ch; }
MMSKeySymbol MMSInputLISThread::getSymbol(int code, unsigned short value) { unsigned char type = KTYP(value); unsigned char index = KVAL(value); TRACEOUT("MMSINPUT", "KEYCODE: TYPE=%d(0x%x), INDEX=%d(0x%x), value=%d(0x%x)", type, type, index, index, value, value); switch (type) { case KT_FN: if (index < 12) return (MMSKeySymbol)(MMSKEY_F1 + index); break; case KT_LETTER: case KT_LATIN: switch (index) { case 0x1c: return MMSKEY_PRINT; case 0x7f: return MMSKEY_BACKSPACE; case 0x08: return MMSKEY_BACKSPACE; case 0x09: return MMSKEY_TAB; case 0x0d: return MMSKEY_RETURN; case 0x18: return MMSKEY_CANCEL; case 0x1b: return MMSKEY_ESCAPE; case 0x20: return MMSKEY_SPACE; case 0x21: return MMSKEY_EXCLAMATION_MARK; case 0x22: return MMSKEY_QUOTATION; case 0x23: return MMSKEY_NUMBER_SIGN; case 0x24: return MMSKEY_DOLLAR_SIGN; case 0x25: return MMSKEY_PERCENT_SIGN; case 0x26: return MMSKEY_AMPERSAND; case 0x27: return MMSKEY_APOSTROPHE; case 0x28: return MMSKEY_PARENTHESIS_LEFT; case 0x29: return MMSKEY_PARENTHESIS_RIGHT; case 0x2a: return MMSKEY_ASTERISK; case 0x2b: return MMSKEY_PLUS_SIGN; case 0x2c: return MMSKEY_COMMA; case 0x2d: return MMSKEY_MINUS_SIGN; case 0x2e: return MMSKEY_PERIOD; case 0x2f: return MMSKEY_SLASH; case 0x30: return MMSKEY_0; case 0x31: return MMSKEY_1; case 0x32: return MMSKEY_2; case 0x33: return MMSKEY_3; case 0x34: return MMSKEY_4; case 0x35: return MMSKEY_5; case 0x36: return MMSKEY_6; case 0x37: return MMSKEY_7; case 0x38: return MMSKEY_8; case 0x39: return MMSKEY_9; case 0x3a: return MMSKEY_COLON; case 0x3b: return MMSKEY_SEMICOLON; case 0x3c: return MMSKEY_LESS_THAN_SIGN; case 0x3d: return MMSKEY_EQUALS_SIGN; case 0x3e: return MMSKEY_GREATER_THAN_SIGN; case 0x3f: return MMSKEY_QUESTION_MARK; case 0x40: return MMSKEY_AT; case 0x41: return MMSKEY_CAPITAL_A; case 0x42: return MMSKEY_CAPITAL_B; case 0x43: return MMSKEY_CAPITAL_C; case 0x44: return MMSKEY_CAPITAL_D; case 0x45: return MMSKEY_CAPITAL_E; case 0x46: return MMSKEY_CAPITAL_F; case 0x47: return MMSKEY_CAPITAL_G; case 0x48: return MMSKEY_CAPITAL_H; case 0x49: return MMSKEY_CAPITAL_I; case 0x4a: return MMSKEY_CAPITAL_J; case 0x4b: return MMSKEY_CAPITAL_K; case 0x4c: return MMSKEY_CAPITAL_L; case 0x4d: return MMSKEY_CAPITAL_M; case 0x4e: return MMSKEY_CAPITAL_N; case 0x4f: return MMSKEY_CAPITAL_O; case 0x50: return MMSKEY_CAPITAL_P; case 0x51: return MMSKEY_CAPITAL_Q; case 0x52: return MMSKEY_CAPITAL_R; case 0x53: return MMSKEY_CAPITAL_S; case 0x54: return MMSKEY_CAPITAL_T; case 0x55: return MMSKEY_CAPITAL_U; case 0x56: return MMSKEY_CAPITAL_V; case 0x57: return MMSKEY_CAPITAL_W; case 0x58: return MMSKEY_CAPITAL_X; case 0x59: return MMSKEY_CAPITAL_Y; case 0x5a: return MMSKEY_CAPITAL_Z; case 0x5b: return MMSKEY_SQUARE_BRACKET_LEFT; case 0x5c: return MMSKEY_BACKSLASH; case 0x5d: return MMSKEY_SQUARE_BRACKET_RIGHT; case 0x5e: return MMSKEY_CIRCUMFLEX_ACCENT; case 0x5f: return MMSKEY_UNDERSCORE; case 0x60: return MMSKEY_GRAVE_ACCENT; case 0x61: return MMSKEY_SMALL_A; case 0x62: return MMSKEY_SMALL_B; case 0x63: return MMSKEY_SMALL_C; case 0x64: return MMSKEY_SMALL_D; case 0x65: return MMSKEY_SMALL_E; case 0x66: return MMSKEY_SMALL_F; case 0x67: return MMSKEY_SMALL_G; case 0x68: return MMSKEY_SMALL_H; case 0x69: return MMSKEY_SMALL_I; case 0x6a: return MMSKEY_SMALL_J; case 0x6b: return MMSKEY_SMALL_K; case 0x6c: return MMSKEY_SMALL_L; case 0x6d: return MMSKEY_SMALL_M; case 0x6e: return MMSKEY_SMALL_N; case 0x6f: return MMSKEY_SMALL_O; case 0x70: return MMSKEY_SMALL_P; case 0x71: return MMSKEY_SMALL_Q; case 0x72: return MMSKEY_SMALL_R; case 0x73: return MMSKEY_SMALL_S; case 0x74: return MMSKEY_SMALL_T; case 0x75: return MMSKEY_SMALL_U; case 0x76: return MMSKEY_SMALL_V; case 0x77: return MMSKEY_SMALL_W; case 0x78: return MMSKEY_SMALL_X; case 0x79: return MMSKEY_SMALL_Y; case 0x7a: return MMSKEY_SMALL_Z; case 0x7b: return MMSKEY_CURLY_BRACKET_LEFT; case 0x7c: return MMSKEY_VERTICAL_BAR; case 0x7d: return MMSKEY_CURLY_BRACKET_RIGHT; case 0x7e: return MMSKEY_TILDE; default: return MMSKEY_UNKNOWN; } break; case KT_PAD: switch (value) { case K_P0: return MMSKEY_0; case K_P1: return MMSKEY_1; case K_P2: return MMSKEY_2; case K_P3: return MMSKEY_3; case K_P4: return MMSKEY_4; case K_P5: return MMSKEY_5; case K_P6: return MMSKEY_6; case K_P7: return MMSKEY_7; case K_P8: return MMSKEY_8; case K_P9: return MMSKEY_9; case K_PPLUS: return MMSKEY_PLUS_SIGN; case K_PMINUS: return MMSKEY_MINUS_SIGN; case K_PSTAR: return MMSKEY_ASTERISK; case K_PSLASH: return MMSKEY_SLASH; case K_PENTER: return MMSKEY_RETURN; case K_PCOMMA: return MMSKEY_COMMA; case K_PDOT: return MMSKEY_PERIOD; case K_PPARENL: return MMSKEY_PARENTHESIS_LEFT; case K_PPARENR: return MMSKEY_PARENTHESIS_RIGHT; default: return MMSKEY_UNKNOWN; } break; } switch (value) { case K_LEFT: return MMSKEY_CURSOR_LEFT; case K_RIGHT: return MMSKEY_CURSOR_RIGHT; case K_UP: return MMSKEY_CURSOR_UP; case K_DOWN: return MMSKEY_CURSOR_DOWN; case K_ENTER: return MMSKEY_RETURN; case K_CTRL: return MMSKEY_CONTROL; case K_SHIFT: return MMSKEY_SHIFT; case K_ALT: return MMSKEY_ALT; case K_ALTGR: return MMSKEY_ALTGR; case K_INSERT: return MMSKEY_INSERT; case K_REMOVE: return MMSKEY_DELETE; case K_FIND: return MMSKEY_HOME; case K_SELECT: return MMSKEY_END; case K_PGUP: return MMSKEY_PAGE_UP; case K_PGDN: return MMSKEY_PAGE_DOWN; case K_NUM: return MMSKEY_NUM_LOCK; case K_HOLD: return MMSKEY_SCROLL_LOCK; case K_PAUSE: return MMSKEY_PAUSE; case K_BREAK: return MMSKEY_BREAK; case K_CAPS: return MMSKEY_CAPS_LOCK; case K_P0: return MMSKEY_INSERT; case K_P1: return MMSKEY_END; case K_P2: return MMSKEY_CURSOR_DOWN; case K_P3: return MMSKEY_PAGE_DOWN; case K_P4: return MMSKEY_CURSOR_LEFT; case K_P5: return MMSKEY_BEGIN; case K_P6: return MMSKEY_CURSOR_RIGHT; case K_P7: return MMSKEY_HOME; case K_P8: return MMSKEY_CURSOR_UP; case K_P9: return MMSKEY_PAGE_UP; case K_PPLUS: return MMSKEY_PLUS_SIGN; case K_PMINUS: return MMSKEY_MINUS_SIGN; case K_PSTAR: return MMSKEY_ASTERISK; case K_PSLASH: return MMSKEY_SLASH; case K_PENTER: return MMSKEY_RETURN; case K_PCOMMA: return MMSKEY_COMMA; case K_PDOT: return MMSKEY_PERIOD; case K_PPARENL: return MMSKEY_PARENTHESIS_LEFT; case K_PPARENR: return MMSKEY_PARENTHESIS_RIGHT; } return MMSKEY_UNKNOWN; }
static inline gii_event_mask GII_keyboard_handle_data(gii_input *inp, int code) { linkbd_priv *priv = LINKBD_PRIV(inp); gii_event ev; struct kbentry entry; int symval, labelval; gii_event_mask mask; _giiEventBlank(&ev, sizeof(gii_key_event)); if (code & 0x80) { code &= 0x7f; ev.key.type = evKeyRelease; priv->keydown_buf[code] = 0; } else if (priv->keydown_buf[code] == 0) { ev.key.type = evKeyPress; priv->keydown_buf[code] = 1; } else { ev.key.type = evKeyRepeat; } ev.key.button = code; /* First update modifiers here so linkey.c can use the value */ ev.key.modifiers = priv->modifiers; if (ev.key.type == evKeyRelease && GII_KTYP(priv->keydown_sym[code]) != GII_KT_MOD && priv->keydown_sym[code] != GIIK_VOID) { /* We can use the cached values */ ev.key.sym = priv->keydown_sym[code]; ev.key.label = priv->keydown_label[code]; } else { /* Temporarily switch back to the old mode because unicodes aren't available through table lookup in MEDIUMRAW */ if (ioctl(priv->fd, KDSKBMODE, priv->old_mode) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDSKBMODE) failed.\n"); return 0; } /* Look up the keysym without modifiers, which will give us * the key label (more or less). */ entry.kb_table = 0; entry.kb_index = code; if (ioctl(priv->fd, KDGKBENT, &entry) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDGKBENT) failed.\n"); return 0; } labelval = entry.kb_value; if (priv->old_mode == K_UNICODE) labelval &= 0x0fff; /* Now look up the full keysym in the kernel's table */ /* calculate kernel-like shift value */ entry.kb_table = ((priv->modifiers & GII_MOD_SHIFT) ? (1<<KG_SHIFT) : 0) | ((priv->modifiers & GII_MOD_CTRL) ? (1<<KG_CTRL) : 0) | ((priv->modifiers & GII_MOD_ALT) ? (1<<KG_ALT) : 0) | ((priv->modifiers & GII_MOD_ALTGR) ? (1<<KG_ALTGR) : 0) | ((priv->modifiers & GII_MOD_META) ? (1<<KG_ALT) : 0) | ((priv->modifiers & GII_MOD_CAPS) ? (1<<KG_CAPSSHIFT) : 0); entry.kb_index = code; if (ioctl(priv->fd, KDGKBENT, &entry) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDGKBENT) failed.\n"); return 0; } /* Switch back to MEDIUMRAW */ if (ioctl(priv->fd, KDSKBMODE, K_MEDIUMRAW) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDSKBMODE) failed.\n"); return 0; } switch (entry.kb_value) { case K_HOLE: DPRINT_EVENTS("Linux-kbd: NOSUCHKEY\n"); break; case K_NOSUCHMAP: DPRINT_EVENTS("Linux-kbd: NOSUCHMAP\n"); entry.kb_value = K_HOLE; break; } symval = entry.kb_value; if (priv->old_mode == K_UNICODE) symval &= 0x0fff; _gii_linkey_trans(code, labelval, symval, &ev.key); if (ev.key.type == evKeyPress) { if (priv->accent) { if (GII_KTYP(ev.key.sym) != GII_KT_MOD) { handle_accent(priv, symval, &ev); } } else if (KTYP(symval) == KT_DEAD) { priv->accent = GII_KVAL(ev.key.sym); } } if (GII_KTYP(ev.key.sym) == GII_KT_DEAD) { ev.key.sym = GIIK_VOID; } } /* Keep track of modifier state */ if (GII_KTYP(ev.key.label) == GII_KT_MOD) { /* Modifers don't repeat */ if (ev.key.type == evKeyRepeat) return 0; handle_modifier(priv, &ev); } /* Now update modifiers again to get the value _after_ the current event */ ev.key.modifiers = priv->modifiers; if (ev.any.type == evKeyPress) { priv->keydown_sym[code] = ev.key.sym; priv->keydown_label[code] = ev.key.label; } DPRINT_EVENTS("KEY-%s button=0x%02x modifiers=0x%02x " "sym=0x%04x label=0x%04x\n", (ev.key.type == evKeyRelease) ? "UP" : ((ev.key.type == evKeyPress) ? "DN" : "RP"), ev.key.button, ev.key.modifiers, ev.key.sym, ev.key.label); if (priv->call_vtswitch) { if (ev.key.label == GIIK_CtrlL && priv->needctrl2switch) { if (ev.key.type == evKeyRelease) { priv->ctrlstate = 0; } else if (ev.key.type == evKeyPress) { priv->ctrlstate = 1; } } /* Check for console switch. Unfortunately, the kernel doesn't * recognize KT_CONS when the keyboard is in RAW or MEDIUMRAW * mode, so _we_ have to. Sigh. */ if ((ev.key.type == evKeyPress) && (KTYP(entry.kb_value) == KT_CONS) && priv->ctrlstate) { int rc; int new_cons = 1+KVAL(entry.kb_value); /* Clear the keydown buffer, since we'll never know what keys the user pressed (or released) while they were away. */ DPRINT_MISC("Flushing all keys.\n"); rc = GII_keyboard_flush_keys(inp); DPRINT_MISC("Switching to console %d.\n", new_cons); if (ioctl(priv->fd, VT_ACTIVATE, new_cons) < 0) { perror("ioctl(VT_ACTIVATE)"); } return rc; } } mask = (1 << ev.any.type); if (! (inp->curreventmask & mask)) return 0; /* finally queue the key event */ ev.any.size = sizeof(gii_key_event); ev.any.origin = inp->origin; _giiEvQueueAdd(inp, &ev); return (1 << ev.any.type); }
static void readKernelMapping(KeySymsPtr pKeySyms, CARD8 *pModMap) { KeySym *k; int i; static unsigned char tbl[GLYPHS_PER_KEY] = { 0, /* unshifted */ 1, /* shifted */ 0, /* modeswitch unshifted */ 0 /* modeswitch shifted */ }; /* * Read the mapping from the kernel. * Since we're still using the XFree86 scancode->AT keycode mapping * routines, we need to convert the AT keycodes to Linux keycodes, * then translate the Linux keysyms into X keysyms. * * First, figure out which tables to use for the modeswitch columns * above, from the XF86Config fields. */ if (xf86Info.specialKeyMap[K_INDEX_RIGHTCTL] == KM_MODESHIFT || xf86Info.specialKeyMap[K_INDEX_RIGHTCTL] == KM_MODELOCK) tbl[2] = 4; /* control */ else if (xf86Info.specialKeyMap[K_INDEX_RIGHTALT] == KM_MODESHIFT || xf86Info.specialKeyMap[K_INDEX_RIGHTALT] == KM_MODELOCK) tbl[2] = 2; /* AltGr */ else tbl[2] = 8; /* alt */ tbl[3] = tbl[2] | 1; #ifndef ASSUME_CUSTOM_KEYCODES for (i = 0, k = map+GLYPHS_PER_KEY; i < NUM_AT2LNX; ++i) #else /* !ASSUME_CUSTOM_KEYCODES */ for (i = 0, k = map; i < NUM_AT2LNX; ++i) #endif /* !ASSUME_CUSTOM_KEYCODES */ { struct kbentry kbe; int j; #ifndef ASSUME_CUSTOM_KEYCODES kbe.kb_index = at2lnx[i]; #else /* !ASSUME_CUSTOM_KEYCODES */ kbe.kb_index = i; #endif /* !ASSUME_CUSTOM_KEYCODES */ for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) { unsigned short kval; *k = NoSymbol; kbe.kb_table = tbl[j]; if ( #ifndef ASSUME_CUSTOM_KEYCODES kbe.kb_index == 0 || #endif /* !ASSUME_CUSTOM_KEYCODES */ ioctl(xf86Info.consoleFd, KDGKBENT, &kbe)) continue; kval = KVAL(kbe.kb_value); switch (KTYP(kbe.kb_value)) { case KT_LATIN: case KT_LETTER: *k = linux_to_x[kval]; break; case KT_FN: if (kval <= 19) *k = XK_F1 + kval; else switch (kbe.kb_value) { case K_FIND: *k = XK_Home; /* or XK_Find */ break; case K_INSERT: *k = XK_Insert; break; case K_REMOVE: *k = XK_Delete; break; case K_SELECT: *k = XK_End; /* or XK_Select */ break; case K_PGUP: *k = XK_Prior; break; case K_PGDN: *k = XK_Next; break; case K_HELP: *k = XK_Help; break; case K_DO: *k = XK_Execute; break; case K_PAUSE: *k = XK_Pause; break; case K_MACRO: *k = XK_Menu; break; default: break; } break; case KT_SPEC: switch (kbe.kb_value) { case K_ENTER: *k = XK_Return; break; case K_BREAK: *k = XK_Break; break; case K_CAPS: *k = XK_Caps_Lock; break; case K_NUM: *k = XK_Num_Lock; break; case K_HOLD: *k = XK_Scroll_Lock; break; case K_COMPOSE: *k = XK_Multi_key; break; default: break; } break; case KT_PAD: switch (kbe.kb_value) { case K_PPLUS: *k = XK_KP_Add; break; case K_PMINUS: *k = XK_KP_Subtract; break; case K_PSTAR: *k = XK_KP_Multiply; break; case K_PSLASH: *k = XK_KP_Divide; break; case K_PENTER: *k = XK_KP_Enter; break; case K_PCOMMA: *k = XK_KP_Separator; break; case K_PDOT: *k = XK_KP_Decimal; break; case K_PPLUSMINUS: *k = XK_KP_Subtract; break; default: if (kval <= 9) *k = XK_KP_0 + kval; break; } break; /* * KT_DEAD keys are for accelerated diacritical creation. */ case KT_DEAD: switch (kbe.kb_value) { case K_DGRAVE: *k = XK_dead_grave; break; case K_DACUTE: *k = XK_dead_acute; break; case K_DCIRCM: *k = XK_dead_circumflex; break; case K_DTILDE: *k = XK_dead_tilde; break; case K_DDIERE: *k = XK_dead_diaeresis; break; } break; case KT_CUR: switch (kbe.kb_value) { case K_DOWN: *k = XK_Down; break; case K_LEFT: *k = XK_Left; break; case K_RIGHT: *k = XK_Right; break; case K_UP: *k = XK_Up; break; } break; case KT_SHIFT: switch (kbe.kb_value) { case K_ALTGR: *k = XK_Alt_R; break; case K_ALT: *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L); break; case K_CTRL: *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L); break; case K_CTRLL: *k = XK_Control_L; break; case K_CTRLR: *k = XK_Control_R; break; case K_SHIFT: *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L); break; case K_SHIFTL: *k = XK_Shift_L; break; case K_SHIFTR: *k = XK_Shift_R; break; default: break; } break; /* * KT_ASCII keys accumulate a 3 digit decimal number that gets * emitted when the shift state changes. We can't emulate that. */ case KT_ASCII: break; case KT_LOCK: if (kbe.kb_value == K_SHIFTLOCK) *k = XK_Shift_Lock; break; default: break; } } if (k[-1] == k[-2]) k[-1] = NoSymbol; if (k[-2] == k[-3]) k[-2] = NoSymbol; if (k[-3] == k[-4]) k[-3] = NoSymbol; if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol; if (k[-1] == k[-4] && k[-2] == k[-3] && k[-2] == NoSymbol) k[-1] =NoSymbol; } #ifdef ASSUME_CUSTOM_KEYCODES /* * Find the Mapping for the special server functions */ for (i = 0; i < NR_KEYS; ++i) { struct kbentry kbe; int special = 0; kbe.kb_index = i; kbe.kb_table = 0; /* Plain map */ if (!ioctl(xf86Info.consoleFd, KDGKBENT, &kbe)) switch (kbe.kb_value) { case K(KT_LATIN,0x7f): /* This catches DEL too... But who cares? */ special = KEY_BackSpace; break; case K_PMINUS: special = KEY_KP_Minus; break; case K_PPLUS: special = KEY_KP_Plus; break; case K_F1: special = KEY_F1; break; case K_F2: special = KEY_F2; break; case K_F3: special = KEY_F3; break; case K_F4: special = KEY_F4; break; case K_F5: special = KEY_F5; break; case K_F6: special = KEY_F6; break; case K_F7: special = KEY_F7; break; case K_F8: special = KEY_F8; break; case K_F9: special = KEY_F9; break; case K_F10: special = KEY_F10; break; case K_F11: special = KEY_F11; break; case K_F12: special = KEY_F12; break; case K_ALT: special = KEY_Alt; break; case K_ALTGR: special = KEY_AltLang; break; case K_CONS: special = KEY_SysReqest; break; } SpecialServerMap[i] = special; } #endif /* ASSUME_CUSTOM_KEYCODES */ }
void SDL_EVDEV_Poll(void) { struct input_event events[32]; int i, len; SDL_evdevlist_item *item; SDL_Scancode scan_code; int mouse_button; SDL_Mouse *mouse; #ifdef SDL_INPUT_LINUXKD Uint16 modstate; struct kbentry kbe; static char keysym[8]; char *end; Uint32 kval; #endif #if SDL_USE_LIBUDEV SDL_UDEV_Poll(); #endif mouse = SDL_GetMouse(); for (item = _this->first; item != NULL; item = item->next) { while ((len = read(item->fd, events, (sizeof events))) > 0) { len /= sizeof(events[0]); for (i = 0; i < len; ++i) { switch (events[i].type) { case EV_KEY: if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) { mouse_button = events[i].code - BTN_MOUSE; if (events[i].value == 0) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]); } else if (events[i].value == 1) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]); } break; } /* Probably keyboard */ scan_code = SDL_EVDEV_translate_keycode(events[i].code); if (scan_code != SDL_SCANCODE_UNKNOWN) { if (events[i].value == 0) { SDL_SendKeyboardKey(SDL_RELEASED, scan_code); } else if (events[i].value == 1 || events[i].value == 2 /* Key repeated */ ) { SDL_SendKeyboardKey(SDL_PRESSED, scan_code); #ifdef SDL_INPUT_LINUXKD if (_this->console_fd >= 0) { kbe.kb_index = events[i].code; /* Convert the key to an UTF-8 char */ /* Ref: http://www.linuxjournal.com/article/2783 */ modstate = SDL_GetModState(); kbe.kb_table = 0; /* Ref: http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */ kbe.kb_table |= -( (modstate & KMOD_LCTRL) != 0) & (1 << KG_CTRLL | 1 << KG_CTRL); kbe.kb_table |= -( (modstate & KMOD_RCTRL) != 0) & (1 << KG_CTRLR | 1 << KG_CTRL); kbe.kb_table |= -( (modstate & KMOD_LSHIFT) != 0) & (1 << KG_SHIFTL | 1 << KG_SHIFT); kbe.kb_table |= -( (modstate & KMOD_RSHIFT) != 0) & (1 << KG_SHIFTR | 1 << KG_SHIFT); kbe.kb_table |= -( (modstate & KMOD_LALT) != 0) & (1 << KG_ALT); kbe.kb_table |= -( (modstate & KMOD_RALT) != 0) & (1 << KG_ALTGR); if (ioctl(_this->console_fd, KDGKBENT, (unsigned long)&kbe) == 0 && ((KTYP(kbe.kb_value) == KT_LATIN) || (KTYP(kbe.kb_value) == KT_ASCII) || (KTYP(kbe.kb_value) == KT_LETTER))) { kval = KVAL(kbe.kb_value); /* While there's a KG_CAPSSHIFT symbol, it's not useful to build the table index with it * because 1 << KG_CAPSSHIFT overflows the 8 bits of kb_table * So, we do the CAPS LOCK logic here. Note that isalpha depends on the locale! */ if ( modstate & KMOD_CAPS && isalpha(kval) ) { if ( isupper(kval) ) { kval = tolower(kval); } else { kval = toupper(kval); } } /* Convert to UTF-8 and send */ end = SDL_UCS4ToUTF8( kval, keysym); *end = '\0'; SDL_SendKeyboardText(keysym); } } #endif /* SDL_INPUT_LINUXKD */ } } break; case EV_ABS: switch(events[i].code) { case ABS_X: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y); break; case ABS_Y: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value); break; default: break; } break; case EV_REL: switch(events[i].code) { case REL_X: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0); break; case REL_Y: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value); break; case REL_WHEEL: SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value); break; case REL_HWHEEL: SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0); break; default: break; } break; case EV_SYN: switch (events[i].code) { case SYN_DROPPED: SDL_EVDEV_sync_device(item); break; default: break; } break; } } } } }
/* keycode_to_char: [fdwatch thread] * Helper function. * KEYCODE is a Linux kernel keycode, not an Allegro keycode. * * In the process of doing the translation, we may find that the user * has pressed a key that for VT switching. In that case a negative * number is returned, the absolute value of which is the VT to * switch to. Yes, ugly. */ static int keycode_to_char(int keycode) { const unsigned int modifiers = the_keyboard.modifiers; struct kbentry kbe; int keymap; int ascii; /* build kernel keymap number */ keymap = 0; if (modifiers & ALLEGRO_KEYMOD_SHIFT) keymap |= 1; if (modifiers & ALLEGRO_KEYMOD_ALTGR) keymap |= 2; if (modifiers & ALLEGRO_KEYMOD_CTRL) keymap |= 4; if (modifiers & ALLEGRO_KEYMOD_ALT) keymap |= 8; /* map keycode to type and value */ kbe.kb_table = keymap; kbe.kb_index = keycode; ioctl(the_keyboard.fd, KDGKBENT, &kbe); if (keycode == KEY_BACKSPACE) ascii = 8; else { if (kbe.kb_value == K_NOSUCHMAP) { /* invalid keymaps */ /* FIXME: Maybe we should just redo the */ /* ioctl with keymap 0? */ ascii = 0; } else { /* most keys come here */ ascii = KVAL(kbe.kb_value); } } /* finally do some things based on key type */ switch (KTYP(kbe.kb_value)) { case KT_CONS: /* VT switch key -- return a negative number */ return -( KVAL(kbe.kb_value)+1 ); case KT_LETTER: /* apply capslock translation. */ if (modifiers & ALLEGRO_KEYMOD_CAPSLOCK) return ascii ^ 0x20; else return ascii; case KT_LATIN: case KT_ASCII: return ascii; case KT_PAD: { int val = KVAL(kbe.kb_value); if (modifiers & ALLEGRO_KEYMOD_NUMLOCK) { if ((val >= 0) && (val < NUM_PAD_KEYS)) ascii = pad_asciis[val]; } else { if ((val >= 0) && (val < NUM_PAD_KEYS)) ascii = pad_asciis_no_numlock[val]; } return ascii; } case KT_SPEC: if (keycode == KEY_ENTER) return '\r'; else return 0; default: /* dunno */ return 0; } }
static DFBInputDeviceKeySymbol keyboard_get_symbol( int code, unsigned short value, DFBInputDeviceKeymapSymbolIndex level ) { unsigned char type = KTYP(value); unsigned char index = KVAL(value); int base = (level == DIKSI_BASE); switch (type) { case KT_FN: if (index < 20) return DFB_FUNCTION_KEY( index + 1 ); break; case KT_LETTER: case KT_LATIN: switch (index) { case 0x1c: return DIKS_PRINT; case 0x7f: return DIKS_BACKSPACE; case 0xa4: return 0x20ac; /* euro currency sign */ default: return index; } break; case KT_DEAD: switch (value) { case K_DGRAVE: return DIKS_DEAD_GRAVE; case K_DACUTE: return DIKS_DEAD_ACUTE; case K_DCIRCM: return DIKS_DEAD_CIRCUMFLEX; case K_DTILDE: return DIKS_DEAD_TILDE; case K_DDIERE: return DIKS_DEAD_DIAERESIS; case K_DCEDIL: return DIKS_DEAD_CEDILLA; default: break; } break; case KT_PAD: if (index <= 9 && level != DIKSI_BASE) return DIKS_0 + index; break; case 0xe: /* special IPAQ H3600 case - AH */ switch (index) { case 0x20: return DIKS_CALENDAR; case 0x1a: return DIKS_BACK; case 0x1c: return DIKS_MEMO; case 0x21: return DIKS_POWER; } break; case 0xd: /* another special IPAQ H3600 case - AH */ switch (index) { case 0x2: return DIKS_DIRECTORY; case 0x1: return DIKS_MAIL; /* Q on older iPaqs */ } break; } switch (value) { case K_LEFT: return DIKS_CURSOR_LEFT; case K_RIGHT: return DIKS_CURSOR_RIGHT; case K_UP: return DIKS_CURSOR_UP; case K_DOWN: return DIKS_CURSOR_DOWN; case K_ENTER: return DIKS_ENTER; case K_CTRL: return DIKS_CONTROL; case K_SHIFT: return DIKS_SHIFT; case K_ALT: return DIKS_ALT; case K_ALTGR: return DIKS_ALTGR; case K_INSERT: return DIKS_INSERT; case K_REMOVE: return DIKS_DELETE; case K_FIND: return DIKS_HOME; case K_SELECT: return DIKS_END; case K_PGUP: return DIKS_PAGE_UP; case K_PGDN: return DIKS_PAGE_DOWN; case K_NUM: return DIKS_NUM_LOCK; case K_HOLD: return DIKS_SCROLL_LOCK; case K_PAUSE: return DIKS_PAUSE; case K_BREAK: return DIKS_BREAK; case K_CAPS: return DIKS_CAPS_LOCK; case K_P0: return DIKS_INSERT; case K_P1: return DIKS_END; case K_P2: return DIKS_CURSOR_DOWN; case K_P3: return DIKS_PAGE_DOWN; case K_P4: return DIKS_CURSOR_LEFT; case K_P5: return DIKS_BEGIN; case K_P6: return DIKS_CURSOR_RIGHT; case K_P7: return DIKS_HOME; case K_P8: return DIKS_CURSOR_UP; case K_P9: return DIKS_PAGE_UP; case K_PPLUS: return DIKS_PLUS_SIGN; case K_PMINUS: return DIKS_MINUS_SIGN; case K_PSTAR: return DIKS_ASTERISK; case K_PSLASH: return DIKS_SLASH; case K_PENTER: return DIKS_ENTER; case K_PCOMMA: return base ? DIKS_DELETE : DIKS_COMMA; case K_PDOT: return base ? DIKS_DELETE : DIKS_PERIOD; case K_PPARENL: return DIKS_PARENTHESIS_LEFT; case K_PPARENR: return DIKS_PARENTHESIS_RIGHT; } /* special keys not in the map, hack? */ if (code == 99) return DIKS_PRINT; if (code == 124) /* keypad equal key */ return DIKS_EQUALS_SIGN; if (code == 125) /* left windows key */ return DIKS_META; if (code == 126) /* right windows key */ return DIKS_META; if (code == 127) /* context menu key */ return DIKS_SUPER; return DIKS_NULL; }
static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) { u_char acia_stat; int scancode; int break_flag; /* save frame for register dump */ kbd_pt_regs = fp; repeat: if (acia.mid_ctrl & ACIA_IRQ) if (atari_MIDI_interrupt_hook) atari_MIDI_interrupt_hook(); acia_stat = acia.key_ctrl; /* check out if the interrupt came from this ACIA */ if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ)) return; if (acia_stat & ACIA_OVRN) { /* a very fast typist or a slow system, give a warning */ /* ...happens often if interrupts were disabled for too long */ printk( KERN_DEBUG "Keyboard overrun\n" ); scancode = acia.key_data; /* Turn off autorepeating in case a break code has been lost */ del_timer( &atakeyb_rep_timer ); rep_scancode = 0; if (ikbd_self_test) /* During self test, don't do resyncing, just process the code */ goto interpret_scancode; else if (IS_SYNC_CODE(scancode)) { /* This code seem already to be the start of a new packet or a * single scancode */ kb_state.state = KEYBOARD; goto interpret_scancode; } else { /* Go to RESYNC state and skip this byte */ kb_state.state = RESYNC; kb_state.len = 1; /* skip max. 1 another byte */ goto repeat; } } if (acia_stat & ACIA_RDRF) /* received a character */ { scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */ mark_bh(KEYBOARD_BH); interpret_scancode: switch (kb_state.state) { case KEYBOARD: switch (scancode) { case 0xF7: kb_state.state = AMOUSE; kb_state.len = 0; break; case 0xF8: case 0xF9: case 0xFA: case 0xFB: kb_state.state = RMOUSE; kb_state.len = 1; kb_state.buf[0] = scancode; break; case 0xFC: kb_state.state = CLOCK; kb_state.len = 0; break; case 0xFE: case 0xFF: kb_state.state = JOYSTICK; kb_state.len = 1; kb_state.buf[0] = scancode; break; case 0xF1: /* during self-test, note that 0xf1 received */ if (ikbd_self_test) { ++ikbd_self_test; self_test_last_rcv = jiffies; break; } /* FALL THROUGH */ default: break_flag = scancode & BREAK_MASK; scancode &= ~BREAK_MASK; if (ikbd_self_test) { /* Scancodes sent during the self-test stand for broken * keys (keys being down). The code *should* be a break * code, but nevertheless some AT keyboard interfaces send * make codes instead. Therefore, simply ignore * break_flag... * */ int keyval = plain_map[scancode], keytyp; set_bit( scancode, broken_keys ); self_test_last_rcv = jiffies; keyval = plain_map[scancode]; keytyp = KTYP(keyval) - 0xf0; keyval = KVAL(keyval); printk( KERN_WARNING "Key with scancode %d ", scancode ); if (keytyp == KT_LATIN || keytyp == KT_LETTER) { if (keyval < ' ') printk( "('^%c') ", keyval + '@' ); else printk( "('%c') ", keyval ); } printk( "is broken -- will be ignored.\n" ); break; } else if (test_bit( scancode, broken_keys )) break; if (break_flag) { del_timer( &atakeyb_rep_timer ); rep_scancode = 0; } else { del_timer( &atakeyb_rep_timer ); rep_scancode = scancode; atakeyb_rep_timer.expires = jiffies + key_repeat_delay; atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL; add_timer( &atakeyb_rep_timer ); } handle_scancode(break_flag | scancode); break; } break; case AMOUSE: kb_state.buf[kb_state.len++] = scancode; if (kb_state.len == 5) { kb_state.state = KEYBOARD; /* not yet used */ /* wake up someone waiting for this */ } break; case RMOUSE: kb_state.buf[kb_state.len++] = scancode; if (kb_state.len == 3) { kb_state.state = KEYBOARD; if (atari_mouse_interrupt_hook) atari_mouse_interrupt_hook(kb_state.buf); } break; case JOYSTICK: kb_state.buf[1] = scancode; kb_state.state = KEYBOARD; atari_joystick_interrupt(kb_state.buf); break; case CLOCK: kb_state.buf[kb_state.len++] = scancode; if (kb_state.len == 6) { kb_state.state = KEYBOARD; /* wake up someone waiting for this. But will this ever be used, as Linux keeps its own time. Perhaps for synchronization purposes? */ /* wake_up_interruptible(&clock_wait); */ } break; case RESYNC: if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) { kb_state.state = KEYBOARD; goto interpret_scancode; } kb_state.len--; break; } } #if 0 if (acia_stat & ACIA_CTS) /* cannot happen */; #endif if (acia_stat & (ACIA_FE | ACIA_PE)) { printk("Error in keyboard communication\n"); } /* handle_scancode() can take a lot of time, so check again if * some character arrived */ goto repeat; }
static int keyboard_notifier_call(struct notifier_block *blk, unsigned long code, void *_param) { struct keyboard_notifier_param *param = _param; struct vc_data *vc = param->vc; int ret = NOTIFY_OK; if (!param->down) return ret; switch (code) { case KBD_KEYCODE: if (console_show) { if (param->value == BRAILLE_KEY) { console_show = 0; beep(880); vc_maybe_cursor_moved(vc); vc_refresh(vc); ret = NOTIFY_STOP; } } else { ret = NOTIFY_STOP; switch (param->value) { case KEY_INSERT: beep(440); console_show = 1; lastVC = -1; braille_write(console_buf); break; case KEY_LEFT: if (vc_x > 0) { vc_x -= WIDTH; if (vc_x < 0) vc_x = 0; } else if (vc_y >= 1) { beep(880); vc_y--; vc_x = vc->vc_cols-WIDTH; } else beep(220); break; case KEY_RIGHT: if (vc_x + WIDTH < vc->vc_cols) { vc_x += WIDTH; } else if (vc_y + 1 < vc->vc_rows) { beep(880); vc_y++; vc_x = 0; } else beep(220); break; case KEY_DOWN: if (vc_y + 1 < vc->vc_rows) vc_y++; else beep(220); break; case KEY_UP: if (vc_y >= 1) vc_y--; else beep(220); break; case KEY_HOME: vc_follow_cursor(vc); break; case KEY_PAGEUP: vc_x = 0; vc_y = 0; break; case KEY_PAGEDOWN: vc_x = 0; vc_y = vc->vc_rows-1; break; default: ret = NOTIFY_OK; break; } if (ret == NOTIFY_STOP) vc_refresh(vc); } break; case KBD_POST_KEYSYM: { unsigned char type = KTYP(param->value) - 0xf0; if (type == KT_SPEC) { unsigned char val = KVAL(param->value); int on_off = -1; switch (val) { case KVAL(K_CAPS): on_off = vc_kbd_led(kbd_table + fg_console, VC_CAPSLOCK); break; case KVAL(K_NUM): on_off = vc_kbd_led(kbd_table + fg_console, VC_NUMLOCK); break; case KVAL(K_HOLD): on_off = vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK); break; } if (on_off == 1) beep(880); else if (on_off == 0) beep(440); } } case KBD_UNBOUND_KEYCODE: case KBD_UNICODE: case KBD_KEYSYM: /* Unused */ break; } return ret; }
static int kbd(int noblock) { unsigned char dt, brk, val; unsigned code; loop: if (noblock) { if ((inb(KBSTATP) & KBINRDY) == 0) return (-1); } else while((inb(KBSTATP) & KBINRDY) == 0) ; dt = inb(KBDATAP); brk = dt & 0x80; /* brk == 1 on key release */ dt = dt & 0x7f; /* keycode */ if (shfts) code = shift_map[dt]; else if (ctls) code = ctrl_map[dt]; else code = plain_map[dt]; val = KVAL(code); switch (KTYP(code) & 0x0f) { case KT_LATIN: if (brk) break; if (alts) val |= 0x80; if (val == 0x7f) /* map delete to backspace */ val = '\b'; return val; case KT_LETTER: if (brk) break; if (caps) val -= 'a'-'A'; return val; case KT_SPEC: if (brk) break; if (val == KVAL(K_CAPS)) caps = !caps; else if (val == KVAL(K_ENTER)) { enter: /* Wait for key up */ while (1) { while((inb(KBSTATP) & KBINRDY) == 0) ; dt = inb(KBDATAP); if (dt & 0x80) /* key up */ break; } return 10; } break; case KT_PAD: if (brk) break; if (val < 10) return val; if (val == KVAL(K_PENTER)) goto enter; break; case KT_SHIFT: switch (val) { case KG_SHIFT: case KG_SHIFTL: case KG_SHIFTR: shfts = brk ? 0 : 1; break; case KG_ALT: case KG_ALTGR: alts = brk ? 0 : 1; break; case KG_CTRL: case KG_CTRLL: case KG_CTRLR: ctls = brk ? 0 : 1; break; } break; case KT_LOCK: switch (val) { case KG_SHIFT: case KG_SHIFTL: case KG_SHIFTR: if (brk) shfts = !shfts; break; case KG_ALT: case KG_ALTGR: if (brk) alts = !alts; break; case KG_CTRL: case KG_CTRLL: case KG_CTRLR: if (brk) ctls = !ctls; break; } break; } if (brk) return (-1); /* Ignore initial 'key up' codes */ goto loop; }
static void keyboard_console_handler(void) { unsigned char buffer[128], scancode; int pressed, repeated, num_bytes, i, key, extended; int vt, orig_vt; struct kbentry entry; struct vt_stat vt_state; num_bytes = read(key_fd, &buffer, sizeof(buffer)); if (num_bytes > 0) { for (i = 0; i < num_bytes; i++) { scancode = kernel_to_scancode[buffer[i] & 0x7F]; pressed = (buffer[i] & 0x80) ^ 0x80; repeated = pressed && key_state[scancode]; key_state[scancode] = pressed; /* Since we took over keyboard control, we have to map our keypresses to ascii * in order to report them in our own keyboard buffer */ extended = 0; switch (scancode) { case SC_CAPSLOCK: if (pressed) key_leds ^= LED_CAP; break; case SC_NUMLOCK: if (pressed) key_leds ^= LED_NUM; break; case SC_SCROLLLOCK: if (pressed) key_leds ^= LED_SCR; break; default: extended = fb_hScancodeToExtendedKey( scancode ); break; } /* Fill in kbentry struct for KDGKBENT query */ entry.kb_table = 0; /* modifier table */ if (key_state[SC_LSHIFT] || key_state[SC_RSHIFT]) entry.kb_table |= 0x1; if (key_state[SC_ALTGR]) entry.kb_table |= 0x2; if (key_state[SC_CONTROL]) entry.kb_table |= 0x4; if (key_state[SC_ALT]) entry.kb_table |= 0x8; entry.kb_index = scancode; /* keycode */ ioctl(key_fd, KDGKBENT, &entry); if (scancode == SC_BACKSPACE) key = 8; else if (entry.kb_value == K_NOSUCHMAP) key = 0; else { key = KVAL(entry.kb_value); switch (KTYP(entry.kb_value)) { case KT_LETTER: if (key_leds & LED_CAP) key ^= 0x20; break; case KT_LATIN: case KT_ASCII: break; case KT_PAD: if (key < NUM_PAD_KEYS) { if (key_leds & LED_NUM) key = pad_numlock_ascii[key]; else key = pad_ascii[key]; } else key = 0; break; case KT_SPEC: if (scancode == SC_ENTER) key = '\r'; break; case KT_CONS: vt = key + 1; if( pressed && (ioctl(key_fd, VT_GETSTATE, &vt_state) >= 0) ) { orig_vt = vt_state.v_active; if (vt != orig_vt) { if (__fb_con.gfx_exit) { gfx_save(); ioctl(key_fd, KDSETMODE, KD_TEXT); } ioctl(key_fd, VT_ACTIVATE, vt); ioctl(key_fd, VT_WAITACTIVE, vt); while (ioctl(key_fd, VT_WAITACTIVE, orig_vt) < 0) usleep(50000); if (__fb_con.gfx_exit) { ioctl(key_fd, KDSETMODE, KD_GRAPHICS); gfx_restore(); } memset(key_state, FALSE, 128); } else { key_state[scancode] = FALSE; } extended = 0; } /* fallthrough */ default: key = 0; break; } } if( extended ) key = extended; if( pressed && key ) { key_buffer[key_tail] = key; if (((key_tail + 1) & (KEY_BUFFER_SIZE - 1)) == key_head) key_head = (key_head + 1) & (KEY_BUFFER_SIZE - 1); key_tail = (key_tail + 1) & (KEY_BUFFER_SIZE - 1); } if( gfx_key_handler ) gfx_key_handler( pressed, repeated, scancode, key ); } } /* CTRL + C */ if( key_state[SC_CONTROL] && key_state[SC_C] ) kill(main_pid, SIGINT); }