]>
Commit | Line | Data |
---|---|---|
aea415b1 MPS |
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 |