Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: uinput - add UI_GET_SYSNAME ioctl to retrieve the sysfs path

uinput is used in the xorg-integration-tests suite and in the wayland
test suite. These automated tests suites create many virtual input
devices and then hook something to read these newly created devices.

Currently, uinput does not provide the created input device, which means
that we rely on an heuristic to guess which input node was created.
The problem is that is heuristic is subjected to races between different
uinput devices or even with physical devices. Having a way to retrieve
the sysfs path allows us to find without any doubts the event node.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Benjamin Tissoires and committed by
Dmitry Torokhov
e3480a61 9d51e801

+57 -1
+43
drivers/input/misc/uinput.c
··· 20 20 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> 21 21 * 22 22 * Changes/Revisions: 23 + * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) 24 + * - add UI_GET_SYSNAME ioctl 23 25 * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) 24 26 * - updated ff support for the changes in kernel interface 25 27 * - added MODULE_VERSION ··· 672 670 __ret; \ 673 671 }) 674 672 673 + static int uinput_str_to_user(void __user *dest, const char *str, 674 + unsigned int maxlen) 675 + { 676 + char __user *p = dest; 677 + int len, ret; 678 + 679 + if (!str) 680 + return -ENOENT; 681 + 682 + if (maxlen == 0) 683 + return -EINVAL; 684 + 685 + len = strlen(str) + 1; 686 + if (len > maxlen) 687 + len = maxlen; 688 + 689 + ret = copy_to_user(p, str, len); 690 + if (ret) 691 + return -EFAULT; 692 + 693 + /* force terminating '\0' */ 694 + ret = put_user(0, p + len - 1); 695 + return ret ? -EFAULT : len; 696 + } 697 + 675 698 static long uinput_ioctl_handler(struct file *file, unsigned int cmd, 676 699 unsigned long arg, void __user *p) 677 700 { ··· 706 679 struct uinput_ff_erase ff_erase; 707 680 struct uinput_request *req; 708 681 char *phys; 682 + const char *name; 683 + unsigned int size; 709 684 710 685 retval = mutex_lock_interruptible(&udev->mutex); 711 686 if (retval) ··· 858 829 req->retval = ff_erase.retval; 859 830 uinput_request_done(udev, req); 860 831 goto out; 832 + } 833 + 834 + size = _IOC_SIZE(cmd); 835 + 836 + /* Now check variable-length commands */ 837 + switch (cmd & ~IOCSIZE_MASK) { 838 + case UI_GET_SYSNAME(0): 839 + if (udev->state != UIST_CREATED) { 840 + retval = -ENOENT; 841 + goto out; 842 + } 843 + name = dev_name(&udev->dev->dev); 844 + retval = uinput_str_to_user(p, name, size); 845 + goto out; 861 846 } 862 847 863 848 retval = -EINVAL;
+2
include/linux/uinput.h
··· 20 20 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> 21 21 * 22 22 * Changes/Revisions: 23 + * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) 24 + * - add UI_GET_SYSNAME ioctl 23 25 * 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>) 24 26 * - update ff support for the changes in kernel interface 25 27 * - add UINPUT_VERSION
+12 -1
include/uapi/linux/uinput.h
··· 20 20 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> 21 21 * 22 22 * Changes/Revisions: 23 + * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) 24 + * - add UI_GET_SYSNAME ioctl 23 25 * 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>) 24 26 * - update ff support for the changes in kernel interface 25 27 * - add UINPUT_VERSION ··· 37 35 #include <linux/types.h> 38 36 #include <linux/input.h> 39 37 40 - #define UINPUT_VERSION 3 38 + #define UINPUT_VERSION 4 41 39 42 40 43 41 struct uinput_ff_upload { ··· 74 72 #define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload) 75 73 #define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase) 76 74 #define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase) 75 + 76 + /** 77 + * UI_GET_SYSNAME - get the sysfs name of the created uinput device 78 + * 79 + * @return the sysfs name of the created virtual input device. 80 + * The complete sysfs path is then /sys/devices/virtual/input/--NAME-- 81 + * Usually, it is in the form "inputN" 82 + */ 83 + #define UI_GET_SYSNAME(len) _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 300, len) 77 84 78 85 /* 79 86 * To write a force-feedback-capable driver, the upload_effect