洛达应用层开发教程系列12-按键配置3

通过上面的两节,我们已经能够正常使用我们自己的按键配置了,但是我们并不知道到代码是如何调用运行的,那么本节就做一个简要的分析梳理

主要通过Power key为例,其他的按键依次类推。

  1. 初始化
    首先讲的肯定是初始化啦
    // 首先看到下面这个函数,基本上洛达的按键初始化都是在这里配置的了
    void apps_event_key_event_init(void)
    {
        // 本函数重点就讲这个两个函数
        // ...
        status = airo_key_event_init();
        // ...
        /* Register key callback. */
        status = airo_key_register_callback(_apps_key_airo_key_callback, NULL);
    }
    
    /*
        本函数就是从nvdm中读取我们的按键的配置,然后保存到airo_key_config中
        哎?这个nvdm是什么呢?
        还记得上一节讲的按键配置config tool的配置吗,我们是config tool工具后,结果保存到nvdm.bin和filesystem.bin中
        这里的读取nvdm就是从上面的文件中读取我们的按键配置,然后保存到airo_key_config中
    */
    bool airo_key_event_init(void)
    {
        // ...
        ret  = nvkey_read_data(airo_nvkey_key[i], (uint8_t *)(&airo_key_config[i]), &leng);
        // ...
    }
    
    /*
        这个就是按键的回调函数,不管什么按键,到执行了动作之后,通过一顿解析,就会跑到这里来,然后调用ui_shell_send_event发送到对应的APPs中去,大家可以看看第一节的入门知识,然后对应的APPs接收到后,就会进行相应的动作,比如发送到music app,指定play或者pause
    */
    static void _apps_key_airo_key_callback(airo_key_event_t event, uint8_t key_data, void *user_data)
    {
        // ...
        status = ui_shell_send_event(true, EVENT_PRIORITY_MIDDLE, EVENT_GROUP_UI_SHELL_KEY,
                                        (key_data & 0xFF) | ((event & 0xFF) << 8),
                                        p_key_action, sizeof(uint16_t), NULL, 0);
        // ...
    }
    
    /*
        本函数就是注册上面的回调函数,当我们处理按键的时候,函数会调用airo_key_event_context.callback这个,最终调用上面的函数,执行事件的发送工作,这个后面会讲,这个函数同时也会进行powerkey Init
    */
    bool airo_key_register_callback(airo_key_callback_t callback, void *user_data)
    {
        // ...
        airo_key_event_context.callback  = callback;
        // ...
        airo_powerkey_init();
        // ...
    }
    
    /*
        这个函数就是对于powerkey的初始化,首先看到的就是回调函数,这个两个回调的作用就是用来发送press和release状态的
        然后就是注册回调函数
    */
    bool airo_powerkey_init(void)
    {
        // ...
        config.callback1  = airo_powerkey_callback1;
        config.user_data1 = NULL;
        config.callback2  = airo_powerkey_callback2;
        config.user_data2 = NULL;
        //...
        ret = pmu_pwrkey_normal_key_init(&config);
        //...
    }
    
    /*
        用来发送press状态
    */
    static void airo_powerkey_callback1(void)
    {
        airo_powerkey_send_state(AIRO_KEY_DRIVEN_PRESS);
    }
    
    /*
        用来发送release状态
    */
    static void airo_powerkey_callback2(void)
    {
        airo_powerkey_send_state(AIRO_KEY_DRIVEN_RELEASE);
    }
    
    /*
        用来注册回调函数,当检测到按键的触发(中断)之后,就会调用相应的回调函数,发送相应的按键状态,经过一些列的处理发送APPs
        RG_INT_PWRKEY_RISE->airo_powerkey_callback1
        RG_INT_PWRKEY_FALL->airo_powerkey_callback2
    */
    pmu_operate_status_t pmu_pwrkey_normal_key_init(pmu_pwrkey_config_t *config)
    {
        status = pmu_register_callback_2565(RG_INT_PWRKEY_RISE, config->callback1,config->user_data1);
    
        status = pmu_register_callback_2565(RG_INT_PWRKEY_FALL,config->callback2,config->user_data2);
    }
    
    pmu_status_t pmu_register_callback_2565(pmu_interrupt_index_2565_t pmu_int_ch, pmu_callback_t callback, void *user_data)
    {
        // 这是一个数组,用来保存上面的回调函数,当产生中断,就会去判断,是否是电源键的中断,如果是就调用相应的回调函数
        pmu_function_table_2565
    }
    
  2. 处理流程
    到上面我们power key初始化就完成了,下面我从产生中断的地方开始,再梳理一遍
    // 从这里函数看就差不多,没必要还往上看了,没有什么意义
    // 
    void pmu_eint_handler(void *parameter)
    {
        // 通过判断之后,如果是Power key,就会调用这个函数,根据pwrkey_flag去调用press还是release函数
        pmu_pwrkey_handler(pwrkey_flag);
        {
            // 根据pwrkey_flag调用下面的回调函数,看到下面的回调函数,是不是很眼熟,就是上面注册的airo_powerkey_callback1和airo_powerkey_callback2
            pmu_function_table_2565[RG_INT_PWRKEY_RISE].pmu_callback();
            pmu_function_table_2565[RG_INT_PWRKEY_FALL].pmu_callback();
            {
                airo_powerkey_callback1();
                {
                    airo_powerkey_send_state(AIRO_KEY_DRIVEN_PRESS);
                    {
                        // 不管是power key,还是captouch,eint,gsensor等按键都是都是调用这个函数,通过这个函数处理完后,在调用airo_key_state_machine这个函数,去处理是单击,双击,长按等
                        airo_key_process_key(&key_event, AIRO_KEY_POWERKEY);
                        {
                            airo_key_state_machine(index, config_index, key_name, action_type);
                            {
                                // 重点关注这个两个数组,就是通过这个两个表,去判断此时的按键事件是单击,双击,长按等,大家可以多花的时间,去搞懂,如果你需要四击及以上,就需要通过在下面这个两个表加,这里不细说
                                key_state_machine_table[key_state_max][KEY_ACTION_MAX];
                                key_next_state;
    
                                // 如果上面处理出来了,就会调用这个函数,我们往里面看就会知道
                                airo_key_callbak_ex(p_key_note->event, key_name, index);
                                {
                                    // 看到这个,大家是不是又熟悉感,这个不就是airo_key_register_callback注册的回调函数嘛!
                                    airo_key_event_context.callback(event, key_name, airo_key_event_context.user_data);
                                    {
                                        _apps_key_airo_key_callback;
                                        {
                                            // 到这里就会发送到我们APPs当中,这里之前已经说过了
                                            status = ui_shell_send_event(true, EVENT_PRIORITY_MIDDLE, EVENT_GROUP_UI_SHELL_KEY,
                                                                (key_data & 0xFF) | ((event & 0xFF) << 8),
                                                                p_key_action, sizeof(uint16_t), NULL, 0);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                airo_powerkey_callback2();
                {
                    airo_powerkey_send_state(AIRO_KEY_DRIVEN_RELEASE);
                }
            }
        }
    }
    

总结

通过上面的初始化和处理流程的讲解,我们对按键处理过程,应该说是非常熟悉了,当我们分析按键的log的时候,就会事半功倍,并且对于如果要添加四击及以上按键,也有了一个大概的了解。