枕上从妨一夜睡,灯前读尽十年诗。这篇文章主要讲述Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值相关的知识,希望能为你提供帮助。
android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值
题外话:一个问题研究到最后,那边记录文档的前半部分基本上都是没用的,甚至是错误的。
重点在最后,前边不过一些假想猜測。
http://blog.csdn.net/kangear/article/details/40072707
在调试一下红外遥控器input驱动时,直接採用的是一个半成品的驱动在上边实现的自己的设备的匹配,但同一时候遇到了一些关于input输入子系统的疑惑。
按键一般有「按下和抬起」两个状态一般使用0和1来分别表示。一般例如以下方式上报按键键值
就能够完毕「按下和抬起」两个状态的收集。
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);
发出的,它只会发出当前的值
。它不过一个「同步」,意思是数据都准备好了,能够发送了。
【Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值】还是没有对驱动了解的非常清楚加上自己的一些瞎想像误导了自己。内核input驱动中是不区分POWER键,WAKEUP键;真是有差异了,问题一定是出在了自己的驱动代码中。
推荐阅读
- 使用apply的方法将伪数组转化为数组
- 使用MyBatis-Gererator自动生成Dao.Model.Mapping相关文件
- spring4+srpingmvc+mybatis基本框架(app框架搭建一)
- Android之使用JAVA占位符格式数据(很实用)
- spring——IOC容器BeanFactory和ApplicationContext对比
- Cube 技术解读 | Cube 小程序技术详解
- Flutter 专题89 图解基本 Overlay 悬浮新手引导 #yyds干货盘点#
- 事务的隔离级别与MVCC
- Exiting with failure status due to previous erro异常处理