Android Linux有一套内核与应用层通信的机制,其中应用比较广泛的就是input系统,即驱动通过linux的input系统,上报事件,例如按键、耳机插拔、触摸屏信息等,在adb命令行中输入getevent可以看到当前系统注册的事件类型
root@msm8916_32:/ # getevent
getevent
add device 1: /dev/input/event13
name: "msm8x16-snd-card-mtp Headset Jack" //耳机插拔事件
add device 2: /dev/input/event12
name: "msm8x16-snd-card-mtp Button Jack" //耳机按键事件
add device 3: /dev/input/event10 //PMIC按键事件
name: "qpnp_pon"
add device 4: /dev/input/event9
name: "pressure"
add device 5: /dev/input/event4 //指南针
name: "compass"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 6: /dev/input/event2
name: "hbtp_vm"
add device 7: /dev/input/event1 //触摸屏
name: "FT5x36"
add device 8: /dev/input/event0
name: "input_mt_wrapper"
could not get driver version for /dev/input/mice, Not a typewriter
add device 9: /dev/input/event3
name: "gyroscope"
add device 10: /dev/input/event8
name: "proximity"
add device 11: /dev/input/event7 //光感
name: "light"
add device 12: /dev/input/event6
name: "bma_interrupt"
add device 13: /dev/input/event5
name: "bma2x2-accel"
add device 14: /dev/input/event11 //gpio按键事件
name: "gpio-keys"
如果我们想在驱动中新加入一种事件类型,该怎么做呢?
1. 定义input设备 struct input_dev *input;
2. 为input设备分配空间: input = input_allocate_device();
3. 调用input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code),设置输入设备支持的类型,例如input_set_capability(mbhc->headset_jack.jack->input_dev, EV_KEY, 0xF9);表示使mbhc->headset_jack.jack->input_dev支持EV_KEY类型的0xF9编码输入。注意这个函数不能少,否则执行第四步时内核不会上报事件
4. 在需要输入的地方调用input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value),也可以调用input_report_key、input_report_switch等函数
5. 调用input_sync(struct input_dev *dev),同步上报事件,如果不调用input_sync(struct input_dev *dev),上报event事件会有延时。
例如:
xxx_init()
{
...
struct input_dev *input;
...
input = input_allocate_device();
...
ret = request_threaded_irq(gpio_to_irq(cradle_detect_gpio), NULL, cradle_detect_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "cradle_detect", data); //申请中断
}
static irqreturn_t cradle_detect_irq(int irq, void *data)
{
struct wcd_mbhc *mbhc = data;
int ret = IRQ_HANDLED;
unsigned int code = 0xf9;
input_set_capability(mbhc->headset_jack.jack->input_dev, EV_KEY, code);
if (0 == __gpio_get_value(cradle_detect_gpio)){
pr_info("howard cradle_detect_gpio low, reporting event\n");
input_report_key(mbhc->headset_jack.jack->input_dev, code, 0);
}
else {
pr_info("howard cradle_detect_gpio high, reporting event\n");
input_report_key(mbhc->headset_jack.jack->input_dev, code, 1);
}
input_sync(mbhc->headset_jack.jack->input_dev);
return ret;}
运行结果,在命令行运行cat /proc/kmsg可以看到检测到按键
<6>[ 3140.814354] Howard detect cradle irq 493 gpio value 0
<6>[ 3140.814363] howard cradle_detect_gpio low, reporting event
<6>[ 3141.106513] Howard detect cradle irq 493 gpio value 1
<6>[ 3141.106522] howard cradle_detect_gpio high, reporting event
用getevent可以看到有号码为0xf9的类型为1(EV_KEY)的事件上报:
/dev/input/event13: 0001 00f9 00000000
/dev/input/event13: 0000 0000 00000000
/dev/input/event13: 0001 00f9 00000001
/dev/input/event13: 0000 0000 00000000