#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
struct btn_irq {
int irq;
int pin;
char name[10];
};
static struct btn_irq btns_irq[6]={
{.irq=IRQ_EINT8,.pin=S3C2410_GPG0,.name="key0" ,},
{.irq=IRQ_EINT11,.pin=S3C2410_GPG3,.name="key1",},
{.irq=IRQ_EINT13,.pin=S3C2410_GPG5,.name="key2",},
{.irq=IRQ_EINT14,.pin=S3C2410_GPG6,.name="key3",},
{.irq=IRQ_EINT15,.pin=S3C2410_GPG7,.name="key4",},
{.irq=IRQ_EINT19,.pin=S3C2410_GPG11,.name="key5",}
};
static volatile int key_press=0;
static volatile int key_no=6;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static irqreturn_t button_isr(int irq,void *dev_id)
{
int down;
int i;
for(i=0;i<6;i++)
{
if(irq==btns_irq[i].irq)
{
down=!s3c2410_gpio_getpin(btns_irq[i].pin);
if(!down)
{
key_press=1;
key_no=i;
wake_up_interruptible(&button_waitq);
}
else
{
key_press=0;
}
}
}
return IRQ_RETVAL(IRQ_HANDLED);
}
int btn_open(struct inode *inode,struct file *filp)
{
int i;
int err=0;
for(i=0;i<6;i++)
{
err=request_irq(btns_irq[i].irq,button_isr,IRQ_TYPE_EDGE_RISING,btns_irq[i].name,NULL);
}
key_press=0;
return 0;
}
static int btn_read(struct file *filp,char *buff,size_t count,loff_t *offp)
{
if(!key_press)
{
if(filp->f_flags&O_NONBLOCK)
return -EAGAIN;
else
wait_event_interruptible(button_waitq,key_press);
}
key_press=0;
/*调试时用来显示按键的按下
if(key_no<6)
{
printk("the %s is press down\n",btns_irq[key_no].name);
key_no=6;
}
*/
copy_to_user(buff,btns_irq[key_no].name,count);
return 0;
}
static int btn_close(struct inode *inode,struct file *filp)
{
int i;
for(i=0;i<6;i++)
{
free_irq(btns_irq[i].irq,NULL);
}
//printk("kernel close \n");
return 0;
}
static struct file_operations btn_fops={
.owner = THIS_MODULE,
.open = btn_open,
.release= btn_close,
.read = btn_read,
};
static int __init buttondev_init(void)
{
int ret=register_chrdev(240,"/dev/buttondev",&btn_fops);
if(ret<0)
return ret;
return 0;
}
static void __exit buttondev_exit(void)
{
unregister_chrdev(240,"buttondev");
}
module_init(buttondev_init);
module_exit(buttondev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SUST"); |