历史上的今天

今天是:2024年11月19日(星期二)

2019年11月19日 | ARM Linux内核Input输入子系统浅解

发布者:东土大唐88 来源: 51hei关键字:ARM  Linux内核  Input  输入子系统 手机看文章 扫描二维码
随时随地手机看文章

--以触摸屏驱动为例

第一章、了解linux input子系统

 

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

图1  input输入子系统

 

驱动层和硬件相关,直接捕捉和获取硬件设备的数据信息等(包括触摸屏被按下、按下位置、鼠标移动、键盘按下等等),然后将数据信息报告到核心层。核心层负责连接驱动层和事件处理层,设备驱动(device driver)和处理程序(handler)的注册需要通过核心层来完成,核心层接收来自驱动层的数据信息,并将数据信息选择对应的handler去处理,最终handler将数据复制到用户空间。


先了解三个定义在/linux/input.h下重要的结构体input_dev、input_handler、input_handle。

struct input_dev {

      void *private;

 

      const char *name;

      const char *phys;

      const char *uniq;

      struct input_id id;      //与input_handler匹配用的id

 

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

      unsigned long keybit[NBITS(KEY_MAX)];      //按键事件支持的子事件类型

      unsigned long relbit[NBITS(REL_MAX)];

      unsigned long absbit[NBITS(ABS_MAX)];      //绝对坐标事件支持的子事件类型

      unsigned long mscbit[NBITS(MSC_MAX)];

      unsigned long ledbit[NBITS(LED_MAX)];

      unsigned long sndbit[NBITS(SND_MAX)];

      unsigned long ffbit[NBITS(FF_MAX)];

      unsigned long swbit[NBITS(SW_MAX)];

      int ff_effects_max;

 

      unsigned int keycodemax;

      unsigned int keycodesize;

      void *keycode;

 

      unsigned int repeat_key;

      struct timer_list timer;

 

      struct pt_regs *regs;

      int state;

      int sync;

 

      int abs[ABS_MAX + 1];

      int rep[REP_MAX + 1];

 

      unsigned long key[NBITS(KEY_MAX)];

      unsigned long led[NBITS(LED_MAX)];

      unsigned long snd[NBITS(SND_MAX)];

      unsigned long sw[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, int value);

      int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);

      int (*erase_effect)(struct input_dev *dev, int effect_id);

 

      struct input_handle *grab;      //当前占有该设备的handle

 

      struct mutex mutex;      /* serializes open and close operations */

      unsigned int users;            //打开该设备的用户量

 

      struct class_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中有定义,深入跟踪

struct list_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结构体桥接,具体后面说明。

 

struct input_handler {

 

      void *private;

 

      void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);

      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;      //提供给用户对设备操作的函数指针

      int minor;

      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中有定义

 

struct input_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 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 memoryn");

            err = -ENOMEM;

            goto fail;

      }

 

      …

 

      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.version = 0x0100;

 

      tsdev ->open    = xxx_open;

      tsdev ->close   =xxx_close;

 

      tsdev ->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_SYN);            //设置支持的事件类型

tsdev ->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);           

      input_set_abs_params(tsdev, ABS_X, 0, 0x400, 0, 0);            //限定绝对坐标X的取值范围

      input_set_abs_params(tsdev, ABS_Y, 0, 0x400, 0, 0);            //同上

      input_set_abs_params(tsdev, ABS_PRESSURE, 0, 1000, 0, 0);      //触摸屏压力值范围

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ..[12]
关键字:ARM  Linux内核  Input  输入子系统 引用地址:ARM Linux内核Input输入子系统浅解

上一篇:u-boot-1.3.4 移植到S3C2440
下一篇:ARM嵌入式系统的学习步骤

推荐阅读

最近看了不少网上网友的应用案例,在STM32晶振问题上不少都栽了跟头。我自己也碰见过一次。就是电容值搞错了。ourdev有网友说:他的设备隔几天系统就出问题,系统时钟变慢。----------------------------------------有网友说:国产的晶振,我们用在产品里吃过很多亏。发出去几百个货(出厂都检验合格),到客户那里几个有时就不起振了(几个月后),后来...
据外媒报道,近日,Velodyne Lidar公司宣布推出下一代激光雷达传感器 - Alpha Prime™,利用该公司的专利环视技术,能够利用一个传感器就满足自动驾驶出行行业内的最高综合性能规范。该款传感器是一个无与伦比的解决方案,可用于交通、货运和机器人等自动驾驶市场的感知和视野领域。Alpha Prime具备超高的电力效率,如今已经开放订购和交付。Alpha P...
中美两国在尖端科技上的竞争越演越烈。继5G之后,量子科技或将成为美国最为忌惮的中国科技。 10月16日,中共中央政治局集体学习量子科技。就在此前一天,美国国务院发布了《关键与新兴技术国家战略》,详细介绍了美国为保持全球领导力而强调发展“关键与新兴技术”,明确了20项关键与新兴技术的清单,其中就包括量子信息科学。 中美为何如此重视量子科技?...
感谢IT之家网友 @假装的努力@HHXu97@ConstantineYHN 的线索投递,华为 Mate 40 和 P40 Pro 已经推送了鸿蒙HarmonyOS 2.0.0.212 版本更新,大小为 309MB、321MB。  更新包 1 更新日志  [安全]  合入 2021 年 11 月安全补丁,增强手机系统安全。  更新包 2 更新日志  本次更新优化了与部分蓝牙耳机的兼容性,推荐您进...

史海拾趣

问答坊 | AI 解惑

用什么也别用害人的红外一体机!(转)

转自:http://www.1000bbs.com/dispbbs.asp?boardid=51&Id=261604 首先声明一下身份:辽宁锦州安防器材经销商、工程商。 我开始选择红外一体机,是因为甲方点着名要这玩意。 选了哪些厂家的哪些型号的红外机,恕我不一一列举了。总之,深圳的 ...…

查看全部问答∨

WINCE SDK平台改变后出现的问题!求助!

WINCE SDK平台改变后出现的问题: fatal error LNK1112: module machine type \'ARM\' conflicts with target machine type \'SH3\' 这要怎么解决啊???…

查看全部问答∨

求驱动函数

菜鸟请高手指点 有三个设备A、B、C A是最底层,然后挂载B到A上面,也就是原来设备栈的顺序是 A--B (由底到顶) 现在我想在A,B的设备栈里面加入C,但是我不希望设备栈的顺序是 A--B--C(由底到顶) ,而是希望希望设备栈的顺序 是 A--C--B(由底到顶) ...…

查看全部问答∨

verilog中的task 可以在定义的模块之外调用么?

例如 taskA 在moduleA中定义, 而moduleB与moduleA有可能是嵌套关系,也可能是并列的被高层模块调用,那么moduleB能调用taskA么?…

查看全部问答∨

关于lpc2292 arm的初始化外部总线控制器 问题

我现在程序在外部flash运行,LPC2292,外部flash是sst39vf1601,在外部flash的0x10000地址(也就是arm看到的0x80010000地址开始我是烧的fpga程序,这个已经是没问题的),在用EASYJTAG-H外部仿真的时候,在MAIN入口处,我也看到了数据。startup.s的设 ...…

查看全部问答∨

SEFS安全透明加密内核

软件名称:SEFS安全透明加密内核 软件版本:1.0 建议分类:系统安全/文件加密 软件大小:635K 安装平台:Win2000/xp/2003 软件语言:简体中文/繁体中文/英文 软件授权:共享软件 软件主页:http://www.sefs.net 支持邮箱:admin@sefs.ne ...…

查看全部问答∨

一份很不错的红外遥控资料

<IMG border=0 src="file:///D:/123.jpg">…

查看全部问答∨

msp430f149栈溢出的问题

大家好,我在编译一个代码出现了栈溢出警告, 理论上讲我的数据段为: map文件 6 152 bytes of CODE  memory 1 268 bytes of DATA  memory (+ 56 absolute )   463 bytes of CONST memory   而栈的使用情况 ...…

查看全部问答∨

vb上位机 51单片机下位机 编程

Visual Basic设计完成了上位机界面;同时利用51单片机作为下位机微处理器,采集无刷电机运行工作中的电压、电流和转速等基本参数,通过串行通讯口将数据上传至上位机系统中。上位机系统对下位机上传的数据加以分析计算,直观的绘制个参数的变化曲线 ...…

查看全部问答∨

C2000/MSP430/电源的在线学习不能用了!!!!

C2000/MSP430/电源的在线学习不能用了!!!! 求关注,你们那里有这个现象没?…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved