⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 button.c

📁 s3c2410 按键驱动程序, 测试已经通过
💻 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 + -