linux uinput
本文以 2.6.22.7 的kernel 为基础。
首先 uinput 是一个字符设备, 其次它还是一个 input 设备。另外它可以是一个鼠标或者键盘设备。
从 init 部分说起吧。
static const struct file_operations uinput_fops = {
.owner = THIS_MODULE,
.open = uinput_open,
.release = uinput_release,
.read = uinput_read,
.write = uinput_write,
.poll = uinput_poll,
.unlocked_ioctl = uinput_ioctl,
};
static struct miscdevice uinput_misc = {
.fops = &uinput_fops,
.minor = UINPUT_MINOR,
.name = UINPUT_NAME,
};
static int __init uinput_init(void)
{
return misc_register(&uinput_misc);
}
首先说说 miscdevice, 很方便的东西,对 device 做了简单的包装,
当 misc_register 的时候就完成了 设备的 注册安装一类的东东, 不用自己再操心了。真是懒人的设计阿。
所有的 misc 设备公用同一个主设备号,在 misc_init 中,
static int __init misc_init(void)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *ent;
ent = create_proc_entry("misc", 0, NULL);
if (ent)
ent->proc_fops = &misc_proc_fops;
#endif
misc_class = class_create(THIS_MODULE, "misc");
if (IS_ERR(misc_class))
return PTR_ERR(misc_class);
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices/n",
MISC_MAJOR);
class_destroy(misc_class);
return -EIO;
}
return 0;
}
register_chrdev 接口真 BT ,
__register_chrdev_region(major, 0, 256, name);
直接占用了 0 到 255 的次设备号,注册 misc 类型设备的时候,直接从里面取就是了。
而在 misc_open 通过设备节点把 file_operations 指向对应的设备驱动上去, 很良好的设计, 呵呵。
有点类似其他总线的设计, 但是只有 device_list, 没有 driver_list, 当然也不需要。
不在 misc 上浪费时间了。 接下来再到 uinput 中去。
从uinput_open 说起吧, uinput_open 其实啥事情都没干。。做了一些简单的初始化工作。
要创建一个 input 设备,我们在调用input_register_device 前需要设置 好input_dev的各种属性。
而设置input_dev的属性在 uinput_setup_device 接口中, 但驱动怎么知道你想模拟什么设备呢?
又需要通过 uinput_ioctl 设置先。 很糟糕的设计。 用户若是不知道这些流程,如何能使用这个模拟驱动?
下面是一个使用 uinput 的用户态程序:
int setup_uinput_device(char *device)
{
// Temporary variable
int i=0;
// Open the input device
//uinp_fd = open("/dev/input/uinput", O_WRONLY | O_NDELAY);
uinp_fd = open(device, O_WRONLY | O_NDELAY);
if (uinp_fd == 0)
{
printf("Unable to open /dev/input/uinput/n");
return -1;
}
memset(&uinp,0,sizeof(uinp)); // Intialize the uInput device to NULL
strncpy(uinp.name, "HID Keyboard Device", strlen("HID Keyboard Device"));
uinp.id.version = 4;
uinp.id.bustype = BUS_USB;
uinp.id.product = 1;
uinp.id.vendor = 1;
// Setup the uinput device
ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
ioctl(uinp_fd, UI_SET_EVBIT, EV_REL);
ioctl(uinp_fd, UI_SET_RELBIT, REL_X);
ioctl(uinp_fd, UI_SET_RELBIT, REL_Y);
for (i=0; i < 256; i++) {
ioctl(uinp_fd, UI_SET_KEYBIT, i);
}
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MOUSE);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_TOUCH);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MOUSE);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_LEFT);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MIDDLE);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_RIGHT);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_FORWARD);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_BACK);
write(uinp_fd, &uinp, sizeof(uinp));
if (ioctl(uinp_fd, UI_DEV_CREATE))
{
printf("Unable to create UINPUT device.");
return -1;
}
return 1;
}
很变态的流程, 先用 ioctl 设置参数(模拟鼠标,键盘), 再 write, 在第一次 write 的时候创建 inputdev,
然后 ioctl 调用 UI_DEV_CREATE 向系统注册 . BT............
今天先写到这里拉。。
linux uinput 分析。
最新推荐文章于 2024-05-19 15:52:07 发布