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

📄 button.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 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>#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_EINT0,	IRQ_EINT2,	IRQ_EINT11,	IRQ_EINT19};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_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*/}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;			//获取键盘值			DEMO_devices->key=code;        		printk("get key %d\n",DEMO_devices->key);			flag = 1;			wake_up_interruptible(&(DEMO_devices->wq));		}	}	writel(readl(S3C2410_GPBDAT)&0xffffff3f,S3C2410_GPBDAT);}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_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;}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 + -