📄 pc_keyb.c
字号:
scancode);#endif return 0; } } } else if (scancode >= SC_LIM) { /* This happens with the FOCUS 9000 keyboard Its keys PF1..PF12 are reported to generate 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f Moreover, unless repeated, they do not generate key-down events, so we have to zero up_flag below */ /* Also, Japanese 86/106 keyboards are reported to generate 0x73 and 0x7d for \ - and \ | respectively. */ /* Also, some Brazilian keyboard is reported to produce 0x73 and 0x7e for \ ? and KP-dot, respectively. */ *keycode = high_keys[scancode - SC_LIM]; if (!*keycode) { if (!raw_mode) {#ifdef KBD_REPORT_UNKN printk(KERN_INFO "keyboard: unrecognized scancode (%02x)" " - ignored\n", scancode);#endif } return 0; } } else *keycode = scancode; return 1;}char pckbd_unexpected_up(unsigned char keycode){ /* unexpected, but this can happen: maybe this was a key release for a FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ if (keycode >= SC_LIM || keycode == 85) return 0; else return 0200;}int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data) {#if defined CONFIG_PSMOUSE unsigned long flags; if (rqst == PM_RESUME) { if (queue) { /* Aux port detected */ if (aux_count == 0) { /* Mouse not in use */ spin_lock_irqsave(&kbd_controller_lock, flags); /* * Dell Lat. C600 A06 enables mouse after resume. * When user touches the pad, it posts IRQ 12 * (which we do not process), thus holding keyboard. */ kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */ kb_wait(); kbd_write_command(KBD_CCMD_WRITE_MODE); kb_wait(); kbd_write_output(AUX_INTS_OFF); spin_unlock_irqrestore(&kbd_controller_lock, flags); } } }#endif return 0;}static inline void handle_mouse_event(unsigned char scancode){#ifdef CONFIG_PSMOUSE static unsigned char prev_code;// printk ("PS/2 mouse scancode is %x\n",scancode); if (mouse_reply_expected) { if (scancode == AUX_ACK) { mouse_reply_expected--; return; } mouse_reply_expected = 0; } else if(scancode == AUX_RECONNECT2 && prev_code == AUX_RECONNECT1 && aux_reconnect) { printk (KERN_INFO "PS/2 mouse reconnect detected\n"); queue->head = queue->tail = 0; /* Flush input queue */ __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ return; } prev_code = scancode; add_mouse_randomness(scancode); if (aux_count) { int head = queue->head; queue->buf[head] = scancode; head = (head + 1) & (AUX_BUF_SIZE-1); if (head != queue->tail) { queue->head = head; kill_fasync(&queue->fasync, SIGIO, POLL_IN); wake_up_interruptible(&queue->proc_list); } }#endif}static unsigned char kbd_exists = 1;static inline void handle_keyboard_event(unsigned char scancode){#ifdef CONFIG_VT kbd_exists = 1; if (do_acknowledge(scancode)) handle_scancode(scancode, !(scancode & 0x80));#endif tasklet_schedule(&keyboard_tasklet);} /* * This reads the keyboard status port, and does the * appropriate action. * * It requires that we hold the keyboard controller * spinlock. */static unsigned char handle_kbd_event(void){ unsigned char status = kbd_read_status(); unsigned int work = 10000; while ((--work > 0) && (status & KBD_STAT_OBF)) { unsigned char scancode; scancode = kbd_read_input(); /* Error bytes must be ignored to make the Synaptics touchpads compaq use work */#if 1 /* Ignore error bytes */ if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))#endif {// printk("cao enter kbd_int status is %x\n",status); if (status & KBD_STAT_MOUSE_OBF) handle_mouse_event(scancode); else handle_keyboard_event(scancode); } status = kbd_read_status(); } if (!work) printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n", status); return status;}static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs){#ifdef CONFIG_VT kbd_pt_regs = regs;#endif//printk("cao into keyboard_int irq is %d\n",irq); spin_lock_irq(&kbd_controller_lock); handle_kbd_event(); spin_unlock_irq(&kbd_controller_lock);}/* * send_data sends a character to the keyboard and waits * for an acknowledge, possibly retrying if asked to. Returns * the success status. * * Don't use 'jiffies', so that we don't depend on interrupts */static int send_data(unsigned char data){ int retries = 3; do { unsigned long timeout = KBD_TIMEOUT; acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */ resend = 0; reply_expected = 1; kbd_write_output_w(data); for (;;) { if (acknowledge) return 1; if (resend) break; mdelay(1); if (!--timeout) {#ifdef KBD_REPORT_TIMEOUTS printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?(%02x)\n", data);#endif return 0; } } } while (retries-- > 0);#ifdef KBD_REPORT_TIMEOUTS printk(KERN_WARNING "keyboard: Too many NACKs -- noisy kbd cable?\n");#endif return 0;}void pckbd_leds(unsigned char leds){ if (kbd_exists && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) { send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */ kbd_exists = 0; }}#define DEFAULT_KEYB_REP_DELAY 250#define DEFAULT_KEYB_REP_RATE 30 /* cps */static struct kbd_repeat kbdrate={ DEFAULT_KEYB_REP_DELAY, DEFAULT_KEYB_REP_RATE};static unsigned char parse_kbd_rate(struct kbd_repeat *r){ static struct r2v{ int rate; unsigned char val; } kbd_rates[]={ {5,0x14}, {7,0x10}, {10,0x0c}, {15,0x08}, {20,0x04}, {25,0x02}, {30,0x00} }; static struct d2v{ int delay; unsigned char val; } kbd_delays[]={{250,0}, {500,1}, {750,2}, {1000,3} }; int rate=0,delay=0; if (r != NULL){ int i,new_rate=30,new_delay=250; if (r->rate <= 0) r->rate=kbdrate.rate; if (r->delay <= 0) r->delay=kbdrate.delay; for (i=0; i < sizeof(kbd_rates)/sizeof(struct r2v); i++) if (kbd_rates[i].rate == r->rate){ new_rate=kbd_rates[i].rate; rate=kbd_rates[i].val; break; } for (i=0; i < sizeof(kbd_delays)/sizeof(struct d2v); i++) if (kbd_delays[i].delay == r->delay){ new_delay=kbd_delays[i].delay; delay=kbd_delays[i].val; break; } r->rate=new_rate; r->delay=new_delay; } return (delay << 5) | rate;}static int write_kbd_rate(unsigned char r){ if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)){ send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */ return 0; }else return 1;}static int pckbd_rate(struct kbd_repeat *rep){ if (rep == NULL) return -EINVAL; else{ unsigned char r=parse_kbd_rate(rep); struct kbd_repeat old_rep; memcpy(&old_rep,&kbdrate,sizeof(struct kbd_repeat)); if (write_kbd_rate(r)){ memcpy(&kbdrate,rep,sizeof(struct kbd_repeat)); memcpy(rep,&old_rep,sizeof(struct kbd_repeat)); return 0; } } return -EIO;}/* * In case we run on a non-x86 hardware we need to initialize both the * keyboard controller and the keyboard. On a x86, the BIOS will * already have initialized them. * * Some x86 BIOSes do not correctly initialize the keyboard, so the * "kbd-reset" command line options can be given to force a reset. * [Ranger] */#ifdef __i386__ int kbd_startup_reset __initdata = 0;#else int kbd_startup_reset __initdata = 1;#endif/* for "kbd-reset" cmdline param */static int __init kbd_reset_setup(char *str){ kbd_startup_reset = 1; return 1;}__setup("kbd-reset", kbd_reset_setup);#define KBD_NO_DATA (-1) /* No data */#define KBD_BAD_DATA (-2) /* Parity or other error */static int __init kbd_read_data(void){ int retval = KBD_NO_DATA; unsigned char status; status = kbd_read_status(); if (status & KBD_STAT_OBF) { unsigned char data = kbd_read_input(); retval = data; if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) retval = KBD_BAD_DATA; } return retval;}static void __init kbd_clear_input(void){ int maxread = 100; /* Random number */ do { if (kbd_read_data() == KBD_NO_DATA) break; } while (--maxread);}static int __init kbd_wait_for_input(void){ long timeout = KBD_INIT_TIMEOUT; do { int retval = kbd_read_data(); if (retval >= 0) return retval; mdelay(1); } while (--timeout); return -1;}static void kbd_write_command_w(int data){ unsigned long flags; spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); kbd_write_command(data); spin_unlock_irqrestore(&kbd_controller_lock, flags);}static void kbd_write_output_w(int data){ unsigned long flags; spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); kbd_write_output(data); spin_unlock_irqrestore(&kbd_controller_lock, flags);}#if defined(__alpha__) || defined(CONFIG_ARCH_EDB7312)/* * Some Alphas cannot mask some/all interrupts, so we have to * make sure not to allow interrupts AT ALL when polling for * specific return values from the keyboard. * * I think this should work on any architecture, but for now, only Alpha. */static int kbd_write_command_w_and_wait(int data){ unsigned long flags; int input; spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); kbd_write_command(data); input = kbd_wait_for_input(); spin_unlock_irqrestore(&kbd_controller_lock, flags); return input;}static int kbd_write_output_w_and_wait(int data){ unsigned long flags; int input; spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); kbd_write_output(data); input = kbd_wait_for_input(); spin_unlock_irqrestore(&kbd_controller_lock, flags); return input;}#elsestatic int kbd_write_command_w_and_wait(int data){ kbd_write_command_w(data); return kbd_wait_for_input();}static int kbd_write_output_w_and_wait(int data){ kbd_write_output_w(data); return kbd_wait_for_input();}#endif /* __alpha__ */#if defined CONFIG_PSMOUSEstatic void kbd_write_cmd(int cmd){ unsigned long flags; spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); kbd_write_command(KBD_CCMD_WRITE_MODE); kb_wait(); kbd_write_output(cmd); spin_unlock_irqrestore(&kbd_controller_lock, flags);}#endif /* CONFIG_PSMOUSE */static char * __init initialize_kbd(void){ int status; /* * Test the keyboard interface. * This seems to be the only way to get it going. * If the test is successful a x55 is placed in the input buffer. */ kbd_write_command_w(KBD_CCMD_SELF_TEST); if (kbd_wait_for_input() != 0x55) return "Keyboard failed self test"; /* * Perform a keyboard interface test. This causes the controller * to test the keyboard clock and data lines. The results of the * test are placed in the input buffer. */ kbd_write_command_w(KBD_CCMD_KBD_TEST); if (kbd_wait_for_input() != 0x00) return "Keyboard interface failed self test"; /* * Enable the keyboard by allowing the keyboard clock to run. */ kbd_write_command_w(KBD_CCMD_KBD_ENABLE); /* * Reset keyboard. If the read times out * then the assumption is that no keyboard is * plugged into the machine. * This defaults the keyboard to scan-code set 2. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -