input 子系統 五 事件上報及監聽

2021-09-11 06:34:57 字數 4475 閱讀 4613

事件的生產者 是 input 裝置驅動 // 還可能是 使用者空間通過write介面 上報的事件,這個可以忽略不計.

途徑 input.

c(input core)

,到達 handler,

然後由handler 提供給消費者.

事件的生產者可以看做都是 裝置驅動 ,但是消費者 不一定是 應用程式,可能是 kernel 其他模組,例如 key input 的消費者可以是 console subsystem

;

evdev 監聽之前 和 監聽之後 ,上報流程不一樣, 區別 在 if

(handle->open)

監聽之前,

(handle->open) 為 假,不會傳送到 handler

監聽之後,

(handle->open) 為 真, 會傳送到 handler

input_report_key // 這一句 呼叫 在 驅動檔案裡面,但是 實現在 include/linux/input.h

----

----

----

----

----

-// 往下 為 input core 的實現(input.c)

input_event

(dev, ev_key, code,

!!value)

;// 檢查dev 是否支援該事件

input_handle_event

(dev, type, code, value);if

(disposition & input_pass_to_handlers)

if(disposition & input_flush)

}

上文**重點講解:

list_for_each_entry_rcu

(handle,

&dev->h_list, d_node)

這個會遍歷 該 device 的 handle , 每匹配一次(該 device 和 handler)

,就會產生乙個handle

一般至少會有乙個handle ,就是 device 和 evdev handler 匹配產生的handler

demo 中產生了兩次匹配

1. device 和 evdev handler ,產生了handle 1

2. device 和 kbd handler , 產生了 handle 2

然後會分別檢查 handle->open

1. handle 1 在 裝置被監聽之前,

(handle->open)為假,在監聽之後,

(handle->open)被加1

,為真 2. handle 2

(handle->open) 為 真

然後 呼叫 input_to_handler

1. handle1 對應的 不會呼叫 input_to_handler

2. handle2 對應的 會呼叫 input_to_handler

input_to_handler

(handle, vals, count)

;// 執行兩次

handler->events //如果handler實現了handler->events,則優先呼叫 handler->events ,否則,呼叫 handler->event

----

----

----

----

----

----

----

----

-------

//往下為 handler 的實現 evdev.c

evdev_events // 這裡分析 evdev handler

evdev_pass_values

static

void

__pass_event

(struct evdev_client *client,

const

struct input_event *event)

client->tail =

(client->head -2)

&(client->bufsize -1)

;

client->buffer[client->tail]

.time = event->time;

client->buffer[client->tail]

.type = ev_syn;

client->buffer[client->tail]

.code = syn_dropped;

client->buffer[client->tail]

.value =

0;

client->packet_head = client->tail;

if(wakeup)

wake_up_interruptible

(&evdev->wait)

;

// 緩衝區 由 struct evdev_client *client; 管理 , struct evdev_client *client; 中有 buffer 成員

// struct evdev_client *client; 由 rcu 鍊錶管理.

evdev_open

unsigned

int size =

sizeof

(struct evdev_client)

+ bufsize *

sizeof

(struct input_event)

;// 計算環形佇列緩衝區大小

client =

kzalloc

(size, gfp_kernel | __gfp_nowarn)

;// 申請緩衝區 // client 中 有 buffer 成員

evdev_attach_client

(evdev, client)

;// 將 client 串入鍊錶

list_add_tail_rcu

(&client->node,

&evdev->client_list)

; file->private_data = client;

evdev_open_device

handle->open ++

;

open 了之後,建立了緩衝區.建立緩衝區 ,

64 位元組

這個buffer的作用是,上層open了此節點,但是沒有讀取此節點的資料的時候,會儲存到該緩衝區

在open 之前,evdev handler 就沒有接收到 事件,事件消亡在 input.c

- 阻塞流程

evdev_poll

poll_wait

(file,

&evdev->wait, wait)

;- 喚醒流程

evdev_pass_values

if(v->type == ev_syn && v->code == syn_report)

wakeup = true;

if(wakeup)

wake_up_interruptible

(&evdev->wait)

;

static ssize_t evdev_read

(struct file *file,

char __user *buffer,size_t count, loff_t *ppos)

struct evdev *evdev = client->evdev;

evdev_fetch_next_event

(client,

&event)

*event = client->buffer[client->tail++];

input_event_to_user

(buffer + read,

&event)

input子系統五 多點上報協議

multi touch protocol.txt abs mt position x x 0 abs mt position y y 0 syn mt report abs mt position x x 1 abs mt position y y 1 syn mt report syn repor...

input子系統五 多點上報協議

multi touch protocol.txt 一 type a 1檢測到2點按下,最小事件序列的上報形式為 abs mt position x x 0 abs mt position y y 0 syn mt report abs mt position x x 1 abs mt positio...

input子系統五 總結框架

通過前面的學習,我們可以看到輸入子系統可以分為三大塊 input核心層 input handler層 input裝置層 input核心層的主要功能主要有以下幾點 1 提供函式介面比如 input裝置和input handler的註冊函式 2 申請和維護子系統需要的一些資源 裝置鍊錶和handler鍊...