一、如何在MiniGUI中添加新的IAL引擎:(假设新的IAL引擎为_NAME_IAL)
例如:(ial.c文件中)
A)#ifdef _NAME _IAL
#include "NAME.h"
#endif
B)在input数组中添加
#ifdef _NAME _IAL
{"NAME ", InitNAMEInput, TermNAMEInput},
#endif
二、如何编写IAL引擎:
1.在MiniGUI中引入了输入抽象层(InputAbstractLayer ,IAL)的概念,它大大提高了MiniGUI的可移植性。
2.IAL是定义的一组不依赖于任何特殊硬件的抽象接口。而我们这里所说的IAL引擎则是对IAL定义的抽象接口的实现的底层代码。
3.IAL接口对下是IAL引擎,这些引擎使用了输入设备驱动提供的一些函数;对上则是应用程序或是GDI,上层MiniGUI库中ParseEvent()函数将通过这些IAL引擎将收集到的鼠标键盘事件转换为MiniGUI中的消息。
4.MiniGUI IAL结构如下:
在代码实现上,MiniGUI通过INPUT数据结构来表示输入引擎
typedef struct tagINPUT
{
char*id;
// Initialization and termination
BOOL (*init_input) (struct tagINPUT *input, const char* mdev, const char* mtype);
void (*term_input) (void);
// Mouse operations
int(*update_mouse) (void);
void (*get_mouse_xy) (int* x, int* y);
void (*set_mouse_xy) (int x, int y);
int(*get_mouse_button) (void);
void (*set_mouse_range) (int minx, int miny, int maxx, int maxy);
void (*suspend_mouse) (void);
int (*resume_mouse) (void);
// Keyboard operations
int(*update_keyboard) (void);
const char* (*get_keyboard_state) (void);
void (*suspend_keyboard) (void);
int (*resume_keyboard) (void);
void (*set_leds) (unsigned int leds);
// Event
#ifdef _LITE_VERSION
int (*wait_event) (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,
struct timeval *timeout);
#else
int (*wait_event) (int which, fd_set *in, fd_set *out, fd_set *except,
struct timeval *timeout);
#endif
char mdev [MAX_PATH + 1];
}INPUT;
extern INPUT* cur_input;
系统启动后,将根据配置文件寻找特定的输入引擎作为当前的输入引擎,并对全局变量cur_input(表当前使用的输入引擎)赋值。为书写方便,定义了当前引擎的C语言宏。
#define IAL_InitInput(*cur_input->init_input)
#define IAL_TermInput(*cur_input->term_input)
#define IAL_UpdateMouse(*cur_input->update_mouse)
#define IAL_GetMouseXY(*cur_input->get_mouse_xy)
#define IAL_GetMouseButton(*cur_input->get_mouse_button)
#define IAL_SetMouseXYif (cur_input->set_mouse_xy) (*cur_input->set_mouse_xy)
#define IAL_SetMouseRangeif (cur_input->set_mouse_range) (*cur_input->set_mouse_range)
#define IAL_SuspendMouseif (cur_input->suspend_mouse) (*cur_input->suspend_mouse)
#define IAL_UpdateKeyboard(*cur_input->update_keyboard)
#define IAL_GetKeyboardState(*cur_input->get_keyboard_state)
#define IAL_SuspendKeyboardif (cur_input->suspend_keyboard) (*cur_input->suspend_keyboard)
#define IAL_SetLeds(leds)if (cur_input->set_leds) (*cur_input->set_leds) (leds)
5.我们编写IAL引擎要做的就是在_NAME_IAL.c中实现输入引擎结构中定义的这些函数。如:_NAME_IAL.c:
#include ………
…………..变量定义
/************************ Low Level Input Operations **********************/
mouse_update()
{
……………
}
mouse_getxy()
{
………………..
}
mouse_getbutton()
{
………………..
}
………….IAL引擎结构中定义的其它有关mouse的函数一般无需实现。
Keyboard_update()
{
……………..
}
keyboard_getstate()
{
………
}
……………..同样结构中定义的其它有关keyboard的函数一般无需实现。
Wait_event()
{
………………..
}
InitNAMEInput(INPUT* input, const char* mdev, const char* mtype)
{
…………
input->update_mouse = mouse_update;
input->get_mouse_xy = mouse_getxy;
input->set_mouse_xy = NULL;
input->get_mouse_button = mouse_getbutton;
input->set_mouse_range = NULL;
input->update_keyboard = keyboard_update;
input->get_keyboard_state = keyboard_getstate;
input->set_leds = NULL;
input->wait_event = wait_event;
………………..
}
void TermNAMEInput (void)
{
…………….
}
6.各函数功能说明:开发一输入引擎一般也就是实现以下几个函数。
返回值为触摸屏(鼠标)状态。
返回值int型retvalue变量,其中包含了信息:鼠标事件发生、键盘事件发生或者鼠标和键盘事件都发生了(retvalue |= IAL_MOUSEEVENT,retvalue |= IAL_KEYEVENT)。
7.开发IAL引擎,实现以上函数:
开发IAL引擎准备工作:需对输入设备有些了解:
a)是鼠标、触摸屏还是触摸板?键盘都有哪些键?
b)数据包格式怎样?(同样是触摸屏,不同型号其通过设备文件获得数据结构也不一样,得到的若是A/D转换得来的原始数据处理起来就有些麻烦;键盘的释放与按下状态是通过判断读得的字符最高位0与1来判断,还是对同一键其按下和释放对应两个毫无联系的字符)
c)键盘的编码怎样,和MiniGUI在include/common.h中定义的一样吗?
d)在读得的坐标和屏幕显示坐标间需不需要进行坐标转换?Mouse_getxy中最终返回的坐标为屏幕显示坐标。
e)输入设备驱动支持select系统调用吗?
f)触摸屏(触摸板)驱动中是否解决了抖动消除的问题,是否需要在IAL引擎中解决触摸屏消抖?
总结代码中几个针对具体系统开发的IAL 引擎:
a)引擎包含的各个函数所要做的工作在上面的函数功能说明中已经反应出来,但是具体处理起来,不一定要求有的工作就得在某个函数中完成。比如,从设备文件读取鼠标坐标的信息并对其进行处理,不一定都在Mouse_getxy中完成,可以在Wait_event或update_mouse中完成,在mouse_getxy中只是将最终的显示屏幕坐标赋给mouse_getxy函数的两个参数。
b)IAL引擎的作用是正确分析从设备文件读得的数据,获得鼠标(触摸屏、触摸板)坐标和状态及键盘按键情况(哪个键按下?该键是不是释放了?).这也是我们开发IAL引擎的指南。
c)IAL引擎在MiniGUI的使用(位置):
ParseEvent (msg_queue, IAL_MOUSEEVENT)
ParseEvent (msg_queue, IAL_KEYEVENT)
ParseEvent (msg_queue, 0)
当event是IAL_KEYEVENT时:调用了引擎IAL_UpdateKeyboard ()和IAL_GetKeyboardState ()
当event是IAL_MOUSEEVENT时:调用了引擎IAL_UpdateMouse ()和函数RefreshCursor(&me->x, &me->y, &button)(该函数中调用了IAL_GetMouseXY (x, y)和IAL_GetMouseButton )
Getlwevent(event,&lwe)最终得到了鼠标键盘的坐标状态等具体信息,这些信息由lwe变量带回。
变量Lwe数据结构:
typedef struct _LWEVENT
{
int type;
int count;
DWORD status;
LWEVENTDATA data;
}LWEVENT;
typedef union _LWEVENTDATA {
MOUSEEVENT me;
KEYEVENT ke;
}LWEVENTDATA;
Msg.message=Msg-KEYDOWN
Msg.wparam=ke->scancode
Msg.iparam=ke->status
parseEvent(msg_que,event)将收集到的这些事件转化为上层能理解的消息。
d)有关键盘的IAL引擎就是给state数组赋值。
MiniGUI在include/common.h中列举了每种按键在state数组中的位置(如#define SCANCODE_Z44可以知道state数组中第44个元素表示Z键的状态),我们必须分析从键盘配置文件读取的字符字节的信息,根据这些信息给state数组中相应元素赋值,这样MiniGUI才能根据state数组正确处理这些事件(即MiniGUI是通过state数组中的元素来正确识别哪个键按下的。必须严格根据state数组的规定)。
8.编写输入引擎可参考ipaq.c,它是针对了比较普通的触摸屏的写的。
9.写出触摸屏接口代码,注意:鼠标获取的数据一般是相对坐标,而典型的触摸屏则是绝对坐标(差劲的驱动是直接返回A/D转换得来的原始数据)。