open("/dev/event1", O_RDWR);
---------------------------------------------
vfs
sys_open();
struct file file->f_ops = cdev->ops;
file->f_ops->open();
-------------------------------------------
设备驱动层:输入子系统
input handler 层:evdev.c
cdev;
xxx_ops = {
.open = xxx_open,
.write = xxx_write,
}
static const struct file_operations evdev_fops = {
.owner = THIS_MODULE,
.read = evdev_read,
.write = evdev_write,
.poll = evdev_poll,
.open = evdev_open,
}
实际最终调用了evdev_open();
|
struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
unsigned int size = sizeof(struct evdev_client) +
bufsize * sizeof(struct input_event);
struct evdev_client *client;
client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
client->bufsize = bufsize;
spin_lock_init(&client->buffer_lock);
client->evdev = evdev;
evdev_attach_client(evdev, client);
|
list_add_tail_rcu(&client->node, &evdev->client_list);
file->private_data = client;
总结:
1,为输入设备分配一个缓冲区evdev_client,用户存放input device层上报的数据
2,evdev_client记录到evdev中
3,evdev_client记录到file中,方面其他的接口使用
APP应用调用read函数
ssize_t read(int fd, void *buf, size_t count)
-----------------------------------------------------------------------
vfs
sys_read();
file->f_ops->read();
-------------------------------------------------------------------
evdev.c
static const struct file_operations evdev_fops = {
.read = evdev_read,
}
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;
for (;;) {
if (client->packet_head == client->tail &&
(file->f_flags & O_NONBLOCK))
return -EAGAIN;
while (read + input_event_size() <= count &&
evdev_fetch_next_event(client, &event)) {
|
*event = client->buffer[client->tail++];
if (input_event_to_user(buffer + read, &event))
|
copy_to_user(buffer, event, sizeof(struct input_event)
read += input_event_size();
}
if (!(file->f_flags & O_NONBLOCK)) {
error = wait_event_interruptible(evdev->wait,
client->packet_head != client->tail ||
!evdev->exist || client->revoked);
}
总结:
1,如果没有数据,就会休眠等待
2,如果有数据,就从缓冲区client->buffer[client->tail++]拿数据
通过copy_to_user上报给用户
疑问:
数据到底是如何存放在缓冲区的
等待队列是谁唤醒的
input_report_key(inputdev, pdesc->key_code, 0);
input_sync(inputdev);
input_report_key(inputdev, pdesc->key_code, 0);
input_sync(inputdev);
|
input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value);
|
input_handle_event(dev, type, code, value);
|
if (disposition & INPUT_PASS_TO_HANDLERS) {
struct input_value *v;
v = &dev->vals[dev->num_vals++];
v->type = type;
v->code = code;
v->value = value;
input_pass_values(dev, dev->vals, dev->num_vals)
|
else {
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)
count = input_to_handler(handle, vals, count);
|
struct input_handler *handler = handle->handler;
if (handler->events)
handler->events(handle, vals, count);
else if (handler->event)
for (v = vals; v != end; v++)
handler->event(handle, v->type, v->code, v->value);
}
static struct input_handler evdev_handler = {
.event = evdev_event,
.events = evdev_events,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.legacy_minors = true,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
总结: 如果将数据上报,最终是调用handler中events()或者event()
实际是evdev.c
.event = evdev_event,
.events = evdev_events,