s3c2410kbd.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 219 行

C
219
字号
/* * 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 * * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org> * Samsung S3C2410 keyboard support * * Based on various pxa ipaq drivers. *  * ChangeLog * * 2005-06-21: Arnaud Patard <arnaud.patard@rtp-net.org> *      - Initial version * 2007-04-17: lqm@ucdragon.net *      - modified for 4x4 maxtrix keyboard */#include <linux/config.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/input.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/device.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/regs-gpio.h>/* For id.version */#define S3C2410KBDVERSION   0x0001#define DRV_NAME            "s3c2410-maxtrixkb"MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");MODULE_DESCRIPTION("s3c2410 keyboard driver");MODULE_LICENSE("GPL");#define KEY_CODE_INVALID -1struct s3c2410kbd_button {	int irq;	int pin;	int pin_setting;	int index;	int keycode;};/*static int s3c2410kbd_buttons[] = {	KEY_1,         KEY_2,         KEY_3,         KEY_ESC,	KEY_4,         KEY_5,         KEY_6,         KEY_BACKSPACE,	KEY_7,         KEY_8,         KEY_9,         KEY_ENTER,	KEY_PAGEUP,    KEY_3,         KEY_PAGEDOWN,  KEY_PRINT};*///由于历史问题,仍用U,P代替上下翻、C为更正,B为后退...static int s3c2410kbd_buttons[] = {	KEY_B,        KEY_3,          KEY_2,         KEY_1,	KEY_C,        KEY_6,          KEY_5,         KEY_4,	KEY_ENTER,    KEY_9,          KEY_8,         KEY_7,	KEY_P,        KEY_D,          KEY_0,         KEY_U,};static struct s3c2410kbd_button s3c2410kbd_x[] = {	{  IRQ_EINT0,  S3C2410_GPF0,   S3C2410_GPF0_EINT0,   0<<2 ,KEY_CODE_INVALID},	{  IRQ_EINT2,  S3C2410_GPF2,   S3C2410_GPF2_EINT2,   1<<2 ,KEY_CODE_INVALID},	{  IRQ_EINT11, S3C2410_GPG3,   S3C2410_GPG3_EINT11,  2<<2 ,KEY_CODE_INVALID},	{  IRQ_EINT19, S3C2410_GPG11,  S3C2410_GPG11_EINT19, 3<<2 ,KEY_CODE_INVALID},};static struct s3c2410kbd_button s3c2410kbd_y[] = {	{  0,  S3C2410_GPB6,   S3C2410_GPB6_OUTP,   0 },	{  0,  S3C2410_GPB7,   S3C2410_GPB7_OUTP,   1 },	{  0,  S3C2410_GPB8,   S3C2410_GPB8_OUTP,   2 },	{  0,  S3C2410_GPB9,   S3C2410_GPB9_OUTP,   3 },};struct s3c2410kbd {	struct input_dev  dev;	spinlock_t        lock;	int               count;	int               shift;		char              phys[32];};static struct s3c2410kbd kbd;static irqreturn_t s3c2410kbd_keyevent(int irq, void *dev_id, struct pt_regs *regs){	struct s3c2410kbd_button *button = (struct s3c2410kbd_button *)dev_id;	int down;	int last_key = button->keycode;	if (!button)		return IRQ_HANDLED;	mdelay(10);	down = !(s3c2410_gpio_getpin(button->pin));		//printk(KERN_DEBUG "%d %02x %x\n",down,button->index,button->keycode);	if(last_key != KEY_CODE_INVALID)	{		input_report_key(&kbd.dev, last_key, 0);		input_sync(&kbd.dev);		button->keycode = KEY_CODE_INVALID;		//printk(KERN_DEBUG "%x button %s\n",last_key, "force up");	}	if(down)	{		int i;		//lqm@ucdragon.net must set to input,or interrpt will trigger again		for (i = 0; i < ARRAY_SIZE (s3c2410kbd_x); i++) 		{			s3c2410_gpio_cfgpin(s3c2410kbd_x[i].pin,0);		}		for (i = 0; button->keycode == KEY_CODE_INVALID && i < ARRAY_SIZE (s3c2410kbd_y); i++) 		{			s3c2410_gpio_setpin(s3c2410kbd_y[i].pin,1);			mdelay(1);			if(s3c2410_gpio_getpin(button->pin))			{				button->keycode = s3c2410kbd_buttons[button->index + s3c2410kbd_y[i].index];			}			s3c2410_gpio_setpin(s3c2410kbd_y[i].pin,0);		}		if(button->keycode != KEY_CODE_INVALID && button->keycode != last_key)		{			input_report_key(&kbd.dev, button->keycode, down);			input_sync(&kbd.dev);			//printk(KERN_DEBUG "%x button %s\n",button->keycode, down ? "pressed" : "released");		}		for (i = 0; i < ARRAY_SIZE (s3c2410kbd_x); i++) 		{			s3c2410_gpio_cfgpin(s3c2410kbd_x[i].pin,s3c2410kbd_x[i].pin_setting);		}	}		return IRQ_HANDLED;}int __init s3c2410kbd_init(void){	int i;	printk(KERN_INFO "s3c2410kbd_init\n");	/* Initialise input stuff */	memset(&kbd, 0, sizeof(struct s3c2410kbd));	init_input_dev(&kbd.dev);	kbd.dev.evbit[0] = BIT(EV_KEY);	sprintf(kbd.phys, "input/s3c2410_kbd0");	kbd.dev.private = &kbd;	kbd.dev.name = DRV_NAME;	kbd.dev.phys = kbd.phys;	kbd.dev.id.bustype = BUS_HOST;	kbd.dev.id.vendor = 0xDEAD;	kbd.dev.id.product = 0xBEEF;	kbd.dev.id.version = S3C2410KBDVERSION;	for (i = 0; i < ARRAY_SIZE (s3c2410kbd_buttons); i++) 	{		set_bit(s3c2410kbd_buttons[i], kbd.dev.keybit);	}	for (i = 0; i < ARRAY_SIZE (s3c2410kbd_x); i++) 	{		s3c2410_gpio_cfgpin(s3c2410kbd_x[i].pin,s3c2410kbd_x[i].pin_setting);		request_irq (s3c2410kbd_x[i].irq, s3c2410kbd_keyevent,\		             SA_INTERRUPT, DRV_NAME, &s3c2410kbd_x[i]);		set_irq_type(s3c2410kbd_x[i].irq, IRQT_BOTHEDGE);	}	for (i = 0; i < ARRAY_SIZE (s3c2410kbd_y); i++) 	{		s3c2410_gpio_cfgpin(s3c2410kbd_y[i].pin,s3c2410kbd_y[i].pin_setting);		s3c2410_gpio_setpin(s3c2410kbd_y[i].pin,0);	}		printk(KERN_INFO "%s successfully loaded\n", DRV_NAME);	/* All went ok, so register to the input system */	input_register_device(&kbd.dev);	return 0;}void __exit s3c2410kbd_remove(void){	int i;	for (i = 0; i < ARRAY_SIZE (s3c2410kbd_x); i++)	{		disable_irq(s3c2410kbd_x[i].irq);		free_irq(s3c2410kbd_x[i].irq,&kbd.dev);	}	input_unregister_device(&kbd.dev);}module_init(s3c2410kbd_init);module_exit(s3c2410kbd_remove);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?