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); }
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; }
/* This is our keyboard 'interrupt' routine. * Must run under sunkbd_lock. */ static void __sunkbd_inchar(unsigned char ch, struct pt_regs *regs) { unsigned char keycode; char up_flag; /* 0 or SUNKBD_UBIT */ char raw_mode; if(ch == SKBD_RESET) { kbd_reset_pending = 1; goto out; } if(ch == SKBD_LYOUT) { kbd_layout_pending = 1; goto out; } if(kbd_reset_pending) { sunkbd_type = ch; kbd_reset_pending = 0; if(ch == SUNKBD_TYPE4) send_cmd(SKBDCMD_GLAYOUT); goto out; } else if(kbd_layout_pending) { sunkbd_layout = ch; kbd_layout_pending = 0; goto out; } else if(ch == SKBD_ALLUP) { del_timer (&auto_repeat_timer); memset(key_down, 0, sizeof(key_down)); sun_compute_shiftstate(); goto out; } #ifdef SKBD_DEBUG if(ch == 0x7f) printk("KBD<ALL KEYS UP>"); else printk("KBD<%x %s>", ch, ((ch&0x80) ? "UP" : "DOWN")); #endif /* Whee, a real character. */ if(regs) { pt_regs = regs; last_keycode = keycode = ch; } else { keycode = ch; } do_poke_blanked_console = 1; tasklet_schedule(&console_tasklet); add_keyboard_randomness(keycode); tty = ttytab? ttytab[fg_console]: NULL; if (tty && (!tty->driver_data)) { /* This is to workaround ugly bug in tty_io.c, which does not do locking when it should */ tty = NULL; } kbd = kbd_table + fg_console; if((raw_mode = (kbd->kbdmode == VC_RAW))) { if (kbd_redirected == fg_console+1) push_kbd (keycode); else put_queue(keycode); /* we do not return yet, because we want to maintain * the key_down array, so that we have the correct * values when finishing RAW mode or when changing VT's. */ } up_flag = (keycode & SUNKBD_UBIT); /* The 'up' bit */ keycode &= SUNKBD_KMASK; /* all the rest */ del_timer (&auto_repeat_timer); if(up_flag) { rep = 0; clear_bit(keycode, key_down); } else { if (!norepeat_keys[keycode]) { if (kbd_rate_ticks) { auto_repeat_timer.expires = jiffies + kbd_delay_ticks; add_timer (&auto_repeat_timer); } } rep = test_and_set_bit(keycode, key_down); } #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq hack */ if (l1a_state.l1_down) { if (!up_flag) handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty); goto out; } #endif if(raw_mode) goto out; if(kbd->kbdmode == VC_MEDIUMRAW) { put_queue(keycode + up_flag); goto out; } /* * Small change in philosophy: earlier we defined repetition by * rep = keycode == prev_keycode; * prev_keycode = keycode; * but now by the fact that the depressed key was down already. * Does this ever make a difference? Yes. */ /* * Repeat a key only if the input buffers are empty or the * characters get echoed locally. This makes key repeat usable * with slow applications and under heavy loads. */ if (!rep || (vc_kbd_mode(kbd,VC_REPEAT) && tty && (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) { u_short keysym; u_char type; /* the XOR below used to be an OR */ int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate; ushort *key_map = key_maps[shift_final]; if (key_map != NULL) { keysym = key_map[keycode]; type = KTYP(keysym); if (type >= 0xf0) { type -= 0xf0; if (type == KT_LETTER) { type = KT_LATIN; if (vc_kbd_led(kbd, VC_CAPSLOCK)) { key_map = key_maps[shift_final ^ (1<<KG_SHIFT)]; if (key_map) keysym = key_map[keycode]; } } (*key_handler[type])(keysym & 0xff, up_flag); if (type != KT_SLOCK) kbd->slockstate = 0; } } else { /* maybe beep? */ /* we have at least to update shift_state */ sun_compute_shiftstate(); } } out: tasklet_schedule(&keyboard_tasklet); }
static void keyboard_interrupt(int int_pt_regs) { unsigned char scancode; static unsigned int prev_scancode = 0; /* remember E0, E1 */ char up_flag; /* 0 or 0200 */ char raw_mode; pt_regs = (struct pt_regs *) int_pt_regs; send_cmd(0xAD); /* disable keyboard */ kb_wait(); if ((inb_p(0x64) & kbd_read_mask) != 0x01) goto end_kbd_intr; scancode = inb(0x60); mark_bh(KEYBOARD_BH); if (scancode == 0xfa) { acknowledge = 1; goto end_kbd_intr; } else if (scancode == 0xfe) { resend = 1; goto end_kbd_intr; } else if (scancode == 0) { #ifdef KBD_REPORT_ERR printk("keyboard buffer overflow\n"); #endif goto end_kbd_intr; } else if (scancode == 0xff) { #ifdef KBD_REPORT_ERR printk("keyboard error\n"); #endif prev_scancode = 0; goto end_kbd_intr; } tty = ttytab[fg_console]; kbd = kbd_table + fg_console; if ((raw_mode = vc_kbd_mode(kbd,VC_RAW))) { put_queue(scancode); /* we do not return yet, because we want to maintain the key_down array, so that we have the correct values when finishing RAW mode or when changing VT's */ } if (scancode == 0xe0 || scancode == 0xe1) { prev_scancode = scancode; goto end_kbd_intr; } /* * Convert scancode to keysym, using prev_scancode. */ up_flag = (scancode & 0200); scancode &= 0x7f; if (prev_scancode) { /* * usually it will be 0xe0, but a Pause key generates * e1 1d 45 e1 9d c5 when pressed, and nothing when released */ if (prev_scancode != 0xe0) { if (prev_scancode == 0xe1 && scancode == 0x1d) { prev_scancode = 0x100; goto end_kbd_intr; } else if (prev_scancode == 0x100 && scancode == 0x45) { scancode = E1_PAUSE; prev_scancode = 0; } else { printk("keyboard: unknown e1 escape sequence\n"); prev_scancode = 0; goto end_kbd_intr; } } else { prev_scancode = 0; /* * The keyboard maintains its own internal caps lock and * num lock statuses. In caps lock mode E0 AA precedes make * code and E0 2A follows break code. In num lock mode, * E0 2A precedes make code and E0 AA follows break code. * We do our own book-keeping, so we will just ignore these. */ /* * For my keyboard there is no caps lock mode, but there are * both Shift-L and Shift-R modes. The former mode generates * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs. * So, we should also ignore the latter. - [email protected] */ if (scancode == 0x2a || scancode == 0x36) goto end_kbd_intr; if (e0_keys[scancode]) scancode = e0_keys[scancode]; else if (!raw_mode) { #ifdef KBD_REPORT_UNKN printk("keyboard: unknown scancode e0 %02x\n", scancode); #endif goto end_kbd_intr; } } } else if (scancode >= E0_BASE && !raw_mode) { #ifdef KBD_REPORT_UNKN printk("keyboard: scancode (%02x) not in range 00 - %2x\n", scancode, E0_BASE - 1); #endif goto end_kbd_intr; } /* * At this point the variable `scancode' contains the keysym. * We keep track of the up/down status of the key, and * return the keysym if in MEDIUMRAW mode. * (Note: earlier kernels had a bug and did not pass the up/down * bit to applications.) */ if (up_flag) { clear_bit(scancode, key_down); rep = 0; } else rep = set_bit(scancode, key_down); if (raw_mode) goto end_kbd_intr; if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) { put_queue(scancode + up_flag); goto end_kbd_intr; } /* * Small change in philosophy: earlier we defined repetition by * rep = scancode == prev_keysym; * prev_keysym = scancode; * but now by the fact that the depressed key was down already. * Does this ever make a difference? */ /* * Repeat a key only if the input buffers are empty or the * characters get echoed locally. This makes key repeat usable * with slow applications and under heavy loads. */ if (!rep || (vc_kbd_mode(kbd,VC_REPEAT) && tty && (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) { u_short key_code; u_char type; /* the XOR below used to be an OR */ int shift_final = shift_state ^ kbd->lockstate; key_code = key_map[shift_final][scancode]; type = KTYP(key_code); if (type == KT_LETTER) { type = KT_LATIN; if (vc_kbd_led(kbd,VC_CAPSLOCK)) key_code = key_map[shift_final ^ (1<<KG_SHIFT)][scancode]; } (*key_handler[type])(key_code & 0xff, up_flag); } end_kbd_intr: send_cmd(0xAE); /* enable keyboard */ }