X Window研究笔记(6)

原创 2007年09月15日 16:43:00
X Window研究笔记(6)

转载时请注明出处和作者联系方式
作者联系方式:李先静 <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) (intintint);
    
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;
    }

    }

}



触摸屏的接口

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


触摸屏是作为鼠标来实现的。下面看一个实际例子(tinyx/linux/tslib.c)
KdMouseFuncs TsFuncs = ...{
    TslibInit,
    TslibFini
}
;

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

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

int
TslibInit (
void)
...{
    
int         i;
    KdMouseInfo 
*mi, *next;
    
int         fd= 0;
    
int         n = 0;
   
    
if (!TsInputType)
        TsInputType 
= KdAllocInputType ();
       
    
for (mi = kdMouseInfo; mi; mi = next)
    
...{
        next 
= mi->next;
        
if (mi->inputType)
            
continue;
           
        
if (!mi->name)
        
...{
            
for (i = 0; i < NUM_TS_NAMES; i++)
            
...{
                
if(!(tsDev = ts_open(TsNames[i],0))) continue;
                ts_config(tsDev);
                fd
=ts_fd(tsDev);
                
if (fd >= 0)
                
...{
                    mi
->name = KdSaveString (TsNames[i]);
                    
break;
                }
  
            }
  
        }
  
       
        
if (fd > 0 && tsDev != 0)
          
...{
            mi
->driver = (void *) fd;
            mi
->inputType = TsInputType;
                
if (KdRegisterFd (TsInputType, fd, TsRead, (void *) mi))
                    n
++;
          }

        
else
          
if (fd > 0) close(fd);
        }

}


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

void
TslibFini (
void)
...{
    KdMouseInfo 
*mi;

    KdUnregisterFds (TsInputType, TRUE);
    
for (mi = kdMouseInfo; mi; mi = mi->next)
    
...{
        
if (mi->inputType == TsInputType)
        
...{
            
if(mi->driver) ts_close(tsDev);
            mi
->driver = 0;
            mi
->inputType = 0;
            
if (mi->name != NULL) ...{
                free(mi
->name);
                mi
->name = NULL;
            }

        }

    }

}


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

(待续)
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

X Window研究笔记(6) (转贴)

 X Window研究笔记(6)转载时请注明出处和作者联系方式作者联系方式:李先静 6.X Window输入设备(TinyX)X Window支持的基本输入设备有keyboard、mouse和touc...
  • geng_ch
  • geng_ch
  • 2008年12月16日 00:33
  • 1498

X Window研究笔记

 http://blog.csdn.net/absurd/category/336948.aspx
  • lcj8
  • lcj8
  • 2009年02月17日 17:35
  • 436

X Window研究笔记(10)

X Window研究笔记(10)转载时请注明出处和作者联系方式作者联系方式:李先静 10.X Window扩展机制--扩展(Extension)XWindow中有大量扩展模块,每个扩展模块完成一组相关...
  • absurd
  • absurd
  • 2007年09月23日 11:00
  • 5277

X Window研究笔记(19)

X Window研究笔记(19)转载时请注明出处和作者联系方式作者联系方式:李先静 19.X Window中的图片文件PixmapX Window自己定义了一种图片文件格式,叫做pixmap,与众不同...
  • absurd
  • absurd
  • 2007年10月02日 14:31
  • 3765

X Window研究笔记(7)

X Window研究笔记(7) 转载时请注明出处和作者联系方式 作者联系方式:李先静 7.X Window的运行过程 X Window 的入口在programs/Xserver/dix/mai...
  • absurd
  • absurd
  • 2007年09月18日 21:19
  • 4253

X Window研究笔记(17)

X Window研究笔记(17)转载时请注明出处和作者联系方式作者联系方式:李先静 17.X Window 窗口管理器很多人不知道窗口管理器是怎么回事。他们认为 GNOME 和 KDE 就是窗口管理器...
  • absurd
  • absurd
  • 2007年10月02日 14:03
  • 4107

X Window研究笔记(13)

X Window研究笔记(13)转载时请注明出处和作者联系方式作者联系方式:李先静 13.X Window扩展机制--客户端勾子函数扩展模块是X Window的主要扩展方式,前面我们介绍它在X Ser...
  • absurd
  • absurd
  • 2007年09月27日 21:44
  • 3646

X Window研究笔记(2)

X Window研究笔记(2)转载时请注明出处和作者联系方式作者联系方式:李先静 2.X Window的功能X Window提供了一组非常底层的服务,客户端程序发送请求给X Window, X Win...
  • absurd
  • absurd
  • 2007年09月12日 22:11
  • 7149

X Window研究笔记(21)

X Window研究笔记(21)转载时请注明出处和作者联系方式作者联系方式:李先静 21.X Window 字符串与AtomAtom是X Window中的一大特色,不把它弄清楚,可能会对阅读其它代码形...
  • absurd
  • absurd
  • 2007年10月02日 14:47
  • 4038

X Window研究笔记(12)

X Window研究笔记(12)转载时请注明出处和作者联系方式作者联系方式:李先静 12.X Window扩展机制--截取点XWindow提供了另外一种扩展机制,可以在一些关键位置设置截取点,换句话说...
  • absurd
  • absurd
  • 2007年09月26日 21:08
  • 3301
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:X Window研究笔记(6)
举报原因:
原因补充:

(最多只允许输入30个字)