核心驅動上報EV LED事件失敗原因分析

2021-08-01 16:19:31 字數 2824 閱讀 9782

之前在寫驅動時使用如下方式上報一次ev_led型別事件,使用getevent命令測試卻一直接收不到事件。

input_event(input_dev, ev_led, led_misc, 1);

input_sync(input_dev);

因為趕工無法深究原因,只能先參考普通按鍵上報方式(在上報抬起、按下兩個事件後再上報同步事件)試著修改,結果上層收到了事件,測試通過。

input_event(input_dev, ev_led, led_misc, 0);

input_event(input_dev, ev_led, led_misc, 1);

input_sync(input_dev);

事後我猜想event事件是被過濾掉了:

1. 被getevent命令過濾;

2. 被核心input子系統過濾。

對於第一種猜想,我自己採用最簡單的阻塞式讀取方法,實現了乙個c程式去輪詢裝置節點,卻依然無法獲取event事件,再結合getevent原始碼分析,可以排除getevnt命令過濾的可能性;

剩下的可能就是input子系統本身過濾了event事件,於是我從事件上報的入口函式input_event()分析,將事件上報流程梳理了一遍,希望從中找出答案。

**分析流程:

input_event() -> input_handle_event() -> input_get_disposition()

-> input_pass_values()

首先從入口函式input_event()開始分析:

void input_event(struct input_dev *dev,

unsigned

int type, unsigned

int code, int value)

}

input_event()介面引數列表:

引數描述

dev上報事件的裝置

type

事件總型別

code

事件子型別

value

事件值

經過裝置evbit點陣圖判斷後,event事件被傳遞至input_handle_event()函式進一步處理:

static

void input_handle_event(struct input_dev *dev,

unsigned

int type, unsigned

int code, int value)

/* 快取event事件 */

v = &dev->vals[dev->num_vals++];

v->type = type;

v->code = code;

v->value = value;

}/* 如果描述符包含「input_flush」,重新整理裝置緩衝區,上報之前快取的event事件 */

if (disposition & input_flush) else

if (dev->num_vals >= dev->max_vals - 2)

}

描述符巨集定義:

描述符巨集定義值作用

input_ignore_event

0忽略該事件

input_pass_to_handlers

1事件由handler處理

input_pass_to_device

2事件由裝置處理

input_slot

4多點觸控事件標記

input_flush

8重新整理裝置的事件緩衝區

input_pass_to_all

(input_pass_to_handlers | input_pass_to_device)

事件由handler與裝置同時處理

在input_handle_event()函式裡,描述符disposition決定了event事件的後續處理流程,很有可能是因為描述符的原因,event事件被過濾不做任何處理,接下來我們分析input_get_disposition()函式,看看描述符是怎麼生成的:

static

int input_get_disposition(struct input_dev *dev,

unsigned

int type, unsigned

int code, int value)

break;

/* ev_led事件 */

case ev_led:

if (is_event_supported(code, dev->ledbit, led_max) &&

!!test_bit(code, dev->led) != !!value)

break;

/* 其他事件 */

......

}return disposition;

}

在處理ev_led事件時,可以看到必須滿足兩個條件才能獲得描述符「input_pass_to

_all」:

第乙個條件的結果毫無疑問為「true」,我們重點分析第二個條件:

!!test_bit(code, dev->led)讀取led點陣圖位置,__change_bit(code, dev->led)反置led點陣圖位置,這兩個相呼應的操作要求:在一次上報事件的週期內,ev_led事件的「value」布林值必須經過「true」和「false」的變化才能獲取到描述符「input_pass_to_all」,否則事件將被過濾不做任何處理。

啟動上報功能

啟動上報 在應用剛剛啟動時,向後台上報一些裝置資訊。上報內容 1 裝置資訊 裝置資訊主要通過infodictionary獲取 nsbundle mainbundle infodictionary cfbundleidentifier version cfbundleversion getossyst...

領域驅動設計系列 三 事件驅動上

今天講一下事件驅動,這個不是領域驅動設計裡的事件源 event source 這個以後再講,今天主要講一下如何用事件來解耦,主要的原因是我們有個專案有個功能我覺得用事件的方式比較好,正好寫篇部落格,就不用專門給他們講了。說到解耦,我們很熟悉分層設計,比如上層依賴於抽象,不依賴於具體的實現。比如乙個類...

核心驅動 阻塞型驅動

1 定義 等待佇列頭部 wait queue head t key q 2 初始化 等待佇列頭部 init waitqueue head key q 3 等待事件發生 wait event key q,key num 4 喚醒等待事件 wake up key q 查詢按鍵狀態 key.c inclu...