標籤:關閉 rk3288 syn type i++ log schedule uil 按鍵
本文轉載自:http://blog.csdn.net/kris_fei/article/details/77894406
Rockchip的按鍵驅動位於 kernel/drivers/input/keyboard/rk_keys.c
預設支援的keys在dts中定義:
其中power key作為普通gpio,具有喚醒功能。而其他按鍵比如,volume up/down 可以通過adc精確讀取到gpio的電壓值,原理圖如下:
和一般的按鍵一樣,驅動是通過核心input子系統來將keys註冊供使用者空間使用
static int keys_probe(struct platform_device *pdev){ input = devm_input_allocate_device(dev); input->name = "rk29-keypad"; /* pdev->name; */ input->phys = "gpio-keys/input0"; input->dev.parent = dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; error = input_register_device(input);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
dts keys的解析通過rk_keys_parse_dt()實現。而每個key都會註冊一個定時器函數來處理狀態變化並通知使用者空間。
for (i = 0; i < ddata->nbuttons; i++) { if (button->code) { setup_timer(&button->timer, keys_timer, (unsigned long)button); } }
keys_timer():
static void keys_timer(unsigned long _data){ //普通gpio直接讀取 if (button->type == TYPE_GPIO) state = !!((gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low); else //adc轉成bool狀態值 state = !!button->adc_state; //狀態變化上報事件 if (button->state != state) { button->state = state; input_event(input, EV_KEY, button->code, button->state); input_event(input, EV_KEY, button->code, button->state); input_sync(input); } //10ms後啟動定時器 if (state) mod_timer(&button->timer, jiffies + DEBOUNCE_JIFFIES);}
定時器會處理普通gpio和adc兩種類型的按鍵,當狀態變化時,會向使用者空間上報當前事件、索引值、狀態。預設開機時,定時器處理函數因為檢測不到狀態變化而關閉退出。
定時器的開啟有兩個地方會被調用:
1.系統開機會啟一個工作隊列,每100ms周期性調用一次檢測有沒有按鍵觸發
static void adc_key_poll(struct work_struct *work){ if (!ddata->in_suspend) { //讀取adc電壓 result = rk_key_adc_iio_read(ddata); for (i = 0; i < ddata->nbuttons; i++) { //允許值有一定範圍的漂移 if (result < button->adc_value + DRIFT_ADVALUE && result > button->adc_value - DRIFT_ADVALUE) button->adc_state = 1; else button->adc_state = 0; if (button->state != button->adc_state) mod_timer(&button->timer, jiffies + DEBOUNCE_JIFFIES); } } //周期性調用。ADC_SAMPLE_JIFFIES為100ms schedule_delayed_work(&ddata->adc_poll_work, ADC_SAMPLE_JIFFIES);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
2. power key喚醒時中斷處理會被觸發
static irqreturn_t keys_isr(int irq, void *dev_id){ //上報power key事件 if (button->wakeup && pdata->in_suspend) { button->state = 1; input_event(input, EV_KEY, button->code, button->state); input_sync(input); } if (button->wakeup) wake_lock_timeout(&pdata->wake_lock, WAKE_LOCK_JIFFIES); mod_timer(&button->timer, jiffies + DEBOUNCE_JIFFIES); return IRQ_HANDLED;}
[RK3288][Android6.0] 系統按鍵驅動流程分析【轉】