📄 button.c
字号:
#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>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/poll.h>
#include "demo.h"
MODULE_AUTHOR("fgj");
MODULE_LICENSE("Dual BSD/GPL");
static int irqArray[4]=
{
IRQ_EINT1,
IRQ_EINT2,
IRQ_EINT3,
IRQ_EINT7
};
struct DEMO_dev *DEMO_devices;
static unsigned char demo_inc=0;
static int flag=0;
struct timer_list polling_timer;
static unsigned long polling_jffs=0;
void initButton(void)
{
writel((readl(S3C2410_GPFCON)&(~((3<<14)|(3<<6)|(3<<4)|(3<<2))))|((2<<14)|(2<<6)|(2<<4)|(2<<2)),S3C2410_GPFCON);//GPF7,3,2,1 set EINT
writel((readl(S3C2410_EXTINT0)&(~(7<<4))),S3C2410_EXTINT0);
writel((readl(S3C2410_EXTINT0)|(0<<4)),S3C2410_EXTINT0); //set eint1 low level int
writel((readl(S3C2410_EXTINT0)&(~(7<<8))),S3C2410_EXTINT0);
writel((readl(S3C2410_EXTINT0)|(0<<8)),S3C2410_EXTINT0); //set eint2 low level int
writel((readl(S3C2410_EXTINT0)&(~(7<<12))),S3C2410_EXTINT0);
writel((readl(S3C2410_EXTINT0)|(0<<12)),S3C2410_EXTINT0); //set eint3 low level int
writel((readl(S3C2410_EXTINT0)&(~(7<<28)))),S3C2410_EXTINT0);
writel((readl(S3C2410_EXTINT0)|(0<<28)),S3C2410_EXTINT0); //set eint7 low level int
writel((readl(S3C2410_EINTPEND)|((1<<7))),S3C2410_EINTPEND); //interrupt pending register for 20 extemal interrupts
//(EINT[23:4]) ; clear eint7
writel((readl(S3C2410_EINTMASK)&(~(1<<7))),S3C2410_EINTMASK); //enable eint7
}
//定时器处理函数
void polling_handler(unsigned long data)
{
int code=-1;
writel(readl(S3C2410_ )&0xffffff01,S3C2410_SRCPND);//clear srcpnd 1 2 3 7
mdelay(1);
//扫描按键表,根据中断号,找出所按下的按键。
if((readl(S3C2410_GPFDAT)&(1<<1)) == 0 )
{
code=1;
goto IRQ_OUT;
}
else if( (readl(S3C2410_GPFDAT)&(1<< 2)) == 0 )
{
code=2;
goto IRQ_OUT;
}
else if( (readl(S3C2410_GPFDAT)&(1<< 3)) ==0 )
{
code=3;
goto IRQ_OUT;
}
else if( (readl(S3C2410_GPFDAT)&(1<<7)) == 0 )
{
code=4;
goto IRQ_OUT;
}
IRQ_OUT:
enable_irq(IRQ_EINT1);
enable_irq(IRQ_EINT2);
enable_irq(IRQ_EINT3);
enable_irq(IRQ_EINT7);
if(code>=0)
{
//避免中断连续出现
if((jiffies-polling_jffs)>100)
{
polling_jffs=jiffies;
//获取键盘值
DEMO_devices->key=code;
printk("get key %d\n",DEMO_devices->key);
flag = 1;
wake_up_interruptible(&(DEMO_devices->wq));
}
}
}
static irqreturn_t simplekey_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
//if(demo_inc<=0) return IRQ_HANDLED;
//printk("enter button interrupt\n");
disable_irq(IRQ_EINT1);
disable_irq(IRQ_EINT2);
disable_irq(IRQ_EINT3);
disable_irq(IRQ_EINT7);
polling_timer.expires = jiffies + HZ/5;
add_timer(&polling_timer);
return IRQ_HANDLED;
}
int DEMO_open(struct inode *inode, struct file *filp)
{
struct DEMO_dev *dev;
if(demo_inc>0)return -ERESTARTSYS;
demo_inc++;
dev = container_of(inode->i_cdev, struct DEMO_dev, cdev);
filp->private_data = dev;
return 0;
}
int DEMO_release(struct inode *inode, struct file *filp)
{
demo_inc--;
return 0;
}
ssize_t DEMO_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
struct DEMO_dev *dev = filp->private_data;
int sum=0;
if(flag==1)
{
flag = 0;
sum=1;
if (copy_to_user(buf,&dev->key,1))
{
sum=-EFAULT;
}
}
else
{
if (filp->f_flags & O_NONBLOCK)
{
return -EAGAIN;
}
else
{
if(wait_event_interruptible(dev->wq, flag != 0))
{
return - ERESTARTSYS;
}
flag = 0;
sum=1;
if (copy_to_user(buf,&dev->key,1))
{
sum=-EFAULT;
}
}
}
return sum;
}
unsigned int DEMO_poll(struct file *filp, poll_table *wait)
{
struct DEMO_dev *dev = filp->private_data;
poll_wait(filp, &dev->wq, wait);
if (flag==1) //数据准备好
return POLLIN | POLLRDNORM;
return 0;
}
struct file_operations DEMO_fops = {
.owner = THIS_MODULE,
.read = DEMO_read,
.open = DEMO_open,
.poll= DEMO_poll,
.release = DEMO_release,
};
/*******************************************************
MODULE ROUTINE
*******************************************************/
void DEMO_cleanup_module(void)
{
dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);
int i;
for (i = 0; i <4; i++) {
free_irq(irqArray[i],simplekey_interrupt);
}
if (DEMO_devices)
{
cdev_del(&DEMO_devices->cdev);
kfree(DEMO_devices);
}
unregister_chrdev_region(devno,1);
}
int DEMO_init_module(void)
{
int result;
dev_t dev = 0;
int i=0;
initButton();
dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);
result = register_chrdev_region(dev, 1, "DEMO");
if (result < 0)
{
printk(KERN_WARNING "DEMO: can't get major %d\n", DEMO_MAJOR);
return result;
}
DEMO_devices = kmalloc(sizeof(struct DEMO_dev), GFP_KERNEL);
if (!DEMO_devices)
{
result = -ENOMEM;
goto fail;
}
memset(DEMO_devices, 0, sizeof(struct DEMO_dev));
init_MUTEX(&DEMO_devices->sem);
cdev_init(&DEMO_devices->cdev, &DEMO_fops);
DEMO_devices->cdev.owner = THIS_MODULE;
DEMO_devices->cdev.ops = &DEMO_fops;
result = cdev_add (&DEMO_devices->cdev, dev, 1);
if(result)
{
printk(KERN_NOTICE "Error %d adding DEMO\n", result);
goto fail;
}
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_waitqueue_head(&DEMO_devices->wq);
init_timer(&polling_timer);
polling_timer.data = (unsigned long)0;
polling_timer.function = polling_handler;
return 0;
fail:
DEMO_cleanup_module();
return result;
}
module_init(DEMO_init_module);
module_exit(DEMO_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -