#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/sysdev.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
#include <plat/irq.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <asm/atomic.h>
#include <linux/semaphore.h>
#include <asm/uaccess.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/spinlock.h>
void *dev_id;
atomic_t yuv =ATOMIC_INIT(1);
DECLARE_MUTEX(yuyu_down);
struct timer_list *yuyu_timer;
static DECLARE_WAIT_QUEUE_HEAD(yuyuq);
static struct class *irq_class;
static struct class_device *irq_class_dev;
struct fasync_struct * yuyu_queue;
int major;
int i;
int ev_press=0;
struct pin_desc{
unsigned long pin;
unsigned int irq_val;
unsigned long pin_val;
};
static struct pin_desc pin[4]={
{S3C2410_GPG(0),IRQ_EINT0 ,0x01},
{S3C2410_GPG(3),IRQ_EINT1, 0x02},
{S3C2410_GPG(5),IRQ_EINT13, 0x03},
{S3C2410_GPG(6),IRQ_EINT14, 0x04},
};
static void yuyu_function(data)
{
struct pin_desc* pin_la=(struct pin_desc *)dev_id;
unsigned long val=pin_la->pin_val;
if(val)
{
pin_la->pin_val= pin_la->pin_val|0x80;
}
else
{
pin_la->pin_val=pin_la->pin_val|0x10;
}
ev_press=1;
wake_up_interruptible(&yuyuq);
if(yuyu_queue)
{
kill_fasync(&yuyu_queue ,SIGIO, POLL_IN);
}
}
static irqreturn_t yuyu_irq(int irq, void *dev_id)
{
mod_timer(&yuyu_timer,100);
return IRQ_RETVAL(IRQ_HANDLED);
}
static ssize_t irq_drv_open (struct inode *inode, struct file *file)
{
/*if (atomic_dec_and_test(yuv)!=0)
{
atomic_inc(yuv);
return -EBUSY;
}
*/
init_timer(&yuyu_timer);
yuyu_timer->data = 100;
yuyu_timer->function = yuyu_function;
add_timer(&yuyu_timer);
if(file->f_flags&O_NONBLOCK)
{
if(down_trylock(&yuyu_down))
return -EBUSY;
}
else
{
down(&yuyu_down);
}
for(i=0;i<4;i++)
{
request_irq(pin[i].irq_val, yuyu_irq, IRQF_TRIGGER_LOW , "K1", &pin[i]);
}
return 0;
}
static ssize_t irq_drv_read (struct file *file, char __user *buf, size_t size, loff_t * opps)
{
if (size !=1)
return -EINVAL;
wait_event_interruptible(yuyuq, ev_press);
copy_to_user(buf,& pin[i].pin_val, 1);
ev_press=0;
return size;
}
static unsigned int irq_drv_poll (struct file *file, struct poll_table_struct *table)
{
unsigned int mask=0;
poll_wait(file,&yuyuq,table);
if(ev_press)
mask|=POLLIN|POLLRDNORM;
return mask;
}
static int irq_drv_fsync (int fd, struct file *file, int mode)
{
return fasync_helper( fd, file, mode, &yuyu_queue);
}
static int irq_drv_close (struct inode *inode, struct file *file)
{
int i;
/*atomic_inc(yuv);*/
for(i=0;i<4;i++)
{
free_irq(pin[i].irq_val, &pin[i]);
}
printk("the dev is close");
return 0;
}
static struct file_operations irq_drv_fops = {
.owner = THIS_MODULE,
.open = irq_drv_open,
.read = irq_drv_read,
.release = irq_drv_close,
.poll = irq_drv_poll,
};
static int irq_drv_init(void)
{
major = register_chrdev(0, "irq_drv", &irq_drv_fops);
irq_class=class_create(THIS_MODULE, "irq_drv");
irq_class_dev= device_create(irq_class, NULL, MKDEV(major, 0), NULL, "yuyuirq");
return 0;
}
static void irq_drv_exit(void)
{
unregister_chrdev(major, "irq_drv");
device_destroy( irq_class_dev, MKDEV(major, 0));
class_destroy(irq_class);
return 0;
}
module_init(irq_drv_init);
module_exit(irq_drv_exit);
MODULE_LICENSE("GPL");
信号量sem
最新推荐文章于 2024-04-18 11:24:03 发布