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);
}