android 6.0 字符驱动,[RK3288][Android6.0] 系统按键驱动流程分析

Rockchip的按键驱动位于 kernel/drivers/input/keyboard/rk_keys.c

默认支持的keys在dts中定义:

627f9d2727071dc958915c7a9d2e8650.png

其中power key作为普通gpio,具有唤醒功能。而其他按键比如,volume up/down 可以通过adc精确读取到gpio的电压值,原理图如下:

d6035a0303b408d0a967524957dbbf49.png 

3d925a5e1e58550eea61457ff82807ea.png

和一般的按键一样,驱动是通过内核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);

}

}

1

2

3

4

5

6

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值