zoukankan      html  css  js  c++  java
  • [RK3288][Android6.0] 系统按键驱动流程分析【转】

    本文转载自: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);
            }
        }
    • 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;
    }
  • 相关阅读:
    180726-InfluxDB基本概念小结
    180725-InfluxDB-v1.6.0安装和简单使用小结
    zepto的tap事件的点透问题的几种解决方案
    ZeroclipboardJS+flash实现将内容复制到剪贴板实例
    HighchartsJS创建点状带标识的图表实例
    HighchartsJS创建环形带标识的图表实例
    Bootstrap 4上线啦!!!
    jquery插件jquery.LightBox.js之点击放大图片并左右点击切换图片(仿相册插件)
    如何通过js和jquery获取图片真实的宽度和高度
    js判断图片加载完成后获取图片实际宽高
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7778878.html
Copyright © 2011-2022 走看看