arm shell 获取本地键盘输入值_Linux输入设备详解

本文介绍了Linux内核的input子系统,包括驱动层、核心层和事件处理层的职责。重点讲解了input_dev、input_handler和input_handle三个关键结构体,以及它们在input设备注册和事件处理中的作用。详细阐述了input_dev的注册过程,如input_allocate_device()和input_register_device()函数,以及input_handler的注册。文章还提及了struct evdev_list和struct input_event在数据传输中的角色。
摘要由CSDN通过智能技术生成

➤简介

Linux输入设备总类繁杂,常见的包括有按键、键盘、触摸屏、鼠标、摇杆等等,他们本身就是字符设备,而linux内核将这些设备的共同性抽象出来,简化驱动开发建立了一个input子系统。子系统共分为三层,如图1所示。

图1  input输入子系统

➣驱动层

驱动层和硬件相关,直接捕捉和获取硬件设备的数据信息等(包括触摸屏被按下、按下位置、鼠标移动、键盘按下等等),然后将数据信息报告到核心层。

➣核心层

核心层负责连接驱动层和事件处理层,设备驱动(device driver)和处理程序(handler)的注册需要通过核心层来完成,核心层接收来自驱动层的数据信息,并将数据信息选择对应的handler去处理,最终handler将数据复制到用户空间。

➤重要的结构体input_dev、input_handler、input_handle。

➣input_dev

structinput_dev {void *private;const char *name;const char *phys;const char *uniq;struct inBITS(KEY_MAX)]; //按键事件支持的子事件类型

unsigned longrelbit[NBITS(REL_MAX)];

unsignedlong absbit[NBITS(ABS_Mput_id id; //与input_handler匹配用的id

unsigned long evbit[NBITS(EV_MAX)]; //设备支持的事件类型

unsigned long keybit[NAX)]; //绝对坐标事件支持的子事件类型

unsigned longmscbit[NBITS(MSC_MAX)];

unsignedlongledbit[NBITS(LED_MAX)];

unsignedlongsndbit[NBITS(SND_MAX)];

unsignedlongffbit[NBITS(FF_MAX)];

unsignedlongswbit[NBITS(SW_MAX)];intff_effects_max;

unsignedintkeycodemax;

unsignedintkeycodesize;void *keycode;

unsignedintrepeat_key;structtimer_list timer;struct pt_regs *regs;intstate;intsync;int abs[ABS_MAX + 1];int rep[REP_MAX + 1];

unsignedlongkey[NBITS(KEY_MAX)];

unsignedlongled[NBITS(LED_MAX)];

unsignedlongsnd[NBITS(SND_MAX)];

unsignedlongsw[NBITS(SW_MAX)];int absmax[ABS_MAX + 1]; //绝对坐标事件的最大键值

int absmin[ABS_MAX + 1]; //绝对坐标事件的最小键值

int absfuzz[ABS_MAX + 1];int absflat[ABS_MAX + 1];int (*open)(struct input_dev *dev);void (*close)(struct input_dev *dev);int (*accept)(struct input_dev *dev, struct file *file);int (*flush)(struct input_dev *dev, struct file *file);int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, intvalue);int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);int (*erase_effect)(struct input_dev *dev, inteffect_id);struct input_handle *grab; //当前占有该设备的handle

struct mutex mutex; /*serializes open and close operations*/unsignedint users; //打开该设备的用户量

structclass_device cdev;struct device *dev; /*will be removed soon*/

int dynalloc; /*temporarily*/

struct list_head h_list; //该链表头用于链接该设备所关联的input_handle

struct list_head node; //该链表头用于将设备链接到input_dev_list

};

Input_dev是一个很强大的结构体,它把所有的input设备(触摸屏、键盘、鼠标等)的信息都考虑到了,对于触摸屏来说只用到它里面的一部分而已,尤其是加粗的部分,注意该结构体中最后两行定义的两个list_head结构体,list_head在/linux/list.h中有定义,深入跟踪

structlist_head {struct list_head *next, *prev;

};

该结构体内部并没有定义数据而只定义了两个指向本身结构体的指针,预先说明一下:★所有的input device在注册后会加入一个input_dev_list(输入 设备链表)。★所有的eventhandler在注册后会加入一个input_handler_list(输入处理程序链表),这里的list_head主要的作用是作为input_dev_list和input_handler_list的一个节点来保存地址。Input_dev_list和input_handler_list之间的对应关系由input_handle结构体桥接,具体后面说明。

➣input_handler

structinput_handler {void *private;void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, intvalue);struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);void (*disconnect)(struct input_handle *handle);const struct file_operations *fops; //提供给用户对设备操作的函数指针

intminor;char *name;struct input_device_id *id_table; //与input_dev匹配用的id

struct input_device_id *blacklist; //标记的黑名单

struct list_head h_list; //用于链接和该handler相关的handle

struct list_head node; //用于将该handler链入input_handler_list

};

input_handler顾名思义,它是用来处理input_dev的一个结构体获取回来的数据,相关的处理函数在结构里内部都有定义,最后两行定义的list_head结构体作用同input_dev所定义的一样,这里不再说明。

注:input_device_id结构体在/linux/mod_devicetable.h中有定义

➣input_handle

structinput_handle {void *private;int open; //记录设备打开次数

char *name;struct input_dev *dev; //指向所属的input_dev

struct input_handler *handler; //指向所属的input_handler

struct list_head d_node; //用于链入所指向的input_dev的handle链表

struct list_head h_node; //用于链入所指向的input_handler的handle链表

};

可以看到input_handle中拥有指向input_dev和input_handler的指针,★即input_handle是用来关联input_dev和input_handler。

●为什么用input_handle来关联input_dev和input_handler而不将input_dev和input_handler直接对应呢?

因为一个device可以对应多个handler,而一个handler也可处理多个device。就如一个触摸屏设备可以对应event handler也可以对应tseve handler。

➣input_dev、input_handler、input_handle的关系如下图2所示。

图2  input_dev,input_handler,input_handle关系图

Input device的注册实际上仅仅只有几行代码,因为在input.c中已经将大量的代码封装好了,主需要调用几个关键的函数就能完成对input device的注册。

在xxx_ts.c中预先定义全局变量struct input_dev  tsdev;然后进入到初始化函数

static int __init xxx_probe(struct platform_device *pdev)

{

…if (!(tsdev =input_allocate_device()))

{

printk(KERN_ERR"tsdev: not enough memory\n");

err= -ENOMEM;gotofail;

}

tsdev->name = "xxx TouchScreen"; //xxx为芯片型号

tsdev ->phys = "xxx/event0";

tsdev->id.bustype = BUS_HOST; //设备id,用于匹配handler的id

tsdev ->id.vendor = 0x0005;

tsdev->id.product = 0x0001;

tsdev->id.vers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值