blob: 26ec603fe2208522bf562954e452d69e2500527a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * User level driver support for input subsystem
3 *
4 * Heavily based on evdev.c by Vojtech Pavlik
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
21 *
22 * Changes/Revisions:
Benjamin Tissoirese3480a62014-01-30 17:20:24 -080023 * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
24 * - add UI_GET_SYSNAME ioctl
Anssi Hannulaff462552006-07-19 01:41:09 -040025 * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>)
26 * - updated ff support for the changes in kernel interface
27 * - added MODULE_VERSION
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
29 * - added force feedback support
30 * - added UI_SET_PHYS
31 * 0.1 20/06/2002
32 * - first public version
33 */
Dmitry Torokhova11bc4762017-09-04 12:19:07 -070034#include <uapi/linux/uinput.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/poll.h>
Alexey Dobriyana99bbaf2009-10-04 16:11:37 +040036#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/slab.h>
38#include <linux/module.h>
39#include <linux/init.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/fs.h>
41#include <linux/miscdevice.h>
Dmitry Torokhovd77651a2019-01-14 13:54:55 -080042#include <linux/overflow.h>
Henrik Rydberg47c78e82010-11-27 09:16:48 +010043#include <linux/input/mt.h>
Philip Langdale2d56f3a2008-10-16 22:31:42 -040044#include "../input-compat.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Dmitry Torokhova11bc4762017-09-04 12:19:07 -070046#define UINPUT_NAME "uinput"
47#define UINPUT_BUFFER_SIZE 16
48#define UINPUT_NUM_REQUESTS 16
49
50enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
51
52struct uinput_request {
53 unsigned int id;
54 unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */
55
56 int retval;
57 struct completion done;
58
59 union {
60 unsigned int effect_id;
61 struct {
62 struct ff_effect *effect;
63 struct ff_effect *old;
64 } upload;
65 } u;
66};
67
68struct uinput_device {
69 struct input_dev *dev;
70 struct mutex mutex;
71 enum uinput_state state;
72 wait_queue_head_t waitq;
73 unsigned char ready;
74 unsigned char head;
75 unsigned char tail;
76 struct input_event buff[UINPUT_BUFFER_SIZE];
77 unsigned int ff_effects_max;
78
79 struct uinput_request *requests[UINPUT_NUM_REQUESTS];
80 wait_queue_head_t requests_waitq;
81 spinlock_t requests_lock;
82};
83
Dmitry Torokhov54ce1652012-07-29 22:48:32 -070084static int uinput_dev_event(struct input_dev *dev,
85 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070086{
Dmitry Torokhov373f9712007-04-12 01:34:33 -040087 struct uinput_device *udev = input_get_drvdata(dev);
Deepa Dinamanib3495cec2018-01-01 22:27:11 -080088 struct timespec64 ts;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90 udev->buff[udev->head].type = type;
91 udev->buff[udev->head].code = code;
92 udev->buff[udev->head].value = value;
Deepa Dinamanib3495cec2018-01-01 22:27:11 -080093 ktime_get_ts64(&ts);
Deepa Dinamani152194f2018-01-07 17:44:42 -080094 udev->buff[udev->head].input_event_sec = ts.tv_sec;
95 udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
97
98 wake_up_interruptible(&udev->waitq);
99
100 return 0;
101}
102
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700103/* Atomically allocate an ID for the given request. Returns 0 on success. */
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700104static bool uinput_request_alloc_id(struct uinput_device *udev,
105 struct uinput_request *request)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106{
Dmitry Torokhovc5b35332012-07-29 22:48:32 -0700107 unsigned int id;
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700108 bool reserved = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500110 spin_lock(&udev->requests_lock);
Dmitry Torokhov152c12f2005-06-30 00:47:50 -0500111
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700112 for (id = 0; id < UINPUT_NUM_REQUESTS; id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 if (!udev->requests[id]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 request->id = id;
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500115 udev->requests[id] = request;
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700116 reserved = true;
Dmitry Torokhov152c12f2005-06-30 00:47:50 -0500117 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 }
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700119 }
Dmitry Torokhov152c12f2005-06-30 00:47:50 -0500120
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500121 spin_unlock(&udev->requests_lock);
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700122 return reserved;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123}
124
Dmitry Torokhovc5b35332012-07-29 22:48:32 -0700125static struct uinput_request *uinput_request_find(struct uinput_device *udev,
126 unsigned int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
128 /* Find an input request, by ID. Returns NULL if the ID isn't valid. */
Dmitry Torokhovc5b35332012-07-29 22:48:32 -0700129 if (id >= UINPUT_NUM_REQUESTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 return NULL;
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 return udev->requests[id];
133}
134
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700135static int uinput_request_reserve_slot(struct uinput_device *udev,
136 struct uinput_request *request)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137{
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500138 /* Allocate slot. If none are available right away, wait. */
139 return wait_event_interruptible(udev->requests_waitq,
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700140 uinput_request_alloc_id(udev, request));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141}
142
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700143static void uinput_request_release_slot(struct uinput_device *udev,
144 unsigned int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145{
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500146 /* Mark slot as available */
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700147 spin_lock(&udev->requests_lock);
148 udev->requests[id] = NULL;
149 spin_unlock(&udev->requests_lock);
Dmitry Torokhove7507ed2005-10-17 16:43:32 -0700150
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700151 wake_up(&udev->requests_waitq);
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500152}
153
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700154static int uinput_request_send(struct uinput_device *udev,
155 struct uinput_request *request)
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500156{
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700157 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700159 retval = mutex_lock_interruptible(&udev->mutex);
160 if (retval)
161 return retval;
162
163 if (udev->state != UIST_CREATED) {
164 retval = -ENODEV;
165 goto out;
166 }
167
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700168 init_completion(&request->done);
169
170 /*
171 * Tell our userspace application about this new request
172 * by queueing an input event.
173 */
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700174 uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);
175
176 out:
177 mutex_unlock(&udev->mutex);
178 return retval;
179}
180
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700181static int uinput_request_submit(struct uinput_device *udev,
182 struct uinput_request *request)
183{
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700184 int retval;
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700185
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700186 retval = uinput_request_reserve_slot(udev, request);
187 if (retval)
188 return retval;
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700189
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700190 retval = uinput_request_send(udev, request);
191 if (retval)
192 goto out;
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700193
Dmitry Torokhov8e009112017-09-06 16:31:29 -0700194 if (!wait_for_completion_timeout(&request->done, 30 * HZ)) {
195 retval = -ETIMEDOUT;
196 goto out;
197 }
198
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700199 retval = request->retval;
200
201 out:
202 uinput_request_release_slot(udev, request->id);
203 return retval;
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700204}
205
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700206/*
Dmitry Torokhov54ce1652012-07-29 22:48:32 -0700207 * Fail all outstanding requests so handlers don't wait for the userspace
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700208 * to finish processing them.
209 */
210static void uinput_flush_requests(struct uinput_device *udev)
211{
212 struct uinput_request *request;
213 int i;
214
215 spin_lock(&udev->requests_lock);
216
217 for (i = 0; i < UINPUT_NUM_REQUESTS; i++) {
218 request = udev->requests[i];
219 if (request) {
220 request->retval = -ENODEV;
Dmitry Torokhov6b4877c72017-09-06 16:22:59 -0700221 complete(&request->done);
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700222 }
223 }
224
225 spin_unlock(&udev->requests_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226}
227
Anssi Hannulaff462552006-07-19 01:41:09 -0400228static void uinput_dev_set_gain(struct input_dev *dev, u16 gain)
229{
230 uinput_dev_event(dev, EV_FF, FF_GAIN, gain);
231}
232
233static void uinput_dev_set_autocenter(struct input_dev *dev, u16 magnitude)
234{
235 uinput_dev_event(dev, EV_FF, FF_AUTOCENTER, magnitude);
236}
237
238static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value)
239{
240 return uinput_dev_event(dev, EV_FF, effect_id, value);
241}
242
Dmitry Torokhov54ce1652012-07-29 22:48:32 -0700243static int uinput_dev_upload_effect(struct input_dev *dev,
244 struct ff_effect *effect,
245 struct ff_effect *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700247 struct uinput_device *udev = input_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 struct uinput_request request;
249
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400250 /*
251 * uinput driver does not currently support periodic effects with
252 * custom waveform since it does not have a way to pass buffer of
253 * samples (custom_data) to userspace. If ever there is a device
254 * supporting custom waveforms we would need to define an additional
255 * ioctl (UI_UPLOAD_SAMPLES) but for now we just bail out.
256 */
257 if (effect->type == FF_PERIODIC &&
258 effect->u.periodic.waveform == FF_CUSTOM)
259 return -EINVAL;
260
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500261 request.code = UI_FF_UPLOAD;
Anssi Hannulaff462552006-07-19 01:41:09 -0400262 request.u.upload.effect = effect;
263 request.u.upload.old = old;
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500264
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700265 return uinput_request_submit(udev, &request);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266}
267
268static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
269{
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700270 struct uinput_device *udev = input_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 struct uinput_request request;
272
273 if (!test_bit(EV_FF, dev->evbit))
274 return -ENOSYS;
275
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500276 request.code = UI_FF_ERASE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 request.u.effect_id = effect_id;
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500278
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700279 return uinput_request_submit(udev, &request);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280}
281
Dmitry Torokhove8b95722017-09-01 17:13:43 -0700282static int uinput_dev_flush(struct input_dev *dev, struct file *file)
283{
284 /*
285 * If we are called with file == NULL that means we are tearing
286 * down the device, and therefore we can not handle FF erase
287 * requests: either we are handling UI_DEV_DESTROY (and holding
288 * the udev->mutex), or the file descriptor is closed and there is
289 * nobody on the other side anymore.
290 */
291 return file ? input_ff_flush(dev, file) : 0;
292}
293
Dmitry Torokhov29506412005-11-20 00:51:22 -0500294static void uinput_destroy_device(struct uinput_device *udev)
295{
296 const char *name, *phys;
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700297 struct input_dev *dev = udev->dev;
298 enum uinput_state old_state = udev->state;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500299
Aristeu Sergio Rozanski Filho05cebd32009-05-14 22:01:57 -0700300 udev->state = UIST_NEW_DEVICE;
301
302 if (dev) {
303 name = dev->name;
304 phys = dev->phys;
305 if (old_state == UIST_CREATED) {
306 uinput_flush_requests(udev);
307 input_unregister_device(dev);
308 } else {
309 input_free_device(dev);
310 }
Dmitry Torokhov29506412005-11-20 00:51:22 -0500311 kfree(name);
312 kfree(phys);
313 udev->dev = NULL;
314 }
Dmitry Torokhov29506412005-11-20 00:51:22 -0500315}
316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317static int uinput_create_device(struct uinput_device *udev)
318{
Anssi Hannulaff462552006-07-19 01:41:09 -0400319 struct input_dev *dev = udev->dev;
David Herrmannfbae10d2015-10-25 10:34:13 +0100320 int error, nslot;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500321
322 if (udev->state != UIST_SETUP_COMPLETE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
324 return -EINVAL;
325 }
326
Dmitry Torokhov601bbbe2017-01-31 14:56:43 -0800327 if (test_bit(EV_ABS, dev->evbit)) {
328 input_alloc_absinfo(dev);
329 if (!dev->absinfo) {
330 error = -EINVAL;
David Herrmannfbae10d2015-10-25 10:34:13 +0100331 goto fail1;
Dmitry Torokhov601bbbe2017-01-31 14:56:43 -0800332 }
333
334 if (test_bit(ABS_MT_SLOT, dev->absbit)) {
335 nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
336 error = input_mt_init_slots(dev, nslot, 0);
337 if (error)
338 goto fail1;
339 } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
340 input_set_events_per_packet(dev, 60);
341 }
David Herrmannfbae10d2015-10-25 10:34:13 +0100342 }
343
Elias Vanderstuyftdaf6cd02015-12-18 17:32:19 -0800344 if (test_bit(EV_FF, dev->evbit) && !udev->ff_effects_max) {
345 printk(KERN_DEBUG "%s: ff_effects_max should be non-zero when FF_BIT is set\n",
346 UINPUT_NAME);
347 error = -EINVAL;
348 goto fail1;
349 }
350
Anssi Hannulaff462552006-07-19 01:41:09 -0400351 if (udev->ff_effects_max) {
352 error = input_ff_create(dev, udev->ff_effects_max);
353 if (error)
354 goto fail1;
355
356 dev->ff->upload = uinput_dev_upload_effect;
357 dev->ff->erase = uinput_dev_erase_effect;
358 dev->ff->playback = uinput_dev_playback;
359 dev->ff->set_gain = uinput_dev_set_gain;
360 dev->ff->set_autocenter = uinput_dev_set_autocenter;
Dmitry Torokhove8b95722017-09-01 17:13:43 -0700361 /*
362 * The standard input_ff_flush() implementation does
363 * not quite work for uinput as we can't reasonably
364 * handle FF requests during device teardown.
365 */
366 dev->flush = uinput_dev_flush;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 }
368
Dmitry Torokhov04ce40a2017-09-06 16:42:26 -0700369 dev->event = uinput_dev_event;
370
371 input_set_drvdata(udev->dev, udev);
372
Anssi Hannulaff462552006-07-19 01:41:09 -0400373 error = input_register_device(udev->dev);
374 if (error)
375 goto fail2;
376
Dmitry Torokhov29506412005-11-20 00:51:22 -0500377 udev->state = UIST_CREATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 return 0;
Anssi Hannulaff462552006-07-19 01:41:09 -0400380
381 fail2: input_ff_destroy(dev);
382 fail1: uinput_destroy_device(udev);
383 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384}
385
386static int uinput_open(struct inode *inode, struct file *file)
387{
Dmitry Torokhov29506412005-11-20 00:51:22 -0500388 struct uinput_device *newdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Dmitry Torokhov29506412005-11-20 00:51:22 -0500390 newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 if (!newdev)
Dmitry Torokhov29506412005-11-20 00:51:22 -0500392 return -ENOMEM;
393
Dmitry Torokhov221979a2006-02-19 00:22:36 -0500394 mutex_init(&newdev->mutex);
Dmitry Torokhov0048e602005-06-30 00:48:14 -0500395 spin_lock_init(&newdev->requests_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 init_waitqueue_head(&newdev->requests_waitq);
Dmitry Torokhov29506412005-11-20 00:51:22 -0500397 init_waitqueue_head(&newdev->waitq);
398 newdev->state = UIST_NEW_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
400 file->private_data = newdev;
Dmitry Torokhovdaf8a962010-02-04 00:30:39 -0800401 nonseekable_open(inode, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404}
405
David Herrmannfbae10d2015-10-25 10:34:13 +0100406static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
407 const struct input_absinfo *abs)
408{
Dmitry Torokhovd77651a2019-01-14 13:54:55 -0800409 int min, max, range;
David Herrmannfbae10d2015-10-25 10:34:13 +0100410
411 min = abs->minimum;
412 max = abs->maximum;
413
Peter Hutterer4fef1252018-09-18 09:53:32 -0700414 if ((min != 0 || max != 0) && max < min) {
David Herrmannfbae10d2015-10-25 10:34:13 +0100415 printk(KERN_DEBUG
416 "%s: invalid abs[%02x] min:%d max:%d\n",
417 UINPUT_NAME, code, min, max);
418 return -EINVAL;
419 }
420
Dmitry Torokhovd77651a2019-01-14 13:54:55 -0800421 if (!check_sub_overflow(max, min, &range) && abs->flat > range) {
David Herrmannfbae10d2015-10-25 10:34:13 +0100422 printk(KERN_DEBUG
423 "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
424 UINPUT_NAME, code, abs->flat, min, max);
425 return -EINVAL;
426 }
427
428 return 0;
429}
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431static int uinput_validate_absbits(struct input_dev *dev)
432{
433 unsigned int cnt;
David Herrmannfbae10d2015-10-25 10:34:13 +0100434 int error;
David Herrmannbcb898e2014-07-20 17:16:23 -0700435
436 if (!test_bit(EV_ABS, dev->evbit))
437 return 0;
438
439 /*
440 * Check if absmin/absmax/absfuzz/absflat are sane.
441 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Anshul Gargb6d30962015-07-09 10:18:22 -0700443 for_each_set_bit(cnt, dev->absbit, ABS_CNT) {
David Herrmannfbae10d2015-10-25 10:34:13 +0100444 if (!dev->absinfo)
David Herrmannbcb898e2014-07-20 17:16:23 -0700445 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
David Herrmannfbae10d2015-10-25 10:34:13 +0100447 error = uinput_validate_absinfo(dev, cnt, &dev->absinfo[cnt]);
448 if (error)
449 return error;
David Herrmannbcb898e2014-07-20 17:16:23 -0700450 }
451
452 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453}
454
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800455static int uinput_dev_setup(struct uinput_device *udev,
456 struct uinput_setup __user *arg)
457{
458 struct uinput_setup setup;
459 struct input_dev *dev;
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800460
461 if (udev->state == UIST_CREATED)
462 return -EINVAL;
463
464 if (copy_from_user(&setup, arg, sizeof(setup)))
465 return -EFAULT;
466
467 if (!setup.name[0])
468 return -EINVAL;
469
470 dev = udev->dev;
471 dev->id = setup.id;
472 udev->ff_effects_max = setup.ff_effects_max;
473
474 kfree(dev->name);
475 dev->name = kstrndup(setup.name, UINPUT_MAX_NAME_SIZE, GFP_KERNEL);
476 if (!dev->name)
477 return -ENOMEM;
478
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800479 udev->state = UIST_SETUP_COMPLETE;
480 return 0;
481}
482
483static int uinput_abs_setup(struct uinput_device *udev,
484 struct uinput_setup __user *arg, size_t size)
485{
486 struct uinput_abs_setup setup = {};
487 struct input_dev *dev;
David Herrmannfbae10d2015-10-25 10:34:13 +0100488 int error;
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800489
490 if (size > sizeof(setup))
491 return -E2BIG;
492
493 if (udev->state == UIST_CREATED)
494 return -EINVAL;
495
496 if (copy_from_user(&setup, arg, size))
497 return -EFAULT;
498
499 if (setup.code > ABS_MAX)
500 return -ERANGE;
501
502 dev = udev->dev;
503
David Herrmannfbae10d2015-10-25 10:34:13 +0100504 error = uinput_validate_absinfo(dev, setup.code, &setup.absinfo);
505 if (error)
506 return error;
507
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800508 input_alloc_absinfo(dev);
509 if (!dev->absinfo)
510 return -ENOMEM;
511
512 set_bit(setup.code, dev->absbit);
513 dev->absinfo[setup.code] = setup.absinfo;
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800514 return 0;
515}
516
517/* legacy setup via write() */
518static int uinput_setup_device_legacy(struct uinput_device *udev,
519 const char __user *buffer, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
521 struct uinput_user_dev *user_dev;
522 struct input_dev *dev;
David Herrmann5d9d6e92011-02-11 01:10:44 -0800523 int i;
Dmitry Torokhov152c12f2005-06-30 00:47:50 -0500524 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Dmitry Torokhov29506412005-11-20 00:51:22 -0500526 if (count != sizeof(struct uinput_user_dev))
527 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
Dmitry Torokhov29506412005-11-20 00:51:22 -0500529 if (!udev->dev) {
Dmitry Torokhov04ce40a2017-09-06 16:42:26 -0700530 udev->dev = input_allocate_device();
531 if (!udev->dev)
532 return -ENOMEM;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500533 }
534
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 dev = udev->dev;
536
Dmitry Torokhov4dfcc272011-02-11 01:10:45 -0800537 user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
Dan Carpenter163d2772011-02-18 08:30:52 -0800538 if (IS_ERR(user_dev))
Dmitry Torokhov4dfcc272011-02-11 01:10:45 -0800539 return PTR_ERR(user_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Anssi Hannulaff462552006-07-19 01:41:09 -0400541 udev->ff_effects_max = user_dev->ff_effects_max;
542
David Herrmann5d9d6e92011-02-11 01:10:44 -0800543 /* Ensure name is filled in */
544 if (!user_dev->name[0]) {
Dmitry Torokhov29506412005-11-20 00:51:22 -0500545 retval = -EINVAL;
546 goto exit;
547 }
548
549 kfree(dev->name);
David Herrmann5d9d6e92011-02-11 01:10:44 -0800550 dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
551 GFP_KERNEL);
552 if (!dev->name) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 retval = -ENOMEM;
554 goto exit;
555 }
556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 dev->id.bustype = user_dev->id.bustype;
558 dev->id.vendor = user_dev->id.vendor;
559 dev->id.product = user_dev->id.product;
560 dev->id.version = user_dev->id.version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Dmitry Torokhov72d47362015-09-19 11:22:57 -0700562 for (i = 0; i < ABS_CNT; i++) {
Daniel Mack987a6c02010-08-02 20:15:17 -0700563 input_abs_set_max(dev, i, user_dev->absmax[i]);
564 input_abs_set_min(dev, i, user_dev->absmin[i]);
565 input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
566 input_abs_set_flat(dev, i, user_dev->absflat[i]);
567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
David Herrmannbcb898e2014-07-20 17:16:23 -0700569 retval = uinput_validate_absbits(dev);
570 if (retval < 0)
571 goto exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Dmitry Torokhov29506412005-11-20 00:51:22 -0500573 udev->state = UIST_SETUP_COMPLETE;
574 retval = count;
575
576 exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 kfree(user_dev);
578 return retval;
579}
580
Ryan Malloncbf05412013-09-18 12:40:47 -0700581static ssize_t uinput_inject_events(struct uinput_device *udev,
582 const char __user *buffer, size_t count)
Dmitry Torokhov29506412005-11-20 00:51:22 -0500583{
584 struct input_event ev;
Ryan Malloncbf05412013-09-18 12:40:47 -0700585 size_t bytes = 0;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500586
Ryan Malloncbf05412013-09-18 12:40:47 -0700587 if (count != 0 && count < input_event_size())
Dmitry Torokhov29506412005-11-20 00:51:22 -0500588 return -EINVAL;
589
Ryan Malloncbf05412013-09-18 12:40:47 -0700590 while (bytes + input_event_size() <= count) {
591 /*
592 * Note that even if some events were fetched successfully
593 * we are still going to return EFAULT instead of partial
594 * count to let userspace know that it got it's buffers
595 * all wrong.
596 */
597 if (input_event_from_user(buffer + bytes, &ev))
598 return -EFAULT;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500599
Ryan Malloncbf05412013-09-18 12:40:47 -0700600 input_event(udev->dev, ev.type, ev.code, ev.value);
601 bytes += input_event_size();
Dmitry Torokhovcecf1072018-10-04 17:50:48 -0700602 cond_resched();
Ryan Malloncbf05412013-09-18 12:40:47 -0700603 }
Dmitry Torokhov29506412005-11-20 00:51:22 -0500604
Ryan Malloncbf05412013-09-18 12:40:47 -0700605 return bytes;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500606}
607
Dmitry Torokhov54ce1652012-07-29 22:48:32 -0700608static ssize_t uinput_write(struct file *file, const char __user *buffer,
609 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610{
611 struct uinput_device *udev = file->private_data;
Dmitry Torokhov29506412005-11-20 00:51:22 -0500612 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700614 if (count == 0)
615 return 0;
616
Dmitry Torokhov221979a2006-02-19 00:22:36 -0500617 retval = mutex_lock_interruptible(&udev->mutex);
Dmitry Torokhov29506412005-11-20 00:51:22 -0500618 if (retval)
619 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Dmitry Torokhov29506412005-11-20 00:51:22 -0500621 retval = udev->state == UIST_CREATED ?
Ryan Malloncbf05412013-09-18 12:40:47 -0700622 uinput_inject_events(udev, buffer, count) :
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -0800623 uinput_setup_device_legacy(udev, buffer, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Dmitry Torokhov221979a2006-02-19 00:22:36 -0500625 mutex_unlock(&udev->mutex);
Dmitry Torokhov29506412005-11-20 00:51:22 -0500626
627 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628}
629
Dmitry Torokhov929d1af2012-07-29 22:48:31 -0700630static bool uinput_fetch_next_event(struct uinput_device *udev,
631 struct input_event *event)
632{
633 bool have_event;
634
635 spin_lock_irq(&udev->dev->event_lock);
636
637 have_event = udev->head != udev->tail;
638 if (have_event) {
639 *event = udev->buff[udev->tail];
640 udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
641 }
642
643 spin_unlock_irq(&udev->dev->event_lock);
644
645 return have_event;
646}
647
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700648static ssize_t uinput_events_to_user(struct uinput_device *udev,
649 char __user *buffer, size_t count)
650{
651 struct input_event event;
652 size_t read = 0;
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700653
654 while (read + input_event_size() <= count &&
655 uinput_fetch_next_event(udev, &event)) {
656
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700657 if (input_event_to_user(buffer + read, &event))
658 return -EFAULT;
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700659
660 read += input_event_size();
661 }
662
Dmitry Torokhov00ce7562012-07-29 22:48:32 -0700663 return read;
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700664}
665
666static ssize_t uinput_read(struct file *file, char __user *buffer,
667 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
669 struct uinput_device *udev = file->private_data;
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700670 ssize_t retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
David Herrmannf40033a2012-07-29 22:48:31 -0700672 if (count != 0 && count < input_event_size())
673 return -EINVAL;
674
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700675 do {
676 retval = mutex_lock_interruptible(&udev->mutex);
677 if (retval)
678 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700680 if (udev->state != UIST_CREATED)
681 retval = -ENODEV;
682 else if (udev->head == udev->tail &&
683 (file->f_flags & O_NONBLOCK))
684 retval = -EAGAIN;
685 else
686 retval = uinput_events_to_user(udev, buffer, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700688 mutex_unlock(&udev->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700690 if (retval || count == 0)
691 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
Dmitry Torokhov22ae19c2012-07-29 22:48:31 -0700693 if (!(file->f_flags & O_NONBLOCK))
694 retval = wait_event_interruptible(udev->waitq,
695 udev->head != udev->tail ||
696 udev->state != UIST_CREATED);
697 } while (retval == 0);
Dmitry Torokhov29506412005-11-20 00:51:22 -0500698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 return retval;
700}
701
Al Viroafc9a422017-07-03 06:39:46 -0400702static __poll_t uinput_poll(struct file *file, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 struct uinput_device *udev = file->private_data;
705
706 poll_wait(file, &udev->waitq, wait);
707
708 if (udev->head != udev->tail)
Linus Torvaldsa9a08842018-02-11 14:34:03 -0800709 return EPOLLIN | EPOLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 return 0;
712}
713
Dmitry Torokhov29506412005-11-20 00:51:22 -0500714static int uinput_release(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Dmitry Torokhov29506412005-11-20 00:51:22 -0500716 struct uinput_device *udev = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Dmitry Torokhov29506412005-11-20 00:51:22 -0500718 uinput_destroy_device(udev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 kfree(udev);
720
721 return 0;
722}
723
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400724#ifdef CONFIG_COMPAT
725struct uinput_ff_upload_compat {
Dmitry Torokhovc5b35332012-07-29 22:48:32 -0700726 __u32 request_id;
727 __s32 retval;
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400728 struct ff_effect_compat effect;
729 struct ff_effect_compat old;
730};
731
732static int uinput_ff_upload_to_user(char __user *buffer,
733 const struct uinput_ff_upload *ff_up)
734{
Andrew Mortonb8b4ead2016-03-25 14:20:47 -0700735 if (in_compat_syscall()) {
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400736 struct uinput_ff_upload_compat ff_up_compat;
737
738 ff_up_compat.request_id = ff_up->request_id;
739 ff_up_compat.retval = ff_up->retval;
740 /*
741 * It so happens that the pointer that gives us the trouble
742 * is the last field in the structure. Since we don't support
743 * custom waveforms in uinput anyway we can just copy the whole
744 * thing (to the compat size) and ignore the pointer.
745 */
746 memcpy(&ff_up_compat.effect, &ff_up->effect,
747 sizeof(struct ff_effect_compat));
748 memcpy(&ff_up_compat.old, &ff_up->old,
749 sizeof(struct ff_effect_compat));
750
751 if (copy_to_user(buffer, &ff_up_compat,
752 sizeof(struct uinput_ff_upload_compat)))
753 return -EFAULT;
754 } else {
755 if (copy_to_user(buffer, ff_up,
756 sizeof(struct uinput_ff_upload)))
757 return -EFAULT;
758 }
759
760 return 0;
761}
762
763static int uinput_ff_upload_from_user(const char __user *buffer,
764 struct uinput_ff_upload *ff_up)
765{
Andrew Mortonb8b4ead2016-03-25 14:20:47 -0700766 if (in_compat_syscall()) {
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400767 struct uinput_ff_upload_compat ff_up_compat;
768
769 if (copy_from_user(&ff_up_compat, buffer,
770 sizeof(struct uinput_ff_upload_compat)))
771 return -EFAULT;
772
773 ff_up->request_id = ff_up_compat.request_id;
774 ff_up->retval = ff_up_compat.retval;
775 memcpy(&ff_up->effect, &ff_up_compat.effect,
776 sizeof(struct ff_effect_compat));
777 memcpy(&ff_up->old, &ff_up_compat.old,
778 sizeof(struct ff_effect_compat));
779
780 } else {
781 if (copy_from_user(ff_up, buffer,
782 sizeof(struct uinput_ff_upload)))
783 return -EFAULT;
784 }
785
786 return 0;
787}
788
789#else
790
791static int uinput_ff_upload_to_user(char __user *buffer,
792 const struct uinput_ff_upload *ff_up)
793{
794 if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload)))
795 return -EFAULT;
796
797 return 0;
798}
799
800static int uinput_ff_upload_from_user(const char __user *buffer,
801 struct uinput_ff_upload *ff_up)
802{
803 if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload)))
804 return -EFAULT;
805
806 return 0;
807}
808
809#endif
810
Dmitry Torokhov29506412005-11-20 00:51:22 -0500811#define uinput_set_bit(_arg, _bit, _max) \
812({ \
813 int __ret = 0; \
814 if (udev->state == UIST_CREATED) \
815 __ret = -EINVAL; \
816 else if ((_arg) > (_max)) \
817 __ret = -EINVAL; \
818 else set_bit((_arg), udev->dev->_bit); \
819 __ret; \
820})
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Benjamin Tissoirese3480a62014-01-30 17:20:24 -0800822static int uinput_str_to_user(void __user *dest, const char *str,
823 unsigned int maxlen)
824{
825 char __user *p = dest;
826 int len, ret;
827
828 if (!str)
829 return -ENOENT;
830
831 if (maxlen == 0)
832 return -EINVAL;
833
834 len = strlen(str) + 1;
835 if (len > maxlen)
836 len = maxlen;
837
838 ret = copy_to_user(p, str, len);
839 if (ret)
840 return -EFAULT;
841
842 /* force terminating '\0' */
843 ret = put_user(0, p + len - 1);
844 return ret ? -EFAULT : len;
845}
846
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400847static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
848 unsigned long arg, void __user *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849{
Dmitry Torokhov29506412005-11-20 00:51:22 -0500850 int retval;
Philip Langdale2d56f3a2008-10-16 22:31:42 -0400851 struct uinput_device *udev = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 struct uinput_ff_upload ff_up;
853 struct uinput_ff_erase ff_erase;
854 struct uinput_request *req;
Dmitry Torokhov5b6271bd2005-06-30 00:50:38 -0500855 char *phys;
Benjamin Tissoirese3480a62014-01-30 17:20:24 -0800856 const char *name;
857 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
Dmitry Torokhov221979a2006-02-19 00:22:36 -0500859 retval = mutex_lock_interruptible(&udev->mutex);
Dmitry Torokhov29506412005-11-20 00:51:22 -0500860 if (retval)
861 return retval;
862
863 if (!udev->dev) {
Dmitry Torokhov04ce40a2017-09-06 16:42:26 -0700864 udev->dev = input_allocate_device();
Dan Carpenter781f2dd2017-11-10 10:21:53 -0800865 if (!udev->dev) {
866 retval = -ENOMEM;
867 goto out;
868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 }
870
871 switch (cmd) {
Dmitry Torokhovc0661652017-09-06 16:34:31 -0700872 case UI_GET_VERSION:
873 if (put_user(UINPUT_VERSION, (unsigned int __user *)p))
874 retval = -EFAULT;
875 goto out;
876
877 case UI_DEV_CREATE:
878 retval = uinput_create_device(udev);
879 goto out;
880
881 case UI_DEV_DESTROY:
882 uinput_destroy_device(udev);
883 goto out;
884
885 case UI_DEV_SETUP:
886 retval = uinput_dev_setup(udev, p);
887 goto out;
888
889 /* UI_ABS_SETUP is handled in the variable size ioctls */
890
891 case UI_SET_EVBIT:
892 retval = uinput_set_bit(arg, evbit, EV_MAX);
893 goto out;
894
895 case UI_SET_KEYBIT:
896 retval = uinput_set_bit(arg, keybit, KEY_MAX);
897 goto out;
898
899 case UI_SET_RELBIT:
900 retval = uinput_set_bit(arg, relbit, REL_MAX);
901 goto out;
902
903 case UI_SET_ABSBIT:
904 retval = uinput_set_bit(arg, absbit, ABS_MAX);
905 goto out;
906
907 case UI_SET_MSCBIT:
908 retval = uinput_set_bit(arg, mscbit, MSC_MAX);
909 goto out;
910
911 case UI_SET_LEDBIT:
912 retval = uinput_set_bit(arg, ledbit, LED_MAX);
913 goto out;
914
915 case UI_SET_SNDBIT:
916 retval = uinput_set_bit(arg, sndbit, SND_MAX);
917 goto out;
918
919 case UI_SET_FFBIT:
920 retval = uinput_set_bit(arg, ffbit, FF_MAX);
921 goto out;
922
923 case UI_SET_SWBIT:
924 retval = uinput_set_bit(arg, swbit, SW_MAX);
925 goto out;
926
927 case UI_SET_PROPBIT:
928 retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
929 goto out;
930
931 case UI_SET_PHYS:
932 if (udev->state == UIST_CREATED) {
933 retval = -EINVAL;
934 goto out;
935 }
936
937 phys = strndup_user(p, 1024);
938 if (IS_ERR(phys)) {
939 retval = PTR_ERR(phys);
940 goto out;
941 }
942
943 kfree(udev->dev->phys);
944 udev->dev->phys = phys;
945 goto out;
946
947 case UI_BEGIN_FF_UPLOAD:
948 retval = uinput_ff_upload_from_user(p, &ff_up);
949 if (retval)
David Herrmannba4e9a62014-07-20 17:27:09 -0700950 goto out;
951
Dmitry Torokhovc0661652017-09-06 16:34:31 -0700952 req = uinput_request_find(udev, ff_up.request_id);
953 if (!req || req->code != UI_FF_UPLOAD ||
954 !req->u.upload.effect) {
955 retval = -EINVAL;
956 goto out;
957 }
958
959 ff_up.retval = 0;
960 ff_up.effect = *req->u.upload.effect;
961 if (req->u.upload.old)
962 ff_up.old = *req->u.upload.old;
963 else
964 memset(&ff_up.old, 0, sizeof(struct ff_effect));
965
966 retval = uinput_ff_upload_to_user(p, &ff_up);
967 goto out;
968
969 case UI_BEGIN_FF_ERASE:
970 if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
971 retval = -EFAULT;
972 goto out;
973 }
974
975 req = uinput_request_find(udev, ff_erase.request_id);
976 if (!req || req->code != UI_FF_ERASE) {
977 retval = -EINVAL;
978 goto out;
979 }
980
981 ff_erase.retval = 0;
982 ff_erase.effect_id = req->u.effect_id;
983 if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
984 retval = -EFAULT;
985 goto out;
986 }
987
988 goto out;
989
990 case UI_END_FF_UPLOAD:
991 retval = uinput_ff_upload_from_user(p, &ff_up);
992 if (retval)
Benjamin Tisssoires9d51e802014-01-30 17:16:36 -0800993 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Dmitry Torokhovc0661652017-09-06 16:34:31 -0700995 req = uinput_request_find(udev, ff_up.request_id);
996 if (!req || req->code != UI_FF_UPLOAD ||
997 !req->u.upload.effect) {
998 retval = -EINVAL;
Benjamin Tisssoires9d51e802014-01-30 17:16:36 -0800999 goto out;
Dmitry Torokhovc0661652017-09-06 16:34:31 -07001000 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
Dmitry Torokhovc0661652017-09-06 16:34:31 -07001002 req->retval = ff_up.retval;
1003 complete(&req->done);
1004 goto out;
1005
1006 case UI_END_FF_ERASE:
1007 if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
1008 retval = -EFAULT;
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -08001009 goto out;
Dmitry Torokhovc0661652017-09-06 16:34:31 -07001010 }
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -08001011
Dmitry Torokhovc0661652017-09-06 16:34:31 -07001012 req = uinput_request_find(udev, ff_erase.request_id);
1013 if (!req || req->code != UI_FF_ERASE) {
1014 retval = -EINVAL;
Benjamin Tisssoires9d51e802014-01-30 17:16:36 -08001015 goto out;
Dmitry Torokhovc0661652017-09-06 16:34:31 -07001016 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
Dmitry Torokhovc0661652017-09-06 16:34:31 -07001018 req->retval = ff_erase.retval;
1019 complete(&req->done);
1020 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
Dmitry Torokhov29506412005-11-20 00:51:22 -05001022
Benjamin Tissoirese3480a62014-01-30 17:20:24 -08001023 size = _IOC_SIZE(cmd);
1024
1025 /* Now check variable-length commands */
1026 switch (cmd & ~IOCSIZE_MASK) {
1027 case UI_GET_SYSNAME(0):
1028 if (udev->state != UIST_CREATED) {
1029 retval = -ENOENT;
1030 goto out;
1031 }
1032 name = dev_name(&udev->dev->dev);
1033 retval = uinput_str_to_user(p, name, size);
1034 goto out;
Benjamin Tissoires052876f8e2015-12-18 17:20:09 -08001035
1036 case UI_ABS_SETUP & ~IOCSIZE_MASK:
1037 retval = uinput_abs_setup(udev, p, size);
1038 goto out;
Benjamin Tissoirese3480a62014-01-30 17:20:24 -08001039 }
1040
Benjamin Tisssoires9d51e802014-01-30 17:16:36 -08001041 retval = -EINVAL;
Dmitry Torokhov29506412005-11-20 00:51:22 -05001042 out:
Dmitry Torokhov221979a2006-02-19 00:22:36 -05001043 mutex_unlock(&udev->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 return retval;
1045}
1046
Philip Langdale2d56f3a2008-10-16 22:31:42 -04001047static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1048{
1049 return uinput_ioctl_handler(file, cmd, arg, (void __user *)arg);
1050}
1051
1052#ifdef CONFIG_COMPAT
Ricky Liangaffa80b2016-05-20 10:58:59 -07001053
1054#define UI_SET_PHYS_COMPAT _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
1055
Dmitry Torokhov54ce1652012-07-29 22:48:32 -07001056static long uinput_compat_ioctl(struct file *file,
1057 unsigned int cmd, unsigned long arg)
Philip Langdale2d56f3a2008-10-16 22:31:42 -04001058{
Ricky Liangaffa80b2016-05-20 10:58:59 -07001059 if (cmd == UI_SET_PHYS_COMPAT)
1060 cmd = UI_SET_PHYS;
1061
Philip Langdale2d56f3a2008-10-16 22:31:42 -04001062 return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
1063}
1064#endif
1065
Arjan van de Ven2b8693c2007-02-12 00:55:32 -08001066static const struct file_operations uinput_fops = {
Dmitry Torokhov29506412005-11-20 00:51:22 -05001067 .owner = THIS_MODULE,
1068 .open = uinput_open,
1069 .release = uinput_release,
1070 .read = uinput_read,
1071 .write = uinput_write,
1072 .poll = uinput_poll,
1073 .unlocked_ioctl = uinput_ioctl,
Philip Langdale2d56f3a2008-10-16 22:31:42 -04001074#ifdef CONFIG_COMPAT
1075 .compat_ioctl = uinput_compat_ioctl,
1076#endif
Arnd Bergmann6038f372010-08-15 18:52:59 +02001077 .llseek = no_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078};
1079
1080static struct miscdevice uinput_misc = {
Dmitry Torokhov29506412005-11-20 00:51:22 -05001081 .fops = &uinput_fops,
1082 .minor = UINPUT_MINOR,
1083 .name = UINPUT_NAME,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084};
PrasannaKumar Muralidharanca75d602016-08-25 22:30:49 +05301085module_misc_device(uinput_misc);
1086
Kay Sievers8905aaa2010-08-19 09:52:28 -07001087MODULE_ALIAS_MISCDEV(UINPUT_MINOR);
1088MODULE_ALIAS("devname:" UINPUT_NAME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090MODULE_AUTHOR("Aristeu Sergio Rozanski Filho");
1091MODULE_DESCRIPTION("User level driver support for input subsystem");
1092MODULE_LICENSE("GPL");