




已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MTK MMI event 小结 1在MTK MMI 里面有各种event,最常见的有跟交互相关的 按键event,触摸屏event。跟各种具体事件比如电话event,短信event,电量event,信号量event,timer event等等。MTK 都有相应的处理方式,跟交互相关的 按键(KeyBrd.c)和触摸屏(TouchScreen.c) 各有一套自己的机子,timer event 已经在 MTK timer 小结 3 介绍过,还有一套机制就是处理各种其他事件,它主要分为普通事件和interrupt event,interrupt event 主要用于需要弹出的对话框的event。M T K MMI event 小结 2今天主要看分析,常用事件机制。做过MTK开发的童鞋应该知道要接受 MTK L4 层的消息,用一个注册函数 SetProtocolEventHandler,注册一个event 的处理函数。比如短信,电话,电池电量,信号量等等都是通过这个函数来注册消息。当L4 层处理完封装事件后,就会把这个event 发送到MMI task 里来(消息发送可以看 MTK task 小结 5 ),然后MMI task 通过这个event 机制,找到相应的处理函数,进行处理。实现这种机制,也是考虑到零活性和扩张性。如果都在MMI task 里面,用 switch case 来处理,那就很疯狂了,长度不说,写个应用,定义个消息,都要去改MMI task,所以这个机制实现虽然比较简单,但是还是很有必要的。昨天也说到,这个机制的 event 主要有两种,普通event 和 intrrupt event(中断事件),这些主要是一些需要中断当前应用的事件(主要是看那些弹出框),比如电话,有些应用需要提前处理这个消息,还有些应用需要在这个事件处理完毕后处理。还是看代码吧在MMI task 最后,会调用函数 ProtocolEventHandler,这个函数就是找到 相应event 的 相应 处理函数(平台不一样,可能实际的函数名字有些区别,但是流程基本上一样的,我这里被 #define 到 mmi_frm_execute_current_protocol_handler)注意:event的处理函数使用SetProtocolEventHandler来注册。/ MsgStruct 是具体事件的 消息体void mmi_frm_execute_current_protocol_handler(U16 eventID, void *MsgStruct, int mod_src, void *peerBuf) U16 count = 0; PsExtPeerFuncPtr currFuncPtr = NULL; U8 interrup_result = MMI_FALSE; /* False not handle interrupt, True will handle */ MMI_BOOL query_result = MMI_FALSE, execute_result = MMI_FALSE; interrupt_event_hdlr int_func = NULL, post_int_func = NULL;mmi_frm_int_event_type current_frm_int_event;idx = mmi_frm_search_event(); / 遍历 protocolEventHandler 查找是否有event 注册了回调函数 / 虽然这个方法感觉比较笨,就一个数组,实际上对速度没有什么影响 for (count = 0; count 0) protocolEventHandlercount.eventID = protocolEventHandlercount - 1.eventID; protocolEventHandlercount.entryFuncPtr = protocolEventHandlercount - 1.entryFuncPtr; protocolEventHandlercount - 1.eventID = eventID; protocolEventHandlercount - 1.entryFuncPtr = (PsFuncPtr) currFuncPtr; break; / 这个就是查找是否是中断事件 current_frm_int_event = mmi_frm_interrupt_event_converter(eventID, MsgStruct); if (current_frm_int_event 0) / 查看该中断事件是否有 注册 提前处理函数 query_result = mmi_frm_query_interrupt_event_information(current_frm_int_event, &int_func, &post_int_func); / 如果有 调用该函数 if (query_result & int_func) /* New interruption mechanism */ execute_result = (*int_func)(current_frm_int_event); /根据 event 相应的回调函数 以及 前面处理的结果,来决定是否处理该事件 / 要注意的是,如果 interrput 提前处理函数 返回 true,那么 这里就不会执行 if (currFuncPtr) & (!interrup_result) & (!execute_result) (*currFuncPtr) (MsgStruct, mod_src, peerBuf); else MMI_TRACE(MMI_FW_TRC_G1_FRM, MMI_FRM_INFO_EVENT_EXECURPTO_NO_HDLR, eventID); / interrupt event 最后处理函数 if (query_result & post_int_func) execute_result = (*post_int_func)(current_frm_int_event); 看完这个,其实觉得挺简单的,对吧。就是一个数组,数组里关联了 event id 和 对应的处理函数。还有就是增加了一种 intrrupt event。可以注册这种event 的 pre_handler and post_handler。这样如果需要,可以提前做处理或者不响应该事件。M T K MMI event 小结 3昨天大概的说了下,普通 event 的执行过程。中间还有几个函数没有介绍,这里简单介绍一下/ 这个函数就是简单把 L4c 的interrupt消息,转换成 MMI 层interrupt的消息static mmi_frm_int_event_type mmi_frm_interrupt_event_converter(U16 event_id, void *msg) mmi_frm_int_event_type frm_interrupt_event = 0; switch (event_id) / GPIO 消息 case PRT_EQ_GPIO_DETECT_IND: mmi_eq_gpio_detect_ind_struct *gpio_detect_ind = (mmi_eq_gpio_detect_ind_struct *)msg; switch (gpio_detect_ind-gpio_device) / 翻盖关闭 case EXT_DEV_CLAM_CLOSE: frm_interrupt_event = MMI_FRM_INT_CLAM_CLOSE; break; / 翻盖打开 case EXT_DEV_CLAM_OPEN: frm_interrupt_event = MMI_FRM_INT_CLAM_OPEN; break; / 耳机插入 拔出 case EXT_DEV_EARPHONE: if (gpio_detect_ind-on_off = 1) frm_interrupt_event = MMI_FRM_INT_EARPHONE_PLUG_IN; else frm_interrupt_event = MMI_FRM_INT_EARPHONE_PLUG_OUT; break; break; / 充电信息, case PRT_BATTERY_STATUS_IND: mmi_eq_battery_status_ind_struct *battery_status_ind = (mmi_eq_battery_status_ind_struct*)msg; frm_interrupt_event = mmi_frm_get_frm_int_event_macro( battery_status_ind-battery_status, mmi_frm_int_event_battery_table, sizeof(mmi_frm_int_event_battery_table) / sizeof(mmi_frm_int_event_battery_table0); /* For low battery indication */ if (battery_status_ind-battery_status = PMIC_VBAT_STATUS) if (battery_status_ind-battery_voltage = BATTERY_LOW_WARNING) frm_interrupt_event = MMI_FRM_INT_BATTERY_LOW_WARNING; else if (battery_status_ind-battery_voltage = BATTERY_LOW_TX_PROHIBIT) frm_interrupt_event = MMI_FRM_INT_BATTERY_LOW_TX_PROHIBIT; break; case MSG_ID_TIMER_EXPIRY: case MSG_ID_MMI_EQ_POWER_ON_IND: case MSG_ID_MMI_EQ_KEYPAD_DETECT_IND: break; default: /其他 interrupt event,主要是弹出框相关,短信报告等等 frm_interrupt_event = mmi_frm_get_frm_int_event_macro( event_id, mmi_frm_int_event_convert_table, sizeof(mmi_frm_int_event_convert_table) / sizeof(mmi_frm_int_event_convert_table0); break; return frm_interrupt_event;这个函数就是把 L4C 的消息转换到 MMI 的消息,然后通过 mmi_frm_query_interrupt_event_information 这个函数去查找,是否有相应的注册。这个函数比较简单,就是数组里去比较。还有一个常用的函数是 SetProtocolEventHandler,也就是注册一个消息的地回调函数。具体也没有什么可说的,无非就是循环查找是否有这个 event。1,如果有,看func 是否为空,为空表示去掉这个event 的注册,不为空,就直接修改 这个event 的 func(定时器到时时所要实现的功能函数)2,没有,就增加一个event。这里注意,由一个小小的优化,就是判断,event 数组的最后是否为无效的 event,如果无效,那么减少总注册event 的个数。这个样可以减少 循环查询的次数。MTK MMI event 小结 4 今天打算说说key event。MTK的key envent 管理其实跟 MTK (MMI event小结2) 说的protocol event 机制也差不了多少,简单来说,就是app 通过注册某一个key 的回调函数,当这个key事件产生是,该机制就去找到相应的回调函数,进行回调。先说说key 的 event 有哪些:1 key down 按键按下 KEY_EVENT_DOWN2 key up 按键弹起 KEY_EVENT_UP3 key long press 按键长按 KEY_LONG_PRESS。默认好像是长按1.5 记不清楚了,可以自己设置,函数Kbd_SetLongPressTime,不过除非必不得已,不要去随便修改,可能会引起其他应用出问题,要修改,也要先获得当前值,退出应用时设置回原来的值。4 key repeat 按键按下一直不放,发送该消息 KEY_REPEAT。 举个简单例子,pc 上当输入时,如果长按 a 键,那么回不停的增加a,这个就是repeat动作。这个的时间好像是0.5s,也就是按住键 0.5 s 之后,每隔0.5s,就会发送一个repeat 消息。设置函数Kbd_SetRepeatTime还有两个不常用的 KEY_HALF_PRESS_DOWN和KEY_HALF_PRESS_UP,也就是说的 2step 可以。先讲一下按键的处理流程。当按键被按键之后,MMI task 会收到 MSG_ID_MMI_EQ_KEYPAD_DETECT_IND这个消息,在系统初始化的时候,已经注册了这个消息的处理函数 mmi_frm_key_handle。也就是说 mmi_frm_key_handle 是处理按键过程的函数。这个函数 mmi_frm_key_handle 收到这个消息后,会 通过 该消息带的函数,去取当前发生的按键事件(实际这个函数就是一个按键缓存队列里去第一个,用一个按键缓存队列,可以防止按键大量的丢失,可以起到同步驱动和MMI层,驱动产生按键事件很快而MMI有可能比较慢,可以简单的理解为生产者和消费者的关系,跑题了 )。 取到当前按键后,看当前是否可以进行操作,比如是否有触摸笔按下等等。MTK MMI event 小结 5 昨天说了一下key event 的基本情况,今天直接从代码开始吧先看执行key event 函数 mmi_frm_key_handlevoid mmi_frm_key_handle(void *paraBuff) kbd_data k; U32 msg_count; mmi_eq_keypad_detect_ind_struct *p; / 判断参数是否为空 / 在 初始化时,系统就注册了 MSG_ID_MMI_EQ_KEYPAD_DETECT_IND 的回调函数为 mmi_frm_key_handle / 当收到这个消息是,表示有按键事件要处理, / 这个paraBuff 是 keyTask 传过来的参数,里面的内容是获取按键信息的函数指针 if (paraBuff != NULL) drv_get_key_func new_key_ptr; p = (mmi_eq_keypad_detect_ind_struct*) paraBuff; new_key_ptr = (drv_get_key_func) (p-func); /判断是否是新的函数指针,如果是的话,需要进行一些清理工作 if (new_key_ptr != keypad_ptr) / 新的函数指针,则进行清理,并且判断是否有按键需要处理 if (!mmi_kbd_process_keyptr_change(void *)new_key_ptr) return; /清理 按键 事件缓存buffer ClearKeyEvents(); keypad_ptr = new_key_ptr; / 通过 while (1)来不停的从按键缓存里获取按键信息 / 当然这里不会无限死循环,后面会进行相应处理 while (1) /1)判读是否是挂起,2)是否key需要处理 if (g_mmi_suspend_key_flag = MMI_FALSE) & keypad_ptr &(*(keypad_ptr)(&k) = MMI_TRUE) if (k.Keydata0 != KEY_INVALID) #if defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) kal_bool is_pen_enabled, is_pen_down; / 获得触摸屏状态 mmi_pen_get_state(&is_pen_enabled, &is_pen_down); #endif /* defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) */ #if defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) /如果触摸屏按下,那么保存状态 if (is_pen_down & (k.Keyevent = WM_KEYPRESS) U16 KeyMapIndex; / 不允许 按键处理 is_allow_key_action = MMI_FALSE; / 把驱动的按键和MMI 按键进行转换 KeyMapIndex = mmi_frm_get_idx_from_device_key_code(k.Keydata0); if (nKeyPadStatusKeyMapIndex = KEY_EVENT_UP) KEYBRD_MESSAGE KeyBrdMsg; KeyBrdMsg.nKeyCode = nKeyPadMapKeyMapIndex.nMMIKeyCode; if (mmi_frm_is_2step_keyCode(KeyBrdMsg.nKeyCode) nKeyPadStatusKeyMapIndex = KEY_HALF_PRESS_DOWN; pressKey = HALF_DOWN_STATUS; key_is_pressing_count+; else nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN; pressKey = FULL_DOWN_STATUS; key_is_pressing_count+; else #endif /* defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) */ /如果按键是弹起,那么还原原来按键状态,也就是弹起状态 if (k.Keyevent = WM_KEYRELEASE) & (is_allow_key_action = MMI_FALSE) #if defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) /* Reset allow key flag and Update key status even if pen is down*/ U16 KeyMapIndex; KeyMapIndex = mmi_frm_get_idx_from_device_key_code(k.Keydata0); if (nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN) | (nKeyPadStatusKeyMapIndex = KEY_HALF_PRESS_DOWN) | (nKeyPadStatusKeyMapIndex = KEY_LONG_PRESS) | (nKeyPadStatusKeyMapIndex = KEY_REPEAT) nKeyPadStatusKeyMapIndex = KEY_EVENT_UP; key_is_pressing_count-; prevKeyMapIndex = prevKeyMapIndex; #endif /* defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) */ is_allow_key_action = MMI_TRUE; / 按键是否可以处理 if (is_allow_key_action = MMI_TRUE) if (k.Keyevent = WM_KEYPRESS) & (mmi_kbd_get_key_is_pressing_count() = 0) | k.Keyevent = DRV_WM_KEYLONGPRESS | k.Keyevent = DRV_WM_KEYREPEATED | k.Keyevent = DRV_WM_KEYFULLPRESS) #if defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) /关闭触摸屏 mmi_pen_disable(); #endif /真正处理按键事件 mmi_frm_convert_process_key_event(k.Keyevent, k.Keydata0); if (k.Keyevent = WM_KEYRELEASE) & (mmi_kbd_get_key_is_pressing_count() = 0) #if defined(_MMI_TOUCH_SCREEN_) | defined(_MMI_HANDWRITING_PAD_) /重新打开触摸屏 mmi_pen_enable(); #endif / 获得MMI task 消息队列消息个数 msg_get_ext_queue_info(mmi_ext_qid, &msg_count); /如果外部有消息或者内部消息,则跳出该循环 if (msg_count 0 | OslNumOfCircularQMsgs() 0) /表示还有key需要处理,在MMI task 里会直接调用这个函数进行再处理 g_keypad_flag = MMI_TRUE; break; else / 没有key消息要处理 g_keypad_flag = MMI_FALSE; break; /* while(1) */ MMI_TRACE(MMI_FW_TRC_G1_FRM, MMI_FRM_KEY_HDLR_END);1) 这里key 用while (1)来处理,不停的从key 消息buffer里取出按键信息,然后处理,这么做可以防止task中不停的发送消息,可以理解为共享内存。同样当有其他消息来时,需要跳出来处理其他消息,处理完毕后还需要再来处理。2)这里跟触摸屏的事件进行了冲突处理,也就是按键和触摸屏不能同时工作,这两者也没有优先级。3)实际真正处理按键 是在 mmi_frm_convert_process_key_event里面,下次在分析MTK MMI event 小结 6在 MTK MMI event 小结 5 中,提到了event 处理函数 mmi_frm_key_handle,这个函数主要作用是判断是否需要处理按键,从按键缓存里面持续的读取按键信息,然后调用 mmi_frm_convert_process_key_event 进行处理。这个函数没有什么可说的,最多是在屏幕旋转的情况下,把 导航键 转换一下,接着它调用了 ProcessKeyEvent, 这个函数主要是对于一些状态的处理,防止key down 和up 不成对,出现混乱。void ProcessKeyEvent(U32 MsgType, U16 DeviceKeyCode) MMI_BOOL isKeyPaired; U16 KeyMapIndex; /*-*/ /* Code Body */ /*-*/ / 按键影射,把驱动的按键码,转换成MMI 的按键消息 KeyMapIndex = mmi_frm_get_idx_from_device_key_code(DeviceKeyCode); if (KeyMapIndex = MAX_KEYS) return; / 处理各种按键事件,没有什么可以多说的, / 主体结构都一样, / 1 判断状态是否正常 / 2 正常 则调用 KeyEventHandler 处理, 否则忽略该事件 if (MsgType = WM_KEYPRESS) / 这里处理 多按键同时按下的情况。这里需要硬件支持 if (KeyMapIndex != prevKeyMapIndex) & (g_kbd_concurrent_key_mode = CONCURRENT_KEY_MODE_1_KEY) isKeyPaired = (nKeyPadStatusprevKeyMapIndex = KEY_EVENT_UP); prevKeyMapIndex = KeyMapIndex; /判断案件状态是否正常,防止不匹配 if (nKeyPadStatusKeyMapIndex = KEY_EVENT_UP) KEYBRD_MESSAGE KeyBrdMsg; KeyBrdMsg.nKeyCode = nKeyPadMapKeyMapIndex.nMMIKeyCode; if (mmi_frm_is_2step_keyCode(KeyBrdMsg.nKeyCode) nKeyPadStatusKeyMapIndex = KEY_HALF_PRESS_DOWN; key_is_pressing_count+; KeyBrdMsg.nMsgType = KEY_HALF_PRESS_DOWN; else nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN; /* same with KEY_FULL_PRESS_DOWN */ key_is_pressing_count+; KeyBrdMsg.nMsgType = KEY_EVENT_DOWN; / 处理按键事件 KeyEventHandler(KEYBRD_MESSAGE*) & KeyBrdMsg); else /* Ignore the event */ else if (MsgType = WM_KEYRELEASE) if (nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN) | (nKeyPadStatusKeyMapIndex = KEY_LONG_PRESS) | (nKeyPadStatusKeyMapIndex = KEY_REPEAT) | (nKeyPadStatusKeyMapIndex = KEY_HALF_PRESS_DOWN) KEYBRD_MESSAGE KeyBrdMsg; nKeyPadStatusKeyMapIndex = KEY_EVENT_UP; key_is_pressing_count-; KeyBrdMsg.nMsgType = KEY_EVENT_UP; KeyBrdMsg.nKeyCode = nKeyPadMapKeyMapIndex.nMMIKeyCode; KeyEventHandler(KEYBRD_MESSAGE*) & KeyBrdMsg); else /* Ignore the event */ /* +Robin, modified by Max Chen */ else if (MsgType = DRV_WM_KEYLONGPRESS) if (nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN) KEYBRD_MESSAGE KeyBrdMsg; nKeyPadStatusKeyMapIndex = KEY_LONG_PRESS; KeyBrdMsg.nMsgType = KEY_LONG_PRESS; KeyBrdMsg.nKeyCode = nKeyPadMapKeyMapIndex.nMMIKeyCode; KeyEventHandler(KEYBRD_MESSAGE*) & KeyBrdMsg); else /* Ignore the event */ else if (MsgType = DRV_WM_KEYREPEATED) if (nKeyPadStatusKeyMapIndex = KEY_LONG_PRESS) | (nKeyPadStatusKeyMapIndex = KEY_REPEAT) KEYBRD_MESSAGE KeyBrdMsg; nKeyPadStatusKeyMapIndex = KEY_REPEAT; KeyBrdMsg.nMsgType = KEY_REPEAT; KeyBrdMsg.nKeyCode = nKeyPadMapKeyMapIndex.nMMIKeyCode; KeyEventHandler(KEYBRD_MESSAGE*) & KeyBrdMsg); else /* Ignore the event */ else if (MsgType = DRV_WM_KEYFULLPRESS) /* * Only in two-stage ke
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GSNOR-IN-1-生命科学试剂-MCE
- 2025福建泉州晋江国际机场招聘25人模拟试卷及答案详解(新)
- 安全培训效果评价计划课件
- 2025吉林农业大学招聘高层次人才7人模拟试卷及参考答案详解1套
- 广州货架安全管理培训课件
- 2025年第2批次浙江宁波前湾产业集团有限公司招聘9人考前自测高频考点模拟试题及完整答案详解
- 首饰产品质量承诺书6篇
- 智能制造产业智能化生产
- 2025福建泉州市安溪县部分公办学校专项招聘编制内新任教师65人(三)考前自测高频考点模拟试题及参考答案详解
- 直播带货合伙人合同协议书5篇
- 5.15 探寻新航路 课件 2024-2025学年部编版九年级历史上学期
- 联合投标协议书新(2024版)
- 新《主体结构及装饰装修》考试习题库大全-中(多选题)
- 长期护理机构照护服务记录表(护理员用表)2-4-5
- 2024年江苏省射阳县事业单位招聘35人历年高频考题难、易错点模拟试题(共500题)附带答案详解
- 产品营销市场调查报告
- 传奇地图编号
- 宠物用品授权书
- GB/T 1504-2024铸铁轧辊
- 食品行业创新与研发
- 电力各种材料重量表总
评论
0/150
提交评论