(本文僅用于本人學習記錄,僅供參考)
耳機按鍵檢測到動作後事件上報,涉及到輸入子系統。
Input_report_key(cod3034x->input,jd->button,) //向輸入子系統報告産生按鍵事件
|-- input_event(dev,EV_KEY,code,!!value)
|-- is_event_supported(type,dev->evbit,EV_MAX)
|-- input_handle_event(dev,type,code,value)
|-- input_get_disposition(dev,type,code,&value)
|-- input_pass_values(dev,dev->vals,dev->num_vals)
|-- input_to_handler(handle,vals,count)
Input_sync(cod3034x->input);//通知接收者,一個報告發送完畢。
Static inline void Input_report_key(struct input_dev *dev,unsigned int code,int value)
{
input_event(dev,EV_KEY,code,!!value);
}
Input_report_key函數的參數1是産生事件的輸入裝置,參數2是産生的事件,參數3是事件的值。
注:C語言中的感歎号(!)是邏輯運算操作符,經過該操作符運算後的值隻有2種情況,要麼為1,即True,要麼為0,即False。在進行邏輯運算時,所有非0的值都會被認為是 True,而隻有 0 值會被認為是False。是以對變量進行2次非運算(!!)就能将其轉化成 1 或者0,且變量原本的邏輯值保持不變。
void input_event(struct input_dev *dev,unsigned int type,unsigned int code,int value)
{
unsigned long flag;
if(is_event_supported(type,dev->evbit,EV_MAX))
{
input_handle_event(dev,type,code,value);
}
}
input_event函數的參數1是input_device裝置,參數2是事件的類型,參數3是産生的事件,參數4是事件的值。該函數裡面用到了is_event_supported()函數,用于檢查輸入裝置是否支援該事件。支援傳回1,不支援傳回0。
static void input_handle_event(struct input_dev *dev,unsigned int type,unsigned int code,int value)
{
int disposition;
disposition = input_get_disposition(dev,type,code,&value);
if(disposition&INPUT_PASS_TO_HANDLERS)
{
struct input_value *v;
v=&dev->vals[dev->num_vals++];
v->type=type;
v->code=code;
v->value=value;
}
input_pass_values(dev,dev->vals,dev->num_vals);
}
input_handle_event函數向輸入子系統傳送事件資訊,參數1是輸入裝置input_dev,參數2是事件類型,參數3是鍵碼,參數4是鍵值。input_get_disposition()确定事件的處理方式,傳回值主要有以下幾種:
INPUT_IGNORE_EVENT:表示忽略事件,不進行處理。
INPUT_PASS_TO_HANDLERS:表示事件交給handler處理。
INPUT_PASS_TO_DEVICE:表示将事件交給input_dev處理。
INPUT_PASS_TO_ALL:表示将事件交給handler和 input_dev共同處理。
static void input_pass_values(struct input_dev *dev,struct input_value *vals,unsigned int count)
{
struct input_handle *handle;
struct input_value *v;
handle=rcu_dereference(dev->grab);
if(handle)
count=input_to_handler(handle,vals,count);
else
list_for_each_entry_rcu(handle,&dev->h_list,d_node)
if(handle->open)
{
count=input_to_handler(handle,vals,count);
if(!count)
break;
}
}
input_pass_values()函數用于确定input_dev的handler,并通過input_to_handler()調用handler的event函數。在上述代碼中,rcu_dereference(),該接口用來擷取RCU protected pointer。reader要通路RCU保護的共享資料,當然要擷取RCU protected pointer,然後通過該指針進行dereference的操作。dev->grab是強制為input device的handler,如果rcu_dereference()函數傳回值不為空,說明有為input_device強制指定handler,就直接調用handler的event函數。如果為NULL,表示沒有為input_device強制指定handler,就會通過周遊input device->h_list上的handle成員。如果該handle被打開,表示該裝置已經被一個使用者程序使用,就會調用與輸入裝置對應的handler的event函數。
注:隻有在handle被打開的情況下才會接收到事件,這就是說,隻有裝置被使用者程式使用時,才有必要向使用者空間導出資訊。
static unsigned int input_to_handler(struct input_handle *handle,struct input_value *vals,unsigned int count)
{
struct input_handler *handler=handle->handler;
struct input_value *end=vals;
struct input_value *v;
if(handler->filter)
{
for(v=vals;v!=vals+count;v++)
{
if(handler->filter(handle,v->type,v->code,v->value))
continue;
if(end!=v)
*end=*v;
end++;
}
count=end-vals;
}
if(!count)
return ;
if(handler->events)
handler->event(handle,vals,count);
else if(handler->event)
for(v=vals;v!=vals+count;v++)
handler->event(handle,v->type,v->code,v->value);
return count;
}
首先通過所有過濾器傳遞事件,然後,如果事件未被過濾掉,則通過所有打開的句柄。該函數被調用,而dev-> event_lock被禁止并且中斷被禁用。
[samsung][Z205]