uinput.c 19.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 *  User level driver support for input subsystem
 *
 * Heavily based on evdev.c by Vojtech Pavlik
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
 *
 * Changes/Revisions:
23 24 25
 *	0.3	09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>)
 *		- updated ff support for the changes in kernel interface
 *		- added MODULE_VERSION
L
Linus Torvalds 已提交
26 27 28 29 30 31 32
 *	0.2	16/10/2004 (Micah Dowty <micah@navi.cx>)
 *		- added force feedback support
 *              - added UI_SET_PHYS
 *	0.1	20/06/2002
 *		- first public version
 */
#include <linux/poll.h>
33
#include <linux/sched.h>
L
Linus Torvalds 已提交
34 35 36 37 38 39
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uinput.h>
40
#include <linux/input/mt.h>
41
#include "../input-compat.h"
L
Linus Torvalds 已提交
42 43 44

static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
45
	struct uinput_device	*udev = input_get_drvdata(dev);
L
Linus Torvalds 已提交
46 47 48 49 50 51 52 53 54 55 56 57

	udev->buff[udev->head].type = type;
	udev->buff[udev->head].code = code;
	udev->buff[udev->head].value = value;
	do_gettimeofday(&udev->buff[udev->head].time);
	udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;

	wake_up_interruptible(&udev->waitq);

	return 0;
}

58
/* Atomically allocate an ID for the given request. Returns 0 on success. */
59
static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request)
L
Linus Torvalds 已提交
60 61
{
	int id;
62
	int err = -1;
L
Linus Torvalds 已提交
63

64
	spin_lock(&udev->requests_lock);
65

66
	for (id = 0; id < UINPUT_NUM_REQUESTS; id++) {
L
Linus Torvalds 已提交
67 68
		if (!udev->requests[id]) {
			request->id = id;
69
			udev->requests[id] = request;
70 71
			err = 0;
			break;
L
Linus Torvalds 已提交
72
		}
73
	}
74

75
	spin_unlock(&udev->requests_lock);
76
	return err;
L
Linus Torvalds 已提交
77 78
}

79
static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id)
L
Linus Torvalds 已提交
80 81 82 83
{
	/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
	if (id >= UINPUT_NUM_REQUESTS || id < 0)
		return NULL;
84

L
Linus Torvalds 已提交
85 86 87
	return udev->requests[id];
}

88
static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request)
L
Linus Torvalds 已提交
89
{
90 91 92 93
	/* Allocate slot. If none are available right away, wait. */
	return wait_event_interruptible(udev->requests_waitq,
					!uinput_request_alloc_id(udev, request));
}
L
Linus Torvalds 已提交
94

95 96 97 98
static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request)
{
	/* Mark slot as available */
	udev->requests[request->id] = NULL;
99
	wake_up(&udev->requests_waitq);
100 101

	complete(&request->done);
L
Linus Torvalds 已提交
102 103
}

104
static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request)
L
Linus Torvalds 已提交
105
{
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
	int retval;

	retval = uinput_request_reserve_slot(udev, request);
	if (retval)
		return retval;

	retval = mutex_lock_interruptible(&udev->mutex);
	if (retval)
		return retval;

	if (udev->state != UIST_CREATED) {
		retval = -ENODEV;
		goto out;
	}

L
Linus Torvalds 已提交
121
	/* Tell our userspace app about this new request by queueing an input event */
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
	uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);

 out:
	mutex_unlock(&udev->mutex);
	return retval;
}

/*
 * Fail all ouitstanding requests so handlers don't wait for the userspace
 * to finish processing them.
 */
static void uinput_flush_requests(struct uinput_device *udev)
{
	struct uinput_request *request;
	int i;
L
Linus Torvalds 已提交
137

138 139 140 141 142 143 144 145 146 147 148
	spin_lock(&udev->requests_lock);

	for (i = 0; i < UINPUT_NUM_REQUESTS; i++) {
		request = udev->requests[i];
		if (request) {
			request->retval = -ENODEV;
			uinput_request_done(udev, request);
		}
	}

	spin_unlock(&udev->requests_lock);
L
Linus Torvalds 已提交
149 150
}

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
static void uinput_dev_set_gain(struct input_dev *dev, u16 gain)
{
	uinput_dev_event(dev, EV_FF, FF_GAIN, gain);
}

static void uinput_dev_set_autocenter(struct input_dev *dev, u16 magnitude)
{
	uinput_dev_event(dev, EV_FF, FF_AUTOCENTER, magnitude);
}

static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value)
{
	return uinput_dev_event(dev, EV_FF, effect_id, value);
}

static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
L
Linus Torvalds 已提交
167
{
168
	struct uinput_device *udev = input_get_drvdata(dev);
L
Linus Torvalds 已提交
169
	struct uinput_request request;
170
	int retval;
L
Linus Torvalds 已提交
171

172 173 174 175 176 177 178 179 180 181 182
	/*
	 * uinput driver does not currently support periodic effects with
	 * custom waveform since it does not have a way to pass buffer of
	 * samples (custom_data) to userspace. If ever there is a device
	 * supporting custom waveforms we would need to define an additional
	 * ioctl (UI_UPLOAD_SAMPLES) but for now we just bail out.
	 */
	if (effect->type == FF_PERIODIC &&
			effect->u.periodic.waveform == FF_CUSTOM)
		return -EINVAL;

183 184 185
	request.id = -1;
	init_completion(&request.done);
	request.code = UI_FF_UPLOAD;
186 187
	request.u.upload.effect = effect;
	request.u.upload.old = old;
188

189 190 191 192 193
	retval = uinput_request_submit(udev, &request);
	if (!retval) {
		wait_for_completion(&request.done);
		retval = request.retval;
	}
194 195

	return retval;
L
Linus Torvalds 已提交
196 197 198 199
}

static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
{
200
	struct uinput_device *udev = input_get_drvdata(dev);
L
Linus Torvalds 已提交
201
	struct uinput_request request;
202
	int retval;
L
Linus Torvalds 已提交
203 204 205 206

	if (!test_bit(EV_FF, dev->evbit))
		return -ENOSYS;

207 208 209
	request.id = -1;
	init_completion(&request.done);
	request.code = UI_FF_ERASE;
L
Linus Torvalds 已提交
210
	request.u.effect_id = effect_id;
211

212 213 214 215 216
	retval = uinput_request_submit(udev, &request);
	if (!retval) {
		wait_for_completion(&request.done);
		retval = request.retval;
	}
217 218

	return retval;
L
Linus Torvalds 已提交
219 220
}

221
static void uinput_destroy_device(struct uinput_device *udev)
L
Linus Torvalds 已提交
222
{
223
	const char *name, *phys;
224 225 226 227
	struct input_dev *dev = udev->dev;
	enum uinput_state old_state = udev->state;

	udev->state = UIST_NEW_DEVICE;
228

229 230 231 232 233 234 235 236 237
	if (dev) {
		name = dev->name;
		phys = dev->phys;
		if (old_state == UIST_CREATED) {
			uinput_flush_requests(udev);
			input_unregister_device(dev);
		} else {
			input_free_device(dev);
		}
238 239 240
		kfree(name);
		kfree(phys);
		udev->dev = NULL;
L
Linus Torvalds 已提交
241 242 243
	}
}

244
static int uinput_create_device(struct uinput_device *udev)
L
Linus Torvalds 已提交
245
{
246
	struct input_dev *dev = udev->dev;
247 248 249 250
	int error;

	if (udev->state != UIST_SETUP_COMPLETE) {
		printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
L
Linus Torvalds 已提交
251 252 253
		return -EINVAL;
	}

254 255 256 257 258 259 260 261 262 263
	if (udev->ff_effects_max) {
		error = input_ff_create(dev, udev->ff_effects_max);
		if (error)
			goto fail1;

		dev->ff->upload = uinput_dev_upload_effect;
		dev->ff->erase = uinput_dev_erase_effect;
		dev->ff->playback = uinput_dev_playback;
		dev->ff->set_gain = uinput_dev_set_gain;
		dev->ff->set_autocenter = uinput_dev_set_autocenter;
264
	}
L
Linus Torvalds 已提交
265

266 267 268 269
	error = input_register_device(udev->dev);
	if (error)
		goto fail2;

270
	udev->state = UIST_CREATED;
L
Linus Torvalds 已提交
271 272

	return 0;
273 274 275 276

 fail2:	input_ff_destroy(dev);
 fail1: uinput_destroy_device(udev);
	return error;
L
Linus Torvalds 已提交
277 278 279 280
}

static int uinput_open(struct inode *inode, struct file *file)
{
281
	struct uinput_device *newdev;
L
Linus Torvalds 已提交
282

283
	newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL);
L
Linus Torvalds 已提交
284
	if (!newdev)
285 286
		return -ENOMEM;

287
	mutex_init(&newdev->mutex);
288
	spin_lock_init(&newdev->requests_lock);
L
Linus Torvalds 已提交
289
	init_waitqueue_head(&newdev->requests_waitq);
290 291
	init_waitqueue_head(&newdev->waitq);
	newdev->state = UIST_NEW_DEVICE;
L
Linus Torvalds 已提交
292 293

	file->private_data = newdev;
294
	nonseekable_open(inode, file);
L
Linus Torvalds 已提交
295 296 297 298 299 300 301 302 303

	return 0;
}

static int uinput_validate_absbits(struct input_dev *dev)
{
	unsigned int cnt;
	int retval = 0;

304
	for (cnt = 0; cnt < ABS_CNT; cnt++) {
L
Linus Torvalds 已提交
305 306 307
		if (!test_bit(cnt, dev->absbit))
			continue;

308
		if (input_abs_get_max(dev, cnt) <= input_abs_get_min(dev, cnt)) {
L
Linus Torvalds 已提交
309 310 311
			printk(KERN_DEBUG
				"%s: invalid abs[%02x] min:%d max:%d\n",
				UINPUT_NAME, cnt,
312 313
				input_abs_get_min(dev, cnt),
				input_abs_get_max(dev, cnt));
L
Linus Torvalds 已提交
314 315 316 317
			retval = -EINVAL;
			break;
		}

318 319
		if (input_abs_get_flat(dev, cnt) >
		    input_abs_get_max(dev, cnt) - input_abs_get_min(dev, cnt)) {
L
Linus Torvalds 已提交
320
			printk(KERN_DEBUG
321
				"%s: abs_flat #%02x out of range: %d "
L
Linus Torvalds 已提交
322
				"(min:%d/max:%d)\n",
323 324 325 326
				UINPUT_NAME, cnt,
				input_abs_get_flat(dev, cnt),
				input_abs_get_min(dev, cnt),
				input_abs_get_max(dev, cnt));
L
Linus Torvalds 已提交
327 328 329 330 331 332 333
			retval = -EINVAL;
			break;
		}
	}
	return retval;
}

334 335 336 337 338 339 340
static int uinput_allocate_device(struct uinput_device *udev)
{
	udev->dev = input_allocate_device();
	if (!udev->dev)
		return -ENOMEM;

	udev->dev->event = uinput_dev_event;
341
	input_set_drvdata(udev->dev, udev);
342 343 344 345 346

	return 0;
}

static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count)
L
Linus Torvalds 已提交
347 348 349
{
	struct uinput_user_dev	*user_dev;
	struct input_dev	*dev;
350
	int			i;
351
	int			retval;
L
Linus Torvalds 已提交
352

353 354 355 356 357 358 359 360
	if (count != sizeof(struct uinput_user_dev))
		return -EINVAL;

	if (!udev->dev) {
		retval = uinput_allocate_device(udev);
		if (retval)
			return retval;
	}
L
Linus Torvalds 已提交
361 362 363

	dev = udev->dev;

364
	user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
365 366
	if (!user_dev)
		return -ENOMEM;
L
Linus Torvalds 已提交
367 368 369 370 371 372

	if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
		retval = -EFAULT;
		goto exit;
	}

373 374
	udev->ff_effects_max = user_dev->ff_effects_max;

375 376
	/* Ensure name is filled in */
	if (!user_dev->name[0]) {
377 378 379 380 381
		retval = -EINVAL;
		goto exit;
	}

	kfree(dev->name);
382 383 384
	dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
			     GFP_KERNEL);
	if (!dev->name) {
L
Linus Torvalds 已提交
385 386 387 388 389 390 391 392 393
		retval = -ENOMEM;
		goto exit;
	}

	dev->id.bustype	= user_dev->id.bustype;
	dev->id.vendor	= user_dev->id.vendor;
	dev->id.product	= user_dev->id.product;
	dev->id.version	= user_dev->id.version;

394 395 396 397 398 399
	for (i = 0; i < ABS_CNT; i++) {
		input_abs_set_max(dev, i, user_dev->absmax[i]);
		input_abs_set_min(dev, i, user_dev->absmin[i]);
		input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
		input_abs_set_flat(dev, i, user_dev->absflat[i]);
	}
L
Linus Torvalds 已提交
400 401 402 403

	/* check if absmin/absmax/absfuzz/absflat are filled as
	 * told in Documentation/input/input-programming.txt */
	if (test_bit(EV_ABS, dev->evbit)) {
404 405 406
		retval = uinput_validate_absbits(dev);
		if (retval < 0)
			goto exit;
407 408
		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
409
			input_mt_init_slots(dev, nslot);
410 411 412
		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
			input_set_events_per_packet(dev, 60);
		}
L
Linus Torvalds 已提交
413 414
	}

415 416 417 418
	udev->state = UIST_SETUP_COMPLETE;
	retval = count;

 exit:
L
Linus Torvalds 已提交
419 420 421 422
	kfree(user_dev);
	return retval;
}

423 424 425 426
static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char __user *buffer, size_t count)
{
	struct input_event ev;

427
	if (count < input_event_size())
428 429
		return -EINVAL;

430
	if (input_event_from_user(buffer, &ev))
431 432 433 434
		return -EFAULT;

	input_event(udev->dev, ev.type, ev.code, ev.value);

435
	return input_event_size();
436 437
}

L
Linus Torvalds 已提交
438 439 440
static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
	struct uinput_device *udev = file->private_data;
441
	int retval;
L
Linus Torvalds 已提交
442

443
	retval = mutex_lock_interruptible(&udev->mutex);
444 445 446 447 448 449
	if (retval)
		return retval;

	retval = udev->state == UIST_CREATED ?
			uinput_inject_event(udev, buffer, count) :
			uinput_setup_device(udev, buffer, count);
L
Linus Torvalds 已提交
450

451
	mutex_unlock(&udev->mutex);
L
Linus Torvalds 已提交
452

453
	return retval;
L
Linus Torvalds 已提交
454 455 456 457 458 459 460
}

static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
	struct uinput_device *udev = file->private_data;
	int retval = 0;

461
	if (udev->state != UIST_CREATED)
L
Linus Torvalds 已提交
462 463
		return -ENODEV;

464
	if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK))
L
Linus Torvalds 已提交
465 466 467
		return -EAGAIN;

	retval = wait_event_interruptible(udev->waitq,
468
			udev->head != udev->tail || udev->state != UIST_CREATED);
L
Linus Torvalds 已提交
469 470 471
	if (retval)
		return retval;

472
	retval = mutex_lock_interruptible(&udev->mutex);
473 474 475 476 477 478 479
	if (retval)
		return retval;

	if (udev->state != UIST_CREATED) {
		retval = -ENODEV;
		goto out;
	}
L
Linus Torvalds 已提交
480

481 482
	while (udev->head != udev->tail && retval + input_event_size() <= count) {
		if (input_event_to_user(buffer + retval, &udev->buff[udev->tail])) {
483 484 485
			retval = -EFAULT;
			goto out;
		}
L
Linus Torvalds 已提交
486
		udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
487
		retval += input_event_size();
L
Linus Torvalds 已提交
488 489
	}

490
 out:
491
	mutex_unlock(&udev->mutex);
492

L
Linus Torvalds 已提交
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
	return retval;
}

static unsigned int uinput_poll(struct file *file, poll_table *wait)
{
	struct uinput_device *udev = file->private_data;

	poll_wait(file, &udev->waitq, wait);

	if (udev->head != udev->tail)
		return POLLIN | POLLRDNORM;

	return 0;
}

508
static int uinput_release(struct inode *inode, struct file *file)
L
Linus Torvalds 已提交
509
{
510
	struct uinput_device *udev = file->private_data;
L
Linus Torvalds 已提交
511

512
	uinput_destroy_device(udev);
L
Linus Torvalds 已提交
513 514 515 516 517
	kfree(udev);

	return 0;
}

518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
#ifdef CONFIG_COMPAT
struct uinput_ff_upload_compat {
	int			request_id;
	int			retval;
	struct ff_effect_compat	effect;
	struct ff_effect_compat	old;
};

static int uinput_ff_upload_to_user(char __user *buffer,
				    const struct uinput_ff_upload *ff_up)
{
	if (INPUT_COMPAT_TEST) {
		struct uinput_ff_upload_compat ff_up_compat;

		ff_up_compat.request_id = ff_up->request_id;
		ff_up_compat.retval = ff_up->retval;
		/*
		 * It so happens that the pointer that gives us the trouble
		 * is the last field in the structure. Since we don't support
		 * custom waveforms in uinput anyway we can just copy the whole
		 * thing (to the compat size) and ignore the pointer.
		 */
		memcpy(&ff_up_compat.effect, &ff_up->effect,
			sizeof(struct ff_effect_compat));
		memcpy(&ff_up_compat.old, &ff_up->old,
			sizeof(struct ff_effect_compat));

		if (copy_to_user(buffer, &ff_up_compat,
				 sizeof(struct uinput_ff_upload_compat)))
			return -EFAULT;
	} else {
		if (copy_to_user(buffer, ff_up,
				 sizeof(struct uinput_ff_upload)))
			return -EFAULT;
	}

	return 0;
}

static int uinput_ff_upload_from_user(const char __user *buffer,
				      struct uinput_ff_upload *ff_up)
{
	if (INPUT_COMPAT_TEST) {
		struct uinput_ff_upload_compat ff_up_compat;

		if (copy_from_user(&ff_up_compat, buffer,
				   sizeof(struct uinput_ff_upload_compat)))
			return -EFAULT;

		ff_up->request_id = ff_up_compat.request_id;
		ff_up->retval = ff_up_compat.retval;
		memcpy(&ff_up->effect, &ff_up_compat.effect,
			sizeof(struct ff_effect_compat));
		memcpy(&ff_up->old, &ff_up_compat.old,
			sizeof(struct ff_effect_compat));

	} else {
		if (copy_from_user(ff_up, buffer,
				   sizeof(struct uinput_ff_upload)))
			return -EFAULT;
	}

	return 0;
}

#else

static int uinput_ff_upload_to_user(char __user *buffer,
				    const struct uinput_ff_upload *ff_up)
{
	if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload)))
		return -EFAULT;

	return 0;
}

static int uinput_ff_upload_from_user(const char __user *buffer,
				      struct uinput_ff_upload *ff_up)
{
	if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload)))
		return -EFAULT;

	return 0;
}

#endif

605 606 607 608 609 610 611 612 613 614 615
#define uinput_set_bit(_arg, _bit, _max)		\
({							\
	int __ret = 0;					\
	if (udev->state == UIST_CREATED)		\
		__ret =  -EINVAL;			\
	else if ((_arg) > (_max))			\
		__ret = -EINVAL;			\
	else set_bit((_arg), udev->dev->_bit);		\
	__ret;						\
})

616 617
static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
				 unsigned long arg, void __user *p)
L
Linus Torvalds 已提交
618
{
619
	int			retval;
620
	struct uinput_device	*udev = file->private_data;
L
Linus Torvalds 已提交
621 622 623 624
	struct uinput_ff_upload ff_up;
	struct uinput_ff_erase  ff_erase;
	struct uinput_request   *req;
	int                     length;
625
	char			*phys;
L
Linus Torvalds 已提交
626

627
	retval = mutex_lock_interruptible(&udev->mutex);
628 629 630 631 632 633 634
	if (retval)
		return retval;

	if (!udev->dev) {
		retval = uinput_allocate_device(udev);
		if (retval)
			goto out;
L
Linus Torvalds 已提交
635 636 637 638 639 640 641 642
	}

	switch (cmd) {
		case UI_DEV_CREATE:
			retval = uinput_create_device(udev);
			break;

		case UI_DEV_DESTROY:
643
			uinput_destroy_device(udev);
L
Linus Torvalds 已提交
644 645 646
			break;

		case UI_SET_EVBIT:
647
			retval = uinput_set_bit(arg, evbit, EV_MAX);
L
Linus Torvalds 已提交
648 649 650
			break;

		case UI_SET_KEYBIT:
651
			retval = uinput_set_bit(arg, keybit, KEY_MAX);
L
Linus Torvalds 已提交
652 653 654
			break;

		case UI_SET_RELBIT:
655
			retval = uinput_set_bit(arg, relbit, REL_MAX);
L
Linus Torvalds 已提交
656 657 658
			break;

		case UI_SET_ABSBIT:
659
			retval = uinput_set_bit(arg, absbit, ABS_MAX);
L
Linus Torvalds 已提交
660 661 662
			break;

		case UI_SET_MSCBIT:
663
			retval = uinput_set_bit(arg, mscbit, MSC_MAX);
L
Linus Torvalds 已提交
664 665 666
			break;

		case UI_SET_LEDBIT:
667
			retval = uinput_set_bit(arg, ledbit, LED_MAX);
L
Linus Torvalds 已提交
668 669 670
			break;

		case UI_SET_SNDBIT:
671
			retval = uinput_set_bit(arg, sndbit, SND_MAX);
L
Linus Torvalds 已提交
672 673 674
			break;

		case UI_SET_FFBIT:
675
			retval = uinput_set_bit(arg, ffbit, FF_MAX);
L
Linus Torvalds 已提交
676 677
			break;

678 679 680 681
		case UI_SET_SWBIT:
			retval = uinput_set_bit(arg, swbit, SW_MAX);
			break;

682 683 684 685
		case UI_SET_PROPBIT:
			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
			break;

L
Linus Torvalds 已提交
686
		case UI_SET_PHYS:
687 688 689 690
			if (udev->state == UIST_CREATED) {
				retval = -EINVAL;
				goto out;
			}
L
Linus Torvalds 已提交
691 692 693 694 695
			length = strnlen_user(p, 1024);
			if (length <= 0) {
				retval = -EFAULT;
				break;
			}
696 697 698
			kfree(udev->dev->phys);
			udev->dev->phys = phys = kmalloc(length, GFP_KERNEL);
			if (!phys) {
L
Linus Torvalds 已提交
699 700 701
				retval = -ENOMEM;
				break;
			}
702
			if (copy_from_user(phys, p, length)) {
L
Linus Torvalds 已提交
703
				udev->dev->phys = NULL;
704 705
				kfree(phys);
				retval = -EFAULT;
L
Linus Torvalds 已提交
706 707
				break;
			}
708
			phys[length - 1] = '\0';
L
Linus Torvalds 已提交
709 710 711
			break;

		case UI_BEGIN_FF_UPLOAD:
712 713
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
L
Linus Torvalds 已提交
714
				break;
715

L
Linus Torvalds 已提交
716
			req = uinput_request_find(udev, ff_up.request_id);
717
			if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
L
Linus Torvalds 已提交
718 719 720
				retval = -EINVAL;
				break;
			}
721

L
Linus Torvalds 已提交
722
			ff_up.retval = 0;
723
			ff_up.effect = *req->u.upload.effect;
724
			if (req->u.upload.old)
725
				ff_up.old = *req->u.upload.old;
726 727 728
			else
				memset(&ff_up.old, 0, sizeof(struct ff_effect));

729
			retval = uinput_ff_upload_to_user(p, &ff_up);
L
Linus Torvalds 已提交
730 731 732 733 734 735 736
			break;

		case UI_BEGIN_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}
737

L
Linus Torvalds 已提交
738
			req = uinput_request_find(udev, ff_erase.request_id);
739
			if (!req || req->code != UI_FF_ERASE) {
L
Linus Torvalds 已提交
740 741 742
				retval = -EINVAL;
				break;
			}
743

L
Linus Torvalds 已提交
744 745 746 747 748 749
			ff_erase.retval = 0;
			ff_erase.effect_id = req->u.effect_id;
			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}
750

L
Linus Torvalds 已提交
751 752 753
			break;

		case UI_END_FF_UPLOAD:
754 755
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
L
Linus Torvalds 已提交
756
				break;
757

L
Linus Torvalds 已提交
758
			req = uinput_request_find(udev, ff_up.request_id);
759 760
			if (!req || req->code != UI_FF_UPLOAD ||
			    !req->u.upload.effect) {
L
Linus Torvalds 已提交
761 762 763
				retval = -EINVAL;
				break;
			}
764

L
Linus Torvalds 已提交
765
			req->retval = ff_up.retval;
766
			uinput_request_done(udev, req);
L
Linus Torvalds 已提交
767 768 769 770 771 772 773
			break;

		case UI_END_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}
774

L
Linus Torvalds 已提交
775
			req = uinput_request_find(udev, ff_erase.request_id);
776
			if (!req || req->code != UI_FF_ERASE) {
L
Linus Torvalds 已提交
777 778 779
				retval = -EINVAL;
				break;
			}
780

L
Linus Torvalds 已提交
781
			req->retval = ff_erase.retval;
782
			uinput_request_done(udev, req);
L
Linus Torvalds 已提交
783 784 785 786 787
			break;

		default:
			retval = -EINVAL;
	}
788 789

 out:
790
	mutex_unlock(&udev->mutex);
L
Linus Torvalds 已提交
791 792 793
	return retval;
}

794 795 796 797 798 799 800 801 802 803 804 805
static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	return uinput_ioctl_handler(file, cmd, arg, (void __user *)arg);
}

#ifdef CONFIG_COMPAT
static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
}
#endif

806
static const struct file_operations uinput_fops = {
807 808 809 810 811 812 813
	.owner		= THIS_MODULE,
	.open		= uinput_open,
	.release	= uinput_release,
	.read		= uinput_read,
	.write		= uinput_write,
	.poll		= uinput_poll,
	.unlocked_ioctl	= uinput_ioctl,
814 815 816
#ifdef CONFIG_COMPAT
	.compat_ioctl	= uinput_compat_ioctl,
#endif
817
	.llseek		= no_llseek,
L
Linus Torvalds 已提交
818 819 820
};

static struct miscdevice uinput_misc = {
821 822 823
	.fops		= &uinput_fops,
	.minor		= UINPUT_MINOR,
	.name		= UINPUT_NAME,
L
Linus Torvalds 已提交
824
};
825 826
MODULE_ALIAS_MISCDEV(UINPUT_MINOR);
MODULE_ALIAS("devname:" UINPUT_NAME);
L
Linus Torvalds 已提交
827 828 829 830 831 832 833 834 835 836 837 838 839 840

static int __init uinput_init(void)
{
	return misc_register(&uinput_misc);
}

static void __exit uinput_exit(void)
{
	misc_deregister(&uinput_misc);
}

MODULE_AUTHOR("Aristeu Sergio Rozanski Filho");
MODULE_DESCRIPTION("User level driver support for input subsystem");
MODULE_LICENSE("GPL");
841
MODULE_VERSION("0.3");
L
Linus Torvalds 已提交
842 843 844 845

module_init(uinput_init);
module_exit(uinput_exit);