注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

小白的博客

嵌入式爱好者

 
 
 

日志

 
 

input输入子系统第一个驱动编写笔记  

2012-09-13 21:10:43|  分类: 韦东山视频第二轮 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
目的不是写出来这些代码,而是搞明白如何写出这些代码:

#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/timer.h>
#include <linux/input.h>

#include <asm/uaccess.h>
#include <asm/io.h>
#include <mach/regs-gpio.h>
#include <asm/poll.h>
struct key_desc {
int irq;
int pin;
int event;
char *name;
};

static struct key_desc keys_desc[4] = {
{IRQ_EINT0  , S3C2410_GPF(0) ,KEY_L        , "key1"},
{IRQ_EINT2  , S3C2410_GPF(2) ,KEY_S   , "key2"},
{IRQ_EINT11 , S3C2410_GPG(3) ,KEY_ENTER    , "key3"},
{IRQ_EINT19 , S3C2410_GPG(11),KEY_LEFTSHIFT, "key4"},
};

static struct input_dev *buttons_dev;
static struct timer_list timer;
static struct key_desc *gkey_desc;
static int key_sign=0;

static irqreturn_t handler_buttons(int irq, void *dev_id)
{
gkey_desc = (struct key_desc *)dev_id;
key_sign=1;
mod_timer(&timer , jiffies+HZ/100);

return 0;
}

static void buttons_timer_handler(unsigned long data)
{
int pin_stat ;
if(key_sign==0)
return -1;
pin_stat = s3c2410_gpio_getpin(gkey_desc->pin);
if(pin_stat==0)
{
input_event(buttons_dev , EV_KEY , gkey_desc->event, 1);
input_sync(buttons_dev);
}
else
{
input_event(buttons_dev , EV_KEY , gkey_desc->event, 0);
input_sync(buttons_dev);
}
key_sign=0;
}

static int buttons_init(void)
{
int i;
buttons_dev = input_allocate_device();
set_bit(EV_KEY        ,   buttons_dev->evbit);
set_bit(EV_REP        ,   buttons_dev->evbit);
set_bit(KEY_L         ,   buttons_dev->keybit);
set_bit(KEY_S         ,   buttons_dev->keybit);
set_bit(KEY_ENTER     ,   buttons_dev->keybit);
set_bit(KEY_LEFTSHIFT ,   buttons_dev->keybit);
input_register_device(buttons_dev);
for(i=0 ; i<4 ; i++)
{
request_irq(keys_desc[i].irq , handler_buttons , IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING , keys_desc[i].name , &keys_desc[i]);
}
init_timer(&timer);
timer.function = buttons_timer_handler;
add_timer(&timer);
return 0;
}

static void buttons_exit(void)
{
int i;
del_timer(&timer);
for(i=0 ; i<4 ; i++)
{
free_irq(keys_desc[i].irq , &keys_desc[i]);
}
input_unregister_device(buttons_dev);
input_free_device(buttons_dev);
}

module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");

上一节里面我们讲了输入子系统的框架,本节我们就以一个输入子系统驱动的例子来分析一个如何来写代码:
首先我们要明白输入子系统分为两层,底层分为handler和dev两块,而我们写驱动需要完成的是底层的dev,handler和顶层也就是input.c已经由内核完成了,下面我们就来看看本驱动程序都做了什么:
1、分配了一个input_dev结构体
2、设置这个结构体
3、注册这个结构体,我们在来具体看一下源码:
input_register_device(buttons_dev);
       //设置定时器超时处理函数
      dev->timer.function = input_repeat_key;
      //寻找能够处理该dev的handler,并在二者之间建立联系
      list_for_each_entry(handler, &input_handler_list, node)
            input_attach_handler(dev, handler);
4、一旦发生了中断,就会上报事件:
input_event(buttons_dev , EV_KEY , gkey_desc->event, 1);
      //判断是否支持该类事件,我们在设置input_dev结构体的时候设置了dev支持哪类事件
      is_event_supported(type, dev->evbit, EV_MAX)
      input_handle_event(dev, type, code, value);
            case EV_KEY:
                  //判断是否支持该事件,我们在设置input_dev结构体的时候设置了dev支持哪些事件
                  is_event_supported(code, dev->keybit, KEY_MAX)
5、一旦超时,执行超时处理函数:
static void input_repeat_key(unsigned long data)
     input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
          //找到dev所对应的handle
          handle = rcu_dereference(dev->grab);
          //调用handler->event来处理该事件
          handle->handler->event(handle, type, code, value);

这样,整个input输入子系统的大的框架就被我们搞清楚了,真爽!!!
  评论这张
 
阅读(974)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017