linux輸入子系統(4)

來源:互聯網
上載者:User
1.5     



附隨報告的傳遞

輸入子系統裝置報告各種事件通過
input_report_XXX
族函數,例如
程式清單

1
.5




中報告按鍵事件。按鍵、相對座標、絕對座標和同步附隨報告的函數如
程式清單
1
.12

所示。

 

程式清單

1


.

12


 

附隨報告函數

/* include/linux/input.h */

static inline void input_report_key(struct input_dev
*dev, unsigned int code, int value)

{

        
input_event(dev,
EV_KEY, code, !!value);                                                                                  

}

 

static inline void input_report_rel(struct input_dev
*dev, unsigned int code, int value)

{

        
input_event(dev,
EV_REL, code, value);

}

 

static inline void input_report_abs(struct input_dev
*dev, unsigned int code, int value)

{

        
input_event(dev,
EV_ABS, code, value);

}

 

static inline void input_sync(struct input_dev *dev)

{

        
input_event(dev,
EV_SYN, SYN_REPORT, 0);

}

可以看到,這四個函數都調用了
input_event
,並且在


將按鍵的
value
轉化為布爾類型的值。所以按鍵傳給
input core

value

0(
釋放
)
或者
1(
按下
)

input_event
函數的代碼如
程式清單
1
.13

所示。

程式清單

1


.

13


 
input_event

/* driver/input/input.c */

void input_event(struct input_dev *dev, unsigned int
type, unsigned int code, int value)

{

        
unsigned
long flags;

 

        
if
(is_event_supported(type, dev->evbit, EV_MAX)) {

                  
spin_lock_irqsave(&dev->event_lock,
flags);

                  
add_input_randomness(type,
code, value);                                                                        

                  
input_handle_event(dev,
type, code, value);                                                                       

                  
spin_unlock_irqrestore(&dev->event_lock,
flags);

        
}

}

EXPORT_SYMBOL(input_event);

本函數總共有兩行有效調用:


由於輸入事件具有隨機性,因此用輸入事件來增加核心熵池的熵。


呼叫事件分發函數
input_handle_event
,做進一步的傳遞。

input_handle_event
的代碼如所示。

 

/* driver/input/input.c */

#define INPUT_IGNORE_EVENT       
        
0

#define INPUT_PASS_TO_HANDLERS      
1

#define INPUT_PASS_TO_DEVICE    
        
2

#define INPUT_PASS_TO_ALL  
                  
(INPUT_PASS_TO_HANDLERS
| INPUT_PASS_TO_DEVICE)

 

static void input_handle_event(struct input_dev *dev,

                           
      
unsigned int type, unsigned int code,
int value)

{

        
int
disposition = INPUT_IGNORE_EVENT;

 

        
switch
(type) {

        

····························

        
case
EV_KEY:

                  
if
(is_event_supported(code, dev->keybit, KEY_MAX) &&                                            

                  
   
!!test_bit(code, dev->key) != value) {                                                                        

 

                           
if
(value != 2) {                                                                                                         

                                    
__change_bit(code,
dev->key);                                                                       

                                    
if
(value)                                                                                                          

                                              
input_start_autorepeat(dev,
code);

                           
}

 

                           
disposition
= INPUT_PASS_TO_HANDLERS;                                                    


                                

                  
}

                  
break;

 

        
case
EV_ABS:

                  
if
(is_event_supported(code, dev->absbit, ABS_MAX)) {                                               

 

                           
value
= input_defuzz_abs_event(value,                                                                    

                                              
dev->abs[code],
dev->absfuzz[code]);

 

                           
if
(dev->abs[code] != value) {                                                                                  

                                    
dev->abs[code]
= value;

                                    
disposition
= INPUT_PASS_TO_HANDLERS;

                           
}

                  
}

                  
break;

 

        
case
EV_REL:

                  
if
(is_event_supported(code, dev->relbit, REL_MAX) && value)                                    

                           
disposition
= INPUT_PASS_TO_HANDLERS;

 

                  
break;

        
        

························

        
}

 

        
if
(disposition != INPUT_IGNORE_EVENT && type != EV_SYN)

                  
dev->sync
= 0;

 

        
if
((disposition & INPUT_PASS_TO_DEVICE) && dev->event)

                  
dev->event(dev,
type, code, value);

 

        
if
(disposition & INPUT_PASS_TO_HANDLERS)

                  
input_pass_event(dev,
type, code, value);

}

上述代碼中去除了其他事件的部分,線面說明按鍵、相對座標和絕對座標的處理部分:


檢查按鍵是否為驅動所支援,只有之前註冊過的按鍵才會繼續傳遞。


檢查報告的按鍵狀態是否和上次相同。如果連續多次報告按鍵按下,則只處理第一次。


如果不是連擊事件。


翻轉按鍵的目前狀態
(
按下和釋放
)


如果是按下,則開始連擊計時。


標記訊息傳遞方向。


檢查絕對座標軸是否驅動所支援的。


根據當前報告的值和上次報告的值確定傳給處理常式的絕對值大小。


如果本次需要報告的絕對值和上次不同,則將事件傳遞給處理函數。


檢查相對座標軸是否被驅動所支援。

可以看到
input_handle_event
分發事件有兩個方向:驅動的回呼函數
dev->event

input core

input_pass_event
。下面繼續分析
input_pass_event
,代碼如
程式清單
1
.14

所示。

 

程式清單

1


.

14


 
input_pass_event

/* driver/input/input.c */

static void input_pass_event(struct input_dev *dev, unsigned
int type, unsigned int code, int value)

{

        
struct
input_handle *handle;

 

        
rcu_read_lock();

        
handle =
rcu_dereference(dev->grab);                                                                                         

        
if
(handle)

                  
handle->handler->event(handle,
type, code, value);

        
else

                  
list_for_each_entry_rcu(handle,
&dev->h_list, d_node)                                                    

                           
if
(handle->open)                                                                                                      

                                    
handle->handler->event(handle,
type, code, value);                                        

        
rcu_read_unlock();

}

 

這個函數將事件分發給相關的
handler


擷取獨佔裝置的
handle
的指標。如果有獨佔裝置的
handle
,則僅僅將事件傳給獨佔的
handle
對應的
handler


遍曆與此裝置串連的每一個
handle


如果
hnadle
已經被開啟。


將事件分發給
handler
的事件處理函數。

到這裡,
input core
分發事件的任務已經完成,接下來由各個
handler
處理接收到的事件。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.