【原创】管中窥豹--从按键处理看回调函数的实现

时间:2021-12-14 16:14:37

      系统启动以后, 调用tmc_define_tasks()创建AMSS所需要的各个Task,其中包括ui_task,它起到了一个中间层的作用,即所有AMSS底层服务组件的消息,都将经由ui_task而转到AEE,并最终转到具体的AppApplet)的执行代码里面(HandleEvent())。在UI_init中会调用ui_key_init()注册上层UI对于底层按键(包括一些自定义的事件,比如耳机插拔,充电器插拔,HOOK检测等等)的回调函数。

void ui_key_init( void )
{
      (void) kpd_sub_srvc(ui_kpd_sub_cb);

      if (ui_kpd_handle.status == HS_SUBSCRIBED) 
      {      
            //这里注册keypad的回调函数
            (void) kpd_reg_key_event(ui_kpd_handle, ui_key_event_cb);
      }
}
      这里注册回调函数的过程其实很简单,就是把处理按键事件(或自定义事件)的回调函数ui_key_event_cb的指针赋值给一个全局变量keypad_event_cb :
      if ( keypad_event_cb ) return(FALSE);
            keypad_event_cb = cb;  //cbui_key_event_cb的函数指针

      之后系统在扫描键盘发现有键按下,或则检测到自定义的事件发生(耳机,充电器,USB插拔等)就会调用 keypad_pass_key_code( )来向上层UI报告,在这里就实现了函数的回调。
void keypad_pass_key_code( byte key_code, byte key_parm )
{
      if ( keypad_event_cb )
      {
            keypad_key_event_type key_event;   //记录按键或自定义事件的键值
            key_event.key_code = key_code;
            key_event.key_parm = key_parm;
            keypad_event_cb ( key_event );   //利用保存回调函数地址的全局变量,实现函数回调
      }
}

      最后,我们回头来看看回调函数里面做了什么:

void ui_key_event_cb( keypad_key_event_type key_event )
{

      word isave;                
      INTLOCK_SAV( isave );         /* Disable interrupts and save PSW */

       if (((ui_key_buffer.wr_idx + 1) & UI_KEY_BUF_MASK) != ui_key_buffer.rd_idx) 
      {
            //把key放在buffer里,等待被读取
            ui_key_buffer.data[ui_key_buffer.wr_idx] = key_event.key_code;
            ui_key_buffer.key_parm[ui_key_buffer.wr_idx] = key_event.key_parm;
            ui_key_buffer.wr_idx = (ui_key_buffer.wr_idx+1) & UI_KEY_BUF_MASK;
      }  

       INTFREE_SAV( isave );       /* Restore interrupts (PSW) */

      (void) rex_set_sigs( &ui_tcb, UI_KEY_SIG );  //向ui_task发送消息

}

       ui_task在接收到回调函数发送的UI_KEY_SIG消息后就会,就会调用handle_keys把buffer中的物理键值转化成逻辑键值传递给App。

      AEE_Event( EVT_KEY_PRESS, last_vcode, dwparam );
      AEE_Event( EVT_KEY, last_vcode, dwparam );
      AEE_Event( EVT_KEY_RELEASE, last_vcode, dwparam );