?? lkkbd.c
字號:
switch (lk->id[2]) { case 0x00: /* All okay */ break; case LK_STUCK_KEY: printk (KERN_ERR "lkkbd: Stuck key on keyboard at " "%s\n", lk->phys); break; case LK_SELFTEST_FAILED: printk (KERN_ERR "lkkbd: Selftest failed on keyboard " "at %s, keyboard may not work " "properly\n", lk->phys); break; default: printk (KERN_ERR "lkkbd: Unknown error %02x on " "keyboard at %s\n", lk->id[2], lk->phys); break; } /* * Try to hint user if there's a stuck key. */ if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0) printk (KERN_ERR "Scancode of stuck key is 0x%02x, keycode " "is 0x%04x\n", lk->id[3], lk->keycode[lk->id[3]]); return;}/* * lkkbd_interrupt() is called by the low level driver when a character * is received. */static irqreturn_tlkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs){ struct lkkbd *lk = serio_get_drvdata (serio); int i; DBG (KERN_INFO "Got byte 0x%02x\n", data); if (lk->ignore_bytes > 0) { DBG (KERN_INFO "Ignoring a byte on %s\n", lk->name); lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; if (lk->ignore_bytes == 0) lkkbd_detection_done (lk); return IRQ_HANDLED; } switch (data) { case LK_ALL_KEYS_UP: input_regs (&lk->dev, regs); for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++) if (lk->keycode[i] != KEY_RESERVED) input_report_key (&lk->dev, lk->keycode[i], 0); input_sync (&lk->dev); break; case LK_METRONOME: DBG (KERN_INFO "Got LK_METRONOME and don't " "know how to handle...\n"); break; case LK_OUTPUT_ERROR: DBG (KERN_INFO "Got LK_OUTPUT_ERROR and don't " "know how to handle...\n"); break; case LK_INPUT_ERROR: DBG (KERN_INFO "Got LK_INPUT_ERROR and don't " "know how to handle...\n"); break; case LK_KBD_LOCKED: DBG (KERN_INFO "Got LK_KBD_LOCKED and don't " "know how to handle...\n"); break; case LK_KBD_TEST_MODE_ACK: DBG (KERN_INFO "Got LK_KBD_TEST_MODE_ACK and don't " "know how to handle...\n"); break; case LK_PREFIX_KEY_DOWN: DBG (KERN_INFO "Got LK_PREFIX_KEY_DOWN and don't " "know how to handle...\n"); break; case LK_MODE_CHANGE_ACK: DBG (KERN_INFO "Got LK_MODE_CHANGE_ACK and ignored " "it properly...\n"); break; case LK_RESPONSE_RESERVED: DBG (KERN_INFO "Got LK_RESPONSE_RESERVED and don't " "know how to handle...\n"); break; case 0x01: DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n"); lk->ignore_bytes = LK_NUM_IGNORE_BYTES; lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; schedule_work (&lk->tq); break; default: if (lk->keycode[data] != KEY_RESERVED) { input_regs (&lk->dev, regs); if (!test_bit (lk->keycode[data], lk->dev.key)) input_report_key (&lk->dev, lk->keycode[data], 1); else input_report_key (&lk->dev, lk->keycode[data], 0); input_sync (&lk->dev); } else printk (KERN_WARNING "%s: Unknown key with " "scancode 0x%02x on %s.\n", __FILE__, data, lk->name); } return IRQ_HANDLED;}/* * lkkbd_event() handles events from the input module. */static intlkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, int value){ struct lkkbd *lk = dev->private; unsigned char leds_on = 0; unsigned char leds_off = 0; switch (type) { case EV_LED: CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK); CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE); CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK); CHECK_LED (LED_SLEEP, LK_LED_WAIT); if (leds_on != 0) { lk->serio->write (lk->serio, LK_CMD_LED_ON); lk->serio->write (lk->serio, leds_on); } if (leds_off != 0) { lk->serio->write (lk->serio, LK_CMD_LED_OFF); lk->serio->write (lk->serio, leds_off); } return 0; case EV_SND: switch (code) { case SND_CLICK: if (value == 0) { DBG ("%s: Deactivating key clicks\n", __FUNCTION__); lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); } else { DBG ("%s: Activating key clicks\n", __FUNCTION__); lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); } return 0; case SND_BELL: if (value != 0) lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); return 0; } break; default: printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n", __FUNCTION__, type, code, value); } return -1;}/* * lkkbd_reinit() sets leds and beeps to a state the computer remembers they * were in. */static voidlkkbd_reinit (void *data){ struct lkkbd *lk = data; int division; unsigned char leds_on = 0; unsigned char leds_off = 0; /* Ask for ID */ lk->serio->write (lk->serio, LK_CMD_REQUEST_ID); /* Reset parameters */ lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS); /* Set LEDs */ CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK); CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE); CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK); CHECK_LED (LED_SLEEP, LK_LED_WAIT); if (leds_on != 0) { lk->serio->write (lk->serio, LK_CMD_LED_ON); lk->serio->write (lk->serio, leds_on); } if (leds_off != 0) { lk->serio->write (lk->serio, LK_CMD_LED_OFF); lk->serio->write (lk->serio, leds_off); } /* * Try to activate extended LK401 mode. This command will * only work with a LK401 keyboard and grants access to * LAlt, RAlt, RCompose and RShift. */ lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401); /* Set all keys to UPDOWN mode */ for (division = 1; division <= 14; division++) lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, division)); /* Enable bell and set volume */ lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL); lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume)); /* Enable/disable keyclick (and possibly set volume) */ if (test_bit (SND_CLICK, lk->dev.snd)) { lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); } else { lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); } /* Sound the bell if needed */ if (test_bit (SND_BELL, lk->dev.snd)) lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);}/* * lkkbd_connect() probes for a LK keyboard and fills the necessary structures. */static intlkkbd_connect (struct serio *serio, struct serio_driver *drv){ struct lkkbd *lk; int i; int err; if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL))) return -ENOMEM; memset (lk, 0, sizeof (struct lkkbd)); init_input_dev (&lk->dev); set_bit (EV_KEY, lk->dev.evbit); set_bit (EV_LED, lk->dev.evbit); set_bit (EV_SND, lk->dev.evbit); set_bit (EV_REP, lk->dev.evbit); set_bit (LED_CAPSL, lk->dev.ledbit); set_bit (LED_SLEEP, lk->dev.ledbit); set_bit (LED_COMPOSE, lk->dev.ledbit); set_bit (LED_SCROLLL, lk->dev.ledbit); set_bit (SND_BELL, lk->dev.sndbit); set_bit (SND_CLICK, lk->dev.sndbit); lk->serio = serio; INIT_WORK (&lk->tq, lkkbd_reinit, lk); lk->bell_volume = bell_volume; lk->keyclick_volume = keyclick_volume; lk->ctrlclick_volume = ctrlclick_volume; lk->dev.keycode = lk->keycode; lk->dev.keycodesize = sizeof (lk_keycode_t); lk->dev.keycodemax = LK_NUM_KEYCODES; lk->dev.event = lkkbd_event; lk->dev.private = lk; serio_set_drvdata (serio, lk); err = serio_open (serio, drv); if (err) { serio_set_drvdata (serio, NULL); kfree (lk); return err; } sprintf (lk->name, "DEC LK keyboard"); sprintf (lk->phys, "%s/input0", serio->phys); memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES); for (i = 0; i < LK_NUM_KEYCODES; i++) set_bit (lk->keycode[i], lk->dev.keybit); lk->dev.name = lk->name; lk->dev.phys = lk->phys; lk->dev.id.bustype = BUS_RS232; lk->dev.id.vendor = SERIO_LKKBD; lk->dev.id.product = 0; lk->dev.id.version = 0x0100; lk->dev.dev = &serio->dev; input_register_device (&lk->dev); printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys); lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); return 0;}/* * lkkbd_disconnect() unregisters and closes behind us. */static voidlkkbd_disconnect (struct serio *serio){ struct lkkbd *lk = serio_get_drvdata (serio); input_unregister_device (&lk->dev); serio_close (serio); serio_set_drvdata (serio, NULL); kfree (lk);}static struct serio_device_id lkkbd_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_LKKBD, .id = SERIO_ANY, .extra = SERIO_ANY, }, { 0 }};MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);static struct serio_driver lkkbd_drv = { .driver = { .name = "lkkbd", }, .description = DRIVER_DESC, .id_table = lkkbd_serio_ids, .connect = lkkbd_connect, .disconnect = lkkbd_disconnect, .interrupt = lkkbd_interrupt,};/* * The functions for insering/removing us as a module. */static int __initlkkbd_init (void){ serio_register_driver(&lkkbd_drv); return 0;}static void __exitlkkbd_exit (void){ serio_unregister_driver(&lkkbd_drv);}module_init (lkkbd_init);module_exit (lkkbd_exit);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -