Linux版本:linux-3.13.3
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函数。
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按键。
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设备创建完成。
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层。