Commit 41e979f822b34e789560ae2752f26f4a018f5d7e
Committed by
Dmitry Torokhov
1 parent
bef3768d8f
Input: Make EVIOSCSABS work in evdev.
Signed-off-by: Vojtech Pavlik <vojtech@suse.cz> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Showing 1 changed file with 180 additions and 199 deletions Side-by-side Diff
drivers/input/evdev.c
... | ... | @@ -236,7 +236,7 @@ |
236 | 236 | event_compat.value = event->value; |
237 | 237 | |
238 | 238 | if (copy_to_user(buffer + retval, &event_compat, |
239 | - sizeof(struct input_event_compat))) return -EFAULT; | |
239 | + sizeof(struct input_event_compat))) return -EFAULT; | |
240 | 240 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); |
241 | 241 | retval += sizeof(struct input_event_compat); |
242 | 242 | } |
... | ... | @@ -272,7 +272,7 @@ |
272 | 272 | |
273 | 273 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { |
274 | 274 | if (copy_to_user(buffer + retval, list->buffer + list->tail, |
275 | - sizeof(struct input_event))) return -EFAULT; | |
275 | + sizeof(struct input_event))) return -EFAULT; | |
276 | 276 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); |
277 | 277 | retval += sizeof(struct input_event); |
278 | 278 | } |
279 | 279 | |
280 | 280 | |
281 | 281 | |
282 | 282 | |
283 | 283 | |
284 | 284 | |
285 | 285 | |
286 | 286 | |
287 | 287 | |
288 | 288 | |
289 | 289 | |
290 | 290 | |
291 | 291 | |
292 | 292 | |
293 | 293 | |
294 | 294 | |
295 | 295 | |
296 | 296 | |
297 | 297 | |
298 | 298 | |
... | ... | @@ -371,105 +371,112 @@ |
371 | 371 | |
372 | 372 | default: |
373 | 373 | |
374 | - if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) | |
374 | + if (_IOC_TYPE(cmd) != 'E') | |
375 | 375 | return -EINVAL; |
376 | 376 | |
377 | - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | |
377 | + if (_IOC_DIR(cmd) == _IOC_READ) { | |
378 | 378 | |
379 | - long *bits; | |
380 | - int len; | |
379 | + if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | |
381 | 380 | |
382 | - switch (_IOC_NR(cmd) & EV_MAX) { | |
383 | - case 0: bits = dev->evbit; len = EV_MAX; break; | |
384 | - case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | |
385 | - case EV_REL: bits = dev->relbit; len = REL_MAX; break; | |
386 | - case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | |
387 | - case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | |
388 | - case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | |
389 | - case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | |
390 | - case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | |
391 | - default: return -EINVAL; | |
381 | + long *bits; | |
382 | + int len; | |
383 | + | |
384 | + switch (_IOC_NR(cmd) & EV_MAX) { | |
385 | + case 0: bits = dev->evbit; len = EV_MAX; break; | |
386 | + case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | |
387 | + case EV_REL: bits = dev->relbit; len = REL_MAX; break; | |
388 | + case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | |
389 | + case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | |
390 | + case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | |
391 | + case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | |
392 | + case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | |
393 | + default: return -EINVAL; | |
394 | + } | |
395 | + len = NBITS(len) * sizeof(long); | |
396 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
397 | + return copy_to_user(p, bits, len) ? -EFAULT : len; | |
392 | 398 | } |
393 | - len = NBITS(len) * sizeof(long); | |
394 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
395 | - return copy_to_user(p, bits, len) ? -EFAULT : len; | |
396 | - } | |
397 | 399 | |
398 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { | |
399 | - int len; | |
400 | - len = NBITS(KEY_MAX) * sizeof(long); | |
401 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
402 | - return copy_to_user(p, dev->key, len) ? -EFAULT : len; | |
403 | - } | |
400 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { | |
401 | + int len; | |
402 | + len = NBITS(KEY_MAX) * sizeof(long); | |
403 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
404 | + return copy_to_user(p, dev->key, len) ? -EFAULT : len; | |
405 | + } | |
404 | 406 | |
405 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { | |
406 | - int len; | |
407 | - len = NBITS(LED_MAX) * sizeof(long); | |
408 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
409 | - return copy_to_user(p, dev->led, len) ? -EFAULT : len; | |
410 | - } | |
407 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { | |
408 | + int len; | |
409 | + len = NBITS(LED_MAX) * sizeof(long); | |
410 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
411 | + return copy_to_user(p, dev->led, len) ? -EFAULT : len; | |
412 | + } | |
411 | 413 | |
412 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { | |
413 | - int len; | |
414 | - len = NBITS(SND_MAX) * sizeof(long); | |
415 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
416 | - return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | |
417 | - } | |
414 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { | |
415 | + int len; | |
416 | + len = NBITS(SND_MAX) * sizeof(long); | |
417 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
418 | + return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | |
419 | + } | |
418 | 420 | |
419 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | |
420 | - int len; | |
421 | - if (!dev->name) return -ENOENT; | |
422 | - len = strlen(dev->name) + 1; | |
423 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
424 | - return copy_to_user(p, dev->name, len) ? -EFAULT : len; | |
425 | - } | |
421 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | |
422 | + int len; | |
423 | + if (!dev->name) return -ENOENT; | |
424 | + len = strlen(dev->name) + 1; | |
425 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
426 | + return copy_to_user(p, dev->name, len) ? -EFAULT : len; | |
427 | + } | |
426 | 428 | |
427 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | |
428 | - int len; | |
429 | - if (!dev->phys) return -ENOENT; | |
430 | - len = strlen(dev->phys) + 1; | |
431 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
432 | - return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | |
433 | - } | |
429 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | |
430 | + int len; | |
431 | + if (!dev->phys) return -ENOENT; | |
432 | + len = strlen(dev->phys) + 1; | |
433 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
434 | + return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | |
435 | + } | |
434 | 436 | |
435 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | |
436 | - int len; | |
437 | - if (!dev->uniq) return -ENOENT; | |
438 | - len = strlen(dev->uniq) + 1; | |
439 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
440 | - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | |
441 | - } | |
437 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | |
438 | + int len; | |
439 | + if (!dev->uniq) return -ENOENT; | |
440 | + len = strlen(dev->uniq) + 1; | |
441 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
442 | + return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | |
443 | + } | |
442 | 444 | |
443 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | |
445 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | |
444 | 446 | |
445 | - int t = _IOC_NR(cmd) & ABS_MAX; | |
447 | + int t = _IOC_NR(cmd) & ABS_MAX; | |
446 | 448 | |
447 | - abs.value = dev->abs[t]; | |
448 | - abs.minimum = dev->absmin[t]; | |
449 | - abs.maximum = dev->absmax[t]; | |
450 | - abs.fuzz = dev->absfuzz[t]; | |
451 | - abs.flat = dev->absflat[t]; | |
449 | + abs.value = dev->abs[t]; | |
450 | + abs.minimum = dev->absmin[t]; | |
451 | + abs.maximum = dev->absmax[t]; | |
452 | + abs.fuzz = dev->absfuzz[t]; | |
453 | + abs.flat = dev->absflat[t]; | |
452 | 454 | |
453 | - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | |
454 | - return -EFAULT; | |
455 | + if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | |
456 | + return -EFAULT; | |
455 | 457 | |
456 | - return 0; | |
458 | + return 0; | |
459 | + } | |
460 | + | |
457 | 461 | } |
458 | 462 | |
459 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
463 | + if (_IOC_DIR(cmd) == _IOC_WRITE) { | |
460 | 464 | |
461 | - int t = _IOC_NR(cmd) & ABS_MAX; | |
465 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
462 | 466 | |
463 | - if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | |
464 | - return -EFAULT; | |
467 | + int t = _IOC_NR(cmd) & ABS_MAX; | |
465 | 468 | |
466 | - dev->abs[t] = abs.value; | |
467 | - dev->absmin[t] = abs.minimum; | |
468 | - dev->absmax[t] = abs.maximum; | |
469 | - dev->absfuzz[t] = abs.fuzz; | |
470 | - dev->absflat[t] = abs.flat; | |
469 | + if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | |
470 | + return -EFAULT; | |
471 | 471 | |
472 | - return 0; | |
472 | + dev->abs[t] = abs.value; | |
473 | + dev->absmin[t] = abs.minimum; | |
474 | + dev->absmax[t] = abs.maximum; | |
475 | + dev->absfuzz[t] = abs.fuzz; | |
476 | + dev->absflat[t] = abs.flat; | |
477 | + | |
478 | + return 0; | |
479 | + } | |
473 | 480 | } |
474 | 481 | } |
475 | 482 | return -EINVAL; |
... | ... | @@ -484,6 +491,28 @@ |
484 | 491 | #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) |
485 | 492 | #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) |
486 | 493 | |
494 | +#ifdef __BIG_ENDIAN | |
495 | +#define bit_to_user(bit, max) \ | |
496 | +do { \ | |
497 | + int i; \ | |
498 | + int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | |
499 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | |
500 | + for (i = 0; i < len / sizeof(compat_long_t); i++) \ | |
501 | + if (copy_to_user((compat_long_t*) p + i, \ | |
502 | + (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ | |
503 | + sizeof(compat_long_t))) \ | |
504 | + return -EFAULT; \ | |
505 | + return len; \ | |
506 | +} while (0) | |
507 | +#else | |
508 | +#define bit_to_user(bit, max) \ | |
509 | +do { \ | |
510 | + int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | |
511 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | |
512 | + return copy_to_user(p, (bit), len) ? -EFAULT : len; \ | |
513 | +} while (0) | |
514 | +#endif | |
515 | + | |
487 | 516 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
488 | 517 | { |
489 | 518 | struct evdev_list *list = file->private_data; |
... | ... | @@ -491,9 +520,6 @@ |
491 | 520 | struct input_dev *dev = evdev->handle.dev; |
492 | 521 | struct input_absinfo abs; |
493 | 522 | void __user *p = compat_ptr(arg); |
494 | -#ifdef __BIG_ENDIAN | |
495 | - int i; | |
496 | -#endif | |
497 | 523 | |
498 | 524 | if (!evdev->exist) return -ENODEV; |
499 | 525 | |
500 | 526 | |
501 | 527 | |
502 | 528 | |
503 | 529 | |
504 | 530 | |
505 | 531 | |
506 | 532 | |
507 | 533 | |
508 | 534 | |
509 | 535 | |
510 | 536 | |
511 | 537 | |
512 | 538 | |
513 | 539 | |
514 | 540 | |
515 | 541 | |
516 | 542 | |
517 | 543 | |
518 | 544 | |
519 | 545 | |
... | ... | @@ -511,141 +537,96 @@ |
511 | 537 | |
512 | 538 | default: |
513 | 539 | |
514 | - if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) | |
540 | + if (_IOC_TYPE(cmd) != 'E') | |
515 | 541 | return -EINVAL; |
516 | 542 | |
517 | - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | |
543 | + if (_IOC_DIR(cmd) == _IOC_READ) { | |
518 | 544 | |
519 | - long *bits; | |
520 | - int len; | |
545 | + if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | |
546 | + long *bits; | |
547 | + int max; | |
521 | 548 | |
522 | - switch (_IOC_NR(cmd) & EV_MAX) { | |
523 | - case 0: bits = dev->evbit; len = EV_MAX; break; | |
524 | - case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | |
525 | - case EV_REL: bits = dev->relbit; len = REL_MAX; break; | |
526 | - case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | |
527 | - case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | |
528 | - case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | |
529 | - case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | |
530 | - case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | |
531 | - default: return -EINVAL; | |
549 | + switch (_IOC_NR(cmd) & EV_MAX) { | |
550 | + case 0: bits = dev->evbit; max = EV_MAX; break; | |
551 | + case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; | |
552 | + case EV_REL: bits = dev->relbit; max = REL_MAX; break; | |
553 | + case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; | |
554 | + case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; | |
555 | + case EV_LED: bits = dev->ledbit; max = LED_MAX; break; | |
556 | + case EV_SND: bits = dev->sndbit; max = SND_MAX; break; | |
557 | + case EV_FF: bits = dev->ffbit; max = FF_MAX; break; | |
558 | + default: return -EINVAL; | |
559 | + } | |
560 | + bit_to_user(bits, max); | |
532 | 561 | } |
533 | - len = NBITS_COMPAT(len) * sizeof(compat_long_t); | |
534 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
535 | -#ifdef __BIG_ENDIAN | |
536 | - for (i = 0; i < len / sizeof(compat_long_t); i++) | |
537 | - if (copy_to_user((compat_long_t*) p + i, | |
538 | - (compat_long_t*) bits + i + 1 - ((i % 2) << 1), | |
539 | - sizeof(compat_long_t))) | |
540 | - return -EFAULT; | |
541 | - return len; | |
542 | -#else | |
543 | - return copy_to_user(p, bits, len) ? -EFAULT : len; | |
544 | -#endif | |
545 | - } | |
546 | 562 | |
547 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { | |
548 | - int len; | |
549 | - len = NBITS_COMPAT(KEY_MAX) * sizeof(compat_long_t); | |
550 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
551 | -#ifdef __BIG_ENDIAN | |
552 | - for (i = 0; i < len / sizeof(compat_long_t); i++) | |
553 | - if (copy_to_user((compat_long_t*) p + i, | |
554 | - (compat_long_t*) dev->key + i + 1 - ((i % 2) << 1), | |
555 | - sizeof(compat_long_t))) | |
556 | - return -EFAULT; | |
557 | - return len; | |
558 | -#else | |
559 | - return copy_to_user(p, dev->key, len) ? -EFAULT : len; | |
560 | -#endif | |
561 | - } | |
563 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | |
564 | + bit_to_user(dev->key, KEY_MAX); | |
562 | 565 | |
563 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { | |
564 | - int len; | |
565 | - len = NBITS_COMPAT(LED_MAX) * sizeof(compat_long_t); | |
566 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
567 | -#ifdef __BIG_ENDIAN | |
568 | - for (i = 0; i < len / sizeof(compat_long_t); i++) | |
569 | - if (copy_to_user((compat_long_t*) p + i, | |
570 | - (compat_long_t*) dev->led + i + 1 - ((i % 2) << 1), | |
571 | - sizeof(compat_long_t))) | |
572 | - return -EFAULT; | |
573 | - return len; | |
574 | -#else | |
575 | - return copy_to_user(p, dev->led, len) ? -EFAULT : len; | |
576 | -#endif | |
577 | - } | |
566 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | |
567 | + bit_to_user(dev->led, LED_MAX); | |
578 | 568 | |
579 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { | |
580 | - int len; | |
581 | - len = NBITS_COMPAT(SND_MAX) * sizeof(compat_long_t); | |
582 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
583 | -#ifdef __BIG_ENDIAN | |
584 | - for (i = 0; i < len / sizeof(compat_long_t); i++) | |
585 | - if (copy_to_user((compat_long_t*) p + i, | |
586 | - (compat_long_t*) dev->snd + i + 1 - ((i % 2) << 1), | |
587 | - sizeof(compat_long_t))) | |
588 | - return -EFAULT; | |
589 | - return len; | |
590 | -#else | |
591 | - return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | |
592 | -#endif | |
593 | - } | |
569 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | |
570 | + bit_to_user(dev->snd, SND_MAX); | |
594 | 571 | |
595 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | |
596 | - int len; | |
597 | - if (!dev->name) return -ENOENT; | |
598 | - len = strlen(dev->name) + 1; | |
599 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
600 | - return copy_to_user(p, dev->name, len) ? -EFAULT : len; | |
601 | - } | |
572 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | |
573 | + int len; | |
574 | + if (!dev->name) return -ENOENT; | |
575 | + len = strlen(dev->name) + 1; | |
576 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
577 | + return copy_to_user(p, dev->name, len) ? -EFAULT : len; | |
578 | + } | |
602 | 579 | |
603 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | |
604 | - int len; | |
605 | - if (!dev->phys) return -ENOENT; | |
606 | - len = strlen(dev->phys) + 1; | |
607 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
608 | - return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | |
609 | - } | |
580 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | |
581 | + int len; | |
582 | + if (!dev->phys) return -ENOENT; | |
583 | + len = strlen(dev->phys) + 1; | |
584 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
585 | + return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | |
586 | + } | |
610 | 587 | |
611 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | |
612 | - int len; | |
613 | - if (!dev->uniq) return -ENOENT; | |
614 | - len = strlen(dev->uniq) + 1; | |
615 | - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
616 | - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | |
617 | - } | |
588 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | |
589 | + int len; | |
590 | + if (!dev->uniq) return -ENOENT; | |
591 | + len = strlen(dev->uniq) + 1; | |
592 | + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | |
593 | + return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | |
594 | + } | |
618 | 595 | |
619 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | |
596 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | |
620 | 597 | |
621 | - int t = _IOC_NR(cmd) & ABS_MAX; | |
598 | + int t = _IOC_NR(cmd) & ABS_MAX; | |
622 | 599 | |
623 | - abs.value = dev->abs[t]; | |
624 | - abs.minimum = dev->absmin[t]; | |
625 | - abs.maximum = dev->absmax[t]; | |
626 | - abs.fuzz = dev->absfuzz[t]; | |
627 | - abs.flat = dev->absflat[t]; | |
600 | + abs.value = dev->abs[t]; | |
601 | + abs.minimum = dev->absmin[t]; | |
602 | + abs.maximum = dev->absmax[t]; | |
603 | + abs.fuzz = dev->absfuzz[t]; | |
604 | + abs.flat = dev->absflat[t]; | |
628 | 605 | |
629 | - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | |
630 | - return -EFAULT; | |
606 | + if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | |
607 | + return -EFAULT; | |
631 | 608 | |
632 | - return 0; | |
609 | + return 0; | |
610 | + } | |
633 | 611 | } |
634 | 612 | |
635 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
613 | + if (_IOC_DIR(cmd) == _IOC_WRITE) { | |
636 | 614 | |
637 | - int t = _IOC_NR(cmd) & ABS_MAX; | |
615 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
638 | 616 | |
639 | - if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | |
640 | - return -EFAULT; | |
617 | + int t = _IOC_NR(cmd) & ABS_MAX; | |
641 | 618 | |
642 | - dev->abs[t] = abs.value; | |
643 | - dev->absmin[t] = abs.minimum; | |
644 | - dev->absmax[t] = abs.maximum; | |
645 | - dev->absfuzz[t] = abs.fuzz; | |
646 | - dev->absflat[t] = abs.flat; | |
619 | + if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | |
620 | + return -EFAULT; | |
647 | 621 | |
648 | - return 0; | |
622 | + dev->abs[t] = abs.value; | |
623 | + dev->absmin[t] = abs.minimum; | |
624 | + dev->absmax[t] = abs.maximum; | |
625 | + dev->absfuzz[t] = abs.fuzz; | |
626 | + dev->absflat[t] = abs.flat; | |
627 | + | |
628 | + return 0; | |
629 | + } | |
649 | 630 | } |
650 | 631 | } |
651 | 632 | return -EINVAL; |