文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>X Window研究笔记(6)

X Window研究笔记(6)

时间:2010-03-31  来源:erlongabc

转载时请注明出处和作者联系方式
作者联系方式:李先静 <xianjimli at hotmail dot com>

6.X Window输入设备(TinyX)

X Window支持的基本输入设备有keyboard、mouse和touchscreen,keyboard有自己的驱动接口,而后两者具有相同的驱动接 口。

输入设备的初始化。

  1. X Server在初始化时会调用InitInput函数初始化输入设备。
  2. InitInput调用KdInitInput完成TinyX输入设备的初始化。其参数LinuxMouseFuncs指向mouse 驱动函数,LinuxKeyboardFuncs指向keyboard驱动的函数。
  3. 在 KdInitInput中,创建一个KdMouseInfo对象,放入kdMouseInfo链表中,并初始化这个KdMouseInfo对象。
  4. 在KdInitInput中,把指向keyboard和mouse驱动的指针保存到kdMouseFuncs和 kdKeyboardFuncs两个全局变量之中。
  5. 在KdInitInput中,加载键 盘映射表,初始化按键重复的数据结构,重置输入设备的状态。
  6. 在KdInitInput 中,创建keyboard和mouse设备,并注册这两个输入设备到系统中。
  7. 如果支持 touchscreen,把kdTsFuncs指向TsFuncs。

keyboard的驱动接口

typedef struct _KdKeyboardFuncs ...{
    void            (*Load) (void);
    int             (*Init) (void);
    void            (*Leds) (int);
    void            (*Bell) (int, int, int);
    void            (*Fini) (void);
    int             LockLed;
} KdKeyboardFuncs;


下 面我们来看一个实际例子(tinyx/linux/keyboard.c):

KdKeyboardFuncs LinuxKeyboardFuncs = ...{
    LinuxKeyboardLoad,
    LinuxKeyboardInit,
    LinuxKeyboardLeds,
    LinuxKeyboardBell,
    LinuxKeyboardFini,
    3,
};

LinuxKeyboardLoad: 构建一个键值映射表, 即从原始的按键值到虚拟键值间VK之间的映射。让虚拟键值独立于硬件的,可以提高应用程序的可移植性。

static void
LinuxKeyboardLoad (void)
...{  
    readKernelMapping ();
}    


LinuxKeyboardInit:初始化一些数据结构, 并注册相关回调函数。这样,在有按键事件时,LinuxConsoleFd唤醒select,并调用函数LinuxKeyboardRead读取按键事 件,经过一些转换动作之后,调用KdHandleKeyboardEvent把事件分发出去。
static int
LinuxKeyboardInit (void)
...{
    if (!LinuxKbdType)
        LinuxKbdType = KdAllocInputType ();

    KdRegisterFd (LinuxKbdType, LinuxConsoleFd, LinuxKeyboardRead, 0);
    LinuxKeyboardEnable (LinuxConsoleFd, 0);
    KdRegisterFdEnableDisable (LinuxConsoleFd,
                               LinuxKeyboardEnable,
                               LinuxKeyboardDisable);
    return 1;
}


LinuxKeyboardLeds: 在某些键按下以后,需 要点亮键盘灯(Caps Lock和 Num Lock等),这时候会调用这个函数,这是通过ioctl系统调用实现的。

static void
LinuxKeyboardLeds (int leds)
...{
    ioctl (LinuxConsoleFd, KDSETLED, leds & 7);
}

LinuxKeyboardBell:它的功能是发出蜂鸣声, 至于为什么作为键盘驱动的一部分,可能是由于输入某些键值时要响一声吧(如,\a)。这也是通过ioctl系统调用实现的。
static void
LinuxKeyboardBell (int volume, int pitch, int duration)
...{
    if (volume && pitch)
    ...{
        ioctl(LinuxConsoleFd, KDMKTONE,
              ((1193190 / pitch) & 0xffff) |
              (((unsigned long)duration *
                volume / 50) << 16));

    }
}


LinuxKeyboardFini:~初始化 keyboard设备,即禁用keyboard,然后注销设备描述符。

static void
LinuxKeyboardFini (void)
...{
    LinuxKeyboardDisable (LinuxConsoleFd, 0);
    KdUnregisterFds (LinuxKbdType, FALSE);
}

鼠标的接口:

typedef struct _KdMouseFuncs ...{
    int             (*Init) (void);
    void            (*Fini) (void);
} KdMouseFuncs;

下 面看一个实际例子(tinyx/linux/mouse.c)

KdMouseFuncs LinuxMouseFuncs = ...{
    MouseInit,
    MouseFini,
};

MouseInit 打开设备文件,并注册一些回调函数。这样,在有mouse事件时,fd唤醒 select,并调用函数MouseRead读取mouse事件,经过一些转换动作之后,调用KdHandleMouseEvent把事件分发出去。

char *kdefaultMouse[] =  ...{
    "/dev/mouse",
    "/dev/psaux",
    "/dev/input/mice",
    "/dev/adbmouse",
    "/dev/ttyS0",
    "/dev/ttyS1",
};

#define NUM_DEFAULT_MOUSE    (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))

static int
MouseInit (void)
...{
    int     i;
    int     fd = -1;
    Kmouse  *km;
    KdMouseInfo *mi, *next;
    int     n = 0;
    char    *prot;

    if (!MouseInputType)
    MouseInputType = KdAllocInputType ();

    for (mi = kdMouseInfo; mi; mi = next)
    ...{
    next = mi->next;
    prot = mi->prot;
    if (mi->inputType)
        continue;
    if (!mi->name)
    ...{
        for (i = 0; i < NUM_DEFAULT_MOUSE; i++)
        ...{
        if (kdNoSerialMouse && strstr(kdefaultMouse[i], "/dev/ttyS"))
            continue;
        fd = open (kdefaultMouse[i], 2);
        if (fd >= 0)
        ...{
            mi->name = KdSaveString (kdefaultMouse[i]);
            break;
        }
        }  
    }
    else
        fd = open (mi->name, 2);
           
    if (fd >= 0)
    ...{
        km = (Kmouse *) xalloc (sizeof (Kmouse));
        if (km)
        ...{
        km->iob.fd = fd;
        km->iob.avail = km->iob.used = 0;
       km->prot = 0;
        km->i_prot = 0;
        km->tty = isatty (fd);
        mi->driver = km;
        mi->inputType = MouseInputType;
        MouseFirstProtocol (km, mi->prot);
        if (KdRegisterFd (MouseInputType, fd, MouseRead, (void *) mi))
            n++;
        }
        else
        close (fd);
    }
    }
    return n;
}

MouseFini: ~初始化mouse设备,即注销回调函数,并释放一些数据结构。

static void
MouseFini (void)
...{
    KdMouseInfo *mi;

    KdUnregisterFds (MouseInputType, TRUE);
    for (mi = kdMouseInfo; mi; mi = mi->next)
    ...{
    if (mi->inputType == MouseInputType)
    ...{
        xfree (mi->driver);
        mi->driver = 0;
        mi->inputType = 0;
    }
    }
}



有意思的是,驱动本身的接口并不能说明设备的特性,它 只提供初始化和~初始化这类通用接口,在初始化时才注册设备描述符和相应的读取函数。

(待续)
排行榜 更多 +
合合合军团

合合合军团

策略塔防 下载
街头滑板

街头滑板

体育竞技 下载
武者生存

武者生存

体育竞技 下载