资源描述
开发归档
mtk学习开发归档01
1.1. 各模块功能
Application layer: 包含用户定义的应用程序
Framework layer: 包含消息处理和事件操作。。
UI Layer: 包含ui相关联的函数
MMI Queue: 协议栈/L4将事件写入其中,MMI Task从中读取事件。
L4/NS Queue: MMI Task将事件写入其中,L4 task/Network Simulator从中读取事件。
MMI Task执行流程:
1. 等待消息事件发送给MMI 队列
2. MMI 队列中的消息由协议占发送
3. Framework层执行事件。
4. Framework层出发应用层的回调函数
应用层对接收事件做出回应
(以按键事件为例子)
1.1. L4 -> MMI Task
说明:
1. 协议占向MMI Queue中写入事件
2. MMI Task从MMI Queue中读取
Framework层为最新注册事件调用回调函数
应用层接收到按键事件并做出回应
1.1. MMI->L4
(应用程序发送播放声音请求)
说明:
1.应用层向framework层发送请求,使其向L4队列传送信息
2.Framework将消息写入L4队列
3.L4从L4队列中读取事件并播放请求的声音
1.1.1. Framework 层
1. 为应用程序提供事件句柄API来管理事件句柄
键盘事件句柄API
协议事件句柄API
Misc.Handlers
- Exit Handlers
Set Exit handlers for particular screen
Execute Exit handler for current screen
Clear Crrent Exit Handler
2. History API
3. Queue API
- Create Queue
oslMsgqid OslIntCreateMsgQ(PS8 queue_name,U32 max_msg_size,U32 max_msgs)
- Write to Queue
OSLSTATUS OslIntWriteMsgQ(oslMsgqidmsgqid,void *msgPtr,U32 msgSize, OSLWAITMODE wait_mode)
- Read from Queue
OSLSTATUS OslIntReadMsgQ(oslMsgqidmsgqid,void *msgPtr, U32 *msgSize,OSLWAITMODE wait_mode)
1.1.2. UI 层
2. 窗口函数
Function to enter : void ShowCategoryXScreen(argument list);
Function to exit : void ExitCategoryXScreen(void);
Function to get the size of history : BYTE* GetCategoryXHistory(BYTE* buffer);
Function to get the history : INT GetCategoryXHistorySize(void);
ShowCatagoryXXXScreen
注册事件句柄
预处理UI元素
- 调用重绘函数
RedrawCategoryXXXScreen
- 使用GDI函数绘制窗口
ExitCategoryXXXScreen
- 重新设置函数指针
其他操作依据不同的窗口而定
GetCategoryXXXHistorySize
- 用来返回gui buffer和input buffer的大小
GetCategoryXXXHistory
- 用来返回gui buffer和input buffer的数据
GetCategoryXXXData
- 用来返回input buffer
- 改变softkey labels
Void ChangeLeftSoftkey(STRING_ID s,IMAGE_ID i);
Void ChangeRightSoftkey(STRING_ID s, IMAGE_ID i);
- 改变softkey functions
Void SetLeftSoftkeyFunction(void(*f)(void),KEY_EVENT_TYPE k);
Void SetRightSoftkeyFunction(void(*f)(void),KEY_EVENT_TYPE k);
- 在菜单中获得高亮显示项
INT GetHighlightedItem(void); 设置高亮显示效果
Void SetHighlightedItem(INT item_index); 注册高亮显示句柄
Void RegisterHighlightHandler(void(*fptr)(INT item_index)); 移除高亮显示句柄
Void ClearHighlightHandler(void);
书写应用程序
- 资源
在PixtelDataTypes.h中定义APP_BASE
定义各种资源 ID
Screens
Strings
Images
Menu Items (GlobalMenuItem.h)
书写资源生成函数
Resource Generator(PopulateRes.c)调用
使用宏定义ADD_APPLICATION_XXX
修改ResGenerator的”Makefile”和”readexcel.c”
- Make file
在make file中添加关键宏定义
在 MMI_features$Proj.h中添加feature macro
添加库文件(COMPOBJS)
添加编译列表
创建目录 in mcu\make
添加目录名到CUS_REL_SRC_COMP
- Initialization
初始化函数
1. InitializeAll(Not all)
在现有工程主要工作:
<1.> ADD_APPLICATION (AddApp函数)在framework中来添加新的
应用程序。
void AddApp(U32 nId, S8 *pName, U16 nMinId, U16 nMaxId)
<2.> PopulateXXX :为各个应用程序加载其各种资源(字符串,图片,菜单项)
2. 初始化各种事件句柄
高亮显示句柄
协议事件句柄
- Entry and Exit
标准入口函数
调用执行当前的退出句柄
获得当前窗口的GUI buffer
获得窗口显示元素
注册高亮显示句柄
调用窗口函数绘制窗体
设置退出句柄
标准出口函数
创建History 节点
将入口函数保存入History节点中
填充输入buffer和History 节点中的GUI buffer
保存history
高亮句柄
改变左键和右键句柄
mtk学习开发归档02
1. MMI 和L4通信
1.1. 如何通信
Send/Receive messages thru the message Queue.
#define OslMsgSendExtQueue msg_send_ext_queue
#define OslReceiveMsgExtQ receive_msg_ext_q
SetProtocolEventHandler(FuncCB, msg_id);
1.2. 通信数据
typedef struct ilm_struct {
oslModuleType oslSrcId; // Source module ID.
oslModuleType oslDestId; // Destination module ID.
oslMsgType oslSapId; // service access point.
oslMsgType oslMsgId; // message name ID.
oslParaType *oslDataPtr; //local parameter buffer
oslPeerParaPtr *oslPeerBuffPtr; //peer buffer pointer
} ilm_struct;
1.3. 如何从MMI Queue中侦听消息
OslReadCircularQ(&Message);
OslReceiveMsgExtQ(mmi_qid, &mmi_message);
1.4. 如何在MMI 队列中写入消息
当NVRAM接收到其他消息时:
OslWriteCircularQ(&ilm_ptr);
1.5. 如何从L4C接听消息
注册一个消息回调函数
SetProtocolEventHandler(FuncCB, msg_id);
1.6. 如何向L4C 发送消息
2. 构建一个本地参数指针
3. 将请求数据填充进本地参数指针中。
4. 给结构体ilm_struct赋值。
5. 向L4C发送消息。
消息信息 = 头信息 + 数据信息
Local parameter Header info:
#define LOCAL_PARA_HDR \
kal_uint8 ref_count; \
kal_uint16 msg_len;
peer buffer parameter Header info :
#define PEER_BUFF_HDR \
kal_uint16 pdu_len; \
kal_uint8 ref_count; \
kal_uint8 pb_resvered; \
kal_uint16 free_header_space; \
kal_uint16 free_tail_space;
2.7. 本地参数:(local parameter)
Header info + Data info:
例如:
typedef struct {
LOCAL_PARA_HDR
kal_uint8 volume_type;
kal_uint8 volume_level;
} mmi_eq_set_volume_req_struct;
2.8. 如何创建本地参数:(动态分配内存)
OslConstructDataPtr(sizeof(mmi_at_alarm_query_res_req_struct);
2.9. 何时释放本地参数
当L4接收到消息并处理完成后,会自动释放参数。
OslFreeDataPtr(sizeof(mmi_at_alarm_query_res_req_struct);
Peer buffer parameter:
Header info + Data info
Ex: typedef struct {
PEER_BUFF_HDR
void *ptr;
} mmi_example;
mtk学习开发归档03
如何创建Peer buffer parameter:(动态分配内存)
MMI 不使用 this buffer 和L4通信
construct_peer_buff(pdu_len, header_len, tail_len, direction);
3.1. 何时释放Peer buffer parameter
当L4接收到消息并处理完成后,会自动释放参数。
free_peer_buff(peer_buff);
例程如下:
Set a volume request:
void SetVolumeLevelReq(volume_type_enum volume_type,U8 volume_level)
{
MYQUEUE Message;
mmi_eq_set_volume_req_struct *setVolumeLevelReq;
Message.oslMsgId = MSG_ID_MMI_EQ_SET_VOLUME_REQ;
//Message ID, reference the l4a.h file
setVolumeLevelReq = OslConstructDataPtr(sizeof(mmi_eq_set_volume_req_struct));
//Create local parameter buffer
setVolumeLevelReq->volume_type = volume_type;
setVolumeLevelReq->volume_level = volume_level;
Message.oslDataPtr = (oslParaType *)setVolumeLevelReq; //Local parameter buffer
Message.oslPeerBuffPtr= NULL; //Peer parameter buffer
Message.oslSrcId=MOD_MMI; //Send from Source module
Message.oslDestId=MOD_L4C; //Send to destination module
OslMsgSendExtQueue(&Message); //Send to L4 task
}
每个功能的具体实现(比如说播放音频)都会定义mmi_xxxxx_reg_sturct形式结构体
结构体组成:Header info + Data info:
例如(请求播放音频):
typedef struct
{
LOCAL_PARA_HDR //头信息(Header info)
kal_uint8 sound_id;
kal_uint8 style; /* audio_play_style_enum */
} mmi_eq_play_audio_req_struct;
3.2. 通信数据
#define MYQUEUE ilm_struct
typedef struct ilm_struct {
oslModuleType oslSrcId; // Source module ID.
oslModuleType oslDestId; // Destination module ID.
oslMsgType oslSapId; // service access point.
oslMsgType oslMsgId; // message name ID.
oslParaType *oslDataPtr; //local parameter buffer
oslPeerParaPtr *oslPeerBuffPtr; //peer buffer pointer
} ilm_struct;
3.3. 示例代码
{
MYQUEUE Message;
mmi_eq_play_audio_req_struct *audioPlayReq;
//create local parameter buffer
audioPlayReq = OslConstructDataPtr(sizeof(mmi_eq_play_audio_req_struct));
audioPlayReq->sound_id = (U8) soundId;
audioPlayReq->style = 2; /* style; */
audioPlayReq->identifier = (U16) soundId;
Message.oslMsgId = PRT_EQ_PLAY_AUDIO_REQ; //message id,reference the l4a.h
Message.oslDataPtr = (oslParaType*) audioPlayReq; //local parameter buffer
Message.oslPeerBuffPtr = NULL; //Peer parameter buffer
Message.oslSrcId = MOD_MMI; //Send from Source module
Message.oslDestId = MOD_L4C; //Send to destination module
OslMsgSendExtQueue(&Message); //Send to L4 task
}
1. Network simulator 分析
MMI : Man machine Interface
PMS : Pixtel MMI Simulator
NWS : Network Simulator (MMINWSimulator)
DTD : Document Type Definition
XML : Extensible Markup Language
1.1. 模拟协议栈
1.1.1.
PMS
NWS
XML
(Sends Automatic and
Manual Messages)
Plugins
Data File
Icoming messages
Outgoing messages
Asvc Events
Via File I/O
Calls
Return data
Message Flow
1.1.2. NetWork Simulator任务
1. 联系NWS 和 PMS,模拟MMI 和 协议栈之间的通讯
2. 在数据文件中存储数据来模拟Flash中的数据存储
1.1.3. NWS 同 PMS通讯方式
NWS 同 PMS之间通过三种方式通信
1. 接收从PMS发送给NWS的 incoming messages 例如,拨号请求
2. 对incoming message从NWS发送outgoing message到PMS 例如,获得电话薄入口请求
3. 从NWS发送异步消息到PMS 例如,Boot Up等。
资源的添加
菜单资源
1. 菜单ID : 如ORGANIZER_CALENDER_MENU,这个即是一个菜单的id也就是名字,但要把这个菜单加入到某个父菜单之下,则须指定其父菜单,方式可以参照:ORGANIZER_CALENDER_MENU这个菜单的方法,在res_mainmenu.c里,
ADD_APPLICATION_MENUITEM((MAIN_MENU_ORGANIZER_MENUID,IDLE_SCREEN_MENU_ID,ORG_ENUM_TOTAL,
#if defined(__MMI_CALENDAR__)
ORGANIZER_CALENDER_MENU,
#endif
#if defined(__MMI_TODOLIST__)
ORGANIZER_TODOLIST_MENU,
#endif
ORGANIZER_ALARM_MENU,
#if defined (__MMI_WORLD_CLOCK__)
ORGANIZER_WORLDCLOCK_MENU,
#endif
#ifdef __MMI_MESSAGES_CLUB__
MAIN_MENU_SHORTCUTS_MENUID,
#endif
#ifdef __SLT_LONG_DISTANCE_DDD__
MENU_LONG_DISTANCE_DDD,
#endif
SHOW,MOVEABLEACROSSPARENT,DISP_LIST,
MAIN_MENU_ORGANIZER_TEXT,MAIN_MENU_ORGANIZER_ICON));
这个语句说明菜单ORGANIZER_CALENDER_MENU是菜单MAIN_MENU_ORGANIZER_MENUID的子菜单。而在res_organizer.c里,
ADD_APPLICATION_MENUITEM((ORGANIZER_CALENDER_MENU,MAIN_MENU_ORGANIZER_MENUID,
3,
MENU_GOTO_TASK_CAL,
MENU_ID_CLNDR_JUMP_TO_DATE,
MENU_CAL_TYPE,
SHOW,
MOVEABLETOSHORTCUT,DISP_LIST,
ORGANIZER_MENU_CALENDER_STRINGID,ORGANIZER_MENU_CALENDER_IMAGEID));
这个语句则声明了ORGANIZER_CALENDER_MENU菜单所拥有的子菜单。
关于宏ADD_APPLICATION_STRING2()、ADD_APPLICATION_MENUITEM()可以参考文件Writing Applications Using Pixtel MMI Platform.pdf
更深入的了解可以查看文件夹Document\MMI Design Documents\Pixtel下的文件。
总结:
1、在GlobalMenuItems.h中添加一个菜单ID
例如:#ifdef SWITCH
MENU_ID_FIRST_APP,
#endif
extraResDefs.h:
STR_ID_FIRST_APP//定义字符资源ID
2、在对应的res_XXX.c(如Res_extra.c)文件中添加菜单资源所用函数为:ADD_APPLICATION_MENUITEM()
参数为:
第一个参数: 菜单本身的ID
第二个参数: 父菜单的ID(ref_list.txt中找)
第三个参数: 子菜单的个数
(如果子菜单数不位0,应把子菜单ID依次列出,形如:ID1,ID2,.....)
第四个参数:SHOW或隐藏
第五个参数:菜单的flags 可以Copy
第六个参数:菜单的风格 DISP_LIST等
第七个参数:字符串资源的ID
第八个参数:图片资源的ID
3、搜索父菜单的ID,在父菜单的资源的ADD_APPLICATION_MENUTIEM()中的第三个参数加一,并且列举出菜单的ID
4、添加字符串资源和图片资源,所用函数为:ADD_APPLICATION_STRING2()和ADD_APPLICATION_IMAGE2()
参数一:资源的ID
参数二:默认显示的字符(一般为英文解释)
参数三:描述
5、多国语言:打开..\plutommi\Customer\CustResource\PLUTO_MMI下的ref_lis.text
在末尾添加 形如:
STR_ID_VRSI_DELETE_QUESTION VRSI 20 Delete? Delete? 刪除? 删除?
具体为:
字符串ID 所属程序 长度 描述 英文 繁体中文 简体中文
它们之间用Tab键隔开,如果不确定 可以用Excel打开
二.异同(ADD_APPLICATION_MENUITEM()和 ADD_APPLICATION_MENUITEM2())
MTK添加菜单有两个宏
ADD_APPLICATION_MENUITEM()
ADD_APPLICATION_MENUITEM2()
他们之间有什么区别呢?
首先是结构不同:
ADD_APPLICATION_MENUITEM 需要要指明子菜单个数。例如下面第三个参数为子菜单个数
ADD_APPLICATION_MENUITEM((MENU_BARRING_OPTION,
0, 3,
MENU_BARRING_ACTIVATE,
MENU_BARRING_DEACTIVATE,
MENU_BARRING_QUERY, SHOW, NONMOVEABLE, DISP_LIST, STR_MENU_BARRING_OPTION, NULL));
ADD_APPLICATION_MENUITEM2 不需要指明子菜单个数,子菜单结尾处加一个MENU_ITEM_END标示子菜单项结束。例如
ADD_APPLICATION_MENUITEM2((MENU_ID_UCM_INCALL_OPTION_NEW_CALL, MENU_ID_UCM_INCALL_OPTION,
MENU_ID_UCM_INCALL_OPTION_NEW_CALL_VOICE,
#ifdef __MMI_VOIP__
MENU_ID_UCM_INCALL_OPTION_NEW_CALL_VOIP,
#endif /* __MMI_VOIP__ */
MENU_ITEM_END,
SHOW, MOVEABLEWITHINPARENT, DISP_LIST,
STR_ID_UCM_NEW_CALL,0));
用法上需要注意什么呢?
ADD_APPLICATION_MENUITEM() 任何地方都可以使用。一般用于固定个数不变的菜单。还有叶子菜单(即最底层菜单)。
ADD_APPLICATION_MENUITEM2() 必须要包含子菜单,不能用于叶子菜单。它最大的一个作用是用于动态的菜单。我们知道MTK有个features_switch 里面有好多宏开关,根据宏开关变化 一些菜单也需要改变,这就用到了ADD_APPLICATION_MENUITEM2(), 因为它没有规定子菜单的个数。
三.添加string资源:
首先给该字符串起一个名字,即ID:如STR_GLOBAL_OK,这个即是一个字串的id也就是名字,而这个字串的具体内容(比如STR_GLOBAL_OK的内容是“Ok”),可以用下面的语句来添加:
ADD_APPLICATION_STRING2(STR_GLOBAL_OK, "Ok","Global String- OK");
如果有对应的中文字符,则应在ref_list.txt中按照固定的格式添加中文字串。如:
STR_GLOBAL_OK GLOBAL 6 Global String- OK Ok 確定 确定
1. GlobalDefs.h 中增加ID
2. population.c 中将ID和 string关联
3. plutommi\Customer\CustResource\PLUTO_MMI\ref_list.txt 中增加ID 和各种语言的文本
有了以上3个步骤,即可使用该文本资源了。
编译后,在 plutommi\Customer\CustResource下面 会生成新的
CustStrMap.c 和
CustStrRes.c
这两个文件中就包含了新增的string资源
总结:MMI字符串资源的加入:
1)在ref_list.txt中加入字符串。
2)把字符串ID加入到ID枚举中。
3)使用ADD_APPLICATION_STRING2来加入字符串。
4)使用GetString()获得字符串。
5)使用APP_BASE来保证字符串ID的唯一性
四.加减文件
开发过程中,少不了加减文件, 删除文件实际上是添加文件的相反过程,因此略过。
MTK设置了很多lst 和 pth 文件供用户添加文件,这些都在make文件夹下。用户可以自己添加模块,也可利用原有的lst 和 pth 文件添加。以下以添加在 MTK\make\plutommi 为例:
添加头文件路径:
plutommi.inc
添加本模块路径:
plutommi.pth
添加源文件路径:
plutommi.lis
添加完毕,这些文件就可参与编译了。
添加开关:
开关真是个好东西。依靠它,可以将没有价值的功能瞬间屏蔽,又可以将我们需要但又搁置的功能瞬间启用。能者上,不能者下,多么类似于社会法则。
添加开关 在make文件夹下面的 .mak文件里面。
注意事项:
有人喜欢模仿MTK原做法,在 .mak文件里面使用一个开关管住另外一个开关。那么两个开关不要同名,否则开关起不了关闭的作用。
添加资源与菜单
下面是在6235平台下进行的,其他平台可能代码名称有不同,具体添加方式参考同文件中其他代码的写法就好了,其实MTK的代码需要改动的很少,就是在里面添添,不知道怎么添的时候就参考内部代码。
第一步:添加程序文件:先假设自己写的程序的名字为MyApp
需要添加有:MyAppProt.h (用来存放本程序的所有函数申明,此头文件只被本程序的源文件所加载)
MyAppDefs.h (用来存放本程序的一些普通的资源ID定义)
MyAppTypes.h (用来存放本程序所需的类型,结构,常量定义)
MyAppGprot.h (也是用来存放函数申明的,但是此头文件是被别的程序所加载的,也就是说此文件所申明的都是对外接口)
当然还有源文件MyAppSrc.c
注:以上这些头文件一般放在plutommi\MMI\MyApp\MyAppInc下面,这样方便代码管理
第二步:将文件加入项目
在make\plutommi\下面的三个文件需要修改
1:plutommilis 所需编译的源文件
2:plutommiinc 指明头文件所在目录
3:plutommipth 指明源文件所在目录
第三步:程序开关:
MMI的编译开关一般都放在plutommi\customer\custResource\PLUTO_MMI\MMI_features_switchPLUTO.h中
如下添加:#define _MMI_MYAPP_ (_ON_)
当添加了如上的代码后,在其他文件中的#ifdef _MMI_MYAPP_
.............
.............
#endif
所包围的代码就会被编译。
第四步:为资源添加ID
做完以上三步后,接下来就是添加ID了,资源有很多种,所以添加ID的方式有一些不同
(1)添加基础ID。
在加ID之前先得为本程序添加一个基础ID,因为所有程序的资源ID都是各自为政定义各自的,但这些ID又不能冲突,(因为每种类型的资源ID都是在一个取值空间),所以我们需要基础ID将每个程序的ID取值隔离开来,基础ID为某类资源定义了一个范围,统一定义在plutommi\MMI\INC\MMIDataType.h中
具体就看两个宏定义
/*
* Use this macro two to declare resource id range between RESOURCE_BASE_ENUM_BEGIN()
* and RESOURCE_BASE_ENUM_END()
*/
#define RESOURCE_BASE_RANGE(ap_id, count) \
ap_id, \
GET_RESOURCE_BASE(ap_id) = ap_id, \
GET_RESOURCE_MAX(ap_id) = ap_id + count – 1
/*
* Use these tow macro to get the resource base and resource end
*/
#define GET_RESOURCE_BASE(id) RESOURCE_BASE_##id
#define GET_RESOURCE_MAX(id) RESOURCE_BASE_##id##_END
这样首先通过语句 RESOURCE_BASE_RANGE(ap_id, count) 就可以设定资源 ID的范围,
同时GET_RESOURCE_BASE(ap_id)把ap_id赋给RESOURCE_BASE_##id,
最后再通过类似的语句
#
展开阅读全文