Android下实现触摸屏上的按键


前段时间在电容触摸屏上实现了触摸按键的功能,刚接手的时候一点头绪都没有,后来看了韩超的文章才慢慢理清原理(韩超何许人物?买过Android开发书籍的人应该不会陌生吧),原来从Android 2.1版本后框架层代码就提供了虚拟按键机制。 下面将介绍如何实现触摸式按键:   1.硬件分析 我所使用的触摸屏分辨率是1158*768,可视区域大小是1024*768(这也是LCD屏的大小),在触摸屏两侧总有5个按键。   2.触摸屏按键驱动的修改 既然可视区域在触摸屏中间部位,因此需要在触摸屏驱动中修改input_set_abs_params()函数中的参数
  1. input_set_abs_params(input_dev, ABS_MT_POSITION_X, 61, 1085, 0, 0);
  2. input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);

其中61是可视区域左侧x轴左边坐标,1085是右侧的。

3.Android框架层

Android上层通过读取触摸屏坐标并经过转算后来识别定义好的虚拟按键,代码位于frameworks/base/services/java/com/android/server/KeyInputQueue.java中:

static class Virtualkey{}是负责按键定位的方法;

private void readVirtualKeys(String deviceName)负责读取sys文件,这是最重要的代码,也是与底层sys文件系统沟通的桥梁,它会读取/sys/board_properties/virtualkeys.{deviceName}文件,deviceName一定要与触摸屏设备名称一致,不然会找不到指定的sys文件。

 

4.sys文件系统

前面讲到了readVirtualKeys会读取sys文件,这个sys文件就是定义虚拟按键的坐标以及键值,它的协议格式是一段字符串,每个按键有六项分别用冒号分割,按键按键之间也是用冒号分割,标准格式是:

键类型:键值:按键区域中心x坐标:按键区域中心y坐标:按键区域宽:按键区域高

创建sys文件的代码:

  1. #ifdef VIRTUAL_KEYS
  2. static ssize_t virtual_keys_show(struct kobject *kobj,
  3.              struct kobj_attribute *attr, char *buf)
  4. {
  5.     if (1) {
  6.         
  7.         return sprintf(buf,
  8.          __stringify(EV_KEY) ":" __stringify(KEY_VOLUMEUP) ":1030:370:30:30"
  9.          ":" __stringify(EV_KEY) ":" __stringify(KEY_VOLUMEDOWN) ":1030:470:30:30"
  10.          ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":1030:18:30:30"
  11.          ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":1030:136:30:30"
  12.          ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":1030:236:30:30"
  13.          "\n");
  14.     } else {

  15.     }
  16. }

  17. static struct kobj_attribute virtual_keys_attr = {
  18.     .attr = {
  19.         .name = "virtualkeys.xxxx",
  20.         .mode = S_IRUGO,
  21.     },
  22.     .show = &virtual_keys_show,
  23. };

  24. static struct attribute *properties_attrs[] = {
  25.     &virtual_keys_attr.attr,
  26.     NULL
  27. };

  28. static struct attribute_group properties_attr_group = {
  29.     .attrs = properties_attrs,
  30. };

  31. static void virtual_keys_init(void)
  32. {
  33.     int ret;
  34.     struct kobject *properties_kobj;
  35.     
  36.     properties_kobj = kobject_create_and_add("board_properties", NULL);
  37.     if (properties_kobj)
  38.         ret = sysfs_create_group(properties_kobj,
  39.                      &properties_attr_group);
  40.     if (!properties_kobj || ret)
  41.         pr_err("failed to create board_properties\n");    
  42. }

  43. #endif

其中.name = "virtualkeys.xxxx"的xxxx就是触摸屏设备名称,也就是前面说到的{deviceName},virtual_keys_init()函数可以在触摸屏probe函数中调用。另外,我将可视区域左侧的两侧按键移到了右侧实现,因此五个按键区域中心x坐标都是一样,这部分要在触摸屏驱动增加x轴坐标调整,这部分我就不再说明。

以上步骤完成后可以使用 cat /sys/board_properties/virtualkeys.{deviceName}查看虚拟按键的配置文件,并试试按下触摸屏上按键是否有反应,如果坐标不正确还要进行耐心地校准。

相关内容