博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[RK3288][Android6.0] 系统按键驱动流程分析【转】
阅读量:6575 次
发布时间:2019-06-24

本文共 2434 字,大约阅读时间需要 8 分钟。

本文转载自:

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); } }
  • 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; }
你可能感兴趣的文章
带左右按钮、 渐隐渐现 轮播图
查看>>
body标签中的相关标签
查看>>
css3 animate 和关键帧 @-webkit-keyframes
查看>>
指向结构体变量的指针变量
查看>>
文字链接颜色设置
查看>>
ChannelHandler揭秘(Netty源码死磕5)
查看>>
图片转流
查看>>
Jessica's Reading Problem
查看>>
jQuery实现照片墙,附步骤详解
查看>>
vim编辑器常用命令总结
查看>>
大白话讲解如何给github上项目贡献代码
查看>>
常见幻灯片实现
查看>>
一个页面中,不同子页面见高度不受影响的布局
查看>>
Redis的数据类型及其常用命令
查看>>
ubunto应用软件
查看>>
wireshark----教你如何抓包
查看>>
从txt中读入数据到数组中(fscanf)
查看>>
jquery中的事件与动画
查看>>
XPO学习(3)----数据查询
查看>>
java.util报错
查看>>