S5PV210(TQ210)学习笔记――按键驱动程序 (五)

2014-11-24 03:25:54 · 作者: · 浏览: 11
%x\n", key);
}

close(fd);
}相比轮询方式的按键驱动程序,中断方式编写的按键驱动程序可以很大程度上节省CPU资源,因此,推荐使用中断方式。

二 支持POLL机制

上面这种方式实现的按键驱动程序有个弊端,如果我们不按键,应用程序将会永远阻塞在这里,幸运的是,linux内核提供了poll机制,可以设置超时等待时间,如果在这个时间内读取到键值则正常返回,反之则超时退出。使内核支持poll非常简单,为file_operations的poll成员提供poll处理函数即可。


使内核支持poll还需要以下几步:

添加poll头文件


[cpp]
#include

#include


编写poll处理函数:

[cpp]
static unsigned buttons_poll(struct file *file, poll_table *wait){
unsigned int mask = 0;
poll_wait(file, &button_waitq, wait);

if (pressed)
mask |= POLLIN | POLLRDNORM;

return mask;
}

static unsigned buttons_poll(struct file *file, poll_table *wait){
unsigned int mask = 0;
poll_wait(file, &button_waitq, wait);

if (pressed)
mask |= POLLIN | POLLRDNORM;

return mask;
}将poll处理函数添加给file_operations:


[cpp]
.poll = buttons_poll,

.poll = buttons_poll,这样,驱动程序就支持poll机制了。下面是poll方式的测试程序:


[cpp]
#include
#include
#include
#include
#include

int main(int argc, char **argv){
int fd;
unsigned char key_val;
int ret;

struct pollfd fds[1];

fd = open("/dev/buttons", O_RDWR);
if (fd < 0){
printf("can't open!\n");
}

fds[0].fd = fd;
fds[0].events = POLLIN;
while (1){
ret = poll(fds, 1, 5000);
if (ret == 0){
printf("time out\n");
}
else{
read(fd, &key_val, 1);
printf("key_val = 0x%x\n", key_val);
}
}

return 0;
}

#include
#include
#include
#include
#include

int main(int argc, char **argv){
int fd;
unsigned char key_val;
int ret;

struct pollfd fds[1];

fd = open("/dev/buttons", O_RDWR);
if (fd < 0){
printf("can't open!\n");
}

fds[0].fd = fd;
fds[0].events = POLLIN;
while (1){
ret = poll(fds, 1, 5000);
if (ret == 0){
printf("time out\n");
}
else{
read(fd, &key_val, 1);
printf("key_val = 0x%x\n", key_val);
}
}

return 0;
}这样,应用程序可以限制时间,如果在一定时间内读取不到键值就可以做特殊处理,这种思想在网络通信中应用广泛。

三 支持异步机制

很多情况下,我们的程序在等待按键期间需要处理其它任务而不是在这里空等,这时,就需要采用异步模式了。所谓异步模式,实际上是采用消息机制(以本文的按键程序为例),即当驱动程序检测到按键后发送消息给应用程序,应用程序接收到消息后再去读取键值。与前面的两种模式相比,最大的不同在于异步方式是驱动告诉应用程序来读而不是应用程序主动去读。添加异步支持更加简单,首先是为file_operations注册fasync函数,函数内容如下:

[cpp]
static int buttons_fasync(int fd, struct file * file, int on){
return fasync_helper(fd, file, on, &button_async);
}

static int buttons_fasync(int fd, struct file * file, int on){
return fasync_helper(fd, file, on, &button_async);
}然后再buttons_read函数中添加一行代码,修改后的代码如下:[cpp] view plaincopyprint static ssize_t buttons_read(struct file * file, char __user *data, size_t count, loff_t *loff){
if(count != 1){
printk(KERN_ERR "The driver can only give one key value once!\n");
return -ENOMEM;
}

wait_event_interruptible(button_waitq, pressed);
pressed = 0;

if(copy_to_user(data, &key_val, 1)){
printk(KERN_ERR "The driver can not copy the data to user area!\n");
return -ENOMEM;
}

return 0;
}

static ssize_t buttons_read(struct file * file, char __user *data, size_t count, loff_t *loff){
if(count != 1){
printk(KERN_ERR "The driver can only give one key value once!\n");
return -ENOMEM;
}

wait_event_interruptible(button_waitq, pressed);
pressed = 0;

if(copy_to_user(data, &key_val, 1)){
printk(KERN_ERR "The driver can not copy the data to user area!\n");
r