Linux uinput驱动分析
http://blog.csdn.net/mcgrady_tracy/article/details/22938181
Linux版本:linux-3.13.3
uinput是Linux提供的一个可以在用户空间创建input设备的驱动程序,init部分代码如下:
877 static int __init uinput_init(void)
878 {
879 return misc_register(&uinput_misc);
880 }
在uinput_init函数中,调用misc_register创建了一个混杂设备,所谓混杂设备本质上主设备号为10的一个字符设备,uinput_misc定义如下:
869 static struct miscdevice uinput_misc = {
870 .fops = &uinput_fops,
871 .minor = UINPUT_MINOR,
872 .name = UINPUT_NAME,
873 };
uinput_fops定义如下:
855 static const struct file_operations uinput_fops = {
856 .owner = THIS_MODULE,
857 .open = uinput_open,
858 .release = uinput_release,
859 .read = uinput_read,
860 .write = uinput_write,
861 .poll = uinput_poll,
862 .unlocked_ioctl = uinput_ioctl,
863 #ifdef CONFIG_COMPAT
864 .compat_ioctl = uinput_compat_ioctl,
865 #endif
866 .llseek = no_llseek,
867 };
在uinput应用程序中,我们首先是调用的open系统调用,uinput_open函数实现如下:
289 static int uinput_open(struct inode *inode, struct file *file)
290 {
291 struct uinput_device *newdev;
292
293 newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL);
294 if (!newdev)
295 return -ENOMEM;
296
297 mutex_init(&newdev->mutex);
298 spin_lock_init(&newdev->requests_lock);
299 init_waitqueue_head(&newdev->requests_waitq);
300 init_waitqueue_head(&newdev->waitq);
301 newdev->state = UIST_NEW_DEVICE;
302
303 file->private_data = newdev;
304 nonseekable_open(inode, file);
305
306 return 0;
307 }
其实质是调用kzalloc创建了一个struct uinput_device结构,初始化了struct uinput_device结构中的一些成员。然后再看uinput_ioctl函数:
842 static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
843 {
844 return uinput_ioctl_handler(file, cmd, arg, (void __user *)arg);
845 }
直接调用了uinput_ioctl_handler函数。
在uinput_ioctl_handler函数中,我们只看我们需要的键盘部分:
687 if (!udev->dev) {
688 retval = uinput_allocate_device(udev);
689 if (retval)
690 goto out;
691 }
初始时,struct uinput_device中的dev成员值为NULL,那么会调用uinput_allocate_device函数去创建。
348 static int uinput_allocate_device(struct uinput_device *udev)
349 {
350 udev->dev = input_allocate_device();
351 if (!udev->dev)
352 return -ENOMEM;
353
354 udev->dev->event = uinput_dev_event;
355 input_set_drvdata(udev->dev, udev);
356
357 return 0;
358 }
在uinput_allocate_device函数中,调用input_allocate_device函数去分配了input设备,并设置了它的event为uinput_dev_event。回到ioctl函数中。
693 switch (cmd) {
694 case UI_DEV_CREATE:
695 retval = uinput_create_device(udev);
696 break;
697
698 case UI_DEV_DESTROY:
699 uinput_destroy_device(udev);
700 break;
701
702 case UI_SET_EVBIT:
703 retval = uinput_set_bit(arg, evbit, EV_MAX);
704 break;
705
706 case UI_SET_KEYBIT:
707 retval = uinput_set_bit(arg, keybit, KEY_MAX);
708 break;
在应用程序中,调用了两次ioctl函数:
ret = ioctl(fd, UI_SET_EVBIT, EV_KEY); ret = ioctl(fd, UI_SET_EVBIT, EV_SYN);
即最后设置了struct input_dev结构中的evbit,而evbit中的位表示支持的时间类型。
ret = ioctl(fd, UI_SET_KEYBIT, KEY_D);
设置了struct input_dev结构中的keybit,keybit表示支持的按键键值,这里只支持了KEY_D按键。
然后看write函数:
459 static ssize_t uinput_write(struct file *file, const char __user *buffer,
460 size_t count, loff_t *ppos)
461 {
462 struct uinput_device *udev = file->private_data;
463 int retval;
464
465 if (count == 0)
466 return 0;
467
468 retval = mutex_lock_interruptible(&udev->mutex);
469 if (retval)
470 return retval;
471
472 retval = udev->state == UIST_CREATED ?
473 uinput_inject_events(udev, buffer, count) :
474 uinput_setup_device(udev, buffer, count);
475
476 mutex_unlock(&udev->mutex);
477
478 return retval;
479 }
在wirte函数中,由于此时我们还没有创建input设备,所以此时uinput设备的状态不是UIST_CREATED,所以为首先调用uinput_setup_device函数。
360 static int uinput_setup_device(struct uinput_device *udev,
361 const char __user *buffer, size_t count)
362 {
363 struct uinput_user_dev *user_dev;
364 struct input_dev *dev;
365 int i;
366 int retval;
367
368 if (count != sizeof(struct uinput_user_dev))
369 return -EINVAL;
370
371 if (!udev->dev) {
372 retval = uinput_allocate_device(udev);
373 if (retval)
374 return retval;
375 }
376
377 dev = udev->dev;
378
379 user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
380 if (IS_ERR(user_dev))
381 return PTR_ERR(user_dev);
382
383 udev->ff_effects_max = user_dev->ff_effects_max;
384
385 /* Ensure name is filled in */
386 if (!user_dev->name[0]) {
387 retval = -EINVAL;
388 goto exit;
389 }
390
391 kfree(dev->name);
392 dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
393 GFP_KERNEL);
394 if (!dev->name) {
395 retval = -ENOMEM;
396 goto exit;
397 }
398
399 dev->id.bustype = user_dev->id.bustype;
400 dev->id.vendor = user_dev->id.vendor;
401 dev->id.product = user_dev->id.product;
402 dev->id.version = user_dev->id.version;
403
404 for (i = 0; i < ABS_CNT; i++) {
405 input_abs_set_max(dev, i, user_dev->absmax[i]);
406 input_abs_set_min(dev, i, user_dev->absmin[i]);
407 input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
408 input_abs_set_flat(dev, i, user_dev->absflat[i]);
409 }
410
411 /* check if absmin/absmax/absfuzz/absflat are filled as
412 * told in Documentation/input/input-programming.txt */
413 if (test_bit(EV_ABS, dev->evbit)) {
414 retval = uinput_validate_absbits(dev);
415 if (retval < 0)
416 goto exit;
417 if (test_bit(ABS_MT_SLOT, dev->absbit)) {
418 int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
419 input_mt_init_slots(dev, nslot, 0);
420 } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
421 input_set_events_per_packet(dev, 60);
422 }
423 }
424
425 udev->state = UIST_SETUP_COMPLETE;
426 retval = count;
427
428 exit:
429 kfree(user_dev);
430 return retval;
431 }
那自然是获取应用层创建的struct uinput_user_dev,初始化struct input_dev中的成员。
ret = ioctl(fd, UI_DEV_CREATE);
然后注册struct input_dev设备。
254 static int uinput_create_device(struct uinput_device *udev)
255 {
256 struct input_dev *dev = udev->dev;
257 int error;
258
259 if (udev->state != UIST_SETUP_COMPLETE) {
260 printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
261 return -EINVAL;
262 }
263
264 if (udev->ff_effects_max) {
265 error = input_ff_create(dev, udev->ff_effects_max);
266 if (error)
267 goto fail1;
268
269 dev->ff->upload = uinput_dev_upload_effect;
270 dev->ff->erase = uinput_dev_erase_effect;
271 dev->ff->playback = uinput_dev_playback;
272 dev->ff->set_gain = uinput_dev_set_gain;
273 dev->ff->set_autocenter = uinput_dev_set_autocenter;
274 }
275
276 error = input_register_device(udev->dev);
277 if (error)
278 goto fail2;
279
280 udev->state = UIST_CREATED;
281
282 return 0;
283
284 fail2: input_ff_destroy(dev);
285 fail1: uinput_destroy_device(udev);
286 return error;
287 }
最后调用input_register_device注册了一个input设备,input设备创建完成。
最后是调用write发送数据。
input设备已经创建,那在write函数中自然是调用uinput_inject_events函数。
433 static ssize_t uinput_inject_events(struct uinput_device *udev,
434 const char __user *buffer, size_t count)
435 {
436 struct input_event ev;
437 size_t bytes = 0;
438
439 if (count != 0 && count < input_event_size())
440 return -EINVAL;
441
442 while (bytes + input_event_size() <= count) {
443 /*
444 * Note that even if some events were fetched successfully
445 * we are still going to return EFAULT instead of partial
446 * count to let userspace know that it got it's buffers
447 * all wrong.
448 */
449 if (input_event_from_user(buffer + bytes, &ev))
450 return -EFAULT;
451
452 input_event(udev->dev, ev.type, ev.code, ev.value);
453 bytes += input_event_size();
454 }
455
456 return bytes;
457 }
最后调用input_event函数将报告发送给input层。
最后总结一下,在open函数中,分配了一个uinput_device设备,调用ioctl去注册一个input设备,注册input设备调用的是input_register_device函数,最后在write函数调用input_event发送报告。

浙公网安备 33010602011771号