input驱动分析

本文深入探讨了Linux内核中的input驱动模型,通过一个简单的按钮中断处理例子,介绍了如何初始化、注册input设备以及中断处理。关键函数包括input_allocate_device、input_register_device、input_report_key和input_sync。input驱动涉及按键、触摸屏等多种输入设备,文章详细解析了设备初始化、注册过程以及事件处理流程。
摘要由CSDN通过智能技术生成
                        

      input驱动在linux内核中经常会用到,比如按键类: power button,一般用gpio来做按键模拟,还有touch key等。触摸屏,键盘鼠标,gsensor,gameport等。本文结合一例子对input驱动模型做探讨。

 下面是linux文档中的例子。

#include <linux/input.h>

#include <linux/module.h>

#include <linux/init.h>

#include <asm/irq.h>

#include <asm/io.h>

static struct input_dev *button_dev;//将该button设备定义为input_dev类型

static irqreturn_t  button_interrupt(int irq, void *dummy)//中断处理函数

{

  input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);//向上层汇报键值//BTN_0,inb(BUTTON_PORT) & 1表示是通码还是断码

         input_sync(button_dev);//等待结构体数据都填好后,即数据同步后发送给上层。

         return IRQ_HANDLED;

}

static int __init button_init(void)//button设备的初始化

{

         int error;

    //中断申请,BUTTON_IRQ是中断源,button_interrupt是中断处理函数,0表示中//断类型,是上升沿,下降沿之类,在linux 2.6.35表示0是IRQF_TRIGGER_NONE            //类型;”button”是设备名字;NULL表示设备的相关数据为空

         if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {

                printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);

                return -EBUSY;

        }

    //分配设备内存

         button_dev = input_allocate_device();

         if (!button_dev) {

                   printk(KERN_ERR "button.c: Not enough memory\n");

                   error = -ENOMEM;

                   goto err_free_irq;

         }

    //属性设置

         button_dev->evbit[0] = BIT_MASK(EV_KEY);//表示该input设备是按键事件

         button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);//设置按键的键值

 

         error = input_register_device(button_dev);//注册input设备

         if (error) {

                   printk(KERN_ERR "button.c: Failed to register device\n");

                   goto err_free_dev;

         }

         return 0;

 err_free_dev:

         input_free_device(button_dev);// 注册失败,释放已注册的部分

 err_free_irq:

         free_irq(BUTTON_IRQ, button_interrupt);//释放中断

         return error;

}

 

static void __exit button_exit(void)

{

        input_unregister_device(button_dev);// 注销注册

         free_irq(BUTTON_IRQ, button_interrupt);

}

module_init(button_init);  // button设备初始化部分,生成模块。Linux驱动特有的结构 

module_exit(button_exit);//设备注销模块

 

上面是比较简单的注册 input 设备中断处理例子。

注意几个API函数:

1):

set_bit(EV_KEY, button_dev.evbit); set_bit(BTN_0, button_dev.keybit);

分别用来设置设备所产生的事件以及上报的按键值。Struct iput_dev 中有两个成员,一个是evbit.一个是keybit.分别用表示设备所支持的动作和按键类型。

2): input_register_device(&button_dev);

用来注册一个input device.

3): input_report_key()

用来上层上报一个按键动作

4): input_sync()

等待结构体数据都填好后,本次事件操作已完成,数据同步后发送给上层。

 

一.首先来分析input_allocate_device

struct input_dev *input_allocate_device(void)

{

         struct input_dev *dev;

    // 使用kzalloc函数分配内存

         dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);

         if (dev) {

                   dev->dev.type = &input_dev_type;

                   dev->dev.class = &input_class;

                   device_initialize(&dev->dev);

                   mutex_init(&dev->mutex);

                   spin_lock_init(&dev->event_lock);

                   INIT_LIST_HEAD(&dev->h_list);

                   INIT_LIST_HEAD(&dev->node);

 

                   __module_get(THIS_MODULE);

         }

         return dev;

}

         内存分配成功后,向其成员变量赋值,主要包括input_dev_type(包括设备属性group,设备uevent事件),input_class(设备名以及设备节点),以及设备初始化(kobject是在里初始化的,为创建设备文件系统做准备),还有自旋锁的初始化等。

 

二、注册函数input_register_device

   int input_register_device(struct input_dev *dev)

{

         static atomic_t input_no = ATOMIC_INIT(0);

         struct input_handler *handler;

         const char *path;

         int error;

 

         /* Every input device generates EV_SYN/SYN_REPORT events. */

    //所有设备都支持EV_SYN这种事件类型

         __set_bit(EV_SYN, dev->evbit);

 

         /* KEY_RESERVED is not supposed to be transmitted to userspace. */

         __clear_bit(KEY_RESERVED, dev->ke

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值