📄 keyboard.c
字号:
* (And SCROLLOCK can also be set by the ioctl KDSETLED.) */ if (tty->stopped) start_tty(tty); else stop_tty(tty);}#if 0/* unused at present - and the VC_PAUSE bit is not used anywhere either */static void pause(void){ chg_vc_kbd_mode(kbd,VC_PAUSE);}#endifstatic void num(void){ if (vc_kbd_mode(kbd,VC_APPLIC)) { applkey('P', 1); return; } if (!rep) /* no autorepeat for numlock, ChN */ chg_vc_kbd_led(kbd,VC_NUMLOCK);}static void lastcons(void){ /* pressing alt-printscreen switches to the last used console, ChN */ want_console = last_console;}static void send_intr(void){ got_break = 1;}static void scrll_forw(void){ scrollfront(0);}static void scrll_back(void){ scrollback(0);}static void boot_it(void){ ctrl_alt_del();}static void compose(void){ dead_key_next = 1;}static void do_spec(unsigned char value, char up_flag){ typedef void (*fnp)(void); fnp fn_table[] = { NULL, enter, show_ptregs, show_mem, show_state, send_intr, lastcons, caps_toggle, num, hold, scrll_forw, scrll_back, boot_it, caps_on, compose }; if (up_flag) return; if (value >= SIZE(fn_table)) return; if (!fn_table[value]) return; fn_table[value]();}static void do_lowercase(unsigned char value, char up_flag){ printk("keyboard.c: do_lowercase was called - impossible\n");} static void do_self(unsigned char value, char up_flag){ if (up_flag) return; /* no action, if this is a key release */ if (diacr) value = handle_diacr(value); if (dead_key_next) { dead_key_next = 0; diacr = value; return; } put_queue(value);}#define A_GRAVE '`'#define A_ACUTE '\''#define A_CFLEX '^'#define A_TILDE '~'#define A_DIAER '"'static unsigned char ret_diacr[] = {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };/* If a dead key pressed twice, output a character corresponding to it, *//* otherwise just remember the dead key. */static void do_dead(unsigned char value, char up_flag){ if (up_flag) return; value = ret_diacr[value]; if (diacr == value) { /* pressed twice */ diacr = 0; put_queue(value); return; } diacr = value;}/* If space is pressed, return the character corresponding the pending *//* dead key, otherwise try to combine the two. */unsigned char handle_diacr(unsigned char ch){ int d = diacr; int i; diacr = 0; if (ch == ' ') return d; for (i = 0; i < accent_table_size; i++) if(accent_table[i].diacr == d && accent_table[i].base == ch) return accent_table[i].result; put_queue(d); return ch;}static void do_cons(unsigned char value, char up_flag){ if (up_flag) return; want_console = value;}static void do_fn(unsigned char value, char up_flag){ if (up_flag) return; if (value < SIZE(func_table)) puts_queue(func_table[value]); else printk("do_fn called with value=%d\n", value);}static void do_pad(unsigned char value, char up_flag){ static char *pad_chars = "0123456789+-*/\015,.?"; static 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 void do_cur(unsigned char value, char up_flag){ static char *cur_chars = "BDCA"; if (up_flag) return; applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));}static void do_shift(unsigned char value, char up_flag){ int old_state = shift_state; if (rep) return; /* kludge... */ if (value == KVAL(K_CAPSSHIFT)) { value = KVAL(K_SHIFT); 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 */ if (up_flag && shift_state != old_state && npadch != -1) { put_queue(npadch); npadch = -1; }}/* 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); } } }}static void do_meta(unsigned char value, char up_flag){ if (up_flag) return; if (vc_kbd_mode(kbd, VC_META)) { put_queue('\033'); put_queue(value); } else put_queue(value | 0x80);}static void do_ascii(unsigned char value, char up_flag){ if (up_flag) return; if (npadch == -1) npadch = value; else npadch = (npadch * 10 + value) % 1000;}static void do_lock(unsigned char value, char up_flag){ if (up_flag || rep) return; chg_vc_kbd_lock(kbd, value);}/* * send_data sends a character to the keyboard and waits * for a acknowledge, possibly retrying if asked to. Returns * the success status. */static int send_data(unsigned char data){ int retries = 3; int i; do { kb_wait(); acknowledge = 0; resend = 0; outb_p(data, 0x60); for(i=0; i<0x20000; i++) { inb_p(0x64); /* just as a delay */ if (acknowledge) return 1; if (resend) break; } if (!resend) return 0; } while (retries-- > 0); return 0;}/* * This routine is the bottom half of the keyboard interrupt * routine, and runs with all interrupts enabled. It does * console changing, led setting and copy_to_cooked, which can * take a reasonably long time. * * Aside from timing (which isn't really that important for * keyboard interrupts as they happen often), using the software * interrupt routines for this thing allows us to easily mask * this when we don't want any of the above to happen. Not yet * used, but this allows for easy and efficient race-condition * prevention later on. */static void kbd_bh(void * unused){ static unsigned char old_leds = 0xff; unsigned char leds = kbd_table[fg_console].ledstate; if (leds != old_leds) { old_leds = leds; if (!send_data(0xed) || !send_data(leds)) send_data(0xf4); /* re-enable kbd if any errors */ } if (want_console >= 0) { if (want_console != fg_console) { last_console = fg_console; change_console(want_console); } want_console = -1; } if (got_break) { if (tty && !I_IGNBRK(tty)) { if (I_BRKINT(tty)) { flush_input(tty); flush_output(tty); if (tty->pgrp > 0) kill_pg(tty->pgrp, SIGINT, 1); } else { cli(); if (LEFT(&tty->read_q) >= 2) { set_bit(tty->read_q.head, &tty->readq_flags); put_queue(TTY_BREAK); put_queue(0); } sti(); } } got_break = 0; } do_keyboard_interrupt(); cli(); if ((inb_p(0x64) & kbd_read_mask) == 0x01) fake_keyboard_interrupt(); sti();}long no_idt[2] = {0, 0};/* * This routine reboots the machine by asking the keyboard * controller to pulse the reset-line low. We try that for a while, * and if it doesn't work, we do some other stupid things. */void hard_reset_now(void){ int i, j; extern unsigned long pg0[1024]; sti();/* rebooting needs to touch the page at absolute addr 0 */ pg0[0] = 7; *((unsigned short *)0x472) = 0x1234; for (;;) { for (i=0; i<100; i++) { kb_wait(); for(j = 0; j < 100000 ; j++) /* nothing */; outb(0xfe,0x64); /* pulse reset low */ } __asm__("\tlidt _no_idt"); }}unsigned long kbd_init(unsigned long kmem_start){ int i; struct kbd_struct * kbd; kbd = kbd_table + 0; for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) { kbd->ledstate = KBD_DEFLEDS; kbd->default_ledstate = KBD_DEFLEDS; kbd->lockstate = KBD_DEFLOCK; kbd->modeflags = KBD_DEFMODE; } bh_base[KEYBOARD_BH].routine = kbd_bh; request_irq(KEYBOARD_IRQ,keyboard_interrupt); mark_bh(KEYBOARD_BH); return kmem_start;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -