📄 keyboard.c
字号:
#include <linux/kernel.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/sched.h>#include <linux/kbd_ll.h>#include "usb.h"#define PCKBD_PRESSED 0x00#define PCKBD_RELEASED 0x80#define PCKBD_NEEDS_E0 0x80#define USBKBD_MODIFIER_BASE 120#define USBKBD_KEYCODE_OFFSET 2#define USBKBD_KEYCODE_COUNT 6#define USBKBD_VALID_KEYCODE(key) ((unsigned char)(key) > 3)#define USBKBD_FIND_KEYCODE(down, key, count) \ ((unsigned char*) memscan((down), (key), (count)) < ((down) + (count)))#define USBKBD_REPEAT_DELAY (HZ / 4)#define USBKBD_REPEAT_RATE (HZ / 20)struct usb_keyboard{ struct usb_device *dev; unsigned long down[2]; unsigned char repeat_key; struct timer_list repeat_timer; struct list_head list;};extern unsigned char usb_kbd_map[];static int usb_kbd_probe(struct usb_device *dev);static void usb_kbd_disconnect(struct usb_device *dev);static void usb_kbd_repeat(unsigned long dummy);static LIST_HEAD(usb_kbd_list);static struct usb_driver usb_kbd_driver ={ "keyboard", usb_kbd_probe, usb_kbd_disconnect, {NULL, NULL}};static voidusb_kbd_handle_key(unsigned char key, int flags){ int scancode = (int) usb_kbd_map[key]; if(scancode) { if(scancode & PCKBD_NEEDS_E0) { handle_scancode(0xe0); } handle_scancode((scancode & ~PCKBD_NEEDS_E0) | flags); }}static voidusb_kbd_repeat(unsigned long dev_id){ struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id; unsigned long flags; save_flags(flags); cli(); if(kbd->repeat_key) { usb_kbd_handle_key(kbd->repeat_key, PCKBD_PRESSED); /* reset repeat timer */ kbd->repeat_timer.function = usb_kbd_repeat; kbd->repeat_timer.expires = jiffies + USBKBD_REPEAT_RATE; kbd->repeat_timer.data = (unsigned long) kbd; kbd->repeat_timer.prev = NULL; kbd->repeat_timer.next = NULL; add_timer(&kbd->repeat_timer); } restore_flags(flags);}static intusb_kbd_irq(int state, void *buffer, void *dev_id){ struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id; unsigned long *down = (unsigned long*) buffer; if(kbd->down[0] != down[0] || kbd->down[1] != down[1]) { unsigned char *olddown, *newdown; unsigned char modsdelta, key; int i; /* handle modifier change */ modsdelta = (*(unsigned char*) down ^ *(unsigned char*) kbd->down); if(modsdelta) { for(i = 0; i < 8; i++) { if(modsdelta & 0x01) { int pressed = (*(unsigned char*) down >> i) & 0x01; usb_kbd_handle_key( i + USBKBD_MODIFIER_BASE, pressed ? PCKBD_PRESSED:PCKBD_RELEASED); } modsdelta >>= 1; } } olddown = (unsigned char*) kbd->down + USBKBD_KEYCODE_OFFSET; newdown = (unsigned char*) down + USBKBD_KEYCODE_OFFSET; /* handle released keys */ for(i = 0; i < USBKBD_KEYCODE_COUNT; i++) { key = olddown[i]; if(USBKBD_VALID_KEYCODE(key) && !USBKBD_FIND_KEYCODE(newdown, key, USBKBD_KEYCODE_COUNT)) { usb_kbd_handle_key(key, PCKBD_RELEASED); } } /* handle pressed keys */ kbd->repeat_key = 0; for(i = 0; i < USBKBD_KEYCODE_COUNT; i++) { key = newdown[i]; if(USBKBD_VALID_KEYCODE(key) && !USBKBD_FIND_KEYCODE(olddown, key, USBKBD_KEYCODE_COUNT)) { usb_kbd_handle_key(key, PCKBD_PRESSED); kbd->repeat_key = key; } } /* set repeat timer if any keys were pressed */ if(kbd->repeat_key) { del_timer(&kbd->repeat_timer); kbd->repeat_timer.function = usb_kbd_repeat; kbd->repeat_timer.expires = jiffies + USBKBD_REPEAT_DELAY; kbd->repeat_timer.data = (unsigned long) kbd; kbd->repeat_timer.prev = NULL; kbd->repeat_timer.next = NULL; add_timer(&kbd->repeat_timer); } kbd->down[0] = down[0]; kbd->down[1] = down[1]; } return 1;}static intusb_kbd_probe(struct usb_device *dev){ struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_keyboard *kbd; interface = &dev->config[0].interface[0]; endpoint = &interface->endpoint[0]; if(interface->bInterfaceClass != 3 || interface->bInterfaceSubClass != 1 || interface->bInterfaceProtocol != 1) { return -1; } printk(KERN_INFO "USB HID boot protocol keyboard detected.\n"); kbd = kmalloc(sizeof(struct usb_keyboard), GFP_KERNEL); if(kbd) { memset(kbd, 0, sizeof(*kbd)); kbd->dev = dev; dev->private = kbd; usb_set_configuration(dev, dev->config[0].bConfigurationValue); usb_set_protocol(dev, 0); usb_set_idle(dev, 0, 0); usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), usb_kbd_irq, endpoint->bInterval, kbd); list_add(&kbd->list, &usb_kbd_list); } return 0;}static voidusb_kbd_disconnect(struct usb_device *dev){ struct usb_keyboard *kbd = (struct usb_keyboard*) dev->private; if(kbd) { dev->private = NULL; list_del(&kbd->list); del_timer(&kbd->repeat_timer); kfree(kbd); } printk(KERN_INFO "USB HID boot protocol keyboard removed.\n");}intusb_kbd_init(void){ usb_register(&usb_kbd_driver); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -