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

📄 demo.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 <asm/arch/regs-serial.h>#include "demo.h"MODULE_AUTHOR("fgj");MODULE_LICENSE("Dual BSD/GPL");#define PCLK 50000000struct DEMO_dev *DEMO_devices;static unsigned char demo_inc=0;static int flag = 0;#define portaddr(reg) ((void *)((char*)S3C2410_VA_UART2 + (reg)))#define rd_regb(reg) (__raw_readb(portaddr(reg)))#define rd_regl(reg) (__raw_readl(portaddr(reg)))#define wr_regl(val,reg) \  do { __raw_writel(val,portaddr(reg)); } while(0)#define wr_regb(val,reg) \  do { __raw_writeb(val, portaddr(reg)); } while(0)void initInfraredPort(void){	writel((readl(S3C2410_GPBDAT)|(1<<1)),S3C2410_GPBDAT);	writel((readl(S3C2410_GPBCON)&0x3ffff3),S3C2410_GPBCON);	writel((readl(S3C2410_GPBCON)|(1<<2)),S3C2410_GPBCON);	writel((readl(S3C2410_GPBUP)|(1<<1)),S3C2410_GPBUP);	writel((readl(S3C2410_GPHCON)&0x3c0fff),S3C2410_GPHCON);	writel((readl(S3C2410_GPHCON)|0x2a000),S3C2410_GPHCON);	writel((readl(S3C2410_GPHUP)|0x1c0),S3C2410_GPHUP);	wr_regl((int)(PCLK/16/19200)-1,S3C2410_UBRDIV);	writel((readl(S3C2410_GPBDAT)&0x7fd),S3C2410_GPBDAT);	wr_regl((1<<6)|(0<<4)|(1<<2)|(1<<1)|0,S3C2410_UFCON);	wr_regl((0<<10)|(1<<9)|(1<<8)|(0<<7)|(1<<6)|(0<<5)|(0<<4)|(0<<2)|(0),S3C2410_UCON);	wr_regl(((1<<6)|(0<<3)|(0<<2)|(3)),S3C2410_ULCON);	//printk("--------%d,------\n",rd_regl(S3C2410_ULCON));	wr_regl((0<<10)|(1<<9)|(1<<8)|(0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<2)|(1),S3C2410_UCON);	writel((readl(S3C2410_INTMSK)&(~(1<<15))),S3C2410_INTMSK);	writel((readl(S3C2410_INTSUBMSK)&(~((1<<8)|(1<<6)))),S3C2410_INTSUBMSK);}static irqreturn_t s3c2410infrared_interrupt(int irq, void *dummy, struct pt_regs *fp){	int a;	disable_irq(IRQ_UART2);	disable_irq(IRQ_S3CUART_RX2);	disable_irq(IRQ_S3CUART_ERR2);		a=readl(S3C2410_SUBSRCPND);	//printk("s3c2410infrared_interruptr:%d\n",a);	if(a&(1<<6))	{		a=rd_regl(S3C2410_UTRSTAT);		if(a|1)		{			DEMO_devices->infraredbuf=rd_regb(S3C2410_URXH);			flag = 1;			wake_up_interruptible(&(DEMO_devices->wq));			//printk("rd_regl:%d\n",DEMO_devices->infraredbuf);		}	}	else	{		switch(rd_regl(S3C2410_UERSTAT)) {		case '1':		    	printk("Overrun error\n");	    		break;		case '2':		    	printk("Parity error\n");	    		break;		case '4':		    	printk("Frame error\n");	    		break;		case '8':		    	printk("Breake detect\n");	    		break;		default :		   	break;    		}	}	writel(readl(S3C2410_SRCPND)&(~(1<<15)),S3C2410_SRCPND);	writel(readl(S3C2410_SUBSRCPND)&(~(1<<6)|(1<<8)),S3C2410_SUBSRCPND);	enable_irq(IRQ_UART2);	enable_irq(IRQ_S3CUART_RX2);	enable_irq(IRQ_S3CUART_ERR2);	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->infraredbuf,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->infraredbuf,1))			{				sum=-EFAULT; 			}		}	}	return sum;}ssize_t DEMO_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos){	unsigned char buff;	copy_from_user(&buff, buf,1);	wr_regb(buff,S3C2410_UTXH);	//printk("DEMO_write detect\n");	return 1;}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,	.write=     DEMO_write,	.open =     DEMO_open,	.poll=      DEMO_poll,	.release =  DEMO_release,};/*******************************************************                MODULE ROUTINE*******************************************************/void DEMO_cleanup_module(void){	dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);	free_irq(IRQ_UART2,s3c2410infrared_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;	initInfraredPort();	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;	}	if (request_irq(IRQ_S3CUART_RX2,&s3c2410infrared_interrupt, SA_INTERRUPT, "s3c2410infrared", NULL)) {		printk("request infrared irq failed!\n");		return -1;			}		init_waitqueue_head(&DEMO_devices->wq);	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 + -