diff options
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 199 |
1 files changed, 9 insertions, 190 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 1070db330d35..ed8baa0aec3c 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <linux/input.h> | 19 | #include <linux/input.h> |
| 20 | #include <linux/major.h> | 20 | #include <linux/major.h> |
| 21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
| 22 | #include <linux/compat.h> | 22 | #include "input-compat.h" |
| 23 | 23 | ||
| 24 | struct evdev { | 24 | struct evdev { |
| 25 | int exist; | 25 | int exist; |
| @@ -290,187 +290,6 @@ static int evdev_open(struct inode *inode, struct file *file) | |||
| 290 | return error; | 290 | return error; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | #ifdef CONFIG_COMPAT | ||
| 294 | |||
| 295 | struct input_event_compat { | ||
| 296 | struct compat_timeval time; | ||
| 297 | __u16 type; | ||
| 298 | __u16 code; | ||
| 299 | __s32 value; | ||
| 300 | }; | ||
| 301 | |||
| 302 | struct ff_periodic_effect_compat { | ||
| 303 | __u16 waveform; | ||
| 304 | __u16 period; | ||
| 305 | __s16 magnitude; | ||
| 306 | __s16 offset; | ||
| 307 | __u16 phase; | ||
| 308 | |||
| 309 | struct ff_envelope envelope; | ||
| 310 | |||
| 311 | __u32 custom_len; | ||
| 312 | compat_uptr_t custom_data; | ||
| 313 | }; | ||
| 314 | |||
| 315 | struct ff_effect_compat { | ||
| 316 | __u16 type; | ||
| 317 | __s16 id; | ||
| 318 | __u16 direction; | ||
| 319 | struct ff_trigger trigger; | ||
| 320 | struct ff_replay replay; | ||
| 321 | |||
| 322 | union { | ||
| 323 | struct ff_constant_effect constant; | ||
| 324 | struct ff_ramp_effect ramp; | ||
| 325 | struct ff_periodic_effect_compat periodic; | ||
| 326 | struct ff_condition_effect condition[2]; /* One for each axis */ | ||
| 327 | struct ff_rumble_effect rumble; | ||
| 328 | } u; | ||
| 329 | }; | ||
| 330 | |||
| 331 | /* Note to the author of this code: did it ever occur to | ||
| 332 | you why the ifdefs are needed? Think about it again. -AK */ | ||
| 333 | #ifdef CONFIG_X86_64 | ||
| 334 | # define COMPAT_TEST is_compat_task() | ||
| 335 | #elif defined(CONFIG_IA64) | ||
| 336 | # define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current)) | ||
| 337 | #elif defined(CONFIG_S390) | ||
| 338 | # define COMPAT_TEST test_thread_flag(TIF_31BIT) | ||
| 339 | #elif defined(CONFIG_MIPS) | ||
| 340 | # define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR) | ||
| 341 | #else | ||
| 342 | # define COMPAT_TEST test_thread_flag(TIF_32BIT) | ||
| 343 | #endif | ||
| 344 | |||
| 345 | static inline size_t evdev_event_size(void) | ||
| 346 | { | ||
| 347 | return COMPAT_TEST ? | ||
| 348 | sizeof(struct input_event_compat) : sizeof(struct input_event); | ||
| 349 | } | ||
| 350 | |||
| 351 | static int evdev_event_from_user(const char __user *buffer, | ||
| 352 | struct input_event *event) | ||
| 353 | { | ||
| 354 | if (COMPAT_TEST) { | ||
| 355 | struct input_event_compat compat_event; | ||
| 356 | |||
| 357 | if (copy_from_user(&compat_event, buffer, | ||
| 358 | sizeof(struct input_event_compat))) | ||
| 359 | return -EFAULT; | ||
| 360 | |||
| 361 | event->time.tv_sec = compat_event.time.tv_sec; | ||
| 362 | event->time.tv_usec = compat_event.time.tv_usec; | ||
| 363 | event->type = compat_event.type; | ||
| 364 | event->code = compat_event.code; | ||
| 365 | event->value = compat_event.value; | ||
| 366 | |||
| 367 | } else { | ||
| 368 | if (copy_from_user(event, buffer, sizeof(struct input_event))) | ||
| 369 | return -EFAULT; | ||
| 370 | } | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | static int evdev_event_to_user(char __user *buffer, | ||
| 376 | const struct input_event *event) | ||
| 377 | { | ||
| 378 | if (COMPAT_TEST) { | ||
| 379 | struct input_event_compat compat_event; | ||
| 380 | |||
| 381 | compat_event.time.tv_sec = event->time.tv_sec; | ||
| 382 | compat_event.time.tv_usec = event->time.tv_usec; | ||
| 383 | compat_event.type = event->type; | ||
| 384 | compat_event.code = event->code; | ||
| 385 | compat_event.value = event->value; | ||
| 386 | |||
| 387 | if (copy_to_user(buffer, &compat_event, | ||
| 388 | sizeof(struct input_event_compat))) | ||
| 389 | return -EFAULT; | ||
| 390 | |||
| 391 | } else { | ||
| 392 | if (copy_to_user(buffer, event, sizeof(struct input_event))) | ||
| 393 | return -EFAULT; | ||
| 394 | } | ||
| 395 | |||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int evdev_ff_effect_from_user(const char __user *buffer, size_t size, | ||
| 400 | struct ff_effect *effect) | ||
| 401 | { | ||
| 402 | if (COMPAT_TEST) { | ||
| 403 | struct ff_effect_compat *compat_effect; | ||
| 404 | |||
| 405 | if (size != sizeof(struct ff_effect_compat)) | ||
| 406 | return -EINVAL; | ||
| 407 | |||
| 408 | /* | ||
| 409 | * It so happens that the pointer which needs to be changed | ||
| 410 | * is the last field in the structure, so we can copy the | ||
| 411 | * whole thing and replace just the pointer. | ||
| 412 | */ | ||
| 413 | |||
| 414 | compat_effect = (struct ff_effect_compat *)effect; | ||
| 415 | |||
| 416 | if (copy_from_user(compat_effect, buffer, | ||
| 417 | sizeof(struct ff_effect_compat))) | ||
| 418 | return -EFAULT; | ||
| 419 | |||
| 420 | if (compat_effect->type == FF_PERIODIC && | ||
| 421 | compat_effect->u.periodic.waveform == FF_CUSTOM) | ||
| 422 | effect->u.periodic.custom_data = | ||
| 423 | compat_ptr(compat_effect->u.periodic.custom_data); | ||
| 424 | } else { | ||
| 425 | if (size != sizeof(struct ff_effect)) | ||
| 426 | return -EINVAL; | ||
| 427 | |||
| 428 | if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) | ||
| 429 | return -EFAULT; | ||
| 430 | } | ||
| 431 | |||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | #else | ||
| 436 | |||
| 437 | static inline size_t evdev_event_size(void) | ||
| 438 | { | ||
| 439 | return sizeof(struct input_event); | ||
| 440 | } | ||
| 441 | |||
| 442 | static int evdev_event_from_user(const char __user *buffer, | ||
| 443 | struct input_event *event) | ||
| 444 | { | ||
| 445 | if (copy_from_user(event, buffer, sizeof(struct input_event))) | ||
| 446 | return -EFAULT; | ||
| 447 | |||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | static int evdev_event_to_user(char __user *buffer, | ||
| 452 | const struct input_event *event) | ||
| 453 | { | ||
| 454 | if (copy_to_user(buffer, event, sizeof(struct input_event))) | ||
| 455 | return -EFAULT; | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | static int evdev_ff_effect_from_user(const char __user *buffer, size_t size, | ||
| 461 | struct ff_effect *effect) | ||
| 462 | { | ||
| 463 | if (size != sizeof(struct ff_effect)) | ||
| 464 | return -EINVAL; | ||
| 465 | |||
| 466 | if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) | ||
| 467 | return -EFAULT; | ||
| 468 | |||
| 469 | return 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | #endif /* CONFIG_COMPAT */ | ||
| 473 | |||
| 474 | static ssize_t evdev_write(struct file *file, const char __user *buffer, | 293 | static ssize_t evdev_write(struct file *file, const char __user *buffer, |
| 475 | size_t count, loff_t *ppos) | 294 | size_t count, loff_t *ppos) |
| 476 | { | 295 | { |
| @@ -490,14 +309,14 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, | |||
| 490 | 309 | ||
| 491 | while (retval < count) { | 310 | while (retval < count) { |
| 492 | 311 | ||
| 493 | if (evdev_event_from_user(buffer + retval, &event)) { | 312 | if (input_event_from_user(buffer + retval, &event)) { |
| 494 | retval = -EFAULT; | 313 | retval = -EFAULT; |
| 495 | goto out; | 314 | goto out; |
| 496 | } | 315 | } |
| 497 | 316 | ||
| 498 | input_inject_event(&evdev->handle, | 317 | input_inject_event(&evdev->handle, |
| 499 | event.type, event.code, event.value); | 318 | event.type, event.code, event.value); |
| 500 | retval += evdev_event_size(); | 319 | retval += input_event_size(); |
| 501 | } | 320 | } |
| 502 | 321 | ||
| 503 | out: | 322 | out: |
| @@ -531,7 +350,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, | |||
| 531 | struct input_event event; | 350 | struct input_event event; |
| 532 | int retval; | 351 | int retval; |
| 533 | 352 | ||
| 534 | if (count < evdev_event_size()) | 353 | if (count < input_event_size()) |
| 535 | return -EINVAL; | 354 | return -EINVAL; |
| 536 | 355 | ||
| 537 | if (client->head == client->tail && evdev->exist && | 356 | if (client->head == client->tail && evdev->exist && |
| @@ -546,13 +365,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, | |||
| 546 | if (!evdev->exist) | 365 | if (!evdev->exist) |
| 547 | return -ENODEV; | 366 | return -ENODEV; |
| 548 | 367 | ||
| 549 | while (retval + evdev_event_size() <= count && | 368 | while (retval + input_event_size() <= count && |
| 550 | evdev_fetch_next_event(client, &event)) { | 369 | evdev_fetch_next_event(client, &event)) { |
| 551 | 370 | ||
| 552 | if (evdev_event_to_user(buffer + retval, &event)) | 371 | if (input_event_to_user(buffer + retval, &event)) |
| 553 | return -EFAULT; | 372 | return -EFAULT; |
| 554 | 373 | ||
| 555 | retval += evdev_event_size(); | 374 | retval += input_event_size(); |
| 556 | } | 375 | } |
| 557 | 376 | ||
| 558 | return retval; | 377 | return retval; |
| @@ -823,7 +642,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
| 823 | 642 | ||
| 824 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) { | 643 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) { |
| 825 | 644 | ||
| 826 | if (evdev_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect)) | 645 | if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect)) |
| 827 | return -EFAULT; | 646 | return -EFAULT; |
| 828 | 647 | ||
| 829 | error = input_ff_upload(dev, &effect, file); | 648 | error = input_ff_upload(dev, &effect, file); |
| @@ -1000,7 +819,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 1000 | evdev->handle.handler = handler; | 819 | evdev->handle.handler = handler; |
| 1001 | evdev->handle.private = evdev; | 820 | evdev->handle.private = evdev; |
| 1002 | 821 | ||
| 1003 | strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id)); | 822 | dev_set_name(&evdev->dev, evdev->name); |
| 1004 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | 823 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); |
| 1005 | evdev->dev.class = &input_class; | 824 | evdev->dev.class = &input_class; |
| 1006 | evdev->dev.parent = &dev->dev; | 825 | evdev->dev.parent = &dev->dev; |
