- 论坛徽章:
- 0
|
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <mach/map.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-clock.h>
#include <plat/regs-gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-bank-n.h>
#define key1 1
#define key2 2
#define key3 3
#define key4 4
#define key5 5
#define key6 6
#define key7 7
#define key8 8
#define key9 9
#define key10 10
#define key11 11
#define key12 12
MODULE_AUTHOR("liutao");
MODULE_LICENSE("GPL");
unsigned long gpn_virt,gpncon,gpndat;
struct input_dev* button_devp;
static char *name = "my6410_buttons";
struct button_irq_desc{
int irq;
int pin;
int number;
char *name;
};
int key_code[] = {
key1,key2,key3,key4,
key5,key6,key7,key8,
key9,key10,key11,key12,
};
static struct button_irq_desc button_irqs[] = {
{ IRQ_EINT(0),S3C64XX_GPN(0), 0, "KEY1"},
{ IRQ_EINT(1),S3C64XX_GPN(1), 1, "KEY2"},
{ IRQ_EINT(2),S3C64XX_GPN(2), 2, "KEY3"},
};
static int cval , rval;
/*具体判断是哪个按键按下*/
static void check_key(int Cval,int Rval,int reportval)
{
printk("key check ....\n");
if(Cval == 1 )
{
switch(Rval){
case 1:
printk("key1 down...\n");
input_report_key(button_devp, key1, reportval);
break;
case 2:
printk("key2 down...\n");
input_report_key(button_devp, key2, reportval);
break;
case 3:
printk("key3 down...\n");
input_report_key(button_devp, key3, reportval);
break;
case 4:
printk("key4 down...\n");
input_report_key(button_devp, key4, reportval);
break;
}
}
else if(Cval == 2 )
{
switch(Rval){
case 1:
printk("key5 down...\n");
input_report_key(button_devp, key5, reportval);
break;
case 2:
printk("key6 down...\n");
input_report_key(button_devp, key6, reportval);
break;
case 3:
printk("key7 down...\n");
input_report_key(button_devp, key7, reportval);
break;
case 4:
printk("key8 down...\n");
input_report_key(button_devp, key8, reportval);
break;
}
}
else if(Cval == 3)
{
switch(Rval){
case 1:
printk("key9 down...\n");
input_report_key(button_devp, key9, reportval);
break;
case 2:
printk("key10 down...\n");
input_report_key(button_devp, key10, reportval);
break;
case 3:
printk("key11 down...\n");
input_report_key(button_devp, key11, reportval);
break;
case 4:
printk("key12 down...\n");
input_report_key(button_devp, key12, reportval);
break;
}
}
}
/*扫描键盘判断是Rval */
static int Scan_Keyboard(void)
{
printk("key scan...\n");
//
//pan duan chu na hang zhihou zai pan duan chu na lie
//int readval;
//writel(readl(S3C64XX_GPNDAT),readval);
if((*((unsigned long *)gpndat) & 0x00000080) == 0)
cval = 1;
else if ((*((unsigned long *)gpndat) & 0x00000200) == 0)
cval = 2;
else if ((*((unsigned long *)gpndat) & 0x00000800) == 0)
cval = 3;
else if ((*((unsigned long *)gpndat) & 0x00020001) == 0)
cval = 4;
else{
printk("the key is unknown..\n");
return -1;
}
return 0;
}
/*案件中断函数*/
static irqreturn_t button_interrupt(int irq, void* dev_id)
{
struct button_irq_desc *button_irqs = (struct button_irq_desc*)dev_id;
int updown,retval;
updown = readl(S3C64XX_GPNDAT) & ( 0x1 << button_irqs->number);
retval = updown ? 0 : 1;
switch(button_irqs->irq)
{
case IRQ_EINT(0):
rval = 1;
break;
case IRQ_EINT(1):
rval = 2;
break;
case IRQ_EINT(2):
rval = 3;
break;
default:
break;
}
Scan_Keyboard();
check_key(cval,rval,retval);
input_sync(button_devp);
return IRQ_RETVAL(IRQ_HANDLED);
}
/*GPN0-GPN2 input |||| GPN4---6 和 GPN9 output */
static int port_init(void)
{
gpn_virt = ioremap(0x7f008000,SZ_4K);
gpncon = gpn_virt + 830;
gpndat = gpn_virt + 834;
*((unsigned long *)gpncon) &= ~0xffffffff;
*((unsigned long *)gpncon) |= 0xfff7d5c0; //GPN(4-6 9 output) -> GPN(0-2 input)
return 0;
}
/*申请中断*/
static int Request_Irq(void)
{
int err = 0;
int i;
for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
err = request_irq(button_irqs[i].irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)&button_irqs[i]);
if(err)
{
break;
}
}
if(err)
{
i--;
for(; i >= 0; i--)
{
if(button_irqs[i].irq < 0)
{
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
}
return -EBUSY;
}
set_bit(EV_KEY, button_devp->evbit);
for(i = 0; i < 12; i++)
{
set_bit(key_code[i],button_devp->evbit);
}
return 0;
}
/*模块入口函数*/
static int __init button_init(void)
{
struct input_dev *input_dev;
int ret;
port_init();
input_dev = input_allocate_device();
if(!input_dev){
printk(KERN_ERR"Unable to alloc the input device!!\n");
}
button_devp = input_dev;
button_devp->name = name;
Request_Irq();
ret = input_register_device(button_devp);
if(ret < 0){
printk("input_register_device(): failed !! \n");
}
return ret;
}
/*模块退出执行*/
static void __exit button_exit(void)
{
int i;
for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
}
input_unregister_device(button_devp);
}
module_init(button_init);
module_exit(button_exit); |
|