|
@@ -35,12 +35,12 @@ struct cashd_device {
|
|
|
unsigned int in_status;
|
|
unsigned int in_status;
|
|
|
unsigned int status_changed;
|
|
unsigned int status_changed;
|
|
|
int last_status;
|
|
int last_status;
|
|
|
- int read_flag;
|
|
|
|
|
|
|
+ int first_read;
|
|
|
struct delayed_work delay_work1;
|
|
struct delayed_work delay_work1;
|
|
|
struct delayed_work delay_work2;
|
|
struct delayed_work delay_work2;
|
|
|
void __iomem *gpio_ctl_reg_base;
|
|
void __iomem *gpio_ctl_reg_base;
|
|
|
void __iomem *gpio_status_reg_base;
|
|
void __iomem *gpio_status_reg_base;
|
|
|
- // int count; // debug code
|
|
|
|
|
|
|
+ int count; // debug code
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static int cashd_major = 0;
|
|
static int cashd_major = 0;
|
|
@@ -106,7 +106,7 @@ static int cashd_open(struct inode *inode, struct file *filp)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
filp->private_data = dev;
|
|
filp->private_data = dev;
|
|
|
- dev->read_flag = 0;
|
|
|
|
|
|
|
+ dev->first_read = 0;
|
|
|
pr_info("cashd: Device /dev/cashd%d opened\n", minor);
|
|
pr_info("cashd: Device /dev/cashd%d opened\n", minor);
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -125,17 +125,23 @@ static ssize_t cashd_read(struct file *filp, char __user *buf,
|
|
|
struct cashd_device *dev = filp->private_data;
|
|
struct cashd_device *dev = filp->private_data;
|
|
|
ssize_t bytes_read = 0;
|
|
ssize_t bytes_read = 0;
|
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
+ int nonblock = filp->f_flags & O_NONBLOCK;
|
|
|
|
|
|
|
|
if (!dev)
|
|
if (!dev)
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (!buf || count == 0)
|
|
if (!buf || count == 0)
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
- if(dev->read_flag >= 1)
|
|
|
|
|
|
|
+ if(dev->first_read == 0)
|
|
|
{
|
|
{
|
|
|
- return 0;
|
|
|
|
|
|
|
+ dev->first_read = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (wait_event_interruptible(dev->read_wait, dev->status_changed))
|
|
|
|
|
+ {
|
|
|
|
|
+ // 被信号中断
|
|
|
|
|
+ printk(KERN_INFO "gpio_monitor: wait interrupted by signal\n");
|
|
|
|
|
+ return -ERESTARTSYS;
|
|
|
}
|
|
}
|
|
|
- dev->read_flag++;
|
|
|
|
|
dev->in_status = readl(dev->gpio_status_reg_base);
|
|
dev->in_status = readl(dev->gpio_status_reg_base);
|
|
|
|
|
|
|
|
if(dev->in_status & 0x2)
|
|
if(dev->in_status & 0x2)
|
|
@@ -239,6 +245,7 @@ static int __init cashd_init_device(struct cashd_device *dev, int minor)
|
|
|
dev->buffer_size = BUFFER_SIZE;
|
|
dev->buffer_size = BUFFER_SIZE;
|
|
|
dev->dev_major = cashd_major;
|
|
dev->dev_major = cashd_major;
|
|
|
dev->dev_minor = minor;
|
|
dev->dev_minor = minor;
|
|
|
|
|
+ dev->last_status = -1;
|
|
|
|
|
|
|
|
init_waitqueue_head(&dev->read_wait);
|
|
init_waitqueue_head(&dev->read_wait);
|
|
|
|
|
|