实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出。

下面的程序就是在读取按键信息的时候,如果5000ms内没有按键信息,则自己退出。

首先应用程序执行poll函数

    kernel中的sys_poll

            do_sys_poll

              init_poll_funcptr-->do_poll

            do_poll

              for(;;)

              {

                if(do_pollfd(pfd,pt))

                {  

                  count++;  //如果驱动的poll返回非0值,那么count++

                  //把进程挂到队列中休眠

                   pt=null;}

                if( count || !*timeout || signal_pending(current))

                  break; //如果count非0  超时, 有信号等待处理

              }

              __timeout = schedule_timeout(__time_out);  //休眠 下次执行到上面的判断时,就会超时退出

驱动代码:

#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <linux/fs.h>
#include <asm/arch/regs-gpio.h>
#include <linux/interrupt.h>
#include <linux/poll.h> static struct class *key_class; //创建类
static struct class_device *key_class_devs; //创建类对应的设备 struct pin_desc{
unsigned int pin;
unsigned int key_val;
};
struct pin_desc pins_desc[] = {
{S3C2410_GPF0,0X01},
{S3C2410_GPF2,0X02},
{S3C2410_GPG3,0X03},
{S3C2410_GPG11,0X04},
};
unsigned char keyvals=; static volatile int ev_press = ;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq); static irqreturn_t keys_irq(int irq, void *dev_id)
{
struct pin_desc *pindesc = (struct pin_desc *)dev_id;
unsigned int pinval;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval)
{
keyvals = pindesc->key_val|0x80;
}
else
{
keyvals = pindesc->key_val;
}
ev_press = ;
wake_up_interruptible(&button_waitq);
return IRQ_HANDLED;
} int key_open(struct inode *inode, struct file *fp)
{
request_irq( IRQ_EINT0, keys_irq, IRQT_BOTHEDGE, "key2", &pins_desc[]);
request_irq( IRQ_EINT2, keys_irq, IRQT_BOTHEDGE, "key3", &pins_desc[]);
request_irq( IRQ_EINT11, keys_irq, IRQT_BOTHEDGE, "key4", &pins_desc[]);
request_irq( IRQ_EINT19, keys_irq, IRQT_BOTHEDGE, "key5", &pins_desc[]);
return ;
} ssize_t key_read(struct file *fp, char __user *buff, size_t count, loff_t *offp){ if(count != )
{
return -EINVAL;
}
wait_event_interruptible(button_waitq,ev_press); copy_to_user(buff,&keyvals,);
ev_press = ;
return ;
} ssize_t key_write(struct file *fp, const char __user *buf, size_t count, loff_t *ppos){
} int key_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT0,&pins_desc[]);
free_irq(IRQ_EINT2,&pins_desc[]);
free_irq(IRQ_EINT11,&pins_desc[]);
free_irq(IRQ_EINT19,&pins_desc[]);
} static unsigned int key_poll(struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = ;
poll_wait(file, &button_waitq,wait);
if(ev_press)
mask |= POLLIN|POLLRDNORM;
return mask;
} struct file_operations led_fops={
.owner = THIS_MODULE,
.open = key_open,
.write = key_write,
.read = key_read,
.release = key_close,
.poll = key_poll,
}; int major;
static int key_init(void)
{
major = register_chrdev( ,"key_drv", &led_fops );
key_class = class_create(THIS_MODULE,"key_class");
key_class_devs = class_device_create(key_class,NULL,MKDEV(major,),NULL,"my_keys"); printk("key install Module\n");
return ;
} static void key_exit(void)
{
unregister_chrdev( major, "key_drv" );
class_device_unregister(key_class_devs);
class_destroy(key_class);
printk("key Module exit\n");
} module_init(key_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");

应用测试代码:

#include <stdio.h>
#include <fcntl.h>
#include <poll.h> int main()
{
int fd;
int ret;
struct pollfd pfd[];
unsigned char key_val;
fd = open("/dev/my_keys",O_RDWR);
if(fd<)
{
printf("open failed\n");
return ;
}
pfd[].fd = fd;
pfd[].events = POLLIN;
while()
{
ret = poll(pfd, , );    //如果在5000ms之内没有按下按键 这自动退出
// read(fd, &key_val,1);
if(ret==)
printf("time out\n");
else
{
read(fd, &key_val,);
printf("key:%x\n",key_val);
}
}
}

sd

嵌入式Linux驱动学习之路(十二)按键驱动-poll机制的更多相关文章

  1. 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖

    在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...

  2. 嵌入式Linux驱动学习之路(十四)按键驱动-同步、互斥、阻塞

    目的:同一个时刻,只能有一个应用程序打开我们的驱动程序. ①原子操作: v = ATOMIC_INIT( i )  定义原子变量v并初始化为i atomic_read(v)        返回原子变量 ...

  3. 嵌入式Linux驱动学习之路(十八)LCD驱动

    驱动代码: /************************************************************************* > File Name: lcd ...

  4. 嵌入式Linux驱动学习之路(十)字符设备驱动-my_led

    首先贴上代码: 字符设备驱动代码: /** *file name: led.c */#include <linux/sched.h> #include <linux/signal.h ...

  5. 嵌入式Linux驱动学习之路(十九)触摸屏驱动、tslib测试

    触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断, ...

  6. 嵌入式Linux驱动学习之路(十六)输入子系统

    以前写的一些输入设备的驱动都是采用字符设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的.不同类别的输入设备进行统一的驱动,所以 ...

  7. 嵌入式linux的学习之路[转]

    我认为的一条学习嵌入式Linux的路: 1)学习 Linux系统安装. 常用命令.应用程序安装. 2) 学习 Linux 下的 C 编程.这本书必学<UNIX 环境高级编程>.<UN ...

  8. zigbee学习之路(十二):zigbee协议原理介绍

    一.前言 从今天开始,我们要正式开始进行zigbee相关的通信实验了,我所使用的协议栈是ZStack 是TI ZStack-CC2530-2.3.0-1.4.0版本,大家也可以从TI的官网上直接下载T ...

  9. Object-c学习之路十二(OC的copy)

    oc中的拷贝分为:copy(浅拷贝)和mutablecopy(深拷贝). 浅拷贝也为指针拷贝,拷贝后原来的对象计数器会+1: 深拷贝为对象拷贝,原来的对象计数器不变. 注意:自定义对象拷贝时要实现NS ...

随机推荐

  1. JVM-绘图展现字节码执行引擎执行过程

    在我的上一篇博客JVM-String比较-字节码分析中介绍了String字符串比较的原因,借着分析字节码的机会,我这篇博客将会绘图展现方法内部字节码执行过程. 话不多说,贴上我们将要分析的Java方法 ...

  2. 51nod 算法马拉松18 B 非010串 矩阵快速幂

    非010串 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 如果一个01字符串满足不存在010这样的子串,那么称它为非010串. 求长度为n的非010串的个数.(对1e9+7取模) ...

  3. 从零开始学 Java - Spring 一主多从、多主多从 数据库配置

    待会苹果要开发布会 我写完这篇文章就准备去看发布会了,因为我买了好几包瓜子和啤酒.由于苹果的保密做的越来越差劲,该曝光的信息差不多全部曝光了,我们这种熬夜看发布会的只不过是让这些信息更加真实,或者说是 ...

  4. JavaScript调试 - debugger语句

    语法: debugger 作用: 启动调试器 备注: 1. 可以将debugger语句放在过程的任何地方以中止执行.2. 使用debugger语句类似于在代码中设置断点. 3. debugger语句中 ...

  5. 原型对象prototype和原型属性[[Prototype]]

    构造器:可以被 new 运算符调用, Boolean,Number,String,Date,RegExp,Error,Function,Array,Object 都是构造器,他们有各自的实现方式. 比 ...

  6. SQL 常识

    1.varchar 与 nvarchar 的区别? varchar(n):长度为 n 个字节的可变长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为输 ...

  7. SharePoint 2013 工作流之使用Visio设计篇

    SharePoint 2013增强了工作流,不仅仅基于WorkFlow Foundation 4.0了,设计方式也不仅仅是Designer,还包括Visio中设计,下面我们就一个简单的例子,介绍下. ...

  8. GCD

    Grand Central Dispatch(GCD)包含语言特点.运行库和系统增强功能,它提供系统的.综合的改进,进而去支持并发代码在iOS和OSX多核硬件上的执行. 子系统.CoreFoundat ...

  9. iOS 疑难杂症 — — UITableView 添加 tableFooterView 旋转屏幕后收不到点击事件!!!

    声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblogs.com 正文 新手的烦恼你不懂 - - ## ...

  10. RoboGuice 3.0 (一)入坑篇

    RoboGuice是什么? 一个Android上的依赖注入框架. 依赖注入是什么? 从字面理解,这个框架做了两件事情,第一是去除依赖,第二是注入依赖.简单理解就是,将对象的初始化委托给一个容器控制器, ...