aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-core.c42
-rw-r--r--drivers/hid/hid-debug.c239
-rw-r--r--include/linux/hid-debug.h18
-rw-r--r--include/linux/hid.h26
4 files changed, 276 insertions, 49 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index d4317db85b5..449bd747d11 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -46,7 +46,7 @@
46 46
47int hid_debug = 0; 47int hid_debug = 0;
48module_param_named(debug, hid_debug, int, 0600); 48module_param_named(debug, hid_debug, int, 0600);
49MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)"); 49MODULE_PARM_DESC(debug, "toggle HID debugging messages");
50EXPORT_SYMBOL_GPL(hid_debug); 50EXPORT_SYMBOL_GPL(hid_debug);
51 51
52/* 52/*
@@ -859,7 +859,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
859 struct hid_driver *hdrv = hid->driver; 859 struct hid_driver *hdrv = hid->driver;
860 int ret; 860 int ret;
861 861
862 hid_dump_input(usage, value); 862 hid_dump_input(hid, usage, value);
863 863
864 if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { 864 if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
865 ret = hdrv->event(hid, field, usage, value); 865 ret = hdrv->event(hid, field, usage, value);
@@ -981,7 +981,7 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
981{ 981{
982 unsigned size = field->report_size; 982 unsigned size = field->report_size;
983 983
984 hid_dump_input(field->usage + offset, value); 984 hid_dump_input(field->report->device, field->usage + offset, value);
985 985
986 if (offset >= field->report_count) { 986 if (offset >= field->report_count) {
987 dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count); 987 dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
@@ -1075,6 +1075,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
1075 struct hid_report_enum *report_enum = hid->report_enum + type; 1075 struct hid_report_enum *report_enum = hid->report_enum + type;
1076 struct hid_driver *hdrv = hid->driver; 1076 struct hid_driver *hdrv = hid->driver;
1077 struct hid_report *report; 1077 struct hid_report *report;
1078 char *buf;
1078 unsigned int i; 1079 unsigned int i;
1079 int ret; 1080 int ret;
1080 1081
@@ -1086,18 +1087,36 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
1086 return -1; 1087 return -1;
1087 } 1088 }
1088 1089
1089 dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); 1090 buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE,
1091 interrupt ? GFP_ATOMIC : GFP_KERNEL);
1092
1093 if (!buf) {
1094 report = hid_get_report(report_enum, data);
1095 goto nomem;
1096 }
1097
1098 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1099 "\nreport (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
1100 hid_debug_event(hid, buf);
1090 1101
1091 report = hid_get_report(report_enum, data); 1102 report = hid_get_report(report_enum, data);
1092 if (!report) 1103 if (!report)
1093 return -1; 1104 return -1;
1094 1105
1095 /* dump the report */ 1106 /* dump the report */
1096 dbg_hid("report %d (size %u) = ", report->id, size); 1107 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1097 for (i = 0; i < size; i++) 1108 "report %d (size %u) = ", report->id, size);
1098 dbg_hid_line(" %02x", data[i]); 1109 hid_debug_event(hid, buf);
1099 dbg_hid_line("\n"); 1110 for (i = 0; i < size; i++) {
1111 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1112 " %02x", data[i]);
1113 hid_debug_event(hid, buf);
1114 }
1115 hid_debug_event(hid, "\n");
1116
1117 kfree(buf);
1100 1118
1119nomem:
1101 if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { 1120 if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
1102 ret = hdrv->raw_event(hid, report, data, size); 1121 ret = hdrv->raw_event(hid, report, data, size);
1103 if (ret != 0) 1122 if (ret != 0)
@@ -1756,6 +1775,9 @@ struct hid_device *hid_allocate_device(void)
1756 for (i = 0; i < HID_REPORT_TYPES; i++) 1775 for (i = 0; i < HID_REPORT_TYPES; i++)
1757 INIT_LIST_HEAD(&hdev->report_enum[i].report_list); 1776 INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
1758 1777
1778 init_waitqueue_head(&hdev->debug_wait);
1779 INIT_LIST_HEAD(&hdev->debug_list);
1780
1759 return hdev; 1781 return hdev;
1760err: 1782err:
1761 put_device(&hdev->dev); 1783 put_device(&hdev->dev);
@@ -1844,8 +1866,8 @@ static int __init hid_init(void)
1844 int ret; 1866 int ret;
1845 1867
1846 if (hid_debug) 1868 if (hid_debug)
1847 printk(KERN_WARNING "HID: hid_debug parameter has been deprecated. " 1869 printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n"
1848 "Debugging data are now provided via debugfs\n"); 1870 "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n");
1849 1871
1850 ret = bus_register(&hid_bus_type); 1872 ret = bus_register(&hid_bus_type);
1851 if (ret) { 1873 if (ret) {
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 067e173aa3e..a331a1821e8 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -28,6 +28,10 @@
28 28
29#include <linux/debugfs.h> 29#include <linux/debugfs.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/sched.h>
32#include <linux/uaccess.h>
33#include <linux/poll.h>
34
31#include <linux/hid.h> 35#include <linux/hid.h>
32#include <linux/hid-debug.h> 36#include <linux/hid-debug.h>
33 37
@@ -335,49 +339,86 @@ static const struct hid_usage_entry hid_usage_table[] = {
335 { 0, 0, NULL } 339 { 0, 0, NULL }
336}; 340};
337 341
338static void resolv_usage_page(unsigned page, struct seq_file *f) { 342/* Either output directly into simple seq_file, or (if f == NULL)
343 * allocate a separate buffer that will then be passed to the 'events'
344 * ringbuffer.
345 *
346 * This is because these functions can be called both for "one-shot"
347 * "rdesc" while resolving, or for blocking "events".
348 *
349 * This holds both for resolv_usage_page() and hid_resolv_usage().
350 */
351static char *resolv_usage_page(unsigned page, struct seq_file *f) {
339 const struct hid_usage_entry *p; 352 const struct hid_usage_entry *p;
353 char *buf = NULL;
354
355 if (!f) {
356 buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
357 if (!buf)
358 return ERR_PTR(-ENOMEM);
359 }
340 360
341 for (p = hid_usage_table; p->description; p++) 361 for (p = hid_usage_table; p->description; p++)
342 if (p->page == page) { 362 if (p->page == page) {
343 if (!f) 363 if (!f) {
344 printk("%s", p->description); 364 snprintf(buf, HID_DEBUG_BUFSIZE, "%s",
345 else 365 p->description);
366 return buf;
367 }
368 else {
346 seq_printf(f, "%s", p->description); 369 seq_printf(f, "%s", p->description);
347 return; 370 return NULL;
371 }
348 } 372 }
349 if (!f) 373 if (!f)
350 printk("%04x", page); 374 snprintf(buf, HID_DEBUG_BUFSIZE, "%04x", page);
351 else 375 else
352 seq_printf(f, "%04x", page); 376 seq_printf(f, "%04x", page);
377 return buf;
353} 378}
354 379
355void hid_resolv_usage(unsigned usage, struct seq_file *f) { 380char *hid_resolv_usage(unsigned usage, struct seq_file *f) {
356 const struct hid_usage_entry *p; 381 const struct hid_usage_entry *p;
382 char *buf = NULL;
383 int len = 0;
357 384
358 resolv_usage_page(usage >> 16, f); 385 buf = resolv_usage_page(usage >> 16, f);
359 if (!f) 386 if (IS_ERR(buf)) {
360 printk("."); 387 printk(KERN_ERR "error allocating HID debug buffer\n");
361 else 388 return NULL;
389 }
390
391
392 if (!f) {
393 len = strlen(buf);
394 snprintf(buf+len, max(0, HID_DEBUG_BUFSIZE - len), ".");
395 len++;
396 }
397 else {
362 seq_printf(f, "."); 398 seq_printf(f, ".");
399 }
363 for (p = hid_usage_table; p->description; p++) 400 for (p = hid_usage_table; p->description; p++)
364 if (p->page == (usage >> 16)) { 401 if (p->page == (usage >> 16)) {
365 for(++p; p->description && p->usage != 0; p++) 402 for(++p; p->description && p->usage != 0; p++)
366 if (p->usage == (usage & 0xffff)) { 403 if (p->usage == (usage & 0xffff)) {
367 if (!f) 404 if (!f)
368 printk("%s", p->description); 405 snprintf(buf + len,
406 max(0,HID_DEBUG_BUFSIZE - len - 1),
407 "%s", p->description);
369 else 408 else
370 seq_printf(f, 409 seq_printf(f,
371 "%s", 410 "%s",
372 p->description); 411 p->description);
373 return; 412 return buf;
374 } 413 }
375 break; 414 break;
376 } 415 }
377 if (!f) 416 if (!f)
378 printk("%04x", usage & 0xffff); 417 snprintf(buf + len, max(0, HID_DEBUG_BUFSIZE - len - 1),
418 "%04x", usage & 0xffff);
379 else 419 else
380 seq_printf(f, "%04x", usage & 0xffff); 420 seq_printf(f, "%04x", usage & 0xffff);
421 return buf;
381} 422}
382EXPORT_SYMBOL_GPL(hid_resolv_usage); 423EXPORT_SYMBOL_GPL(hid_resolv_usage);
383 424
@@ -508,13 +549,37 @@ void hid_dump_device(struct hid_device *device, struct seq_file *f)
508} 549}
509EXPORT_SYMBOL_GPL(hid_dump_device); 550EXPORT_SYMBOL_GPL(hid_dump_device);
510 551
511void hid_dump_input(struct hid_usage *usage, __s32 value) { 552/* enqueue string to 'events' ring buffer */
512 if (hid_debug < 2) 553void hid_debug_event(struct hid_device *hdev, char *buf)
554{
555 int i;
556 struct hid_debug_list *list;
557
558 list_for_each_entry(list, &hdev->debug_list, node) {
559 for (i = 0; i <= strlen(buf); i++)
560 list->hid_debug_buf[(list->tail + i) % (HID_DEBUG_BUFSIZE - 1)] =
561 buf[i];
562 list->tail = (list->tail + i) % (HID_DEBUG_BUFSIZE - 1);
563 }
564}
565EXPORT_SYMBOL_GPL(hid_debug_event);
566
567void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value)
568{
569 char *buf;
570 int len;
571
572 buf = hid_resolv_usage(usage->hid, NULL);
573 if (!buf)
513 return; 574 return;
575 len = strlen(buf);
576 snprintf(buf + len, HID_DEBUG_BUFSIZE - len - 1, " = %d\n", value);
577
578 hid_debug_event(hdev, buf);
579
580 kfree(buf);
581 wake_up_interruptible(&hdev->debug_wait);
514 582
515 printk(KERN_DEBUG "hid-debug: input ");
516 hid_resolv_usage(usage->hid, NULL);
517 printk(" = %d\n", value);
518} 583}
519EXPORT_SYMBOL_GPL(hid_dump_input); 584EXPORT_SYMBOL_GPL(hid_dump_input);
520 585
@@ -808,6 +873,7 @@ void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f)
808 873
809} 874}
810 875
876
811static int hid_debug_rdesc_show(struct seq_file *f, void *p) 877static int hid_debug_rdesc_show(struct seq_file *f, void *p)
812{ 878{
813 struct hid_device *hdev = f->private; 879 struct hid_device *hdev = f->private;
@@ -831,6 +897,126 @@ static int hid_debug_rdesc_open(struct inode *inode, struct file *file)
831 return single_open(file, hid_debug_rdesc_show, inode->i_private); 897 return single_open(file, hid_debug_rdesc_show, inode->i_private);
832} 898}
833 899
900static int hid_debug_events_open(struct inode *inode, struct file *file)
901{
902 int err = 0;
903 struct hid_debug_list *list;
904
905 if (!(list = kzalloc(sizeof(struct hid_debug_list), GFP_KERNEL))) {
906 err = -ENOMEM;
907 goto out;
908 }
909
910 if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
911 err = -ENOMEM;
912 goto out;
913 }
914 list->hdev = (struct hid_device *) inode->i_private;
915 file->private_data = list;
916 mutex_init(&list->read_mutex);
917
918 list_add_tail(&list->node, &list->hdev->debug_list);
919
920out:
921 return err;
922}
923
924static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
925 size_t count, loff_t *ppos)
926{
927 struct hid_debug_list *list = file->private_data;
928 int ret = 0, len;
929 DECLARE_WAITQUEUE(wait, current);
930
931 while (ret == 0) {
932 mutex_lock(&list->read_mutex);
933 if (list->head == list->tail) {
934 add_wait_queue(&list->hdev->debug_wait, &wait);
935 set_current_state(TASK_INTERRUPTIBLE);
936
937 while (list->head == list->tail) {
938 if (file->f_flags & O_NONBLOCK) {
939 ret = -EAGAIN;
940 break;
941 }
942 if (signal_pending(current)) {
943 ret = -ERESTARTSYS;
944 break;
945 }
946
947 if (!list->hdev || !list->hdev->debug) {
948 ret = -EIO;
949 break;
950 }
951
952 /* allow O_NONBLOCK from other threads */
953 mutex_unlock(&list->read_mutex);
954 schedule();
955 mutex_lock(&list->read_mutex);
956 set_current_state(TASK_INTERRUPTIBLE);
957 }
958
959 set_current_state(TASK_RUNNING);
960 remove_wait_queue(&list->hdev->debug_wait, &wait);
961 }
962
963 if (ret)
964 goto out;
965
966 /* pass the ringbuffer contents to userspace */
967copy_rest:
968 if (list->tail == list->head)
969 goto out;
970 if (list->tail > list->head) {
971 len = list->tail - list->head;
972
973 if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
974 ret = -EFAULT;
975 goto out;
976 }
977 ret += len;
978 list->head += len;
979 } else {
980 len = HID_DEBUG_BUFSIZE - list->head;
981
982 if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
983 ret = -EFAULT;
984 goto out;
985 }
986 list->head = 0;
987 ret += len;
988 goto copy_rest;
989 }
990
991 }
992out:
993 mutex_unlock(&list->read_mutex);
994 return ret;
995}
996
997static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait)
998{
999 struct hid_debug_list *list = file->private_data;
1000
1001 poll_wait(file, &list->hdev->debug_wait, wait);
1002 if (list->head != list->tail)
1003 return POLLIN | POLLRDNORM;
1004 if (!list->hdev->debug)
1005 return POLLERR | POLLHUP;
1006 return 0;
1007}
1008
1009static int hid_debug_events_release(struct inode *inode, struct file *file)
1010{
1011 struct hid_debug_list *list = file->private_data;
1012
1013 list_del(&list->node);
1014 kfree(list->hid_debug_buf);
1015 kfree(list);
1016
1017 return 0;
1018}
1019
834static const struct file_operations hid_debug_rdesc_fops = { 1020static const struct file_operations hid_debug_rdesc_fops = {
835 .open = hid_debug_rdesc_open, 1021 .open = hid_debug_rdesc_open,
836 .read = seq_read, 1022 .read = seq_read,
@@ -838,16 +1024,31 @@ static const struct file_operations hid_debug_rdesc_fops = {
838 .release = single_release, 1024 .release = single_release,
839}; 1025};
840 1026
1027static const struct file_operations hid_debug_events_fops = {
1028 .owner = THIS_MODULE,
1029 .open = hid_debug_events_open,
1030 .read = hid_debug_events_read,
1031 .poll = hid_debug_events_poll,
1032 .release = hid_debug_events_release,
1033};
1034
1035
841void hid_debug_register(struct hid_device *hdev, const char *name) 1036void hid_debug_register(struct hid_device *hdev, const char *name)
842{ 1037{
843 hdev->debug_dir = debugfs_create_dir(name, hid_debug_root); 1038 hdev->debug_dir = debugfs_create_dir(name, hid_debug_root);
844 hdev->debug_rdesc = debugfs_create_file("rdesc", 0400, 1039 hdev->debug_rdesc = debugfs_create_file("rdesc", 0400,
845 hdev->debug_dir, hdev, &hid_debug_rdesc_fops); 1040 hdev->debug_dir, hdev, &hid_debug_rdesc_fops);
1041 hdev->debug_events = debugfs_create_file("events", 0400,
1042 hdev->debug_dir, hdev, &hid_debug_events_fops);
1043 hdev->debug = 1;
846} 1044}
847 1045
848void hid_debug_unregister(struct hid_device *hdev) 1046void hid_debug_unregister(struct hid_device *hdev)
849{ 1047{
1048 hdev->debug = 0;
1049 wake_up_interruptible(&hdev->debug_wait);
850 debugfs_remove(hdev->debug_rdesc); 1050 debugfs_remove(hdev->debug_rdesc);
1051 debugfs_remove(hdev->debug_events);
851 debugfs_remove(hdev->debug_dir); 1052 debugfs_remove(hdev->debug_dir);
852} 1053}
853 1054
diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h
index 516e12c3323..ec08ac1ad68 100644
--- a/include/linux/hid-debug.h
+++ b/include/linux/hid-debug.h
@@ -24,14 +24,27 @@
24 24
25#ifdef CONFIG_DEBUG_FS 25#ifdef CONFIG_DEBUG_FS
26 26
27void hid_dump_input(struct hid_usage *, __s32); 27void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
28void hid_dump_device(struct hid_device *, struct seq_file *); 28void hid_dump_device(struct hid_device *, struct seq_file *);
29void hid_dump_field(struct hid_field *, int, struct seq_file *); 29void hid_dump_field(struct hid_field *, int, struct seq_file *);
30void hid_resolv_usage(unsigned, struct seq_file *); 30char *hid_resolv_usage(unsigned, struct seq_file *);
31void hid_debug_register(struct hid_device *, const char *); 31void hid_debug_register(struct hid_device *, const char *);
32void hid_debug_unregister(struct hid_device *); 32void hid_debug_unregister(struct hid_device *);
33void hid_debug_init(void); 33void hid_debug_init(void);
34void hid_debug_exit(void); 34void hid_debug_exit(void);
35void hid_debug_event(struct hid_device *, char *);
36
37#define HID_DEBUG_BUFSIZE 512
38
39struct hid_debug_list {
40 char *hid_debug_buf;
41 int head;
42 int tail;
43 struct fasync_struct *fasync;
44 struct hid_device *hdev;
45 struct list_head node;
46 struct mutex read_mutex;
47};
35 48
36#else 49#else
37 50
@@ -44,6 +57,7 @@ void hid_debug_exit(void);
44#define hid_debug_unregister(a) do { } while (0) 57#define hid_debug_unregister(a) do { } while (0)
45#define hid_debug_init() do { } while (0) 58#define hid_debug_init() do { } while (0)
46#define hid_debug_exit() do { } while (0) 59#define hid_debug_exit() do { } while (0)
60#define hid_debug_event(a,b) do { } while (0)
47 61
48#endif 62#endif
49 63
diff --git a/include/linux/hid.h b/include/linux/hid.h
index da09ab140ef..60fa52913f8 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -451,10 +451,6 @@ struct hid_device { /* device report descriptor */
451 char phys[64]; /* Device physical location */ 451 char phys[64]; /* Device physical location */
452 char uniq[64]; /* Device unique identifier (serial #) */ 452 char uniq[64]; /* Device unique identifier (serial #) */
453 453
454 /* debugfs */
455 struct dentry *debug_dir;
456 struct dentry *debug_rdesc;
457
458 void *driver_data; 454 void *driver_data;
459 455
460 /* temporary hid_ff handling (until moved to the drivers) */ 456 /* temporary hid_ff handling (until moved to the drivers) */
@@ -468,6 +464,14 @@ struct hid_device { /* device report descriptor */
468 464
469 /* handler for raw output data, used by hidraw */ 465 /* handler for raw output data, used by hidraw */
470 int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t); 466 int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
467
468 /* debugging support via debugfs */
469 unsigned short debug;
470 struct dentry *debug_dir;
471 struct dentry *debug_rdesc;
472 struct dentry *debug_events;
473 struct list_head debug_list;
474 wait_queue_head_t debug_wait;
471}; 475};
472 476
473static inline void *hid_get_drvdata(struct hid_device *hdev) 477static inline void *hid_get_drvdata(struct hid_device *hdev)
@@ -625,9 +629,7 @@ struct hid_ll_driver {
625 629
626/* HID core API */ 630/* HID core API */
627 631
628#ifdef CONFIG_HID_DEBUG
629extern int hid_debug; 632extern int hid_debug;
630#endif
631 633
632extern int hid_add_device(struct hid_device *); 634extern int hid_add_device(struct hid_device *);
633extern void hid_destroy_device(struct hid_device *); 635extern void hid_destroy_device(struct hid_device *);
@@ -783,21 +785,9 @@ int hid_pidff_init(struct hid_device *hid);
783#define hid_pidff_init NULL 785#define hid_pidff_init NULL
784#endif 786#endif
785 787
786#ifdef CONFIG_HID_DEBUG
787#define dbg_hid(format, arg...) if (hid_debug) \ 788#define dbg_hid(format, arg...) if (hid_debug) \
788 printk(KERN_DEBUG "%s: " format ,\ 789 printk(KERN_DEBUG "%s: " format ,\
789 __FILE__ , ## arg) 790 __FILE__ , ## arg)
790#define dbg_hid_line(format, arg...) if (hid_debug) \
791 printk(format, ## arg)
792#else
793static inline int __attribute__((format(printf, 1, 2)))
794dbg_hid(const char *fmt, ...)
795{
796 return 0;
797}
798#define dbg_hid_line dbg_hid
799#endif /* HID_DEBUG */
800
801#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ 791#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
802 __FILE__ , ## arg) 792 __FILE__ , ## arg)
803#endif /* HID_FF */ 793#endif /* HID_FF */