This article was reproduced from: http://blog.csdn.net/kris_fei/article/details/77894406
The Rockchip key driver is located in the kernel/drivers/input/keyboard/rk_keys.c
The keys that are supported by default are defined in DTS:
Where power key acts as a common gpio with wake-up capability. Other keys such as the volume Up/down can be accurately read to the Gpio voltage value via the ADC, the schematic is as follows:
As with normal keys, the driver registers the keys with the kernel input subsystem for user space.
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 Span class= "Hljs-subst" >= 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
The resolution of the DTS keys is implemented by RK_KEYS_PARSE_DT (). Each key registers a timer function to handle state changes and notifies the user of space.
for (i = 0; i < ddata->nbuttons; i++) { if (button->code) { setup_timer(&button->timer, keys_timer, (unsigned long)button); } }
Keys_timer ():
Staticvoid Keys_timer (unsigned long _data) {Normal Gpio Direct Readif (button-Type= = Type_gpio) state=!! (Gpio_get_value (Button->gpio)?1:0) ^ button->active_low);Else//ADC to BOOL status value state = !! Button->adc_state; //Status change escalation event if (Button->state Span class= "Hljs-subst" >!= 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 after starting timer if (state) Mod_timer ( &button->timer, jiffies + debounce_jiffies)}
The timer handles two types of keys for both ordinary Gpio and ADC, and when the state changes, the current event, key value, state is escalated to the user's space. When turned on by default, the timer handler function closes the exit because it cannot detect a change in state.
There are two places that will be called when the timer is opened:
1. The system opens a task queue, every 100ms periodic call detection there is no key trigger
Staticvoid Adc_key_poll (struct work_struct*work) {if (!ddata->in_suspend) {Read ADC voltage result= Rk_key_adc_iio_read (Ddata); for (i=0; I< Ddata->nbuttons; I++) {Allowable values have a certain range of driftif (Result< button->adc_value+ Drift_advalue&& result> button->adc_value -DRIFT_ Advalue) Button->adc_state = 1; Span class= "Hljs-keyword" >else button->adc_state = 0; if (Button->state != Button->adc_state) Mod_timer (&button-> Timer, jiffies + debounce_jiffies); }} //periodic call. 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
- 21st
2. interrupt processing will be triggered when power key wakes up
static irqreturn_t Keys_isr (int IRQ,void*dev_id) {//escalate Power key event if (Button-> Wakeup && pdata->in_suspend) {Button->state = 1; input_event (input, EV_KEY, button< Span class= "Hljs-subst" >->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] System Key Drive flow analysis "Go"