任志敏
(常州纺织服装职业技术学院机电学院,江苏 常州 213164)
随着Android系统的不断发展,越来越多的嵌入式系统引入Android平台作为系统平台。Android平台的一大优势是使用触摸屏操作APP应用程序,在大多数应用场合利用这一优势效率很高,用户体验良好,但是在有些场合就适应得不是很友好,比如在汽车维修领域使用的发动机检测系统,操作人员一般都携带手套检查相关汽车部件,若要再用到触摸屏,操作起来就不方便,频繁脱戴手套又耗时又不安全,因此还是需要借助传统的物理按键实现相关操作。典型的汽车发动机检测内窥镜如图1所示。
图1 汽车发动机检测内窥镜实物图
从图1可以看出,手柄上有6个物理按键,除了一个电源按键以外,还有5个功能按键,其功能一般是“菜单”,“向上选择”,“向下选择”,“确定”,“返回”。通过这5个按键实现如图2所示的APP窗口操作。
图2 内窥镜APP窗口
按下“菜单”按键,弹出如图2所示的窗口,通过“向上选择”和“向下选择”两个按键选择按钮,用“确定”按键进入对应的功能模块。即原来使用触摸屏实现菜单操作都有5个物理按键完成。
Android系统本身支持的物理按键包括系统功能键和“querty”键盘,系统功能键包括“Home”,“volume up”,“volume down”,“menu”等,“querty”键盘就是日常我们所见的普通键盘上的各种按键。在安装了Android2.2以前的版本的硬件系统上,系统功能键和“querty”键均是真实存在的物理按键,而Android2.2以后的硬件系统,一般保留的物理按键只有系统功能键,“querty”键盘采用软键盘的形式。本文设计的内窥镜采用Android6.0系统,公版的硬件系统电路只引出支持功能键的物理按键[2],其电路图如图3所示。
从图3中可以看出,AVCC为模数转换的参考电压,LRADC0为模数转换引脚,R1~R8为分压电阻,S1~S7一端连接对应的分压电阻,另一端连接电源地,按下S1~S7中任何一个键,通过读取LRADC0引脚的模数转换值就可以感知到底按下了哪个按键,这样做的好处是节省了IO引脚资源,只需要连一个模数转换引脚就可以确定7个按键。在设计过程中,若不需要用到这7个键,按键可以删除,但电阻不可删除。考虑到工业内窥镜录制播放视频时仍旧需要用到麦克风,因此保留音量键VOL+和VOL-,MENU键用于“菜单”键,SEARCH键用于“向上选择”键,HOME键用于“向下选择”键,ESC键用于“确定”键,ENTER键用于“返回”键。
图3 Android6.0公版按键硬件电路
为了响应内窥镜上增加的“菜单”等5个物理按键,需要了解和修改Android6.0的内核文件,第一个文件为模数转换映射文件,位于/linux-3.4/drivers/input/keyboard目录下的sunxi-keyboard.c文件,该文件中定义了一个数组,该数组为static unsigned char keypad_mapindex[64]={0,0,0,0,0,0,0,/*key1*/1,1,1,1,1,1,/*key2*/2,2,2,2,2,2, /*key3*/3,3,3,3,3,/*key4*/4,4,4,4,4,/*key5*/5,5,5,5,5,/*key6*/6,6,6,6,6,6,6,6,6,/*key7*/7,7,7,7,7,7,7,7,7,7,7,7,7/* key 8*/}。
从该数组可以看出,该数组正好对应图3所示的物理按键原理图,把电压一共分成64份,每一份对应一个电压值,大约为0.2V,比如key1键对应图3中的VOL+模数采集点,虽然该点的电压为0.19V,但是每次按下VOL+键模数转换的值不一定完全一样,因此keypad_mapindex数组中设定7个值来相应按下VOL+键。在sunxi-keyboard.c文件中,通过代码
scancode = keypad_mapindex[key_val&0x3f];
input_report_key(sunxikbd_dev, sunxi_scankeycodes[scancode], 0);
上报具体的按键值。
第二个与物理按键相关的同样位于/linux-3.4/drivers/input/keyboard目录下的sun8i-keyboard.h文件。该文件首先定义了数组sunxi_scankeycodes[KEY_MAX_CNT],用于内核上报给系统的值[1]。为了避免与系统自带的值相冲突,本文设计了如图4所示的上报值数组。
图4 课题设计上报值
sunxi_scankeycodes上报数组只是做了一个定义,具体的上报值,比如KEY_VOLUMEUP值是多少呢?
第三个文件是位于/linux-3.4/include/linux目录下的input.h文件,该文件下定义了KEY_VOLUMEUP的值,系统具体上报的默认键值定义最大为248,因此本文自定义的5个上报键值从249开始,这5个上报键值分别是:菜单键KEY_MYMENU具体键值为249;向上选择键KEY_MYUP具体键值为250;向下选择键KEY_MYDOWN具体键值为251;确定键KEY_MYENTER具体键值为252;返回键KEY_MYBACK具体键值为253。
总结一下按键上报的过程,1)Android底层的linux系统内核通过扫描,将物理按键按下的电压转换为数字电压并且映射到数组下标。2)通过keypad_mapindex[64],sunxi_scankeycodes[KEY_MAX_CNT]两个数组关系转化将按键映射到内核中预定义的键值。3)linux内核上报给上层一个具体的键值。
第四个文件是位于Android/device/vendor-name/device-name/configs目录下的sunxi-keyboard.kl文件,该文件是framework层的按键映射文件,增加本文的5个按键映射,修改其配置为:key 114 VOLUME_DOWN;key 115 VOLUME_UP;key 249 MYMENU;key 250 MYUP;key 251 MYDOWN;key 252 MYENTER;key 253 MYBACK。该文件中key为关键字,不能改动,249为input.h定义的上报键值。
第五个文件是位于/frameworks/native/include/android目录下的keycodes.h文件,该文件定义了用于Android应用层的按键键值,修改该文件后,菜单键应用层键值AKEYCODE_MYMENU=300;AKEYCODE_MYUP=301;AKEYCODE_MYDOWN=302;AKEYCODE_MYENTER=303;AKEYCODE_MYBACK=304。需要注意的是,该文件的键值与linux层上报的键值是不同的,那么如何把两者对应起来呢?
第六个文件是位于/frameworks/native/include/input目录下的InputEventLabels.h文件,修改该文件,把增加的5个键的定义加入其中,代码为DEFINE_KEYCODE(MYMENU),DEFINE_KEYCODE(MYUP),DEFINE_KEYCODE(MYDOWN),DEFINE_KEYCODE(MYENTER),DEFINE_KEYCODE(MYBACK)。
第七个文件是位于frameworks/base/core/res/res/values目录下的attrs.xml,修改后代码为
经过以上文件的修改,新增加的5个物理按键就可以响应Android上层APP程序了。
为了测试验证物理按键的响应效果,本文在Android6.0平台上设计了APP程序进行验证[3],测试代码如图5所示。
图5 物理按钮响应验证程序代码
经过测试,系统原有的两个音量键仍旧功能不变,新增加的5个按键可以准确响应。