//write时候调用
static ssize_t Eint_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
}
//read时候调用
//读取按键值
ssize_t Eint_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
if(size != 1)
return -EINVAL;
if (file->f_flags & O_NONBLOCK)
{
//非阻塞 立马返回
if (!ev_press)
return -EAGAIN;
}
else
{
//如果没有按键按下 则休眠
wait_event_interruptible(button_waitq,ev_press);
}
//如果有按键动作发生的话 则返回
copy_to_user(buf, &key_val, 1);
ev_press = 0;//清中断标志位
// printk("key_val = 0x%x\n", key_val);
}
//关闭驱动时候调用
static int Eint_drv_colse(struct inode *inode, struct file *file)
{
#if usingatomic
atomic_inc(&canopen);//自加1
#else
up(&button_lock);
#endif
free_irq(IRQ_EINT0, &pins_desc[0]);//EINT0释放中断
free_irq(IRQ_EINT2, &pins_desc[1]);//EINT2释放中断
free_irq(IRQ_EINT11, &pins_desc[2]);//EINT11释放中断
free_irq(IRQ_EINT19, &pins_desc[3]);//EINT19释放中断
printk("Eint_drv_colse successed!\n");
}
//poll时候调用
// 在规定时间内没有按下按键 就返回超时
//中断没有发生 就return 0,在do_sys_poll中就会让系统休眠,唤醒休眠是chedule_timeout(__timeou)超时
//中断发生 return POLLIN | POLLRDNORM,在do_sys_poll退出休眠,唤醒进程
static unsigned int Eint_drv_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(file, &button_waitq, wait); //加入队列 不会立即休眠
if (ev_press)
mask |= POLLIN | POLLRDNORM;
return mask;
}
//在应用程序中使用fcnt() 时候调用
static int Eint_drvl_fasync (int fd, struct file *filp, int on)
{
printk("\ndrivec:signal_fasync successed !\n");
return fasync_helper (fd, filp, on, &button_async_queue);
}
//告诉内核
static struct file_operations Eint_drv_fops = {
.owner = THIS_MODULE, // 这是一个宏,推向编译模块时自动创建的__this_module变量
.open = Eint_drv_open,
.write = Eint_drv_write,
.read = Eint_drv_read,
.release= Eint_drv_colse,
.poll = Eint_drv_poll,
.fasync = Eint_drvl_fasync,
};
int major;//自动分配主设备号
//安装驱动的时候调用
//注册驱动 创建设备类 创建设备节点 创建虚拟地址 创建定时器任务
int Eint_drv_init(void)
{
// 创建一个定时器
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);
major=register_chrdev( 0, "key_drv",&Eint_drv_fops);//告诉内核 注册驱动
Eint_class = class_create(THIS_MODULE, "key_drv");//获取一个设备信息类
if (IS_ERR(Eint_class))
return PTR_ERR(Eint_class);
Eint_class_devs = class_device_create(Eint_class, NULL, MKDEV(major, 0), NULL, "buttons");
if (unlikely(IS_ERR(Eint_class_devs)))
return PTR_ERR(Eint_class_devs);
//转换虚拟地址
gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
gpfdat = gpfcon+1;
gpgcon =(volatile unsigned long *)ioremap(0x56000060,16);
gpgdat =gpgcon+1;
printk("Eint_drv_init successed!\n");
return 0;
}
//卸载驱动程序的时候调用
//卸载驱动 删除设备 删除设备节点 删除地址映射
void Eint_drv_exit(void)
{
unregister_chrdev( major, "key_drv");//卸载驱动
class_device_unregister(Eint_class_devs);//删除设备
class_destroy(Eint_class);//删除设备节点
iounmap(gpgcon);//删除地址映射
iounmap(gpfcon);
printk("\nEint_drv_exit successed!\n");
}
module_init(Eint_drv_init);
module_exit(Eint_drv_exit);
MODULE_LICENSE("GPL");