之前在寫驅動時使用如下方式上報一次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_event()開始分析:-> input_pass_values()
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...