4. 使用input_device分析
/****************怎样使用input系统--简单的分析********************/
static int __init inputdev_init(void)
{
struct input_dev* inputdev = input_allocate_device(); /*1分配input_dev设备*/
set_bit(EV_KEY, inputdev->evbit); /*设置事件类型--按键类型*/
/*设置按键--->linux系统中已经分配好了按键值--例如
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
*/
set_bit(KEY_1, inputdev->evbit);
set_bit(KEY_2, inputdev->evbit);
set_bit(KEY_3, inputdev->evbit);
set_bit(KEY_4, inputdev->evbit);
/*然后注册设备 */
input_register_device(inputdev);
}
/*当按键值发生变化,要将按键值往上报告----比如在中断处理函数中报告*/
/**dev-->哪个input_dev设备;code-->按键编号KEY_1/2/3/4; value-->键值*/
用函数--input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_report_key(button_dev,KEY_4,1);
input_report_key(button_dev,KEY_3,1);
input_sync(inputdev);-->input_event(dev, EV_SYN, SYN_REPORT, 0);
}
/************再来分析input_report_key()****************/
执行线路:input_report_key()-->input_event-->input_handle_event-->input_pass_event ;
static void input_pass_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
struct input_handler *handler;
struct input_handle *handle;
rcu_read_lock();
handle = rcu_dereference(dev->grab);
if (handle)
handle->handler->event(handle, type, code, value);
else {
bool filtered = false;
/*在dev->h_list中(handle注册中->input_register_handle建立的关系)取得handle*/
list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
if (!handle->open)
continue;
handler = handle->handler;
if (!handler->filter) {
if (filtered)
break;
handler->event(handle, type, code, value); /*接下来调用handler->event处理函数-->evdev_event*/
} else if (handler->filter(handle, type, code, value))
filtered = true;
}
}
}
/*********************接着分析evdev_event()************************/
/*
* Pass incoming event to all connected clients.
*/
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
{
struct evdev *evdev = handle->private;
struct evdev_client *client; /*事件客户端---evdev_client主要是用来接受事件--event*/
struct input_event event;
/*给事件赋值*/
do_gettimeofday(&event.time);
event.type = type;
event.code = code;
event.value = value;
rcu_read_lock();
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_event(client, &event);
else
/*遍历evdev中的链表,接着调用evdev_pass_event,提交客户端client*/
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
rcu_read_unlock();
wake_up_interruptible(&evdev->wait);
}
static void evdev_pass_event(struct evdev_client *client,
struct input_event *event)
{
/*
* Interrupts are disabled, just acquire the lock.
* Make sure we don't leave with the client buffer
* "empty" by having client->head == client->tail.
*/
spin_lock(&client->buffer_lock);
do {
client->buffer[client->head++] = *event; //将事件写入client->buffer中,等待应用程序来处理
client->head &= client->bufsize - 1;
} while (client->head == client->tail);
spin_unlock(&client->buffer_lock);
if (event->type == EV_SYN)
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}