简单的IAL分析
一、程序说明
    1.下面程序是基于一个红外的设备文件,从该设备中能接收到红外遥控的硬件编码。
    2.两个文件需要覆盖掉libmingiui*/src/ial/中的两个文件编译时加上 --enable-video-qvfb
    3.为了简单,就直接在qvfb引擎上进行修改
二、程序源码及代码说明
/*
qvfb.h
*/

#ifndef _IAL_qvfb_h
#define _IAL_qvfb_h

#define kb_dev   "/dev/ir"
//一个现成的红外设备,当按钮按下后可以从这里读到一个整型

#define TIME_KEYUP  30
//设定一个按钮自动弹起的时钟30ms

struct QVFbKeyData
{
    unsigned int unicode;
    //unsigned int modifiers;
    //BYTE press;
    //BYTE repeat;
};//读到红外数据的结构,实际是一个无符号整型

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

BOOL InitQVFBInput (INPUT* input, const char* mdev, const char* mtype);
void TermQVFBInput (void);

#ifdef __cplusplus
}
#endif  /* __cplusplus */

#endif /* _IAL_qvfb_h */

***文件结束************************************

/*
qvfb.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

#include "common.h"

#ifdef _QVFB_IAL

#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "minigui.h"
#include "misc.h"
#include "ial.h"
#include "qvfb.h"


extern unsigned int __mg_timer_counter;
// minigui自带的一个计时器

static int mouse_fd = -1;
static int kbd_fd = -1;
//static POINT mouse_pt;
//static int mouse_buttons;
static struct QVFbKeyData kbd_data;
static unsigned char kbd_state [NR_KEYS];

static unsigned char last = 0;
//保存上一次取道的扫描码
   
static int time_pre = -1 ;

//下面是一个硬件码到扫描码的转化表
static int keycode_scancode[0x21] =
{
 SCANCODE_CURSORBLOCKUP,   /*0x00 UP0   UP*/
 SCANCODE_CURSORBLOCKDOWN,   /*0x01 Down   DOWN*/
 SCANCODE_CURSORBLOCKRIGHT,   /*0x02 Right   RIGHT*/
 SCANCODE_CURSORBLOCKLEFT,   /*0x03 Left    LEFT*/
 0x003C,   /*0x04 Audio  F2*/
 SCANCODE_LEFTALT,   /*0x05 MENU*/
 0x0040,   /*0x06 Radio  电/广F6*/
 SCANCODE_ESCAPE,   /*0x07 Exit    ESC*/
 0x003D,   /*0x08 Pause  F3*/
 0x003B,   /*0x09 FAV   F1*/
 0x0044,   /*0x0A OWER  F10*/
 0x003F,   /*0x0B TV  缩放F5*/
 0x0057,   /*0x0C MUTE  F11*/
 0x0000,   /*0x0D 没有该按钮*/
 0x0042,   /*0x0E TV/Sat 搜台F8*/
 0x003E,   /*0x0F TXT   F4*/
 SCANCODE_0,   /*0x10 0   0*/
 SCANCODE_1,   /*0x11 1   1*/
 SCANCODE_2,   /*0x12 2   2*/
 SCANCODE_3,   /*0x13 3   3*/
 SCANCODE_4,   /*0x14 4   4*/
 SCANCODE_5,   /*0x15 5   5*/
 SCANCODE_6,   /*0x16 6   6*/
 SCANCODE_7,   /*0x17 7   7*/
 SCANCODE_8,   /*0x18 8   8*/
 SCANCODE_9,   /*0x19 9   9*/
 SCANCODE_CAPSLOCK,   /*0x1A quality  CAPLOCK*/
 SCANCODE_BACKSPACE,   /*0x1B recall  BACKSPACE*/
 SCANCODE_PAGEUP,   /*0x1C Sat   PAGEUP*/
 SCANCODE_PAGEDOWN,   /*0x1D Skew  PAGEDOWN*/
 0x0043,   /*0x1E Guid  F9*/
 SCANCODE_ENTER,   /*0x1F OK   ENTER*/
 0x0041   /*0x40 Info  F7*/
};

static unsigned char keycode_to_scancode (unsigned int keycode)
{
 keycode >>= 16;
 keycode &= 0x0FF;
 
 fprintf (stderr, "IAL:keycode = %d!\n",keycode);
 if(keycode >= 0x20)
 {
  keycode = 0x20; 
 }
 return keycode_scancode[keycode];
}

/************************  Low Level Input Operations **********************/
/*
 * Mouse operations -- Event
*鼠标函数空,忽略
 */
static int mouse_update (void)
{
    return 1;
}

static void mouse_getxy (int *x, int* y)
{
 ;
}

static int mouse_getbutton (void)
{
    return 0;
}
////////////////////////////////////////////
static int keyboard_update (void)
{
    struct QVFbKeyData l_kbd_data;
    int ret;
   
 if(!(last & 0x80))
 {
     ret = read (kbd_fd, &l_kbd_data, sizeof (struct QVFbKeyData));
  ////////////////////判断是否有数据
     if (ret == sizeof (struct QVFbKeyData)) {
         kbd_data = l_kbd_data;
     }
     else
     {
         return 0;
     }
  /////////////////////////////////
        //按钮未弹起前不接收其他按钮
     last = keycode_to_scancode (kbd_data.unicode);
     kbd_state[last]=1;   //新按钮按下
     time_pre = __mg_timer_counter;//开始按钮弹起计时
     fprintf (stderr, "IAL:Key Down!\n");
    }
    else
    {
     kbd_state[last & 0x7f]=0;
     time_pre = -1;
 last = 0;
     fprintf (stderr, "IAL:Key Up!\n");
    }
    return NR_KEYS;
}

static const char* keyboard_getstate (void)
{
    return kbd_state;
}

/* NOTE by weiym: Do not ignore the fd_set in, out, and except */
#ifdef _LITE_VERSION
static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,
                struct timeval *timeout)
#else
static int wait_event (int which, fd_set *in, fd_set *out, fd_set *except,
                struct timeval *timeout)
#endif
{
 int interval;
    fd_set rfds;
    int    retvalue = 0;
    int    fd, e;
 ////////////////////////////////
 if(time_pre > 0)
 {
  interval= __mg_timer_counter - time_pre;
  if (interval > TIME_KEYUP)
  {
   //kbd_state[last] = 0;
   last |= 0x80; //发送按钮弹起数据
   retvalue |= IAL_KEYEVENT ;
   return retvalue;
  }
 }
   /////////////////////////////////
    if (!in) {
        in = &rfds;
        FD_ZERO (in);
    }

    if (which & IAL_MOUSEEVENT && mouse_fd >= 0) {
        fd = mouse_fd;
        FD_SET (fd, in);
#ifdef _LITE_VERSION
        if (fd > maxfd) maxfd = fd;
#endif
    }

    if (which & IAL_KEYEVENT){
        fd = kbd_fd;
        FD_SET (kbd_fd, in);
#ifdef _LITE_VERSION
        if (fd > maxfd) maxfd = fd;
#endif
    }

    /* FIXME: pass the real set size */
#ifdef _LITE_VERSION
    e = select (maxfd + 1, in, out, except, timeout) ;
#else
    e = select (FD_SETSIZE, in, out, except, timeout) ;
#endif

    if (e > 0 && time_pre < 0) { //按钮按下后就不产生事件,直到按钮弹起
        fd = mouse_fd;
        /* If data is present on the mouse fd, service it: */
        if (fd >= 0 && FD_ISSET (fd, in)) {
            FD_CLR (fd, in);
            retvalue |= IAL_MOUSEEVENT;
        }

        fd = kbd_fd;
        /* If data is present on the keyboard fd, service it: */
        if (fd >= 0 && FD_ISSET (fd, in)) {
            FD_CLR (fd, in);
            retvalue |= IAL_KEYEVENT;
        }

    } else if (e < 0 || time_pre > 0) {
        return -1;
    }

    return retvalue;
}

BOOL InitQVFBInput (INPUT* input, const char* mdev, const char* mtype)
{
 kbd_fd = open (kb_dev, O_RDONLY); 
    if (kbd_fd < 0)
 {
        fprintf (stderr, "IAL:Can not open /dev/ir !\n");
    }

/////////////////////////////////////////////////////
    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->suspend_mouse= NULL;
    input->resume_mouse = NULL;

    input->update_keyboard = keyboard_update;
    input->get_keyboard_state = keyboard_getstate;
    input->suspend_keyboard = NULL;
    input->resume_keyboard = NULL;
    input->set_leds = NULL;

    input->wait_event = wait_event;

    return TRUE;
}
void TermQVFBInput (void)
{
    if (kbd_fd >= 0)
        close (kbd_fd);
}

#endif /* _QVFB_IAL */

***文件结束************************************