⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joytokey.c

📁 一个linux下的内核模块
💻 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 + -