X Window研究笔记(6)

本文介绍了TinyX系统中输入设备驱动的实现细节,包括键盘、鼠标和触摸屏的驱动接口定义及其初始化过程。详细解释了LinuxKeyboardFuncs和LinuxMouseFuncs的各个函数作用,以及如何在有输入事件时调用相应函数进行事件处理。
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的驱动接口

typedefstruct_KdKeyboardFuncs...{
void(*Load)(void);
int(*Init)(void);
void(*Leds)(int);
void(*Bell)(int,int,int);
void(*Fini)(void);
intLockLed;
}
KdKeyboardFuncs;


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

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

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

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


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

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


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

staticvoid
LinuxKeyboardLeds(
intleds)
...{
ioctl(LinuxConsoleFd,KDSETLED,leds
&7);
}


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

}

}


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

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


鼠标的接口:


typedefstruct_KdMouseFuncs...{
int(*Init)(void);
void(*Fini)(void);
}
KdMouseFuncs;

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

KdMouseFuncsLinuxMouseFuncs=...{
MouseInit,
MouseFini,
}
;

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

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

#defineNUM_DEFAULT_MOUSE(sizeof(kdefaultMouse)/sizeof(kdefaultMouse[0]))

staticint
MouseInit(
void)
...{
inti;
intfd=-1;
Kmouse
*km;
KdMouseInfo
*mi,*next;
intn=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);
}

}

returnn;
}


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

staticvoid
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;
}

}

}



触摸屏的接口

typedefstruct_KdMouseFuncs...{
int(*Init)(void);
void(*Fini)(void);
}
KdMouseFuncs;


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

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

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

int
TslibInit(
void)
...{
inti;
KdMouseInfo
*mi,*next;
intfd=0;
intn=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;
}

}

}

}


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

(待续)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值