zoukankan      html  css  js  c++  java
  • Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值

    Android底层开发之Linux入子系统要不要推断系统休眠状态上报键值

            题外话:一个问题研究到最后,那边记录文档的前半部分基本上都是没用的,甚至是错误的。

    重点在最后,前边不过一些假想猜測。

     http://blog.csdn.net/kangear/article/details/40072707


            在调试一下红外遥控器input驱动时,直接採用的是一个半成品的驱动在上边实现的自己的设备的匹配,但同一时候遇到了一些关于input输入子系统的疑惑。

            按键一般有「按下和抬起」两个状态一般使用01来分别表示。一般例如以下方式上报按键键值就能够完毕「按下和抬起」两个状态的收集。

    input_event(ddata->input, EV_KEY, KEY_POWER, 1);

    input_sync(ddata->input);

            可是近期遇到一个奇怪的问题是内核中的KEY_WAKEUP唤醒键值使用上述方法上报时。用户空间仅仅能检測到状态0,第二次按键时才会有状态1。这样导致Android系统不能正常唤醒,须要按两次才干唤醒系统。

            眼下的解决方法是将之前上报KEY_WAKEUP的地上改为KEY_POWER键值。可是好奇心引着我弄清楚它们是怎么回事。

            经验出这里边上报例如以下一样连续上报1/0状态才干够在用户空间正常的检測到1/0状态。    

        input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);

        input_sync(ddata->input);

        

        input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);

        input_sync(ddata->input);

            直觉告诉我能够是因为我对这个两个api的不了解造成的。比較是凡事必有因的。

            除了KEY_WAKEUP换个其他键值试试。结果和KEY_WAKEUPG一样不能同步,能够判断出是非POWER按键就不行。这能够能所在代码位置有关系:

    }else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){

        input_event(ddata->input, EV_KEY, KEY_POWER, 1);

        input_sync(ddata->input);

    }

            再进一步測试在非PM_SUSPEND_ON电源模式下,全部的按键都是怎样的。測试结果是全部的非POWER按键都出现了按键不能同步的问题。可是不能以点概面。使用GPIO连接的物理按键并不会有此问题。那么就排除了input子系统中做了手脚。

    问题出就出在了Remote control驱动中对的处理。

            找出了问题所在了。确实是出在了Remote control驱动中,上报键值对PM状态进行了推断,假设

    static void remotectl_timer(unsigned long _data)

         if(ddata->press != ddata->pre_press) {

             ddata->pre_press = ddata->press = 0;

     

            if (get_suspend_state()==0){

                 //input_event(ddata->input, EV_KEY, ddata->keycode, 1);

                 //input_sync(ddata->input);

                 input_event(ddata->input, EV_KEY, ddata->keycode, 0);

                        input_sync(ddata->input);

            }else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){

                 //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);

                 //input_sync(ddata->input);

                input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);

                input_sync(ddata->input);

            }

         }

            将过滤条件去除后,能够和GPIO连接的物理按键一样的效果了,即不管系统处理什么样的状态。休眠或者唤醒状态都上传了键值。同一时候这也给我带来了一个疑惑,按键驱动中要不要进行suspend状态推断。依据Android中的经验全部的状态都要上传的。响应不响应是看上层系统的决定。可是假设对于普通的嵌入式Linux系统就不一定了,假设input子系统在系统休眠的时候上传了键值。那么相应的应用层能够就会直接去响应键值。要使用哪种方法实现,这是一个悖论!结合Android的宏这样实现了:

    diff --git a/drivers/input/remotectl/rkxx_remotectl.c b/drivers/input/remotectl/rkxx_remotectl.c

    index db91516..201c5dd 100644

    --- a/drivers/input/remotectl/rkxx_remotectl.c

    +++ b/drivers/input/remotectl/rkxx_remotectl.c

    @@ -306,6 +306,10 @@ static void remotectl_do_something(unsigned long  data)

                     if ((ddata->scanData&0x0ff) == ((~ddata->scanData >> 8)&0x0ff)){

                         if (remotectl_keycode_lookup(ddata)){

                             ddata->press = 1;

    +#ifdef CONFIG_ANDROID // Android OS needs input event whatever suspend state

    +                        input_event(ddata->input, EV_KEY, ddata->keycode, 1);

    +                        input_sync(ddata->input);

    +#else

                             if (ddata->keycode==KEY_POWER || get_suspend_state()==PM_SUSPEND_ON){

                                 input_event(ddata->input, EV_KEY, ddata->keycode, 1);

                                 input_sync(ddata->input);

    @@ -314,6 +318,7 @@ static void remotectl_do_something(unsigned long  data)

                             }

                             //input_event(ddata->input, EV_KEY, ddata->keycode, ddata->press);

                                    //input_sync(ddata->input);

    +#endif // CONFIG_ANDROID

                             ddata->state = RMC_SEQUENCE;

                         }else{

                             ddata->state = RMC_PRELOAD;

    @@ -437,6 +442,10 @@ static void remotectl_timer(unsigned long _data)

         if(ddata->press != ddata->pre_press) {

             ddata->pre_press = ddata->press = 0;

     

    +#ifdef CONFIG_ANDROID // Android OS needs input event whatever suspend state

    +        input_event(ddata->input, EV_KEY, ddata->keycode, 0);

    +        input_sync(ddata->input);

    +#else

             if (get_suspend_state()==0){

                 //input_event(ddata->input, EV_KEY, ddata->keycode, 1);

                 //input_sync(ddata->input);

    @@ -448,6 +457,7 @@ static void remotectl_timer(unsigned long _data)

                 input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);

                 input_sync(ddata->input);

             }

    +#endif // CONFIG_ANDROID

         }

     #ifdef CONFIG_PM

         remotectl_wakeup(_data);

            假设是Android系统。那么不管kernel处理什么样的休眠状态都实时地上报键值。

    这样保证在休眠播放音乐的时候能够控制音频大小。这也正是眼下Android手机的实现方式

    http://blog.csdn.net/kangear/article/details/40072707

           

            另一点:按键中的状0,并非input_sync(ddata->input);发出的,它只会发出当前的值。它不过一个「同步」,意思是数据都准备好了,能够发送了。

    还是没有对驱动了解的非常清楚加上自己的一些瞎想像误导了自己。内核input驱动中是不区分POWER键,WAKEUP键;真是有差异了,问题一定是出在了自己的驱动代码中。


  • 相关阅读:
    枚举扩展,感觉用处很大
    基础缓存操作类
    ASP.NET 4.0 全局取消表单危险字符验证
    拦截所有经过IOC的方法
    关于使用EPPlus插入列,名称管理器公式失效问题案列分析
    IocFactory容器实体
    线程扩展
    IEnumerable扩展支持Add,Remove等操作
    自定义特性。配合枚举使用棒棒哒
    在数据仓储的情况下进一步封装数据库基础操作,此版本为异步版本
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7025712.html
Copyright © 2011-2022 走看看