Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9396467
  • 博文数量: 1747
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20060
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1747)

文章存档

2024年(23)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: LINUX

2011-04-22 08:41:38

如何在MiniGUI中添加新的IAL引擎:(假设新的IAL引擎为_NAME_IAL

1.         ial.c文件中添加新引擎的入口:

例如:(ial.c文件中)

A)       #ifdef _NAME _IAL
       #include "NAME.h"
   #endif

B)       input数组中添加

       #ifdef _NAME _IAL
            {"NAME ", InitNAMEInput, TermNAMEInput},
       #endif

2.       把新的 .c 添加到 Makefile.am 文件中即可。

3.       修改配置文件IAL引擎项,使用这个新的IAL引擎_NAME_IAL.

²        如何编写IAL引擎:

1.         MiniGUI中引入了输入抽象层(Input  Abstract  Layer 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_SetMouseXY          if (cur_input->set_mouse_xy) (*cur_input->set_mouse_xy)

#define IAL_SetMouseRange       if (cur_input->set_mouse_range) (*cur_input->set_mouse_range)

#define IAL_SuspendMouse        if (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_SuspendKeyboard     if (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()

{

………………..

}

InitNAMEInputINPUT* 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.         各函数功能说明:开发一输入引擎一般也就是实现以下几个函数。

Ø         InitNAMEInput函数就是在src/ial/ial.c中定义的NAME输入引擎的初始化函数,它打开触摸屏(鼠标)和键盘设备文件。在成功打开这两个设备文件后,该函数设置了INPUT结构的其它一些成员。其中一些成员被赋值为NULL

Ø         Mouse_update函数始终返回1,表明更新鼠标状态成功。

Ø         Mouse_getxy函数返回由其它函数准备好的鼠标位置,有可能做了适当的边界检查和支持屏幕显示旋转时对坐标的转换。函数的参数是两个指针变量。

Ø         Mouse_getbutton函数返回了触摸屏状态,即用户是否触摸了屏幕,相当于是否按下了左键。(或者鼠标哪个键按下,左键、右键还是当中的那个?)

返回值为触摸屏(鼠标)状态。

Ø         Keyboard_update函数根据其它函数准备好的键盘消息,适当填充了state数组。返回值是NR_KEYS

Ø         Keyboard_state函数直接返回了state数组的地址:“return state”。

Ø         Wait_event函数是输入引擎的核心函数。这个函数首先将先前打开的两个设备的文件描述符与传入的in文件描述符集合并在了一起,然后调用了select系统调用。当select系统调用返回大于0的值时,该函数检查在两个文件描述符上是否有可读的数据等待读取,如果是,则分别从两个文件描述符读取触摸屏和按键数据。

返回值intretvalue变量,其中包含了信息:鼠标事件发生、键盘事件发生或者鼠标和键盘事件都发生了(retvalue |= IAL_MOUSEEVENTretvalue |= IAL_KEYEVENT)。

7.         开发IAL引擎,实现以上函数:

Ø         开发IAL引擎准备工作:需对输入设备有些了解:

a)         是鼠标、触摸屏还是触摸板?键盘都有哪些键?

b)        数据包格式怎样?(同样是触摸屏,不同型号其通过设备文件获得数据结构也不一样,得到的若是A/D转换得来的原始数据处理起来就有些麻烦;键盘的释放与按下状态是通过判断读得的字符最高位01来判断,还是对同一键其按下和释放对应两个毫无联系的字符)

c)        键盘的编码怎样,和MiniGUIinclude/common.h中定义的一样吗?

d)        在读得的坐标和屏幕显示坐标间需不需要进行坐标转换?Mouse_getxy中最终返回的坐标为屏幕显示坐标。

e)         输入设备驱动支持select系统调用吗?

f)         触摸屏(触摸板)驱动中是否解决了抖动消除的问题,是否需要在IAL引擎中解决触摸屏消抖?

Ø         总结代码中几个针对具体系统开发的IAL 引擎:

a)         引擎包含的各个函数所要做的工作在上面的函数功能说明中已经反应出来,但是具体处理起来,不一定要求有的工作就得在某个函数中完成。比如,从设备文件读取鼠标坐标的信息并对其进行处理,不一定都在Mouse_getxy中完成,可以在Wait_eventupdate_mouse中完成,在mouse_getxy中只是将最终的显示屏幕坐标赋给mouse_getxy函数的两个参数。

b)        IAL引擎的作用是正确分析从设备文件读得的数据,获得鼠标(触摸屏、触摸板)坐标和状态及键盘按键情况(哪个键按下?该键是不是释放了?).这也是我们开发IAL引擎的指南。

c)        IAL引擎在MiniGUI的使用(位置):

Ø         \src\sever\server.c L396 函数IdleHandler4Server()中用了输入引擎中的IAL_WaitEvent检查是否有底层输入事件发生,

Ø         当有事件发生时检查是鼠标(触摸屏、触摸板)事件发生还是键盘事件发生,并分别用parseEvent(msg_que,event)函数(\src\sever\server.c)处理这些事件

ParseEvent (msg_queue, IAL_MOUSEEVENT)

ParseEvent (msg_queue, IAL_KEYEVENT)

ParseEvent (msg_queue, 0)

Ø         parseEvent(msg_que,event)函数中首先调用了Getlwevent(event,&lwe) (lwe是在parseEvent中定义的)Getlweventevent,&lwe)中分析event:

eventIAL_KEYEVENT时:

调用了引擎IAL_UpdateKeyboard ()IAL_GetKeyboardState ()

eventIAL_MOUSEEVENT时:

调用了引擎IAL_UpdateMouse ()和函数RefreshCursor(&me->x, &me->y, &button)(该函数中调用了IAL_GetMouseXY (x, y)IAL_GetMouseButton

Getlweventevent,&lwe)最终得到了鼠标键盘的坐标状态等具体信息,这些信息由lwe变量带回。

变量Lwe数据结构:

typedef struct _LWEVENT

{

    int type;

    int count;

    DWORD status;

    LWEVENTDATA data;

}LWEVENT;

typedef union _LWEVENTDATA {

    MOUSEEVENT me;

    KEYEVENT ke;

}LWEVENTDATA;

Ø         parseEvent(msg_que,event)中利用了获得的lwe,将其转化为消息,放到消息队列中。如对键盘:

Msg.message=MsgKEYDOWN

Msg.wparam=ke->scancode

Msg.iparam=ke->status

Ø         Getlwevent(event,&lwe)收集底层输入事件lwe(利用了IAL引擎)

   parseEvent(msg_que,event)将收集到的这些事件转化为上层能理解的消息。

 

d)        有关键盘的IAL引擎就是给state数组赋值。

    MiniGUIinclude/common.h中列举了每种按键在state数组中的位置(如#define SCANCODE_Z  44可以知道state数组中第44个元素表示Z键的状态),我们必须分析从键盘配置文件读取的字符字节的信息,根据这些信息给state数组中相应元素赋值,这样MiniGUI才能根据state数组正确处理这些事件(即MiniGUI是通过state数组中的元素来正确识别哪个键按下的。必须严格根据state数组的规定)。

 

8.         编写输入引擎可参考ipaq.c,它是针对了比较普通的触摸屏的写的。

9.       写出触摸屏接口代码,注意:鼠标获取的数据一般是相对坐标,而典型的触摸屏则是绝对坐标(差劲的驱动是直接返回A/D转换得来的原始数据)。

1、在src/ial/ial.c中添加引擎入口,假设新引擎名字为"mips",需要在前面添加预定义:
#ifdef _MIPS_IAL
#include "mips.h"
#endif

然后在inputs数组中新引擎的初始化和终止函数指针,只需在最后添加:
#ifdef _MIPS_IAL
{"mips", InitMipsInput, TermMipsInput},
#endif

mips.h头文件很简单,只是声明初始化函数和终止函数,可仿照其他输入引擎的头文件。mips.c为具体的输入引擎的实现。输入引擎的实现实际上是给 tagINPUT(src/include/ial.h)数据结构中定义的函数指针赋值,当然你可以全部赋值也可以为需要的赋值。
2、将新的输入引擎文件添加到编译列表中,具体做法是编辑src/ial/Makefile.am文件,在28行"FXRM9200_SRCS = fxrm9200.c fxrm9200.h"后面另起一行添加"MIPS_SRCS = mips.c mips.h", 然后在libial_la_SOURCES变量定义的后面添加"$(MIPS_SRCS)"
3、修改配置文件MiniGUI.cfg中的输入引擎,即将ial_engine的值改为mips,再将mdev改为相应驱动设备名,在我的引擎中是"/dev/i2c-1".
4、重新配置编译minigui.

阅读(3024) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~