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
struct input_dev{ //代表输入设备,会加到全局input_dev队列
const char *name;
}
struct input_handler{//代表输入设备的处理方法,会加到全局input_handler队列

}
struct input_handle{//用来关联某个input_dev和某个input_handler

}
//一个input_dev可有多个input_handler:鼠标可有按键事件evdev和移动事件mousedev
//一个input_handler可以用于多个输入设备:比如按键evdev可用于鼠标和键盘

input_table[8]
input_handler_list

input_register_handler(&evdev_handler->handler)
INIT_LIST_HEAD(&handler->h_list)
input_table[handler->minor>>5] = handler
list_add_tail(&handler->node,&input_handler_list)
list_for_each_entry(dev,&input_dev_list, node)
input_attach_handler(dev,handler)//遍历执行
input_match_device(handler,dev)
if handler->id_table[i].flag & xx
handler->id_table[i].bustype == dev->id.bustype
handler..evbit[] == dev..evbit[]
...
return id->struct input_device_id *id
handler->connect(handler,dev,id) //evdev_connect

evdev_connect(struct input_handler *handler,struct input_dev *dev, const struct input_device_id *id)
//找evdev_table[]中首个未使用的下标minor
evdev = kzmalloc()
INIT_LIST_HEAD(&evdev->client_list)
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)
input_register_handle(&evdev->handle)
struct input_handler *handler=handle->handler
struct input_dev *dev=handle->dev
list_add_tail_rcu(&handle->d_node,&dev->h_list)
list_add_tail_rcu(&handle->h_node,&handler->h_list)
if(handler->start) handler->start(handle)
evdev_install_chrdev(evdev)
evdev_table[evdev->minor]=evdev
device_add(&evdev->dev)//创建设备节点

应用层对设备节点读,就会调用到
evdev_read(struct file *file,char __user *buffer, size_t count, loff_t *ppos)
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
if(BLOCK) wait_event_interruptible(evdev->wait,client->packet_head!=client->tail||!evdev->exist)
while ... evdev_fetch_next_event(client,&event)
input_event_to_user(buffer+retval,&event)
retval+=input_event_size()


evdev_open(struct inode *inode,struct file *file)