📄 joytokey.c
字号:
/* * $Id: joytokey.c,v 1.0 /05/17 Fu Hewei$ * *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include <linux/config.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/input.h>#include <linux/module.h>#include <linux/tty.h>#include <linux/types.h>#include <linux/timer.h>struct timer_data { unsigned int number; unsigned int value; struct timer_list timer;};struct keycode_wrapper { unsigned int state; unsigned int prev_code; unsigned int index; unsigned int heading; unsigned int shift;};struct joykbd_device { struct input_handle handle; int nabs; int nkey; struct keycode_wrapper key_wrapper; struct timer_data wrapper; spinlock_t global_lock; unsigned int prev_input; unsigned int state_dir; unsigned int stack_pointer; __u16 keymap[KEY_MAX - BTN_MISC]; __u16 keypam[KEY_MAX - BTN_MISC]; __u8 absmap[ABS_MAX]; __u8 abspam[ABS_MAX];};static struct joykbd_device* joydev; #define NUM_KEY_OF_BUTTON 47 #define DELAY HZ/4#define PERIOD HZ/33static void repeat_dir(unsigned long ptr){ static u8 dir_code[2][2] = {{0x4B,0x4D},{0x48,0x50}}; struct timer_data* temp = (struct timer_data* )ptr; if(!temp) return; unsigned int code = temp->number; unsigned int value = temp->value; struct timer_list* t_timer = &(temp->timer); if(!t_timer) return; handle_scancode(0xE0, 1); handle_scancode(dir_code[code][(!value) ? 0 : 1], 1); mod_timer(t_timer, jiffies + PERIOD); return;}static unsigned int translate_button_three(unsigned int code, int value, struct keycode_wrapper* wrapper, unsigned int state){ unsigned int *index = &wrapper->index; unsigned int heading = wrapper->heading, prev = wrapper->prev_code; static button_one_key[NUM_KEY_OF_BUTTON] = {0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, 0x2D, 0x15, 0x2C, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0x2B, 0x33, 0x34, 0x35, 0x1A, 0x1B, 0x27, 0x28, 0x29}; switch (state) { case 1: if(value != 1) return 0; printk(KERN_DEBUG "heading (%x) ", heading); if((prev == code || prev == 0x00) && !heading) { handle_scancode(0x0E, 1); handle_scancode(0x8E, 0); } *index = (*index - 1) % NUM_KEY_OF_BUTTON; printk(KERN_DEBUG "index (%x)\n", *index); if(wrapper->shift) handle_scancode(0x2A, 1); printk(KERN_DEBUG "index (%x)\n", *index); handle_scancode(button_one_key[*index], value); break; case 2: if(value) return 0; handle_scancode(button_one_key[*index] | 0x80, value); break; } return 1;}static unsigned int translate_button_one(unsigned int code, int value, struct keycode_wrapper* wrapper, unsigned int state){ unsigned int *index = &wrapper->index; unsigned int heading = wrapper->heading, prev = wrapper->prev_code; static button_one_key[NUM_KEY_OF_BUTTON] = {0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, 0x2D, 0x15, 0x2C, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0x2B, 0x33, 0x34, 0x35, 0x1A, 0x1B, 0x27, 0x28, 0x29}; switch (state) { case 1: if(value != 1) return 0; printk(KERN_DEBUG "heading (%x) ", heading); if((prev == code || prev == 0x03) && !heading) { handle_scancode(0x0E, 1); handle_scancode(0x8E, 0); } if(wrapper->shift) handle_scancode(0x2A, 1); printk(KERN_DEBUG "index (%x)\n", *index); handle_scancode(button_one_key[*index], value); break; case 2: if(value) return 0; handle_scancode(button_one_key[*index] | 0x80, value); *index = (*index + 1) % NUM_KEY_OF_BUTTON; printk(KERN_DEBUG "index (%x)\n", *index); break; } return 1;}static void translate_button_enter(unsigned int code, int value, struct keycode_wrapper* wrapper, unsigned int state){ if(code != 9) return; switch(state) { case 1: handle_scancode(0xE0, 1); handle_scancode(0x1C, value); break; case 2: handle_scancode(0x1C | 0x80, value); break; } return;} static void translate_button_tab(unsigned int code, int value, struct keycode_wrapper* wrapper, unsigned int state) { if(code != 1) return; switch(state) { case 1: handle_scancode(0xF, 1); break; case 2: handle_scancode(0xF | 0X80, 0); break; } return;}static void translate_button_space(unsigned int code, int value, struct keycode_wrapper* wrapper, unsigned int state) { if(code != 6) return; switch(state) { case 1: handle_scancode(0x39, 1); break; case 2: handle_scancode(0x39 | 0x80, 0); break; } return;}static void translate_button_backtrace(unsigned int code, int value, struct keycode_wrapper* wrapper, unsigned int state) { if(code != 2) return; switch(state) { case 1: handle_scancode(0x0E, 1); break; case 2: handle_scancode(0x0E | 0x80, 0); break; } return;}static void emulate_key_code(unsigned int code, int value, struct keycode_wrapper* wrapper){ unsigned int* state = &wrapper->state; switch(code) { case 0: translate_button_one(code, value, wrapper, *state); break; case 9: translate_button_enter(code, value, wrapper, *state); break; case 1: translate_button_tab(code, value, wrapper, *state); break; case 2: translate_button_backtrace(code, value, wrapper, *state); break; case 3: translate_button_three(code, value, wrapper, *state); break; case 6: translate_button_space(code, value, wrapper, *state); break; default: } if(*state == 2) { if(wrapper->heading == 1) wrapper->heading = 0; *state = 1; } else if(*state == 1) { *state = 2; wrapper->prev_code = code; }out: return;}static void emulate_direction_code(unsigned int code, int value, struct joykbd_device* joydev) { unsigned int *state = &joydev->state_dir; static u8 state_one[2][2] = {0x4B,0x4D,0x48,0x50}; static u8 state_two[2] = {0xCB,0xC8}; static u8 state_three[2] = {0xCD,0xD0}; if (value != 0xff && value != 0x0 && value != 0x7f && code != 0 && code != 1) return; if ((value == 0xff || value == 0x0) && *state != 1) return; if (value == 0x7f && *state != 2 && *state != 3) return; switch (*state) { case 1: handle_scancode(0xE0, 1); if (value == 0x0) *state = 2; else if (value == 0xff) *state = 3; handle_scancode(state_one[code][(!value) ? 0 : 1], 1); break; case 2: handle_scancode(state_two[code], 0); *state = 1; break; case 3: handle_scancode(state_three[code], 0); *state = 1; break; default: *state = 1; } return;}static void joykbd_event(struct input_handle *handle, unsigned int type, unsigned int code, int value){ struct joykbd_device* joydev = handle->private; unsigned int number; struct timer_data* t = &joydev->wrapper; unsigned int *h = &joydev->key_wrapper.heading, *s = &joydev->key_wrapper.shift; unsigned long *temp = NULL, this_input = 0, msb, irq_flag_global = 0; spin_lock_irqsave(&joydev->global_lock, irq_flag_global); temp = joydev->stack_pointer ? &this_input : &joydev->prev_input; switch (type) { case EV_KEY: if (code < BTN_MISC || value == 2) goto out; number = joydev->keymap[code - BTN_MISC]; if (number == 4) /* special control key */ { if (value == 0) *h = 1; goto out; } if (number == 5) /* special SHIFT key */ { if (value == 1) /* SHIFT key must stay in kicking down state, the keycode can be switch to BIG */ *s = 1; else { *s = 0; handle_scancode(0x2A | 0x80, 0); } goto out; } *temp = value << 31 | number + 1; break; case EV_ABS: printk(KERN_DEBUG "EV_ABS code=%x value=%x\n", code, value); if(value != 0x7f && value != 0xff && value) { printk(KERN_DEBUG "EV_ABS, value is invalidate (%x) \n", value); goto out; } if(code && code != 1) goto out; number = joydev->absmap[code]; if(value == 0xff || !value) msb = 1; /* kick down 1 */ else if(value == 0x7f) msb = 0; /* kick up 0 */ *temp = (number << 16) | (msb << 31); break; } if((joydev->stack_pointer && (joydev->prev_input ^ (1 << 31)) == this_input) || (!joydev->stack_pointer && (joydev->prev_input >> 31))) { switch(type) { case EV_KEY: printk(KERN_DEBUG "EV_KEY code=%x value=%x\n", code, value); emulate_key_code(number, value, &joydev->key_wrapper); if(!joydev->stack_pointer) joydev->stack_pointer = 1; else if(joydev->stack_pointer) joydev->stack_pointer = 0; break; case EV_ABS: if(!joydev->stack_pointer) { t->number = number; t->value = value; t->timer.expires = jiffies + DELAY; t->timer.data = (void* )t; t->timer.function = repeat_dir; add_timer(&t->timer); emulate_direction_code(number, value, joydev); joydev->stack_pointer = 1; break; } else { del_timer(&t->timer); joydev->stack_pointer = 0; emulate_direction_code(number, value, joydev); break; } } } else if (!joydev->stack_pointer && !(joydev->prev_input >> 31)) joydev->prev_input = 0;out: spin_unlock_irqrestore(&joydev->global_lock, irq_flag_global); return;}void init_keycode_wrapper(struct keycode_wrapper* wrapper){ wrapper->prev_code = 0x200; wrapper->index = 0; wrapper->state = 1; return;} static struct input_handle *joykbd_connect(struct input_handler *handler, struct input_dev *dev){ int i; if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) && (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) && (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit) || test_bit(BTN_1, dev->keybit)))) return NULL; if (joydev) { printk(KERN_INFO "you have just insert a joystick into ths usb socket\n"); return NULL; } if (!(joydev = kmalloc(sizeof(struct joykbd_device), GFP_KERNEL))) return NULL; memset(joydev, 0, sizeof(struct joykbd_device)); joydev->state_dir = 1; init_keycode_wrapper(&joydev->key_wrapper); spin_lock_init(&joydev->global_lock); joydev->handle.dev = dev; joydev->handle.handler = handler; joydev->handle.private = joydev; for (i = 0; i < ABS_MAX; i++) if (test_bit(i, dev->absbit)) { joydev->absmap[i] = joydev->nabs; joydev->abspam[joydev->nabs] = i; joydev->nabs++; } for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++) if (test_bit(i + BTN_MISC, dev->keybit)) { joydev->keymap[i] = joydev->nkey; joydev->keypam[joydev->nkey] = i + BTN_MISC; joydev->nkey++; } for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++) if (test_bit(i + BTN_MISC, dev->keybit)) { joydev->keymap[i] = joydev->nkey; joydev->keypam[joydev->nkey] = i + BTN_MISC; joydev->nkey++; } init_timer(&joydev->wrapper.timer); input_open_device(&joydev->handle); return &joydev->handle;}static void joykbd_disconnect(struct input_handle *handle){ input_close_device(handle);}static struct input_handler joykbd_handler = { event: joykbd_event, connect: joykbd_connect, disconnect: joykbd_disconnect,};static int __init joykbd_init(void){ input_register_handler(&joykbd_handler); return 0;}static void __exit joykbd_exit(void){ input_unregister_handler(&joykbd_handler);}module_init(joykbd_init);module_exit(joykbd_exit);MODULE_AUTHOR("Hewei Fu <snail_314@hotmail>");MODULE_DESCRIPTION("Input driver to joystick for keyboard driver binding");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -