Linux输入子系统简要分析

本章介绍Linux输入子系统的基本概念。

_________ _        _______          _________
\__   __/( (    /|(  ____ )|\     /|\__   __/
   ) (   |  \  ( || (    )|| )   ( |   ) (
   | |   |   \ | || (____)|| |   | |   | |
   | |   | (\ \) ||  _____)| |   | |   | |
   | |   | | \   || (      | |   | |   | |
___) (___| )  \  || )      | (___) |   | |
\_______/|/    )_)|/       (_______)   )_(

 _______           ______   _______           _______
(  ____ \|\     /|(  ___ \ (  ____ \|\     /|(  ____ \
| (    \/| )   ( || (   ) )| (    \/( \   / )| (    \/
| (_____ | |   | || (__/ / | (_____  \ (_) / | (_____
(_____  )| |   | ||  __ (  (_____  )  \   /  (_____  )
      ) || |   | || (  \ \       ) |   ) (         ) |
/\____) || (___) || )___) )/\____) |   | |   /\____) |
\_______)(_______)|/ \___/ \_______)   \_/   \_______)

1.分层

Linux输入子系统分为三层:
* 输入子系统事件处理层(EventHandler):用户编程的接口,并处理驱动层提交的数据。
* 输入子系统核心层(InputCore),为设备驱动层提供接口,核心层会自动把数据提交给事件处理层。
* 输入子系统设备驱动层,实现对硬件的读写访问,中断设置、并把硬件产生的事件转换为核心层定义的规范提交给事件处理层

                        核心层
                        /    \
                      /        \
              事件处理层           设备驱动层
                    /            (键盘、鼠标、TS)
                   /
              设备节点
    (/dev/input/event*)
     (/dev/input/misc)

输入子系统核心代码为driver/input/input.c

2.编程要点

在使用Linux输入子系统进行编程时,需要进行一下三步:
* 分配Input Device结构体
* 在该结构体中设置该设备支持的事件类型及具体事件
* 编写硬件处理函数,如使用中断监听按键的动作
* 将需要处理的事件提交到InputCore
* 将该设备注册到子系统中

2.1 输入子系统支持的事件类型

事件码数字值说明
EV_SYN0x00同步事件
EV_KEY0x01按键事件
EV_REL0x02相对坐标
EV_ABS0x03绝对坐标
EV_MSC0x04其他
EV_SW0x05开关
EV_LED0x11按键 设备灯
EV_SND0x12声音
EV_REP0x14重复
EV_FF0x15力反馈
EV_PWR0x16电源
EV_FF_STATUS0x17力反馈状态

我们所实现的每个设备驱动都可以选择一个或多个进行上报给InputCore

3.简单示例

#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;

 static void button_interrupt(int irq, void*dummy, struct pt_regs *fp)
 {
        //上报事件
        input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1);
        //在上报后sync通知Core有事件要处理
        input_sync(button_dev);
 }

 static int __init button_init(void)
 {
        int error;
        //请求中断,并且在中断服务函数中进行事件上报
        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;
        }
        // 1.分配结构体
        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(EV_KEY);
        //支持按键 BTN_0
        button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);

        //向InputCore注册该设备驱动
        error = input_register_device(button_dev);
        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);
module_exit(button_exit);

由上面的源码可知,相对于自己完全实现字符设备类型驱动而言,我们所进行的编码量已经大为减少。而且层次更为清楚。

原文地址 : http://coderdock.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值