现在的位置: 首页 > 综合 > 正文

应用程序实现多路监听的内核驱动实现

2014年05月30日 ⁄ 综合 ⁄ 共 2003字 ⁄ 字号 评论关闭

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <asm/gpio.h>
#include <plat/gpio-cfg.h>

static int major;
struct cdev btn_cdev;
struct class *cls;
static unsigned char key_val;
static int ispress;
static wait_queue_head_t btn_wq;

static ssize_t btn_read(struct file *file,
char __user *buf,
size_t count,
loff_t *ppos)
{
//如果没有按键操作,休眠,否则继续读取按键值
wait_event_interruptible(btn_wq, ispress);
ispress = 0;
copy_to_user(buf, &key_val, 1);
return count;
}

static irqreturn_t button_isr(int irq, void *dev_id)
{
unsigned int pinstatus = gpio_get_value(S5PV210_GPH0(0));
if (pinstatus == 1)
key_val = 0x50; //松开
else
key_val = 0x51; //按下

ispress = 1;
wake_up_interruptible(&btn_wq);

return IRQ_HANDLED;
}

static unsigned int btn_poll(struct file *file,
struct poll_table_struct * wait)
{
unsigned int mask = 0;

/*1.添加进程到等待队列头中*/
//只是添加到等待队列头中,不会立即休眠
poll_wait(file, &btn_wq, wait);

/*2.判断按键是否有操作*/
if (ispress) {
//有按键操作
mask |= POLLIN|POLLRDNORM; //设备可读,
//数据可读
}
printk("++++ %s ++++\n", __func__);
return mask;
}

static struct file_operations btn_fops = {
.owner  = THIS_MODULE,
.read = btn_read,
.poll = btn_poll
};

static int button_init(void)
{
dev_t dev_id;

/*1.申请设备号*/
alloc_chrdev_region(&dev_id, 0, 1, "buttons");
major = MAJOR(dev_id);

/*2.初始化注册cdev*/
cdev_init(&btn_cdev, &btn_fops);
cdev_add(&btn_cdev, dev_id, 1);

/*3.创建设备节点*/
cls = class_create(THIS_MODULE, "buttons");
device_create(cls, NULL, dev_id, NULL, "button");

/*4.申请GPIO*/
gpio_request(S5PV210_GPH0(0), "KEY_UP");

/*5.注册中断*/
request_irq(IRQ_EINT(0), button_isr, 
IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
"KEY_UP", NULL);

/*6.初始化等待队列头*/
init_waitqueue_head(&btn_wq);

return 0;

}


static void button_exit(void)
{
/*释放中断和GPIO资源*/
free_irq(IRQ_EINT(0), NULL);
gpio_free(S5PV210_GPH0(0));

/*2.删除设备节点*/
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);

/*3.卸载cdev*/
cdev_del(&btn_cdev);

/*4.释放设备号*/
unregister_chrdev_region(MKDEV(major, 0), 1);
}
module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE("GPL v2");

抱歉!评论已关闭.