X Window研究笔记(6)



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的驱动接口



X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02typedef struct _KdKeyboardFuncs ...{

X Window研究笔记(6)_回调函数_03    void            (*Load) (void);

X Window研究笔记(6)_回调函数_03    int             (*Init) (void);

X Window研究笔记(6)_回调函数_03    void            (*Leds) (int);

X Window研究笔记(6)_回调函数_03    void            (*Bell) (int, int, int);

X Window研究笔记(6)_回调函数_03    void            (*Fini) (void);

X Window研究笔记(6)_回调函数_03    int             LockLed;

X Window研究笔记(6)_初始化_09} KdKeyboardFuncs;



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



X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02KdKeyboardFuncs LinuxKeyboardFuncs = ...{

X Window研究笔记(6)_回调函数_03    LinuxKeyboardLoad,

X Window研究笔记(6)_回调函数_03    LinuxKeyboardInit,

X Window研究笔记(6)_回调函数_03    LinuxKeyboardLeds,

X Window研究笔记(6)_回调函数_03    LinuxKeyboardBell,

X Window研究笔记(6)_回调函数_03    LinuxKeyboardFini,

X Window研究笔记(6)_回调函数_03    3,

X Window研究笔记(6)_初始化_09};

X Window研究笔记(6)_键值_19


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



X Window研究笔记(6)_键值_19static void

X Window研究笔记(6)_键值_19LinuxKeyboardLoad (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{  

X Window研究笔记(6)_回调函数_03    readKernelMapping ();

X Window研究笔记(6)_初始化_09}    



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


X Window研究笔记(6)_键值_19static int

X Window研究笔记(6)_键值_19LinuxKeyboardInit (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    if (!LinuxKbdType)

X Window研究笔记(6)_回调函数_03        LinuxKbdType = KdAllocInputType ();

X Window研究笔记(6)_回调函数_03

X Window研究笔记(6)_回调函数_03    KdRegisterFd (LinuxKbdType, LinuxConsoleFd, LinuxKeyboardRead, 0);

X Window研究笔记(6)_回调函数_03    LinuxKeyboardEnable (LinuxConsoleFd, 0);

X Window研究笔记(6)_回调函数_03    KdRegisterFdEnableDisable (LinuxConsoleFd,

X Window研究笔记(6)_回调函数_03                               LinuxKeyboardEnable,

X Window研究笔记(6)_回调函数_03                               LinuxKeyboardDisable);

X Window研究笔记(6)_回调函数_03    return 1;

X Window研究笔记(6)_初始化_09}



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



X Window研究笔记(6)_键值_19static void

X Window研究笔记(6)_键值_19LinuxKeyboardLeds (int leds)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    ioctl (LinuxConsoleFd, KDSETLED, leds & 7);

X Window研究笔记(6)_初始化_09}

X Window研究笔记(6)_键值_19


LinuxKeyboardBell:它的功能是发出蜂鸣声,至于为什么作为键盘驱动的一部分,可能是由于输入某些键值时要响一声吧(如,/a)。这也是通过ioctl系统调用实现的。


X Window研究笔记(6)_键值_19static void

X Window研究笔记(6)_键值_19LinuxKeyboardBell (int volume, int pitch, int duration)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    if (volume && pitch)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03        ioctl(LinuxConsoleFd, KDMKTONE,

X Window研究笔记(6)_回调函数_03              ((1193190 / pitch) & 0xffff) |

X Window研究笔记(6)_回调函数_03              (((unsigned long)duration *

X Window研究笔记(6)_回调函数_03                volume / 50) << 16));

X Window研究笔记(6)_回调函数_03

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_初始化_09}



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



X Window研究笔记(6)_键值_19static void

X Window研究笔记(6)_键值_19LinuxKeyboardFini (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    LinuxKeyboardDisable (LinuxConsoleFd, 0);

X Window研究笔记(6)_回调函数_03    KdUnregisterFds (LinuxKbdType, FALSE);

X Window研究笔记(6)_初始化_09}

X Window研究笔记(6)_键值_19


鼠标的接口:



X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02typedef struct _KdMouseFuncs ...{

X Window研究笔记(6)_回调函数_03    int             (*Init) (void);

X Window研究笔记(6)_回调函数_03    void            (*Fini) (void);

X Window研究笔记(6)_初始化_09} KdMouseFuncs;


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



X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02KdMouseFuncs LinuxMouseFuncs = ...{

X Window研究笔记(6)_回调函数_03    MouseInit,

X Window研究笔记(6)_回调函数_03    MouseFini,

X Window研究笔记(6)_初始化_09};

X Window研究笔记(6)_键值_19


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



X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02char *kdefaultMouse[] =  ...{

X Window研究笔记(6)_回调函数_03    "/dev/mouse",

X Window研究笔记(6)_回调函数_03    "/dev/psaux",

X Window研究笔记(6)_回调函数_03    "/dev/input/mice",

X Window研究笔记(6)_回调函数_03    "/dev/adbmouse",

X Window研究笔记(6)_回调函数_03    "/dev/ttyS0",

X Window研究笔记(6)_回调函数_03    "/dev/ttyS1",

X Window研究笔记(6)_初始化_09};

X Window研究笔记(6)_键值_19

X Window研究笔记(6)_键值_19#define NUM_DEFAULT_MOUSE    (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))

X Window研究笔记(6)_键值_19

X Window研究笔记(6)_键值_19static int

X Window研究笔记(6)_键值_19MouseInit (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    int     i;

X Window研究笔记(6)_回调函数_03    int     fd = -1;

X Window研究笔记(6)_回调函数_03    Kmouse  *km;

X Window研究笔记(6)_回调函数_03    KdMouseInfo *mi, *next;

X Window研究笔记(6)_回调函数_03    int     n = 0;

X Window研究笔记(6)_回调函数_03    char    *prot;

X Window研究笔记(6)_回调函数_03

X Window研究笔记(6)_回调函数_03    if (!MouseInputType)

X Window研究笔记(6)_回调函数_03    MouseInputType = KdAllocInputType ();

X Window研究笔记(6)_回调函数_03

X Window研究笔记(6)_回调函数_03    for (mi = kdMouseInfo; mi; mi = next)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03    next = mi->next;

X Window研究笔记(6)_回调函数_03    prot = mi->prot;

X Window研究笔记(6)_回调函数_03    if (mi->inputType)

X Window研究笔记(6)_回调函数_03        continue;

X Window研究笔记(6)_回调函数_03    if (!mi->name)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03        for (i = 0; i < NUM_DEFAULT_MOUSE; i++)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53        ...{

X Window研究笔记(6)_回调函数_03        if (kdNoSerialMouse && strstr(kdefaultMouse[i], "/dev/ttyS"))

X Window研究笔记(6)_回调函数_03            continue;

X Window研究笔记(6)_回调函数_03        fd = open (kdefaultMouse[i], 2);

X Window研究笔记(6)_回调函数_03        if (fd >= 0)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53        ...{

X Window研究笔记(6)_回调函数_03            mi->name = KdSaveString (kdefaultMouse[i]);

X Window研究笔记(6)_回调函数_03            break;

X Window研究笔记(6)_初始化_59        }

X Window研究笔记(6)_初始化_59        }  

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_回调函数_03    else

X Window研究笔记(6)_回调函数_03        fd = open (mi->name, 2);

X Window研究笔记(6)_回调函数_03           

X Window研究笔记(6)_回调函数_03    if (fd >= 0)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03        km = (Kmouse *) xalloc (sizeof (Kmouse));

X Window研究笔记(6)_回调函数_03        if (km)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53        ...{

X Window研究笔记(6)_回调函数_03        km->iob.fd = fd;

X Window研究笔记(6)_回调函数_03        km->iob.avail = km->iob.used = 0;

X Window研究笔记(6)_回调函数_03       km->prot = 0;

X Window研究笔记(6)_回调函数_03        km->i_prot = 0;

X Window研究笔记(6)_回调函数_03        km->tty = isatty (fd);

X Window研究笔记(6)_回调函数_03        mi->driver = km;

X Window研究笔记(6)_回调函数_03        mi->inputType = MouseInputType;

X Window研究笔记(6)_回调函数_03        MouseFirstProtocol (km, mi->prot);

X Window研究笔记(6)_回调函数_03        if (KdRegisterFd (MouseInputType, fd, MouseRead, (void *) mi))

X Window研究笔记(6)_回调函数_03            n++;

X Window研究笔记(6)_初始化_59        }

X Window研究笔记(6)_回调函数_03        else

X Window研究笔记(6)_回调函数_03        close (fd);

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_回调函数_03    return n;

X Window研究笔记(6)_初始化_09}

X Window研究笔记(6)_键值_19


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



X Window研究笔记(6)_键值_19static void

X Window研究笔记(6)_键值_19MouseFini (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    KdMouseInfo *mi;

X Window研究笔记(6)_回调函数_03

X Window研究笔记(6)_回调函数_03    KdUnregisterFds (MouseInputType, TRUE);

X Window研究笔记(6)_回调函数_03    for (mi = kdMouseInfo; mi; mi = mi->next)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03    if (mi->inputType == MouseInputType)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03        xfree (mi->driver);

X Window研究笔记(6)_回调函数_03        mi->driver = 0;

X Window研究笔记(6)_回调函数_03        mi->inputType = 0;

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_初始化_09}

X Window研究笔记(6)_键值_19

X Window研究笔记(6)_键值_19


触摸屏的接口



X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02typedef struct _KdMouseFuncs ...{

X Window研究笔记(6)_回调函数_03    int             (*Init) (void);

X Window研究笔记(6)_回调函数_03    void            (*Fini) (void);

X Window研究笔记(6)_初始化_09} KdMouseFuncs;



触摸屏是作为鼠标来实现的。下面看一个实际例子(tinyx/linux/tslib.c)


X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02KdMouseFuncs TsFuncs = ...{

X Window研究笔记(6)_回调函数_03    TslibInit,

X Window研究笔记(6)_回调函数_03    TslibFini

X Window研究笔记(6)_初始化_09};

X Window研究笔记(6)_键值_19


TslibInit:打开设备文件,并注册一些回调函数。由于触摸屏涉及到去抖、滤波、校准等功能,相关对于鼠标来说,要复杂得多,所以这里是调用tslib来实现的。


在有笔点事件时,fd唤醒select,并调用函数TsRead读取笔点事件,经过一些转换动作之后,调用KdHandleMouseEvent把事件分发出去。



X Window研究笔记(6)_键值_19int

X Window研究笔记(6)_键值_19TslibInit (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    int         i;

X Window研究笔记(6)_回调函数_03    KdMouseInfo *mi, *next;

X Window研究笔记(6)_回调函数_03    int         fd= 0;

X Window研究笔记(6)_回调函数_03    int         n = 0;

X Window研究笔记(6)_回调函数_03   

X Window研究笔记(6)_回调函数_03    if (!TsInputType)

X Window研究笔记(6)_回调函数_03        TsInputType = KdAllocInputType ();

X Window研究笔记(6)_回调函数_03       

X Window研究笔记(6)_回调函数_03    for (mi = kdMouseInfo; mi; mi = next)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03        next = mi->next;

X Window研究笔记(6)_回调函数_03        if (mi->inputType)

X Window研究笔记(6)_回调函数_03            continue;

X Window研究笔记(6)_回调函数_03           

X Window研究笔记(6)_回调函数_03        if (!mi->name)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53        ...{

X Window研究笔记(6)_回调函数_03            for (i = 0; i < NUM_TS_NAMES; i++)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53            ...{

X Window研究笔记(6)_回调函数_03                if(!(tsDev = ts_open(TsNames[i],0))) continue;

X Window研究笔记(6)_回调函数_03                ts_config(tsDev);

X Window研究笔记(6)_回调函数_03                fd=ts_fd(tsDev);

X Window研究笔记(6)_回调函数_03                if (fd >= 0)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53                ...{

X Window研究笔记(6)_回调函数_03                    mi->name = KdSaveString (TsNames[i]);

X Window研究笔记(6)_回调函数_03                    break;

X Window研究笔记(6)_初始化_59                }  

X Window研究笔记(6)_初始化_59            }  

X Window研究笔记(6)_初始化_59        }  

X Window研究笔记(6)_回调函数_03       

X Window研究笔记(6)_回调函数_03        if (fd > 0 && tsDev != 0)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53          ...{

X Window研究笔记(6)_回调函数_03            mi->driver = (void *) fd;

X Window研究笔记(6)_回调函数_03            mi->inputType = TsInputType;

X Window研究笔记(6)_回调函数_03                if (KdRegisterFd (TsInputType, fd, TsRead, (void *) mi))

X Window研究笔记(6)_回调函数_03                    n++;

X Window研究笔记(6)_初始化_59          }

X Window研究笔记(6)_回调函数_03        else

X Window研究笔记(6)_回调函数_03          if (fd > 0) close(fd);

X Window研究笔记(6)_初始化_59        }

X Window研究笔记(6)_初始化_09}



TslibFini: ~初始化touchscreen设备,即注销相关的回调函数,并释放一些数据结构。



X Window研究笔记(6)_键值_19void

X Window研究笔记(6)_键值_19TslibFini (void)

X Window研究笔记(6)_键值X Window研究笔记(6)_输入设备_02...{

X Window研究笔记(6)_回调函数_03    KdMouseInfo *mi;

X Window研究笔记(6)_回调函数_03

X Window研究笔记(6)_回调函数_03    KdUnregisterFds (TsInputType, TRUE);

X Window研究笔记(6)_回调函数_03    for (mi = kdMouseInfo; mi; mi = mi->next)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53    ...{

X Window研究笔记(6)_回调函数_03        if (mi->inputType == TsInputType)

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53        ...{

X Window研究笔记(6)_回调函数_03            if(mi->driver) ts_close(tsDev);

X Window研究笔记(6)_回调函数_03            mi->driver = 0;

X Window研究笔记(6)_回调函数_03            mi->inputType = 0;

X Window研究笔记(6)_linux_52X Window研究笔记(6)_初始化_53            if (mi->name != NULL) ...{

X Window研究笔记(6)_回调函数_03                free(mi->name);

X Window研究笔记(6)_回调函数_03                mi->name = NULL;

X Window研究笔记(6)_初始化_59            }

X Window研究笔记(6)_初始化_59        }

X Window研究笔记(6)_初始化_59    }

X Window研究笔记(6)_初始化_09}



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


(待续)