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);      //触摸屏压力值范围

If(input_register_device(tsdev) == error)      //注册设备

goto fail;

fail:

input_free_device(tsdev);

printk(“ts probe failedn”);

return err;

}

先看该函数中的tsdev = input_allocate_device(),深入最终,该函数在input.c中有定义

struct input_dev *input_allocate_device(void)

{

struct input_dev *dev;

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

if (dev) {

dev->dynalloc = 1;

dev->cdev.class = &input_class;

class_device_initialize(&dev->cdev);

INIT_LIST_HEAD(&dev->h_list);

INIT_LIST_HEAD(&dev->node);

}

return dev;

}

学过C语言应该都知道malloc函数(开辟内存空间),而这里的kzalloc也类似于C语言中的malloc一样,是linux内核空间分配内存函数,后面的GFP_KERNEL标志意为常规的内存分配,更多的分配标志可参阅先关资料(我也不懂)。再回到前面的函数中来,接着后面的代码为对tsdev结构体中的成员进行赋值初始化,赋值完成后就要开始进入主题:注册设备了,进入到函数input_register_device(tsdev),该函数在input.c中有定义。

int input_register_device(struct input_dev *dev)

{

static atomic_t input_no = ATOMIC_INIT(0);      //定义原子变量,禁止线程并发访问

struct input_handle *handle;            //定义一些变量备后文使用

struct input_handler *handler;

struct input_device_id *id;

const char *path;

int error;

if (!dev->dynalloc) {

printk(KERN_WARNING "input: device %s is statically allocated, will not registern"

"Please convert to input_allocate_device() or contact dtor_core@ameritech.netn",

dev->name ? dev->name : "");

return -EINVAL;

}

mutex_init(&dev->mutex);            //互斥锁初始化,防止临界区代码被并发访问

set_bit(EV_SYN, dev->evbit);            //设置支持同步事件,input设备全部默认支持同步事件

/*

* If delay and period are pre-set by the driver, then autorepeating

* is handled by the driver itself and we don't do it in input.c.

*/

init_timer(&dev->timer);

if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {

dev->timer.data = (long) dev;

dev->timer.function = input_repeat_key;

dev->rep[REP_DELAY] = 250;

dev->rep[REP_PERIOD] = 33;

}

[1].. [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]

linux内核input子系统解析,ARM Linux内核Input输入子系统浅解相关推荐

  1. linux系统调用的封装格式,ARM Linux系统调用的原理

    ARM Linux系统调用的原理ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交互提供了一组接口.在应用程序和硬件之间设置一个额外层具有很多优点.首先,这使得编程更加容易 ...

  2. arm linux免驱usb声卡,arm linux利用alsa驱动并使用usb音频设备

    一.背景: arm linux的内核版本是3.13.0 二.准备工作 添加alsa驱动到内核中,也就是在编译内核的时候加入以下选项: 接下来就重新编译内核即可 三.交叉编译alsa-lib和alsa- ...

  3. 学习arm需要Linux吗,学了半年ARM+linux的一点感想

    从接触51单片机到ARM有一年了.从以前的一点都不懂到现在的有一点懂~~其实也不容易啊.大一的时候我还迷恋着魔兽世界的. 借着写日志的时候把这些日子学到的一些知识整理下........注明这个我其实还 ...

  4. arm linux下看门狗应用,arm linux watchdog 看门狗

    目前手上有个项目需要设计看门狗,是arm+CPLD 方式.由于对看门狗要求很高,打算做一个双看门狗,arm CPLD互相为 对方的看门狗.理论上CPLD是不需要看门狗的,还是这么去设计了.接下来对看门 ...

  5. python linux arm_[Python]python for ARM/LINUX

    按照下面的方法,可以成功将python2.5 build到 ARM /linux , 我已经成功了: Download latest from www.python.org Save into /ho ...

  6. linux运行好麻烦,解析用Linux非常困难、必须用命令行、很老又丑陋及无法运行游戏...

    很多刚接触Linux的人都有四大疑问:使用Linux非常困难.在Linux中,您必须使用命令行.Linux很老又丑陋.Linux无法运行计算机游戏,本文为您解析,打消您对Linux的误解. 前言 对于 ...

  7. 嵌入式基于Linux电机控制,基于嵌入式arm+linux平台的直流电机调速控制系统.pdf

    2012--2013 学年第 二 学期 物电 学院期末考试卷 嵌入式系统与应用 学号 : 姓名 : 班级 : 成绩: 评语: 装 订 (考试题目及要求) 嵌入式大作: 采用实验箱上的电位器作为信号输入 ...

  8. arm linux设置ip地址命令,ARM Linux系统修改动态IP为静态IP地址

    # Wired or wireless interfaces auto eth0 #iface eth0 inet dhcp #        pre-up /bin/grep -v -e " ...

  9. linux内核 noreturn,读《ARM Linux 内核源代码剖析》.......第13章 setup_processor()

    setup_processor首先是查找保存相应处理器信息的结构体,然后根据结构体里的值,对处理器相关的各种变量进行设置. setup_processor static void __init set ...

最新文章

  1. 联想员工亲历联想大裁员:公司不是家
  2. Spring Boot WebFlux-02——WebFlux Web CRUD 实践
  3. 数据结构与算法 / 字符串匹配 / Trie 树
  4. XCTF-高手进阶区:Web_php_include
  5. 因为没钱买衣服,我女朋友不要我了......
  6. java –cp ./:_成为Java流专家–第2部分:中级操作
  7. php 逗号 分割字符串
  8. 4列变成5列 datatable_云南美食界“5巨头”,谁才是NO.1?你家乡的那道菜也在列...
  9. 分治法在排序算法中的应用(JAVA)--归并排序
  10. [数据]matplotlib总结
  11. 如何快速构建一个 Spring Boot 工程?
  12. 在GitHub上分享和展示你的代码
  13. java web 服务开发技术_Java web应用开发技术
  14. 解决springboot的application.yml配置不生效问题
  15. 文件md5怎么会变化
  16. CUDA Occupancy Calculator中计算占用率
  17. 论文必备:深度学习中的网络结构是怎么画的
  18. 用Python做一只真·多足机器人,钢铁蜈蚣能弯曲还能蠕动
  19. C++ Concurrency in Action 2nd Edition
  20. 本地项目关联远程git仓库

热门文章

  1. LeetCode-697. 数组的度
  2. CSS3边框图片、边框阴影、文本阴影
  3. day17 Java的object中常见的方法以及内部类
  4. 页面中鼠标触碰字体后切换颜色且随鼠标移走后改变
  5. vue_devtools的安装及资源(chrome and edge上的安装)
  6. php 检测变量中的回车键_PHP 的变量类型,变量检测
  7. java查找网站在百度排名_百度网站快排系统 - 网站排名如何优化?
  8. python棋盘放米问题_Python基于回溯法子集树模板解决马踏棋盘问题示例
  9. Python练习:快乐的数字
  10. 台式电脑键盘按键错乱_电脑键盘按键怕误触怎么办?用这款软件帮你屏蔽指定键盘按键!支持替换按键!...