一、前言
1 初识linux输入子系统
linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler)、输入子系统核心层(InputCore)和输入子系统设备驱动层。
对于输入子系统设备驱动层而言,主要实现对硬件设备的读写访问,中断设置,并把硬件产生的事件转换为核心层定义的规范提交给事件处理层。
对于核心层而言,为设备驱动层提供了规范和接口。设备驱动层只要关心如何驱动硬件并获得硬件数据(例如按下的按键数据),然后调用核心层提供的接口,核心层会自动把数据提交给事件处理层。
对于事件处理层而言,则是用户编程的接口(设备节点),并处理驱动层提交的数据处理。
对于linux输入子系统的框架结构如下图1所示:
由上图所展现的内容就是linux输入子系统的分层结构。
/dev/input目录下显示的是已经注册在内核中的设备编程接口,用户通过open这些设备文件来打开不同的输入设备进行硬件操作。
事件处理层为不同硬件类型提供了用户访问及处理接口。例如当我们打开设备/dev/input/mice时,会调用到事件处理层的Mouse Handler来处理输入事件,这也使得设备驱动层无需关心设备文件的操作,因为Mouse Handler已经有了对应事件处理的方法。
输入子系统由内核代码drivers/input/input.c构成,它的存在屏蔽了用户到设备驱动的交互细节,为设备驱动层和事件处理层提供了相互通信的统一界面。
下图2简单描述了linux输入子系统的事件处理机制:
图2 linux输入子系统事件处理机制
由上图可知输入子系统核心层提供的支持以及如何上报事件到input event drivers。
二、如何查看输入子系统的信息
root@android:/ # cat /proc/bus/input/devices cat /proc/bus/input/devices I: Bus=0019 Vendor=0001 Product=0001 Version=0100 N: Name="rk29-keypad" P: Phys=gpio-keys/input0 S: Sysfs=/devices/platform/rk29-keypad/input/input0 U: Uniq= H: Handlers=kbd event0 keychord B: PROP=0 B: EV=3 B: KEY=8000 100000 0 0 0 I: Bus=0019 Vendor=0001 Product=0001 Version=0100 N: Name="rkxx-remotectl" P: Phys=gpio-keys/input0 S: Sysfs=/devices/platform/rkxx-remotectl/input/input1 U: Uniq= H: Handlers=kbd event1 keychord B: PROP=0 B: EV=3 B: KEY=c 70110 260000 0 0 0 20100 2000000 7800000 4000a800 1e16c0 19 78000000 10006ffc I: Bus=0003 Vendor=0c45 Product=1109 Version=0100 N: Name="coocaa Device coocaa Wireless Device" P: Phys=usb-usb20_host-1.3/input2 S: Sysfs=/devices/platform/usb20_host/usb2/2-1/2-1.3/2-1.3:1.2/input/input2 U: Uniq= H: Handlers=sysrq kbd event2 keychord B: PROP=0 B: EV=12001b B: KEY=10000 7 ff800000 7ff febeffdf ffefffff ffffffff fffffffe B: ABS=700 0 B: MSC=10 B: LED=1f I: Bus=0003 Vendor=0c45 Product=1109 Version=0100 N: Name="coocaa Device coocaa Wireless Device" P: Phys=usb-usb20_host-1.3/input3 S: Sysfs=/devices/platform/usb20_host/usb2/2-1/2-1.3/2-1.3:1.3/input/input3 U: Uniq= H: Handlers=sysrq kbd event3 keychord B: PROP=0 B: EV=12001f B: KEY=4837fff 72ff32d bf544446 0 0 1 30f90 8b17c007 ffe77bfa d941dfff febeffdf ffefffff ffffffff fffffffe B: REL=40 B: ABS=ffffff01 0 B: MSC=10 B: LED=1f I: Bus=0003 Vendor=0c45 Product=1109 Version=0100 N: Name="coocaa Device coocaa Wireless Device" P: Phys=usb-usb20_host-1.3/input4 S: Sysfs=/devices/platform/usb20_host/usb2/2-1/2-1.3/2-1.3:1.4/input/input4 U: Uniq= H: Handlers=event4 B: PROP=0 B: EV=17 B: KEY=1f0000 0 0 0 0 0 0 0 0 B: REL=103 B: MSC=10 I: Bus=0003 Vendor=0c45 Product=1109 Version=0100 N: Name="coocaa Device coocaa Wireless Device" P: Phys=usb-usb20_host-1.3/input5 S: Sysfs=/devices/platform/usb20_host/usb2/2-1/2-1.3/2-1.3:1.5/input/input5 U: Uniq= H: Handlers=sysrq kbd event5 keychord B: PROP=0 B: EV=12001f B: KEY=4837fff 72ff32d bf544446 0 0 1 30f90 8b17c007 ffff7bfa d941dfff febeffdf ffefffff ffffffff fffffffe B: REL=40 B: ABS=1 0 B: MSC=10 B: LED=1f I: Bus=0003 Vendor=093a Product=2510 Version=0111 N: Name="PixArt USB Optical Mouse" P: Phys=usb-usb20_host-1.2.4/input0 S: Sysfs=/devices/platform/usb20_host/usb2/2-1/2-1.2/2-1.2.4/2-1.2.4:1.0/input/input7 U: Uniq= H: Handlers=event6 B: PROP=0 B: EV=17 B: KEY=70000 0 0 0 0 0 0 0 0 B: REL=103 B: MSC=10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
三、输入子系统的eventx文件是如何生成
源码目录在:drivers/input/evdev.c
static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id){ struct evdev *evdev; int minor; int error; for (minor = 0; minor < EVDEV_MINORS; minor++) if (!evdev_table[minor]) break; if (minor == EVDEV_MINORS) { pr_err("no more free evdev devices\n"); return -ENFILE; } evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); if (!evdev) return -ENOMEM; INIT_LIST_HEAD(&evdev->client_list); spin_lock_init(&evdev->client_lock); mutex_init(&evdev->mutex); init_waitqueue_head(&evdev->wait); dev_set_name(&evdev->dev, "event%d", minor); evdev->exist = true; evdev->minor = minor; evdev->handle.dev = input_get_device(dev); evdev->handle.name = dev_name(&evdev->dev); evdev->handle.handler = handler; evdev->handle.private = evdev; evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; evdev->dev.release = evdev_free; device_initialize(&evdev->dev); error = input_register_handle(&evdev->handle); if (error) goto err_free_evdev; error = evdev_install_chrdev(evdev); if (error) goto err_unregister_handle; error = device_add(&evdev->dev); if (error) goto err_cleanup_evdev; return 0; err_cleanup_evdev: evdev_cleanup(evdev); err_unregister_handle: input_unregister_handle(&evdev->handle); err_free_evdev: put_device(&evdev->dev); return error;}