xinput系统简介
SylixOS提供了一个xinput子系统,对键盘、鼠标、触摸屏等设备进行了一个统一管理,SylixOS的xinput系统支持热插拔,可随意添加删除输入设备,使用上很方便、很灵活,下面我们从一个框架图开始来开始学习SylixOS xinput子系统。
xinput分析
xinput系统框架图
从图中看xinput系统分为3层:xinput设备层驱动层,xinput核心处理层,物理设备层,下面我们结合源码来分析个层的含义
xinput设备驱动层
xinput设备将所有输入设备抽象成了键盘和鼠标设备(xmse、xkbd),并且实现了标准的NEW_1型驱动,如下代码片段所示,这样对于上层如Qt应用就可以像操作普通文件那样对键盘、鼠标、触摸屏等设备进行正常的读操作了。
...
fileop.owner = THIS_MODULE;
fileop.fo_create = xinput_open;
fileop.fo_open = xinput_open;
fileop.fo_close = xinput_close;
fileop.fo_read = xinput_read;
fileop.fo_lstat = xinput_lstat;
fileop.fo_ioctl = xinput_ioctl;
xinput_drv_num = iosDrvInstallEx2(&fileop, LW_DRV_TYPE_NEW_1);
...
xinput核心处理层
xinput的核心处理层负责监控物理设备的热插拔事件,以及从物理设备层取得输入事件,然后通知给xinput设备驱动层,以唤醒上层的应用。这些处理过程都在一个线程中完成,下面代码片段是这个线程的部分工作。
xinput_hotplug_fd = open("/dev/hotplug", O_RDONLY);
for (;;) {
if (need_check) { /* need check if a device has been plug on */
xdev_try_open();
}
...
ret = select(width, &fdset, LW_NULL, LW_NULL, &timeval);
...
temp = read(xinput_hotplug_fd, hpmsg, LW_HOTPLUG_DEV_MAX_MSGSIZE);
...
temp = read(input->fd, (PVOID)&knotify, sizeof(knotify));
API_MsgQueueSend(kdb_xinput.queue, (void *)&knotify, (u_long)temp);
SEL_WAKE_UP_ALL(&kdb_xinput.sel_list, SELREAD);
...
temp = read(input->fd, (PVOID)mnotify,
sizeof(mouse_event_notify) * MAX_INPUT_POINTS);
API_MsgQueueSend(mse_xinput.queue, (void *)mnotify, (u_long)temp);
SEL_WAKE_UP_ALL(&mse_xinput.sel_list, SELREAD);
...
}
...
上面的代码片段只是保留了能够说明工作内容的部分,可能看起来很怪,但从这些片段中足以让我们了解了xinput层3个工作内容:
- 读取“/dev/hotplug”监视设备的插拔;
- 读取knotify(键盘类事件),唤醒xinput读;
- 读取mnotify(鼠标类事件),唤醒xinput读.
代码的详细实现可参看SylixOS源码。
物理设备层
这一层包括了各种输入设备,如USB鼠标、USB键盘、触摸屏、PCI输入设备等,这些设备驱动需要驱动程序员自己编写,需要注意的是,这些设备驱动应该传递下面的键盘或者鼠标事件给xinput子系统。
下面是键盘事件结构:
typedef struct keyboard_event_notify {
int32_t nmsg; /* message num, usually one msg*/
int32_t type; /* press or release */
int32_t ledstate; /* LED stat */
int32_t fkstat; /* func-key stat */
int32_t keymsg[KE_MAX_KEY_ST]; /* key code */
} keyboard_event_notify;
下面是鼠标事件结构:
typedef struct mouse_event_notify {
int32_t ctype; /* coordinate type */
int32_t kstat; /* mouse button stat */
int32_t wscroll[MOUSE_MAX_WHEEL]; /* wheel scroll */
int32_t xmovement; /* the relative displacement */
int32_t ymovement;
/*
* if use absolutely coordinate (such as touch screen)
* if you use touch screen:
* (kstat & MOUSE_LEFT) != 0 (press)
* (kstat & MOUSE_LEFT) == 0 (release)
*/
#define xanalog xmovement /* analog samples values */
#define yanalog ymovement
} mouse_event_notify;