diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/input.c | 279 |
1 files changed, 168 insertions, 111 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 8dcd3931fa62..db52ba0a316f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/random.h> | 18 | #include <linux/random.h> |
19 | #include <linux/major.h> | 19 | #include <linux/major.h> |
20 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
21 | #include <linux/seq_file.h> | ||
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
23 | #include <linux/device.h> | 24 | #include <linux/device.h> |
@@ -316,26 +317,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st | |||
316 | return NULL; | 317 | return NULL; |
317 | } | 318 | } |
318 | 319 | ||
319 | static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | ||
320 | int max, int add_cr) | ||
321 | { | ||
322 | int i; | ||
323 | int len = 0; | ||
324 | |||
325 | for (i = NBITS(max) - 1; i > 0; i--) | ||
326 | if (bitmap[i]) | ||
327 | break; | ||
328 | |||
329 | for (; i >= 0; i--) | ||
330 | len += snprintf(buf + len, max(buf_size - len, 0), | ||
331 | "%lx%s", bitmap[i], i > 0 ? " " : ""); | ||
332 | |||
333 | if (add_cr) | ||
334 | len += snprintf(buf + len, max(buf_size - len, 0), "\n"); | ||
335 | |||
336 | return len; | ||
337 | } | ||
338 | |||
339 | #ifdef CONFIG_PROC_FS | 320 | #ifdef CONFIG_PROC_FS |
340 | 321 | ||
341 | static struct proc_dir_entry *proc_bus_input_dir; | 322 | static struct proc_dir_entry *proc_bus_input_dir; |
@@ -348,7 +329,7 @@ static inline void input_wakeup_procfs_readers(void) | |||
348 | wake_up(&input_devices_poll_wait); | 329 | wake_up(&input_devices_poll_wait); |
349 | } | 330 | } |
350 | 331 | ||
351 | static unsigned int input_devices_poll(struct file *file, poll_table *wait) | 332 | static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) |
352 | { | 333 | { |
353 | int state = input_devices_state; | 334 | int state = input_devices_state; |
354 | poll_wait(file, &input_devices_poll_wait, wait); | 335 | poll_wait(file, &input_devices_poll_wait, wait); |
@@ -357,114 +338,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait) | |||
357 | return 0; | 338 | return 0; |
358 | } | 339 | } |
359 | 340 | ||
360 | #define SPRINTF_BIT(ev, bm) \ | 341 | static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos) |
361 | do { \ | 342 | { |
362 | len += sprintf(buf + len, "B: %s=", #ev); \ | 343 | struct list_head *node; |
363 | len += input_print_bitmap(buf + len, INT_MAX, \ | 344 | loff_t i = 0; |
364 | dev->bm##bit, ev##_MAX, 1); \ | ||
365 | } while (0) | ||
366 | 345 | ||
367 | #define TEST_AND_SPRINTF_BIT(ev, bm) \ | 346 | list_for_each(node, list) |
368 | do { \ | 347 | if (i++ == *pos) |
369 | if (test_bit(EV_##ev, dev->evbit)) \ | 348 | return node; |
370 | SPRINTF_BIT(ev, bm); \ | 349 | |
371 | } while (0) | 350 | return NULL; |
351 | } | ||
372 | 352 | ||
373 | static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) | 353 | static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos) |
374 | { | 354 | { |
375 | struct input_dev *dev; | 355 | if (element->next == list) |
376 | struct input_handle *handle; | 356 | return NULL; |
377 | const char *path; | ||
378 | 357 | ||
379 | off_t at = 0; | 358 | ++(*pos); |
380 | int len, cnt = 0; | 359 | return element->next; |
360 | } | ||
381 | 361 | ||
382 | list_for_each_entry(dev, &input_dev_list, node) { | 362 | static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) |
363 | { | ||
364 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | ||
383 | 365 | ||
384 | path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); | 366 | return list_get_nth_element(&input_dev_list, pos); |
367 | } | ||
385 | 368 | ||
386 | len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", | 369 | static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
387 | dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); | 370 | { |
371 | return list_get_next_element(&input_dev_list, v, pos); | ||
372 | } | ||
388 | 373 | ||
389 | len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); | 374 | static void input_devices_seq_stop(struct seq_file *seq, void *v) |
390 | len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); | 375 | { |
391 | len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : ""); | 376 | /* release lock here */ |
392 | len += sprintf(buf + len, "H: Handlers="); | 377 | } |
393 | 378 | ||
394 | list_for_each_entry(handle, &dev->h_list, d_node) | 379 | static void input_seq_print_bitmap(struct seq_file *seq, const char *name, |
395 | len += sprintf(buf + len, "%s ", handle->name); | 380 | unsigned long *bitmap, int max) |
396 | 381 | { | |
397 | len += sprintf(buf + len, "\n"); | 382 | int i; |
398 | |||
399 | SPRINTF_BIT(EV, ev); | ||
400 | TEST_AND_SPRINTF_BIT(KEY, key); | ||
401 | TEST_AND_SPRINTF_BIT(REL, rel); | ||
402 | TEST_AND_SPRINTF_BIT(ABS, abs); | ||
403 | TEST_AND_SPRINTF_BIT(MSC, msc); | ||
404 | TEST_AND_SPRINTF_BIT(LED, led); | ||
405 | TEST_AND_SPRINTF_BIT(SND, snd); | ||
406 | TEST_AND_SPRINTF_BIT(FF, ff); | ||
407 | TEST_AND_SPRINTF_BIT(SW, sw); | ||
408 | |||
409 | len += sprintf(buf + len, "\n"); | ||
410 | |||
411 | at += len; | ||
412 | |||
413 | if (at >= pos) { | ||
414 | if (!*start) { | ||
415 | *start = buf + (pos - (at - len)); | ||
416 | cnt = at - pos; | ||
417 | } else cnt += len; | ||
418 | buf += len; | ||
419 | if (cnt >= count) | ||
420 | break; | ||
421 | } | ||
422 | 383 | ||
423 | kfree(path); | 384 | for (i = NBITS(max) - 1; i > 0; i--) |
424 | } | 385 | if (bitmap[i]) |
386 | break; | ||
387 | |||
388 | seq_printf(seq, "B: %s=", name); | ||
389 | for (; i >= 0; i--) | ||
390 | seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : ""); | ||
391 | seq_putc(seq, '\n'); | ||
392 | } | ||
393 | |||
394 | static int input_devices_seq_show(struct seq_file *seq, void *v) | ||
395 | { | ||
396 | struct input_dev *dev = container_of(v, struct input_dev, node); | ||
397 | const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); | ||
398 | struct input_handle *handle; | ||
399 | |||
400 | seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", | ||
401 | dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); | ||
402 | |||
403 | seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); | ||
404 | seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : ""); | ||
405 | seq_printf(seq, "S: Sysfs=%s\n", path ? path : ""); | ||
406 | seq_printf(seq, "H: Handlers="); | ||
425 | 407 | ||
426 | if (&dev->node == &input_dev_list) | 408 | list_for_each_entry(handle, &dev->h_list, d_node) |
427 | *eof = 1; | 409 | seq_printf(seq, "%s ", handle->name); |
410 | seq_putc(seq, '\n'); | ||
428 | 411 | ||
429 | return (count > cnt) ? cnt : count; | 412 | input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX); |
413 | if (test_bit(EV_KEY, dev->evbit)) | ||
414 | input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); | ||
415 | if (test_bit(EV_REL, dev->evbit)) | ||
416 | input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX); | ||
417 | if (test_bit(EV_ABS, dev->evbit)) | ||
418 | input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX); | ||
419 | if (test_bit(EV_MSC, dev->evbit)) | ||
420 | input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX); | ||
421 | if (test_bit(EV_LED, dev->evbit)) | ||
422 | input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX); | ||
423 | if (test_bit(EV_SND, dev->evbit)) | ||
424 | input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX); | ||
425 | if (test_bit(EV_FF, dev->evbit)) | ||
426 | input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX); | ||
427 | if (test_bit(EV_SW, dev->evbit)) | ||
428 | input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX); | ||
429 | |||
430 | seq_putc(seq, '\n'); | ||
431 | |||
432 | kfree(path); | ||
433 | return 0; | ||
430 | } | 434 | } |
431 | 435 | ||
432 | static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) | 436 | static struct seq_operations input_devices_seq_ops = { |
437 | .start = input_devices_seq_start, | ||
438 | .next = input_devices_seq_next, | ||
439 | .stop = input_devices_seq_stop, | ||
440 | .show = input_devices_seq_show, | ||
441 | }; | ||
442 | |||
443 | static int input_proc_devices_open(struct inode *inode, struct file *file) | ||
433 | { | 444 | { |
434 | struct input_handler *handler; | 445 | return seq_open(file, &input_devices_seq_ops); |
446 | } | ||
435 | 447 | ||
436 | off_t at = 0; | 448 | static struct file_operations input_devices_fileops = { |
437 | int len = 0, cnt = 0; | 449 | .owner = THIS_MODULE, |
438 | int i = 0; | 450 | .open = input_proc_devices_open, |
451 | .poll = input_proc_devices_poll, | ||
452 | .read = seq_read, | ||
453 | .llseek = seq_lseek, | ||
454 | .release = seq_release, | ||
455 | }; | ||
439 | 456 | ||
440 | list_for_each_entry(handler, &input_handler_list, node) { | 457 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) |
458 | { | ||
459 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | ||
460 | seq->private = (void *)(unsigned long)*pos; | ||
461 | return list_get_nth_element(&input_handler_list, pos); | ||
462 | } | ||
441 | 463 | ||
442 | if (handler->fops) | 464 | static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
443 | len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n", | 465 | { |
444 | i++, handler->name, handler->minor); | 466 | seq->private = (void *)(unsigned long)(*pos + 1); |
445 | else | 467 | return list_get_next_element(&input_handler_list, v, pos); |
446 | len = sprintf(buf, "N: Number=%d Name=%s\n", | 468 | } |
447 | i++, handler->name); | ||
448 | 469 | ||
449 | at += len; | 470 | static void input_handlers_seq_stop(struct seq_file *seq, void *v) |
471 | { | ||
472 | /* release lock here */ | ||
473 | } | ||
450 | 474 | ||
451 | if (at >= pos) { | 475 | static int input_handlers_seq_show(struct seq_file *seq, void *v) |
452 | if (!*start) { | 476 | { |
453 | *start = buf + (pos - (at - len)); | 477 | struct input_handler *handler = container_of(v, struct input_handler, node); |
454 | cnt = at - pos; | ||
455 | } else cnt += len; | ||
456 | buf += len; | ||
457 | if (cnt >= count) | ||
458 | break; | ||
459 | } | ||
460 | } | ||
461 | if (&handler->node == &input_handler_list) | ||
462 | *eof = 1; | ||
463 | 478 | ||
464 | return (count > cnt) ? cnt : count; | 479 | seq_printf(seq, "N: Number=%ld Name=%s", |
480 | (unsigned long)seq->private, handler->name); | ||
481 | if (handler->fops) | ||
482 | seq_printf(seq, " Minor=%d", handler->minor); | ||
483 | seq_putc(seq, '\n'); | ||
484 | |||
485 | return 0; | ||
465 | } | 486 | } |
487 | static struct seq_operations input_handlers_seq_ops = { | ||
488 | .start = input_handlers_seq_start, | ||
489 | .next = input_handlers_seq_next, | ||
490 | .stop = input_handlers_seq_stop, | ||
491 | .show = input_handlers_seq_show, | ||
492 | }; | ||
466 | 493 | ||
467 | static struct file_operations input_fileops; | 494 | static int input_proc_handlers_open(struct inode *inode, struct file *file) |
495 | { | ||
496 | return seq_open(file, &input_handlers_seq_ops); | ||
497 | } | ||
498 | |||
499 | static struct file_operations input_handlers_fileops = { | ||
500 | .owner = THIS_MODULE, | ||
501 | .open = input_proc_handlers_open, | ||
502 | .read = seq_read, | ||
503 | .llseek = seq_lseek, | ||
504 | .release = seq_release, | ||
505 | }; | ||
468 | 506 | ||
469 | static int __init input_proc_init(void) | 507 | static int __init input_proc_init(void) |
470 | { | 508 | { |
@@ -476,20 +514,19 @@ static int __init input_proc_init(void) | |||
476 | 514 | ||
477 | proc_bus_input_dir->owner = THIS_MODULE; | 515 | proc_bus_input_dir->owner = THIS_MODULE; |
478 | 516 | ||
479 | entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL); | 517 | entry = create_proc_entry("devices", 0, proc_bus_input_dir); |
480 | if (!entry) | 518 | if (!entry) |
481 | goto fail1; | 519 | goto fail1; |
482 | 520 | ||
483 | entry->owner = THIS_MODULE; | 521 | entry->owner = THIS_MODULE; |
484 | input_fileops = *entry->proc_fops; | 522 | entry->proc_fops = &input_devices_fileops; |
485 | input_fileops.poll = input_devices_poll; | ||
486 | entry->proc_fops = &input_fileops; | ||
487 | 523 | ||
488 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); | 524 | entry = create_proc_entry("handlers", 0, proc_bus_input_dir); |
489 | if (!entry) | 525 | if (!entry) |
490 | goto fail2; | 526 | goto fail2; |
491 | 527 | ||
492 | entry->owner = THIS_MODULE; | 528 | entry->owner = THIS_MODULE; |
529 | entry->proc_fops = &input_handlers_fileops; | ||
493 | 530 | ||
494 | return 0; | 531 | return 0; |
495 | 532 | ||
@@ -631,6 +668,26 @@ static struct attribute_group input_dev_id_attr_group = { | |||
631 | .attrs = input_dev_id_attrs, | 668 | .attrs = input_dev_id_attrs, |
632 | }; | 669 | }; |
633 | 670 | ||
671 | static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | ||
672 | int max, int add_cr) | ||
673 | { | ||
674 | int i; | ||
675 | int len = 0; | ||
676 | |||
677 | for (i = NBITS(max) - 1; i > 0; i--) | ||
678 | if (bitmap[i]) | ||
679 | break; | ||
680 | |||
681 | for (; i >= 0; i--) | ||
682 | len += snprintf(buf + len, max(buf_size - len, 0), | ||
683 | "%lx%s", bitmap[i], i > 0 ? " " : ""); | ||
684 | |||
685 | if (add_cr) | ||
686 | len += snprintf(buf + len, max(buf_size - len, 0), "\n"); | ||
687 | |||
688 | return len; | ||
689 | } | ||
690 | |||
634 | #define INPUT_DEV_CAP_ATTR(ev, bm) \ | 691 | #define INPUT_DEV_CAP_ATTR(ev, bm) \ |
635 | static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ | 692 | static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ |
636 | { \ | 693 | { \ |