怀抱观古今,寝食展戏谑。这篇文章主要讲述[RK3288][Android6.0] 系统按键驱动流程分析相关的知识,希望能为你提供帮助。
本文转载自:http://blog.csdn.net/kris_fei/article/details/77894406
Rockchip的按键驱动位于
kernel/drivers/input/keyboard/rk_keys.c
【[RK3288][Android6.0] 系统按键驱动流程分析】默认支持的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
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
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
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;
}
推荐阅读
- 使用真机导致Androidstudio打印不出log
- 3.如何搭建Appium自动化测试环境
- Android Fragment间的广播消息接收
- Process 0:0:0 (0x1ffc) Worker 0x00000001E580A1A0 appears to be non-yielding on Scheduler 3. Thread c
- 直播DCloud CTO崔红保(如何玩转H5网站快速转换成App())
- Unity 接入Android SDK-小米sdk
- android中的两种上下文区别
- ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行
- Android SDK 版本