Linux 驱动框架---input子系统框架

  前面从具体(Linux 驱动框架---input子系统)的工作过程学习了Linux的input子系统相关的架构知识,但是前面的学习比较实际缺少总结,所以今天就来总结一下输入子系统的架构分层,站到远处来看输入子系统。总得来说输入子系统由设备驱动层(input_dev的注册),输入子系统核心层(input core),事件处理层(handler),和用户空间四部分。这一部分类别platform驱动框架的内容来学习。

设备驱动层(类似于platform_device)
       就是前面描述的gpio_keys.c 中的probe接口中的处理过程主要负责不同硬件的底层相关的中断,IO等具体硬件相关的配置和对应接口的开发,并负责将不同硬件设备的数据转换为统一的事件,
通过子系统提供的API接口向输入核心汇报。

输入核心参(类似platform_bus)
承上启下的作用上到用户空间的lient,同时提供设备注册和事件层注册并负责设备和事件层的匹配,同时负责通知事件层处理事件,并在、proc等目录下产生相应的信息文件接口。

事件层(platform_drivers)
       负责对设备上报的事件进行处理,中间还引入了input_client的概念,input设备的时间层负责上对接用户空间下对接输入核心层,一个输入设备每次被打开依次设备驱动驱动层就会创建一个client,
事件处理层就负责将设备上报的事件放到每个client然后由用户读写。

中间链接件
      输入子系统的几个部分其中的input_dev(输入设备)和input_handler(事件处理层),当他们俩任何一个新注册进子系统时由子系统核心进行匹配,如果匹配成功将创建一个handle用来绑定dev和handler
这里要注意区分handler和handle 这两个太像了。

总体用一个图片来表示就是:

 参考:https://www.sohu.com/a/128794317_610671

再来看一点输入子系统core的相关内容----事件和事件map等相关的宏的含义及设置方法。

事件省略了一些内容:

struct input_dev {

    unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];

    unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
    unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
    unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
    unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
    unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
    unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
    unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
    unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
    unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
    。
    。
    。
};

具体是怎么描述的设备的的可以从如下接口“可见一斑”:

void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
{
    switch (type) {
    case EV_KEY:
        __set_bit(code, dev->keybit);
        break;

    case EV_REL:
        __set_bit(code, dev->relbit);
        break;

    case EV_ABS:
        input_alloc_absinfo(dev);
        if (!dev->absinfo)
            return;

        __set_bit(code, dev->absbit);
        break;

    case EV_MSC:
        __set_bit(code, dev->mscbit);
        break;

    case EV_SW:
        __set_bit(code, dev->swbit);
        break;

    case EV_LED:
        __set_bit(code, dev->ledbit);
        break;

    case EV_SND:
        __set_bit(code, dev->sndbit);
        break;

    case EV_FF:
        __set_bit(code, dev->ffbit);
        break;

    case EV_PWR:
        /* do nothing */
        break;

    default:
        pr_err("input_set_capability: unknown type %u (code %u)
",
               type, code);
        dump_stack();
        return;
    }

    __set_bit(type, dev->evbit);
}

可以从输入设备的结构体定义内容看到,输入系统共支持的输入类型有事件设备,按键设备,相对坐标,,,,声音控制,,开关等类型事件。也可以从头文件中的定义看到

#define EV_SYN            0x00 //同步事件
#define EV_KEY            0x01 //按键事件
#define EV_REL            0x02 //相对坐标
#define EV_ABS            0x03 //绝对坐标
#define EV_MSC            0x04 //杂项事件
#define EV_SW            0x05 //开关类型事件
#define EV_LED            0x11 //led展示事件(如键盘状态灯)
#define EV_SND            0x12 //声音事件
#define EV_REP            0x14 //重复事件
#define EV_FF            0x15 //力反馈事件
#define EV_PWR            0x16 //电源事件 好像从接口看暂时不支持
#define EV_FF_STATUS    0x17
#define EV_MAX            0x1f
#define EV_CNT            (EV_MAX+1)
/*所以通过上面的接口我盟知道设备支持的时间类型是由evbit位图来标记的,对于具体设备的code则有具体的设备类型的位图来记录。比如前面的gpio_key调用传入的事件类型是按键,而code就是具体按键的键值这个有设备平台信息携带。接下来看一下常见类型的code首先是容易理解的按键当然code就是键值如下不完全列出也不详细解释具体含义。*/

#define KEY_ESC            1
#define KEY_1            2
#define KEY_2            3
#define KEY_3            4
#define KEY_4            5
#define KEY_5            6
。
。
。
//相对坐标
#define REL_X            0x00  //这个代表x轴位移
#define REL_Y            0x01 //这个代表y轴位移
#define REL_Z            0x02  //代表z轴位移
#define REL_RX            0x03  //也是一种轴吧
#define REL_RY            0x04
#define REL_RZ            0x05
#define REL_HWHEEL        0x06
#define REL_DIAL        0x07
#define REL_WHEEL        0x08
#define REL_MISC        0x09

//绝对坐标,具体含义基本可以通过名字看出来也不完全列出来
#define ABS_X            0x00
#define ABS_Y            0x01
#define ABS_Z            0x02
#define ABS_RX            0x03
#define ABS_RY            0x04
#define ABS_RZ            0x05
#define ABS_THROTTLE        0x06
#define ABS_RUDDER        0x07
#define ABS_WHEEL        0x08
#define ABS_GAS            0x09
#define ABS_BRAKE        0x0a
#define ABS_HAT0X        0x10
//其余的还有开关类的,杂项类,LED的等,同时设备的总线输入子系统也定义了就如下几种类型
#define BUS_PCI            0x01
#define BUS_ISAPNP        0x02
#define BUS_USB            0x03
#define BUS_HIL            0x04
#define BUS_BLUETOOTH        0x05
#define BUS_VIRTUAL        0x06

#define BUS_ISA            0x10
#define BUS_I8042        0x11
#define BUS_XTKBD        0x12
#define BUS_RS232        0x13
#define BUS_GAMEPORT        0x14
#define BUS_PARPORT        0x15
#define BUS_AMIGA        0x16
#define BUS_ADB            0x17
#define BUS_I2C            0x18
#define BUS_HOST        0x19
#define BUS_GSC            0x1A
#define BUS_ATARI        0x1B
#define BUS_SPI            0x1C

最后再来看一下输入子系统上报的事件的封装结构体,这结构体定义在includeuapilinuxinput.h 说明用户也是可以使用上面这些内容和定义的如事件

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

其中type和code就是前面提及的时间类型和code最后的value就是事件的具体值,到这里输入子系统的相关内容就算基本结束了,很多细节没有去仔细的看还是我自己的习惯
学习时关注重点粗线条,使用中熟悉细节。

原文地址:https://www.cnblogs.com/w-smile/p/13611125.html