📄 keyboard.c
字号:
if (vc_cons_allocated(i)) break; } set_console(i);}static void incr_console(void){ int i; for (i = fg_console+1; i != fg_console; i++) { if (i == MAX_NR_CONSOLES) i = 0; if (vc_cons_allocated(i)) break; } set_console(i);}static void send_intr(void){ if (!tty) return; tty_insert_flip_char(tty, 0, TTY_BREAK); con_schedule_flip(tty);}static void scroll_forw(void){ scrollfront(0);}static void scroll_back(void){ scrollback(0);}static void boot_it(void){ ctrl_alt_del();}static void compose(void){ dead_key_next = 1;}int spawnpid, spawnsig;static void spawn_console(void){ if (spawnpid) if(kill_proc(spawnpid, spawnsig, 1)) spawnpid = 0;}static void SAK(void){ /* * SAK should also work in all raw modes and reset * them properly. */ do_SAK(tty); reset_vc(fg_console);#if 0 do_unblank_screen(); /* not in interrupt routine? */#endif}static void do_ignore(unsigned char value, char up_flag){}static void do_null(void){ compute_shiftstate();}static void do_spec(unsigned char value, char up_flag){ if (up_flag) return; if (value >= SIZE(spec_fn_table)) return; if ((kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) && !(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value))) return; spec_fn_table[value]();}static void do_lowercase(unsigned char value, char up_flag){ printk(KERN_ERR "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 '"'#define A_CEDIL ','static unsigned char ret_diacr[NR_DEAD] = {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };/* Obsolete - for backwards compatibility only */static void do_dead(unsigned char value, char up_flag){ value = ret_diacr[value]; do_dead2(value,up_flag);}/* * Handle dead key. Note that we now may have several * dead keys modifying the same character. Very useful * for Vietnamese. */static void do_dead2(unsigned char value, char up_flag){ if (up_flag) return; diacr = (diacr ? handle_diacr(value) : value);}/* * We have a combining character DIACR here, followed by the character CH. * If the combination occurs in the table, return the corresponding value. * Otherwise, if CH is a space or equals DIACR, return DIACR. * Otherwise, conclude that DIACR was not combining after all, * queue it and return CH. */unsigned char handle_diacr(unsigned char ch){ int d = diacr; int i; diacr = 0; for (i = 0; i < accent_table_size; i++) { if (accent_table[i].diacr == d && accent_table[i].base == ch) return accent_table[i].result; } if (ch == ' ' || ch == d) return d; put_queue(d); return ch;}static void do_cons(unsigned char value, char up_flag){ if (up_flag) return; set_console(value);}static void do_fn(unsigned char value, char up_flag){ if (up_flag) return; if (value < SIZE(func_table)) { if (func_table[value]) puts_queue(func_table[value]); } else printk(KERN_ERR "do_fn called with value=%d\n", value);}static void do_pad(unsigned char value, char up_flag){ static const char *pad_chars = "0123456789+-*/\015,.?()#"; static const char *app_map = "pqrstuvwxylSRQMnnmPQS"; 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 const 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; /* 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 */ if (up_flag && shift_state != old_state && npadch != -1) { if (kbd->kbdmode == VC_UNICODE) to_utf8(npadch & 0xffff); else put_queue(npadch & 0xff); npadch = -1; }}/* Called after returning from RAW mode or when changing consoles - * recompute k_down[] and shift_state from key_down[] * Maybe called when keymap is undefined so that shift key release is seen */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 = U(key_maps[0][k]); if(KTYP(sym) == KT_SHIFT || KTYP(sym) == KT_SLOCK) { val = KVAL(sym); if (val == KVAL(K_CAPSSHIFT)) val = KVAL(K_SHIFT); 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){ int base; if (up_flag) return; if (value < 10) /* decimal input of code, while Alt depressed */ base = 10; else { /* hexadecimal input of code, while AltGr depressed */ value -= 10; base = 16; } if (npadch == -1) npadch = value; else npadch = npadch * base + value;}static void do_lock(unsigned char value, char up_flag){ if (up_flag || rep) return; chg_vc_kbd_lock(kbd, value);}static void do_slock(unsigned char value, char up_flag){ do_shift(value,up_flag); if (up_flag || rep) return; chg_vc_kbd_slock(kbd, value); /* try to make Alt, oops, AltGr and such work */ if (!key_maps[kbd->lockstate ^ kbd->slockstate]) { kbd->slockstate = 0; chg_vc_kbd_slock(kbd, value); }}/* * The leds display either * (i) the status of NumLock, CapsLock, ScrollLock, or * (ii) whatever pattern of lights people want to show using KDSETLED, or * (iii) specified bits of specified words in kernel memory. */static unsigned char ledstate = 0xff; /* undefined */static unsigned char ledioctl;unsigned char getledstate(void){ return ledstate;}//add by threewater for i2c ps2 keyboard modulesEXPORT_SYMBOL(getledstate);void setledstate(struct kbd_struct *kbd, unsigned int led){ if (!(led & ~7)) { ledioctl = led; kbd->ledmode = LED_SHOW_IOCTL; } else kbd->ledmode = LED_SHOW_FLAGS; set_leds();}static struct ledptr { unsigned int *addr; unsigned int mask; unsigned char valid:1;} ledptrs[3];void register_leds(int console, unsigned int led, unsigned int *addr, unsigned int mask){ struct kbd_struct *kbd = kbd_table + console; if (led < 3) { ledptrs[led].addr = addr; ledptrs[led].mask = mask; ledptrs[led].valid = 1; kbd->ledmode = LED_SHOW_MEM; } else kbd->ledmode = LED_SHOW_FLAGS;}static inline unsigned char getleds(void){ struct kbd_struct *kbd = kbd_table + fg_console; unsigned char leds; if (kbd->ledmode == LED_SHOW_IOCTL) return ledioctl; leds = kbd->ledflagstate; if (kbd->ledmode == LED_SHOW_MEM) { if (ledptrs[0].valid) { if (*ledptrs[0].addr & ledptrs[0].mask) leds |= 1; else leds &= ~1; } if (ledptrs[1].valid) { if (*ledptrs[1].addr & ledptrs[1].mask) leds |= 2; else leds &= ~2; } if (ledptrs[2].valid) { if (*ledptrs[2].addr & ledptrs[2].mask) leds |= 4; else leds &= ~4; } } return leds;}/* * 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(unsigned long dummy){ unsigned char leds = getleds(); if (rep && kbd_repeatkeycode != -1) { tty = ttytab? ttytab[fg_console]: NULL; kbd = kbd_table + fg_console; /* This prevents the kbd_key routine from being called * twice, once by this BH, and once by the interrupt * routine. */ kbd_disable_irq(); kbd_processkeycode(kbd_repeatkeycode, 0, 1); kbd_enable_irq(); } if (leds != ledstate) { ledstate = leds; kbd_leds(leds); if (kbd_ledfunc) kbd_ledfunc(leds); }}EXPORT_SYMBOL(keyboard_tasklet);DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);static void key_callback(unsigned long nr){ rep = 1; tasklet_schedule(&keyboard_tasklet);}typedef void (pm_kbd_func) (void);pm_callback pm_kbd_request_override = NULL;int __init kbd_init(void){ int i; struct kbd_struct kbd0; extern struct tty_driver console_driver; kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS; kbd0.ledmode = LED_SHOW_FLAGS; kbd0.lockstate = KBD_DEFLOCK; kbd0.slockstate = 0; kbd0.modeflags = KBD_DEFMODE; kbd0.kbdmode = VC_XLATE; for (i = 0 ; i < MAX_NR_CONSOLES ; i++) kbd_table[i] = kbd0; ttytab = console_driver.table; kbd_init_hw(); tasklet_enable(&keyboard_tasklet); tasklet_schedule(&keyboard_tasklet); pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -