input_sync(button_dev);    /*通知接收者,一个报告发送完毕*/

参考:http://www.51hei.com/bbs/dpj-27652-1.html  很详细说明

input.c是输入子系统驱动程序顶层框架文件,是一个通用的文件

在connect函数中

for (minor = 0; minor < EVDEV_MINORS; minor++)
  if (!evdev_table[minor])
    break;

找一个空的evdev_table用来存放evdev,其中minor就是/dev/input/evnetx访问时的x

drivers/input/input.c:

class_register(&input_class)//创建一个类,作用和class_create等价,class_create内部就是调用class_register来实现的

//device_create是在input_handler的connect函数中通过device_add实现的,因为device_create实际上就是调用device_add

input_init > err = register_chrdev(INPUT_MAJOR, "input", &input_fops);

static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
};

问:怎么读按键?

input_open_file
struct input_handler *handler = input_table[iminor(inode) >> 5];
new_fops = fops_get(handler->fops) // =>&evdev_fops
file->f_op = new_fops;
err = new_fops->open(inode, file);

app: read > ... > file->f_op->read

input_table数组由谁构造?

input_register_handler      //在内核中找该函数被谁调用,可以发现input分为左右两边,一遍调用input_register_handler ,一遍调用input_register_device

调用input_register_handler 的主要有evdev、键盘、鼠标、触摸屏等输入设备,这部分写好了纯软件代码,硬件相关的在input_register_device中,比如触摸屏驱动程序:s3c2410_ts.c

注册input_handler:
input_register_handler
// 放入数组
input_table[handler->minor >> 5] = handler;

// 放入链表
list_add_tail(&handler->node, &input_handler_list);

// 对于每个input_dev,调用input_attach_handler
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler); // 根据input_handler的id_table判断能否支持这个input_dev

注册输入设备:
input_register_device
// 放入链表
list_add_tail(&dev->node, &input_dev_list);

// 对于每一个input_handler,都调用input_attach_handler
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler); // 根据input_handler的id_table判断能否支持这个input_dev

input_attach_handler
id = input_match_device(handler->id_table, dev);

error = handler->connect(handler, dev, id);

注册input_dev或input_handler时,会两两比较左边的input_dev和右边的input_handler,
根据input_handler的id_table判断这个input_handler能否支持这个input_dev,
如果能支持,则调用input_handler的connect函数建立"连接"

怎么建立连接?
1. 分配一个input_handle结构体
2.
input_handle.dev = input_dev; // 指向左边的input_dev
input_handle.handler = input_handler; // 指向右边的input_handler
3. 注册:
input_handler->h_list = &input_handle;
inpu_dev->h_list = &input_handle;

evdev_connect
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); // 分配一个input_handle

// 设置
evdev->handle.dev = dev; // 指向左边的input_dev
evdev->handle.name = evdev->name;
evdev->handle.handler = handler; // 指向右边的input_handler
evdev->handle.private = evdev;

// 注册
error = input_register_handle(&evdev->handle);

怎么读按键?
app: read
--------------------------
.......
evdev_read
// 无数据并且是非阻塞方式打开,则立刻返回
if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
return -EAGAIN;

// 否则休眠
retval = wait_event_interruptible(evdev->wait,
client->head != client->tail || !evdev->exist);

谁来唤醒?
evdev_event

  input_handle_event(dev, type, code, value);

    input_pass_event(dev, type, code, value);

      list_for_each_entry_rcu(handle, &dev->h_list, d_node)

        handler->event(handle, type, code, value);
          wake_up_interruptible(&evdev->wait);

evdev_event被谁调用?
猜:应该是硬件相关的代码,input_dev那层调用的
在设备的中断服务程序里,确定事件是什么,然后调用相应的input_handler的event处理函数
gpio_keys_isr
// 上报事件
input_event(input, type, button->code, !!state);(上报的时候是从input_handle链表取出handle,在调用handler的event,因此可能有多个支持的handle,在input_pass_event函数中)

input_sync(input);

input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
struct input_handle *handle;

list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);//evdev_event

怎么写符合输入子系统框架的驱动程序?
1. 分配一个input_dev结构体
2. 设置
3. 注册
4. 硬件相关的代码,比如在中断服务程序里上报事件

struct input_dev {

void *private;

const char *name;
const char *phys;
const char *uniq;
struct input_id id;

unsigned long evbit[NBITS(EV_MAX)]; // 表示能产生哪类事件,可以看EV_MAX宏定义处,比如设置了可以参数按键类,然后才设置下面可以产生哪些按键

unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键
unsigned long relbit[NBITS(REL_MAX)]; // 表示能产生哪些相对位移事件, x,y,滚轮
unsigned long absbit[NBITS(ABS_MAX)]; // 表示能产生哪些绝对位移事件, x,y
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)];

测试:
1.
hexdump /dev/event1 (open(/dev/event1), read(), )
               秒               微秒           类     code value(四字节)
0000000 0bb2 0000 0e48 000c 0001 0026 0001 0000(在copy_to_user中拷贝input_event结构体数据)

0000010 0bb2 0000 0e54 000c 0000 0000 0000 0000(这是同步类事件,每个事件后都要发同步)
0000020 0bb2 0000 5815 000e 0001 0026 0000 0000
0000030 0bb2 0000 581f 000e 0000 0000 0000 0000

2. 如果没有启动QT:
cat /dev/tty1   (原因是在tty下会包括keyboard.c,其也调用了input_register_handler,因此在注册驱动的时候除了和evdev关联起来,还和keyboard关联起来了,而keyboard.c的上层是tty)
按:s2,s3,s4
就可以得到ls

或者:
exec 0</dev/tty1(0表示标准输入,将标准输入文件改为tty1,即从tty1得到输入,以前0是从sh文件得到输入,sh是从串口得到输入)
然后可以使用按键来输入

(ps指令可以看到-sh程序的PID,在执行ls -l /proc/PID/fd可以看到-sh程序将标准输入、标准输出、标准错误都指向了窗口)

3. 如果已经启动了QT:
可以点开记事本
然后按:s2,s3,s4

如果可以参数重复类事件,input_event会启动定时器(通过input_start_autorepeat函数),调用定时器函数input_repeat_key继续上报时间,定时器在input_register_device中注册

8、linux下输入子系统的更多相关文章

  1. 12.Linux之输入子系统分析(详解)

    版权声明:本文为博主原创文章,转载请标注出处:   在此节之前,我们学的都是简单的字符驱动,涉及的内容有字符驱动的框架.自动创建设备节点.linux中断.poll机制.异步通知.同步互斥/非阻塞.定时 ...

  2. linux input输入子系统应用分析

    输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理是底层在按键.触摸等动作发送时产生一个中断(或驱动通过timer定时查询),然后CPU通过SPI.I2 C或外部存储器总线读取 ...

  3. linux input输入子系统分析《四》:input子系统整体流程全面分析

    1      input输入子系统整体流程 本节分析input子系统在内核中的实现,包括输入子系统(Input Core),事件处理层(Event Handler)和设备驱动层.由于上节代码讲解了设备 ...

  4. linux内核输入子系统分析

    1.为何引入input system? 以前我们写一些输入设备(键盘.鼠标等)的驱动都是采用字符设备.混杂设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可 ...

  5. Linux/Android——输入子系统input_event传递 (二)【转】

    本文转载自:http://blog.csdn.net/jscese/article/details/42099381 在前文Linux/Android——usb触摸屏驱动 - usbtouchscre ...

  6. Linux下输入某些命令时会提示:bash:command not found

    首先,查看$PATH中是否包含了这些命令. $PATH:决定了shell到哪些目录中去寻找命令或程序,PATH值是一系列的目录.当运行程序时,linux到这些目录下搜索进行编译链接. 格式: PATH ...

  7. Linux下 输入 env 而得到的环境变量解读

    HOSTNAME=Master.Hadoop MAHOUT_HOME=/usr/hadoop/mahout-distribution-0.8 TERM=linux SHELL=/bin/bash HA ...

  8. Linux下clock子系统

    常用API: 1.struct clk *clk_get(struct device *dev, const char *id):从一个时钟list链表中以dev或者字符id名称查找一个时钟clk结构 ...

  9. Linux下触摸屏驱动程序分析

    [摘要: 本文以linux3.5--Exynos4412仄台,剖析触摸屏驱动焦点内容.Linux下触摸屏驱动(以ft5x06_ts为例)须要懂得以下学问: 1. I2C协定 2. Exynos4412 ...

随机推荐

  1. UVA 12075 Counting Triangles

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  2. HDP和HDF

    参考文档: HDP安装: 官方文档:https://docs.hortonworks.com/HDPDocuments/Ambari-2.5.0.3/bk_ambari-installation/co ...

  3. Model、ModelMap、ModelAndView的作用及区别

    Model.ModelMap.ModelAndView的作用及区别 对于MVC框架,控制器controller执行业务逻辑 用于产生模型数据Model 视图view用来渲染模型数据 Model和Mod ...

  4. jquery表格简单插件

    1.一直对jquery插件感觉非常神奇.今天动手写了一个超级简单的案例. 2.效果 3.体会 a.jquery插件编写能力. 须要具备一定js能力的编写.还有写css样式的运用:希望以后这方面会有提高 ...

  5. Android使用BroadCastRecevier广播实现接收短信,并利用Toast弹出显示内容

    在上一篇文章 Android简单实现BroadCastReceiver广播机制 中简单的实现了一个广播机制,这里利用BroadCarstRecevier实现一个接收短信并显示内容的案例,当然至于接收到 ...

  6. POJ 3243 Clever Y Extended-Baby-Step-Giant-Step

    题目大意:给定A,B,C,求最小的非负整数x,使A^x==B(%C) 传说中的EXBSGS算法0.0 卡了一天没看懂 最后硬扒各大神犇的代码才略微弄懂点0.0 參考资料: http://quarter ...

  7. atxserver2安装与使用

    atxserver2的使用 1.首先clone atxserver2代码,此时使用pip3 install requirements后执行python main.py 会提示“ [WinError 1 ...

  8. Spring异步执行(@Async)2点注意事项

    Spring中可以异步执行代码,注解方式是使用@Async注解. 原理.怎么使用,就不说了. 写2点自己遇到过的问题. 1.方法是公有的 // 通知归属人 @Async public void not ...

  9. linux又一次编译安装gd,添加freetype支持,解决验证码不显示问题,Fatal error: Call to undefined function imagettftext()

    问题: Fatal error: Call to undefined function Think\imagettftext() in /var/www/webreg/ThinkPHP/Library ...

  10. body{display:none}

    body{display:none} 使浏览器不显示内容,用这样的代码删除 $document = str_replace('body{display:none}','',$document);