📄 demo.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 + -