📄 button.c
字号:
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2007, 2010 fengGuojin(fgjnew@163.com)
*/
#include <linux/module.h>#include <linux/init.h>#include <linux/input.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch-s3c2410/irqs.h>#include <asm/signal.h>#include <asm/hardware.h>#include <asm/uaccess.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/regs-irq.h>#include <asm/dma.h>MODULE_AUTHOR("FGJ");MODULE_DESCRIPTION("buttons driver");MODULE_LICENSE("GPL");#define DEBUG_DRIVER 1static unsigned char simplekey_keycode[0x08] = { [0] = KEY_1, [1] = KEY_2, [2] = KEY_3, [3] = KEY_4, [4] = KEY_5, [5] = KEY_6, [6] = KEY_7, [7] = KEY_8,};static int irqArray[4]={ IRQ_EINT0, IRQ_EINT2, IRQ_EINT11, IRQ_EINT19};static struct input_dev simplekey_dev;static char *simplekey_name = "simplekey";static char *simplekey_phys = "input0";struct timer_list polling_timer;static unsigned long polling_jffs=0;void polling_handler(unsigned long data){ int code=-1; writel(readl(S3C2410_SRCPND)&0xffffffda,S3C2410_SRCPND);//clear srcpnd 0 2 11 19 mdelay(1); //扫描按键表,根据中断号,找出所按下的按键。 writel(readl(S3C2410_GPBDAT)|0x80,S3C2410_GPBDAT);//set GPB76 to 10 writel(readl(S3C2410_GPBDAT)&0xffffffBf,S3C2410_GPBDAT);//... if((readl(S3C2410_GPFDAT)&(1<< 0)) == 0 ) { code=0; goto IRQ_OUT; } else if( (readl(S3C2410_GPFDAT)&(1<< 2)) == 0 ) { code=2; goto IRQ_OUT; } else if( (readl(S3C2410_GPGDAT)&(1<< 3)) ==0 ) { code=4; goto IRQ_OUT; } else if( (readl(S3C2410_GPGDAT)&(1<<11)) == 0 ) { code=6; goto IRQ_OUT; } writel(readl(S3C2410_SRCPND)&0xffffffda,S3C2410_SRCPND);//clear srcpnd 0 2 11 19 mdelay(1); writel(readl(S3C2410_GPBDAT)|0x40,S3C2410_GPBDAT);//set GPB76 to 01 writel(readl(S3C2410_GPBDAT)&0xffffff7f,S3C2410_GPBDAT);//... if((readl(S3C2410_GPFDAT)&(1<< 0)) == 0 ) { code=1; goto IRQ_OUT; } else if( (readl(S3C2410_GPFDAT)&(1<< 2)) == 0 ) { code=3; goto IRQ_OUT; } else if( (readl(S3C2410_GPGDAT)&(1<< 3)) ==0 ) { code=5; goto IRQ_OUT; } else if( (readl(S3C2410_GPGDAT)&(1<<11)) == 0 ) { code=7; goto IRQ_OUT; }IRQ_OUT: enable_irq(IRQ_EINT0); enable_irq(IRQ_EINT2); enable_irq(IRQ_EINT11); enable_irq(IRQ_EINT19); if(code>=0) { //避免中断连续出现 if((jiffies-polling_jffs)>100) { polling_jffs=jiffies; input_report_key(&simplekey_dev, simplekey_keycode[code], 1); input_report_key(&simplekey_dev, simplekey_keycode[code], 0); input_sync(&simplekey_dev);#if DEBUG_DRIVER printk("key %d\n",code) ;#endif } } writel(readl(S3C2410_GPBDAT)&0xffffff3f,S3C2410_GPBDAT);}static irqreturn_t simplekey_interrupt(int irq, void *dummy, struct pt_regs *fp){ disable_irq(IRQ_EINT0); disable_irq(IRQ_EINT2); disable_irq(IRQ_EINT11); disable_irq(IRQ_EINT19); polling_timer.expires = jiffies + HZ/5; add_timer(&polling_timer); return IRQ_HANDLED;}void initButton(void){ writel((readl(S3C2410_GPGCON)&(~((3<<22)|(3<<6))))|((2<<22)|(2<<6)),S3C2410_GPGCON); //GPG11,3 set EINT writel((readl(S3C2410_GPFCON)&(~((3<<4)|(3<<0))))|((2<<4)|(2<<0)),S3C2410_GPFCON) ; //GPF2,0 set EINT writel((readl(S3C2410_EXTINT0)&(~(7|(7<<8)))),S3C2410_EXTINT0); writel((readl(S3C2410_EXTINT0)|(0|(0<<8))),S3C2410_EXTINT0); //set eint0,2 falling edge int writel((readl(S3C2410_EXTINT1)&(~(7<<12))),S3C2410_EXTINT1); writel((readl(S3C2410_EXTINT1)|(0<<12)),S3C2410_EXTINT1); //set eint11 falling edge int writel((readl(S3C2410_EXTINT2)&(~(0xf<<12))),S3C2410_EXTINT2); writel((readl(S3C2410_EXTINT2)|(0<<12)),S3C2410_EXTINT2); //set eint19 falling edge int writel((readl(S3C2410_GPBCON)&(~((3<<12)|(3<<14)))),S3C2410_GPBCON); writel((readl(S3C2410_GPBCON)|(((1<<12)|(1<<14)))),S3C2410_GPBCON); writel((readl(S3C2410_GPBUP)|(3<<6)),S3C2410_GPBUP); writel((readl(S3C2410_GPBDAT)&(~(3<<6))),S3C2410_GPBDAT); writel((readl(S3C2410_EINTPEND)|((1<<11)|(1<<19))),S3C2410_EINTPEND); //clear eint 11,19 writel((readl(S3C2410_EINTMASK)&(~((1<<11)|(1<<19)))),S3C2410_EINTMASK); //enable eint11,19*/}static int __init simplekey_init(void){ int i; initButton(); polling_jffs=jiffies; for (i = 0; i <4; i++) { if (request_irq(irqArray[i], &simplekey_interrupt, SA_INTERRUPT, "simplekey", NULL)) { printk("request button irq failed!\n"); return -1; } } init_input_dev(&simplekey_dev); simplekey_dev.evbit[0] = BIT(EV_KEY);// | BIT(EV_REP); simplekey_dev.keycode = simplekey_keycode; simplekey_dev.keycodesize = sizeof(unsigned char); simplekey_dev.keycodemax = ARRAY_SIZE(simplekey_keycode); //下面的语句必不可少 for (i = 0; i < 0x78; i++) if (simplekey_keycode[i]) set_bit(simplekey_keycode[i], simplekey_dev.keybit); simplekey_dev.name = simplekey_name; simplekey_dev.phys = simplekey_phys; simplekey_dev.id.bustype = BUS_AMIGA; simplekey_dev.id.vendor = 0x0001; simplekey_dev.id.product = 0x0001; simplekey_dev.id.version = 0x0100; input_register_device(&simplekey_dev);#if DEBUG_DRIVER printk(KERN_ERR "initialize button ok!");#endif init_timer(&polling_timer); polling_timer.data = (unsigned long)0; polling_timer.function = polling_handler; return 0;}static void __exit simplekey_exit(void){ int i; for (i = 0; i <4; i++) { free_irq(irqArray[i],simplekey_interrupt); } input_unregister_device(&simplekey_dev);}module_init(simplekey_init);module_exit(simplekey_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -