kpd_init_keymap(kpd_keymap);
keymap[i] = kpd_keymap[i]; //初始化keymap:kpd_keymap[KPD_NUM_KEYS] = KPD_INIT_KEYMAP();
kpd_init_keymap_state(kpd_keymap_state);
keymap_state[i] = kpd_keymap_state[i]; //kpd_keymap_state[KPD_NUM_MEMS] = {0xffff, 0xffff, 0xffff, 0xffff, 0x00ff};
r = input_register_device(kpd_input_dev);
r = misc_register(&kpd_dev);
/* register IRQ and EINT */
kpd_set_debounce(KPD_KEY_DEBOUNCE); //设置防反跳时间
r = request_irq(kp_irqnr, kpd_irq_handler, IRQF_TRIGGER_NONE, KPD_NAME, NULL); //keypad处理函数
long_press_reboot_function_setting();/* /API 4 for kpd long press reboot function setting */
hrtimer_init(&aee_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); //初始化高精度定时器,相对模式
aee_timer.function = aee_timer_func; //处理函数
hrtimer_init(&aee_timer_5s, CLOCK_MONOTONIC, HRTIMER_MODE_REL); //第二个
aee_timer_5s.function = aee_timer_5s_func;
mtk_kpd_gpio_set();
mtk_kpd_gpios_get //得到DWS里面的设置的行和列的gpio和模式
#ifdef GPIO_KPD_KROW0_PIN
ROW_REG[0] = GPIO_KPD_KROW0_PIN;
GPIO_MODE[0] |= GPIO_KPD_KROW0_PIN_M_KROW;
#endif
/* KCOL: GPIO INPUT + PULL ENABLE + PULL UP */ 设置列的模式
mt_set_gpio_mode(COL_REG[i], ((GPIO_MODE[i] >> 4) & 0x0f));
mt_set_gpio_dir(COL_REG[i], 0);
mt_set_gpio_pull_enable(COL_REG[i], 1);
mt_set_gpio_pull_select(COL_REG[i], 1);
/* KROW: GPIO output + pull disable + pull down */
mt_set_gpio_mode(ROW_REG[i], (GPIO_MODE[i] & 0x0f));
mt_set_gpio_dir(ROW_REG[i], 1);
mt_set_gpio_pull_enable(ROW_REG[i], 0);
mt_set_gpio_pull_select(ROW_REG[i], 0);
long_press_reboot_function_setting();/* /API 4 for kpd long press reboot function setting */
if (get_boot_mode() == NORMAL_BOOT) //如果正常启动
#ifdef ONEKEY_REBOOT_NORMAL_MODE //一个按键重启
pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN,0x01); //使能
pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN,0x00); //去掉
pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD,KPD_PMIC_LPRST_TD); //写入超时时间,11s这里
#endif
#ifdef TWOKEY_REBOOT_NORMAL_MODE
pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN,0x01);
pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN,0x01);
pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD,KPD_PMIC_LPRST_TD);
#endif
esle
#ifdef ONEKEY_REBOOT_OTHER_MODE
pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN,0x01);
pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN,0x00);
pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD,KPD_PMIC_LPRST_TD);
#endif
#ifdef TWOKEY_REBOOT_OTHER_MODE
pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN,0x01);
pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN,0x01);
pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD,KPD_PMIC_LPRST_TD);
#endif
分析keypad处理函数kpd_irq_handler
kpd_irq_handler
tasklet_schedule(&kpd_keymap_tasklet); //调用tasklet
kpd_keymap_handler
kpd_get_keymap_state(new_state); //从寄存器得到keypad状态
for (i = 0; i < KPD_NUM_MEMS; i++) {
change = new_state[i] ^ kpd_keymap_state[i]; //按键有无变化
for (j = 0; j < 16; j++) { //具体按键哪个按键变化
mask = 1U << j;
}
hw_keycode = (i << 4) + j; //得到按键的在keymap具体值
/* bit is 1: not pressed, 0: pressed */
pressed = !(new_state[i] & mask); //判断是按键还是松开
linux_keycode = kpd_keymap[hw_keycode]; //从keymap得到linuxkey
kpd_aee_handler(linux_keycode, pressed); //如果是KEY_VOLUMEUP或者KEY_VOLUMEDOWN
kpd_update_aee_state();
/* if volumeup and volumedown was pressed the same time then start the time of ten seconds */
aee_timer_started = true;
hrtimer_start(&aee_timer_5s, ktime_set(AEE_DELAY_TIME_5S, 0), HRTIMER_MODE_REL); //打开5s
hrtimer_start(&aee_timer, ktime_set(AEE_DELAY_TIME, 0), HRTIMER_MODE_REL); //15s
input_report_key(kpd_input_dev, linux_keycode, pressed); //上报按键
.........处理一些情况
aee_timer_func
/* aee_kernel_reminding("manual dump ", "Triggered by press KEY_VOLUMEUP+KEY_VOLUMEDOWN"); */
aee_trigger_kdb(); //就是使能KDB的操作,一个调试工具,kernel debug bridge
aee_timer_5s_func
/* printk("kpd: vol up+vol down AEE manual dump timer 5s !\n"); */
flags_5s = true;