Skip to content

Commit aea415b

Browse files
marcospsdtor
authored andcommitted
Input: add uinput documentation
Add description of uinput module with a few examples. Signed-off-by: Marcos Paulo de Souza <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 1613976 commit aea415b

File tree

2 files changed

+246
-0
lines changed

2 files changed

+246
-0
lines changed

Documentation/input/input_uapi.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ Linux Input Subsystem userspace API
1818
gamepad
1919
ff
2020
joydev/index
21+
uinput
2122
userio

Documentation/input/uinput.rst

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
=============
2+
uinput module
3+
=============
4+
5+
Introduction
6+
============
7+
8+
uinput is a kernel module that makes it possible to emulate input devices
9+
from userspace. By writing to /dev/uinput (or /dev/input/uinput) device, a
10+
process can create a virtual input device with specific capabilities. Once
11+
this virtual device is created, the process can send events through it,
12+
that will be delivered to userspace and in-kernel consumers.
13+
14+
Interface
15+
=========
16+
17+
::
18+
19+
linux/uinput.h
20+
21+
The uinput header defines ioctls to create, set up, and destroy virtual
22+
devices.
23+
24+
libevdev
25+
========
26+
27+
libevdev is a wrapper library for evdev devices that provides interfaces to
28+
create uinput devices and send events. libevdev is less error-prone than
29+
accessing uinput directly, and should be considered for new software.
30+
31+
For examples and more information about libevdev:
32+
https://www.freedesktop.org/software/libevdev/doc/latest/
33+
34+
Examples
35+
========
36+
37+
Keyboard events
38+
---------------
39+
40+
This first example shows how to create a new virtual device, and how to
41+
send a key event. All default imports and error handlers were removed for
42+
the sake of simplicity.
43+
44+
.. code-block:: c
45+
46+
#include <linux/uinput.h>
47+
48+
void emit(int fd, int type, int code, int val)
49+
{
50+
struct input_event ie;
51+
52+
ie.type = type;
53+
ie.code = code;
54+
ie.value = val;
55+
/* timestamp values below are ignored */
56+
ie.time.tv_sec = 0;
57+
ie.time.tv_usec = 0;
58+
59+
write(fd, &ie, sizeof(ie));
60+
}
61+
62+
int main(void)
63+
{
64+
struct uinput_setup usetup;
65+
66+
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
67+
68+
69+
/*
70+
* The ioctls below will enable the device that is about to be
71+
* created, to pass key events, in this case the space key.
72+
*/
73+
ioctl(fd, UI_SET_EVBIT, EV_KEY);
74+
ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
75+
76+
memset(&usetup, 0, sizeof(usetup));
77+
usetup.id.bustype = BUS_USB;
78+
usetup.id.vendor = 0x1234; /* sample vendor */
79+
usetup.id.product = 0x5678; /* sample product */
80+
strcpy(usetup.name, "Example device");
81+
82+
ioctl(fd, UI_DEV_SETUP, &usetup);
83+
ioctl(fd, UI_DEV_CREATE);
84+
85+
/*
86+
* On UI_DEV_CREATE the kernel will create the device node for this
87+
* device. We are inserting a pause here so that userspace has time
88+
* to detect, initialize the new device, and can start listening to
89+
* the event, otherwise it will not notice the event we are about
90+
* to send. This pause is only needed in our example code!
91+
*/
92+
sleep(1);
93+
94+
/* Key press, report the event, send key release, and report again */
95+
emit(fd, EV_KEY, KEY_SPACE, 1);
96+
emit(fd, EV_SYN, SYN_REPORT, 0);
97+
emit(fd, EV_KEY, KEY_SPACE, 0);
98+
emit(fd, EV_SYN, SYN_REPORT, 0);
99+
100+
/*
101+
* Give userspace some time to read the events before we destroy the
102+
* device with UI_DEV_DESTOY.
103+
*/
104+
sleep(1);
105+
106+
ioctl(fd, UI_DEV_DESTROY);
107+
close(fd);
108+
109+
return 0;
110+
}
111+
112+
Mouse movements
113+
---------------
114+
115+
This example shows how to create a virtual device that behaves like a physical
116+
mouse.
117+
118+
.. code-block:: c
119+
120+
#include <linux/uinput.h>
121+
122+
/* emit function is identical to of the first example */
123+
124+
int main(void)
125+
{
126+
struct uinput_setup usetup;
127+
int i = 50;
128+
129+
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
130+
131+
/* enable mouse button left and relative events */
132+
ioctl(fd, UI_SET_EVBIT, EV_KEY);
133+
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
134+
135+
ioctl(fd, UI_SET_EVBIT, EV_REL);
136+
ioctl(fd, UI_SET_RELBIT, REL_X);
137+
ioctl(fd, UI_SET_RELBIT, REL_Y);
138+
139+
memset(&usetup, 0, sizeof(usetup));
140+
usetup.id.bustype = BUS_USB;
141+
usetup.id.vendor = 0x1234; /* sample vendor */
142+
usetup.id.product = 0x5678; /* sample product */
143+
strcpy(usetup.name, "Example device");
144+
145+
ioctl(fd, UI_DEV_SETUP, &usetup);
146+
ioctl(fd, UI_DEV_CREATE);
147+
148+
/*
149+
* On UI_DEV_CREATE the kernel will create the device node for this
150+
* device. We are inserting a pause here so that userspace has time
151+
* to detect, initialize the new device, and can start listening to
152+
* the event, otherwise it will not notice the event we are about
153+
* to send. This pause is only needed in our example code!
154+
*/
155+
sleep(1);
156+
157+
/* Move the mouse diagonally, 5 units per axis */
158+
while (i--) {
159+
emit(fd, EV_REL, REL_X, 5);
160+
emit(fd, EV_REL, REL_Y, 5);
161+
emit(fd, EV_SYN, SYN_REPORT, 0);
162+
usleep(15000);
163+
}
164+
165+
/*
166+
* Give userspace some time to read the events before we destroy the
167+
* device with UI_DEV_DESTOY.
168+
*/
169+
sleep(1);
170+
171+
ioctl(fd, UI_DEV_DESTROY);
172+
close(fd);
173+
174+
return 0;
175+
}
176+
177+
178+
uinput old interface
179+
--------------------
180+
181+
Before uinput version 5, there wasn't a dedicated ioctl to set up a virtual
182+
device. Programs supportinf older versions of uinput interface need to fill
183+
a uinput_user_dev structure and write it to the uinput file descriptor to
184+
configure the new uinput device. New code should not use the old interface
185+
but interact with uinput via ioctl calls, or use libevdev.
186+
187+
.. code-block:: c
188+
189+
#include <linux/uinput.h>
190+
191+
/* emit function is identical to of the first example */
192+
193+
int main(void)
194+
{
195+
struct uinput_user_dev uud;
196+
int version, rc, fd;
197+
198+
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
199+
rc = ioctl(fd, UI_GET_VERSION, &version);
200+
201+
if (rc == 0 && version >= 5) {
202+
/* use UI_DEV_SETUP */
203+
return 0;
204+
}
205+
206+
/*
207+
* The ioctls below will enable the device that is about to be
208+
* created, to pass key events, in this case the space key.
209+
*/
210+
ioctl(fd, UI_SET_EVBIT, EV_KEY);
211+
ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
212+
213+
memset(&uud, 0, sizeof(uud));
214+
snprintf(uud.name, UINPUT_MAX_NAME_SIZE, "uinput old interface");
215+
write(fd, &uud, sizeof(uud));
216+
217+
ioctl(fd, UI_DEV_CREATE);
218+
219+
/*
220+
* On UI_DEV_CREATE the kernel will create the device node for this
221+
* device. We are inserting a pause here so that userspace has time
222+
* to detect, initialize the new device, and can start listening to
223+
* the event, otherwise it will not notice the event we are about
224+
* to send. This pause is only needed in our example code!
225+
*/
226+
sleep(1);
227+
228+
/* Key press, report the event, send key release, and report again */
229+
emit(fd, EV_KEY, KEY_SPACE, 1);
230+
emit(fd, EV_SYN, SYN_REPORT, 0);
231+
emit(fd, EV_KEY, KEY_SPACE, 0);
232+
emit(fd, EV_SYN, SYN_REPORT, 0);
233+
234+
/*
235+
* Give userspace some time to read the events before we destroy the
236+
* device with UI_DEV_DESTOY.
237+
*/
238+
sleep(1);
239+
240+
ioctl(fd, UI_DEV_DESTROY);
241+
242+
close(fd);
243+
return 0;
244+
}
245+

0 commit comments

Comments
 (0)