2:实现细节
2.1实现kernel层按键事件的上报
首先在KPD_INIT_KEYMAP()中把对应的物理按键定义为KEY_TEST,后面的设置也是根据此表来的。而KEY_TEST在input.h中定义。
文件路径:alps/mediatek/custom/${project}/kernel/dct/dct/cust_kpd.h
/* HW keycode [0 ~ 71] -> Linux keycode*/
#define KPD_INIT_KEYMAP() \
{ \
…
[21] = KEY_TEST, \
…
}
Inpu.h中定义KEY_TEST:
路径:alps/kernel/include/linux/input.h
#define KEY_WIMAX 246
#define KEY_RFKILL 247 /* Key that controls all radios */
#define KEY_MICMUTE 248 /* Mute / unmute the microphone */
#define KEY_TEST 249 /* add a test key */
/* Code 255 is reserved for special needs of AT keyboard driver */
Input输入子系统的注册和上报:
输入子系统的注册:
文件路径:/alps/mediatek/platform/mt6589/kernel/drivers/keypad/kpd.c
static int kpd_pdrv_probe(struct platform_device *pdev)
{
…
/* initialize and register input device (/dev/input/eventX) */
kpd_input_dev = input_allocate_device();
…
__set_bit(EV_KEY, kpd_input_dev->evbit);
for (i = 0; i < KPD_NUM_KEYS; i++) {
if (kpd_keymap[i] != 0)
__set_bit(kpd_keymap[i], kpd_input_dev->keybit);
}
…
r = input_register_device(kpd_input_dev);
…
r = request_irq(MT6589_KP_IRQ_ID, kpd_irq_handler, IRQF_TRIGGER_FALLING, KPD_NAME, NULL);
}
其中:
static u16 kpd_keymap[KPD_NUM_KEYS] = KPD_INIT_KEYMAP();//将我们定义的KEY_TEST注册进输入系统.
r = request_irq(MT6589_KP_IRQ_ID, kpd_irq_handler, IRQF_TRIGGER_FALLING, KPD_NAME, NULL); // 这里注册了按键中断和对应的处理函数.接下来分析kpd_irq_handler()函数.
static irqreturn_t kpd_irq_handler(int irq, void *dev_id)
{
/* use _nosync to avoid deadlock */
disable_irq_nosync(MT6589_KP_IRQ_ID);
tasklet_schedule(&kpd_keymap_tasklet);
return IRQ_HANDLED;
}
//由上可知,中断处理函数只简单的调度了一个tasklet.下面我们分析调度的任务:
static DECLARE_TASKLET(kpd_keymap_tasklet, kpd_keymap_handler, 0);
static void kpd_keymap_handler(unsigned long data)
{
…
linux_keycode = kpd_keymap[hw_keycode];
input_report_key(kpd_input_dev, linux_keycode, pressed);
input_sync(kpd_input_dev);
…
}
Linux内核注册上报的流程基本就这样.
2.2编译/验证
./mk r k;
./mk bootimage
运行上面两条命令后,在alps/out/target/product/${project}就会生成bootimage文件,将此文件下载到手机重新启动后,用adb连接,并输入命令;
root@android:/ # getevent /dev/input/event0
点击我们设置的按键,就会上报事件:
0001 00f900000001
0000 0000 00000000
0001 00f900000000
0000 0000 00000000
上面的0xF9即为我们在input.h里面定义的249.
3:增加keypad layout文件键盘映射,linux和android key映射
文件路径:alps/mediatek//config/${project}/mtk-kpd.kl
key 212 CAMERA
key 211 FOCUS
key 249 TEST
4:修改Java识别keycode
路径:/alps/frameworks/base/include/androidfw/keycodelables.h
static const KeycodeLabel KEYCODES[] = {
…
{ "KANA", 218 },
{ "ASSIST", 219 },
{ "TEST", 220 },
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
{ NULL, 0 }
…
}
路径:/alps/framework /native/include/android/KeyCodes.h
enum {
…
AKEYCODE_TEST = 220,
…
}
5:修改Java键盘事件
路径:alps/frameworks/base/core/java/android/view/KeyEvent.java
public class KeyEvent extends InputEvent implements Parcelable {
…
/** Key code constant: Assist key.
* Launches the global assist activity. Not delivered to applications. */
public static final int KEYCODE_ASSIST = 219;
public static final int KEYCODE_TEST = 220;
private static final int LAST_KEYCODE = KEYCODE_TEST;
…
}
6:修改xml文件描述符
路径:alps/frameworks/base/core/res/res/values/attrs.xml
7:增加验证在android,在此直接打开摄像头。
路径:/alps/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
在interceptKeyBeforeDispatching()增加:
if(keyCode==KeyEvent.KEYCODE_TEST&&event.getAction()==KeyEvent.ACTION_DOWN)
{
Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(intent);
}
以上即为在Android系统中实现物理按键的上报及检测到按键后采取不同的操作方法的简要概述.