aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/Kconfig15
-rw-r--r--drivers/hid/Makefile5
-rw-r--r--drivers/hid/hid-core.c56
-rw-r--r--drivers/hid/hid-debug.c439
-rw-r--r--drivers/hid/hid-input.c13
-rw-r--r--drivers/hid/usbhid/hid-core.c8
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--include/linux/hid-debug.h48
-rw-r--r--include/linux/hid.h22
9 files changed, 455 insertions, 153 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index aba8facecce8..111afbe8de03 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -31,21 +31,6 @@ config HID
31 31
32 If unsure, say Y. 32 If unsure, say Y.
33 33
34config HID_DEBUG
35 bool "HID debugging support"
36 default y
37 depends on HID
38 ---help---
39 This option lets the HID layer output diagnostics about its internal
40 state, resolve HID usages, dump HID fields, etc. Individual HID drivers
41 use this debugging facility to output information about individual HID
42 devices, etc.
43
44 This feature is useful for those who are either debugging the HID parser
45 or any HID hardware device.
46
47 If unsure, say Y.
48
49config HIDRAW 34config HIDRAW
50 bool "/dev/hidraw raw HID device support" 35 bool "/dev/hidraw raw HID device support"
51 depends on HID 36 depends on HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 9b9271d6527a..0de2dff5542c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -3,9 +3,12 @@
3# 3#
4hid-objs := hid-core.o hid-input.o 4hid-objs := hid-core.o hid-input.o
5 5
6ifdef CONFIG_DEBUG_FS
7 hid-objs += hid-debug.o
8endif
9
6obj-$(CONFIG_HID) += hid.o 10obj-$(CONFIG_HID) += hid.o
7 11
8hid-$(CONFIG_HID_DEBUG) += hid-debug.o
9hid-$(CONFIG_HIDRAW) += hidraw.o 12hid-$(CONFIG_HIDRAW) += hidraw.o
10 13
11hid-logitech-objs := hid-lg.o 14hid-logitech-objs := hid-lg.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 48567d8fe358..342b7d36d7bb 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -44,12 +44,10 @@
44#define DRIVER_DESC "HID core driver" 44#define DRIVER_DESC "HID core driver"
45#define DRIVER_LICENSE "GPL" 45#define DRIVER_LICENSE "GPL"
46 46
47#ifdef CONFIG_HID_DEBUG
48int hid_debug = 0; 47int hid_debug = 0;
49module_param_named(debug, hid_debug, int, 0600); 48module_param_named(debug, hid_debug, int, 0600);
50MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)"); 49MODULE_PARM_DESC(debug, "toggle HID debugging messages");
51EXPORT_SYMBOL_GPL(hid_debug); 50EXPORT_SYMBOL_GPL(hid_debug);
52#endif
53 51
54/* 52/*
55 * Register a new report for a device. 53 * Register a new report for a device.
@@ -861,7 +859,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
861 struct hid_driver *hdrv = hid->driver; 859 struct hid_driver *hdrv = hid->driver;
862 int ret; 860 int ret;
863 861
864 hid_dump_input(usage, value); 862 hid_dump_input(hid, usage, value);
865 863
866 if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { 864 if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
867 ret = hdrv->event(hid, field, usage, value); 865 ret = hdrv->event(hid, field, usage, value);
@@ -983,11 +981,10 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
983{ 981{
984 unsigned size = field->report_size; 982 unsigned size = field->report_size;
985 983
986 hid_dump_input(field->usage + offset, value); 984 hid_dump_input(field->report->device, field->usage + offset, value);
987 985
988 if (offset >= field->report_count) { 986 if (offset >= field->report_count) {
989 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);
990 hid_dump_field(field, 8);
991 return -1; 988 return -1;
992 } 989 }
993 if (field->logical_minimum < 0) { 990 if (field->logical_minimum < 0) {
@@ -1078,6 +1075,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
1078 struct hid_report_enum *report_enum; 1075 struct hid_report_enum *report_enum;
1079 struct hid_driver *hdrv; 1076 struct hid_driver *hdrv;
1080 struct hid_report *report; 1077 struct hid_report *report;
1078 char *buf;
1081 unsigned int i; 1079 unsigned int i;
1082 int ret; 1080 int ret;
1083 1081
@@ -1091,18 +1089,38 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
1091 return -1; 1089 return -1;
1092 } 1090 }
1093 1091
1094 dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); 1092 buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE,
1093 interrupt ? GFP_ATOMIC : GFP_KERNEL);
1094
1095 if (!buf) {
1096 report = hid_get_report(report_enum, data);
1097 goto nomem;
1098 }
1099
1100 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1101 "\nreport (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
1102 hid_debug_event(hid, buf);
1095 1103
1096 report = hid_get_report(report_enum, data); 1104 report = hid_get_report(report_enum, data);
1097 if (!report) 1105 if (!report) {
1106 kfree(buf);
1098 return -1; 1107 return -1;
1108 }
1099 1109
1100 /* dump the report */ 1110 /* dump the report */
1101 dbg_hid("report %d (size %u) = ", report->id, size); 1111 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1102 for (i = 0; i < size; i++) 1112 "report %d (size %u) = ", report->id, size);
1103 dbg_hid_line(" %02x", data[i]); 1113 hid_debug_event(hid, buf);
1104 dbg_hid_line("\n"); 1114 for (i = 0; i < size; i++) {
1115 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1116 " %02x", data[i]);
1117 hid_debug_event(hid, buf);
1118 }
1119 hid_debug_event(hid, "\n");
1105 1120
1121 kfree(buf);
1122
1123nomem:
1106 if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { 1124 if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
1107 ret = hdrv->raw_event(hid, report, data, size); 1125 ret = hdrv->raw_event(hid, report, data, size);
1108 if (ret != 0) 1126 if (ret != 0)
@@ -1323,7 +1341,6 @@ static const struct hid_device_id hid_blacklist[] = {
1323 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, 1341 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
1324 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, 1342 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
1325 1343
1326 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
1327 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, 1344 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
1328 { } 1345 { }
1329}; 1346};
@@ -1730,6 +1747,8 @@ int hid_add_device(struct hid_device *hdev)
1730 if (!ret) 1747 if (!ret)
1731 hdev->status |= HID_STAT_ADDED; 1748 hdev->status |= HID_STAT_ADDED;
1732 1749
1750 hid_debug_register(hdev, dev_name(&hdev->dev));
1751
1733 return ret; 1752 return ret;
1734} 1753}
1735EXPORT_SYMBOL_GPL(hid_add_device); 1754EXPORT_SYMBOL_GPL(hid_add_device);
@@ -1766,6 +1785,9 @@ struct hid_device *hid_allocate_device(void)
1766 for (i = 0; i < HID_REPORT_TYPES; i++) 1785 for (i = 0; i < HID_REPORT_TYPES; i++)
1767 INIT_LIST_HEAD(&hdev->report_enum[i].report_list); 1786 INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
1768 1787
1788 init_waitqueue_head(&hdev->debug_wait);
1789 INIT_LIST_HEAD(&hdev->debug_list);
1790
1769 return hdev; 1791 return hdev;
1770err: 1792err:
1771 put_device(&hdev->dev); 1793 put_device(&hdev->dev);
@@ -1777,6 +1799,7 @@ static void hid_remove_device(struct hid_device *hdev)
1777{ 1799{
1778 if (hdev->status & HID_STAT_ADDED) { 1800 if (hdev->status & HID_STAT_ADDED) {
1779 device_del(&hdev->dev); 1801 device_del(&hdev->dev);
1802 hid_debug_unregister(hdev);
1780 hdev->status &= ~HID_STAT_ADDED; 1803 hdev->status &= ~HID_STAT_ADDED;
1781 } 1804 }
1782} 1805}
@@ -1852,6 +1875,10 @@ static int __init hid_init(void)
1852{ 1875{
1853 int ret; 1876 int ret;
1854 1877
1878 if (hid_debug)
1879 printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n"
1880 "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n");
1881
1855 ret = bus_register(&hid_bus_type); 1882 ret = bus_register(&hid_bus_type);
1856 if (ret) { 1883 if (ret) {
1857 printk(KERN_ERR "HID: can't register hid bus\n"); 1884 printk(KERN_ERR "HID: can't register hid bus\n");
@@ -1862,6 +1889,8 @@ static int __init hid_init(void)
1862 if (ret) 1889 if (ret)
1863 goto err_bus; 1890 goto err_bus;
1864 1891
1892 hid_debug_init();
1893
1865 return 0; 1894 return 0;
1866err_bus: 1895err_bus:
1867 bus_unregister(&hid_bus_type); 1896 bus_unregister(&hid_bus_type);
@@ -1871,6 +1900,7 @@ err:
1871 1900
1872static void __exit hid_exit(void) 1901static void __exit hid_exit(void)
1873{ 1902{
1903 hid_debug_exit();
1874 hidraw_exit(); 1904 hidraw_exit();
1875 bus_unregister(&hid_bus_type); 1905 bus_unregister(&hid_bus_type);
1876} 1906}
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 04359ed64b87..6abd0369aedb 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> 2 * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
3 * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> 3 * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
4 * (c) 2007 Jiri Kosina 4 * (c) 2007-2009 Jiri Kosina
5 * 5 *
6 * Some debug stuff for the HID parser. 6 * HID debugging support
7 */ 7 */
8 8
9/* 9/*
@@ -26,9 +26,17 @@
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */ 27 */
28 28
29#include <linux/debugfs.h>
30#include <linux/seq_file.h>
31#include <linux/sched.h>
32#include <linux/uaccess.h>
33#include <linux/poll.h>
34
29#include <linux/hid.h> 35#include <linux/hid.h>
30#include <linux/hid-debug.h> 36#include <linux/hid-debug.h>
31 37
38static struct dentry *hid_debug_root;
39
32struct hid_usage_entry { 40struct hid_usage_entry {
33 unsigned page; 41 unsigned page;
34 unsigned usage; 42 unsigned usage;
@@ -339,72 +347,120 @@ static const struct hid_usage_entry hid_usage_table[] = {
339 { 0, 0, NULL } 347 { 0, 0, NULL }
340}; 348};
341 349
342static void resolv_usage_page(unsigned page) { 350/* Either output directly into simple seq_file, or (if f == NULL)
351 * allocate a separate buffer that will then be passed to the 'events'
352 * ringbuffer.
353 *
354 * This is because these functions can be called both for "one-shot"
355 * "rdesc" while resolving, or for blocking "events".
356 *
357 * This holds both for resolv_usage_page() and hid_resolv_usage().
358 */
359static char *resolv_usage_page(unsigned page, struct seq_file *f) {
343 const struct hid_usage_entry *p; 360 const struct hid_usage_entry *p;
361 char *buf = NULL;
362
363 if (!f) {
364 buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
365 if (!buf)
366 return ERR_PTR(-ENOMEM);
367 }
344 368
345 for (p = hid_usage_table; p->description; p++) 369 for (p = hid_usage_table; p->description; p++)
346 if (p->page == page) { 370 if (p->page == page) {
347 printk("%s", p->description); 371 if (!f) {
348 return; 372 snprintf(buf, HID_DEBUG_BUFSIZE, "%s",
373 p->description);
374 return buf;
375 }
376 else {
377 seq_printf(f, "%s", p->description);
378 return NULL;
379 }
349 } 380 }
350 printk("%04x", page); 381 if (!f)
382 snprintf(buf, HID_DEBUG_BUFSIZE, "%04x", page);
383 else
384 seq_printf(f, "%04x", page);
385 return buf;
351} 386}
352 387
353void hid_resolv_usage(unsigned usage) { 388char *hid_resolv_usage(unsigned usage, struct seq_file *f) {
354 const struct hid_usage_entry *p; 389 const struct hid_usage_entry *p;
390 char *buf = NULL;
391 int len = 0;
392
393 buf = resolv_usage_page(usage >> 16, f);
394 if (IS_ERR(buf)) {
395 printk(KERN_ERR "error allocating HID debug buffer\n");
396 return NULL;
397 }
355 398
356 if (!hid_debug)
357 return;
358 399
359 resolv_usage_page(usage >> 16); 400 if (!f) {
360 printk("."); 401 len = strlen(buf);
402 snprintf(buf+len, max(0, HID_DEBUG_BUFSIZE - len), ".");
403 len++;
404 }
405 else {
406 seq_printf(f, ".");
407 }
361 for (p = hid_usage_table; p->description; p++) 408 for (p = hid_usage_table; p->description; p++)
362 if (p->page == (usage >> 16)) { 409 if (p->page == (usage >> 16)) {
363 for(++p; p->description && p->usage != 0; p++) 410 for(++p; p->description && p->usage != 0; p++)
364 if (p->usage == (usage & 0xffff)) { 411 if (p->usage == (usage & 0xffff)) {
365 printk("%s", p->description); 412 if (!f)
366 return; 413 snprintf(buf + len,
414 max(0,HID_DEBUG_BUFSIZE - len - 1),
415 "%s", p->description);
416 else
417 seq_printf(f,
418 "%s",
419 p->description);
420 return buf;
367 } 421 }
368 break; 422 break;
369 } 423 }
370 printk("%04x", usage & 0xffff); 424 if (!f)
425 snprintf(buf + len, max(0, HID_DEBUG_BUFSIZE - len - 1),
426 "%04x", usage & 0xffff);
427 else
428 seq_printf(f, "%04x", usage & 0xffff);
429 return buf;
371} 430}
372EXPORT_SYMBOL_GPL(hid_resolv_usage); 431EXPORT_SYMBOL_GPL(hid_resolv_usage);
373 432
374static void tab(int n) { 433static void tab(int n, struct seq_file *f) {
375 printk(KERN_DEBUG "%*s", n, ""); 434 seq_printf(f, "%*s", n, "");
376} 435}
377 436
378void hid_dump_field(struct hid_field *field, int n) { 437void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) {
379 int j; 438 int j;
380 439
381 if (!hid_debug)
382 return;
383
384 if (field->physical) { 440 if (field->physical) {
385 tab(n); 441 tab(n, f);
386 printk("Physical("); 442 seq_printf(f, "Physical(");
387 hid_resolv_usage(field->physical); printk(")\n"); 443 hid_resolv_usage(field->physical, f); seq_printf(f, ")\n");
388 } 444 }
389 if (field->logical) { 445 if (field->logical) {
390 tab(n); 446 tab(n, f);
391 printk("Logical("); 447 seq_printf(f, "Logical(");
392 hid_resolv_usage(field->logical); printk(")\n"); 448 hid_resolv_usage(field->logical, f); seq_printf(f, ")\n");
393 } 449 }
394 tab(n); printk("Usage(%d)\n", field->maxusage); 450 tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage);
395 for (j = 0; j < field->maxusage; j++) { 451 for (j = 0; j < field->maxusage; j++) {
396 tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n"); 452 tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n");
397 } 453 }
398 if (field->logical_minimum != field->logical_maximum) { 454 if (field->logical_minimum != field->logical_maximum) {
399 tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); 455 tab(n, f); seq_printf(f, "Logical Minimum(%d)\n", field->logical_minimum);
400 tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); 456 tab(n, f); seq_printf(f, "Logical Maximum(%d)\n", field->logical_maximum);
401 } 457 }
402 if (field->physical_minimum != field->physical_maximum) { 458 if (field->physical_minimum != field->physical_maximum) {
403 tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); 459 tab(n, f); seq_printf(f, "Physical Minimum(%d)\n", field->physical_minimum);
404 tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); 460 tab(n, f); seq_printf(f, "Physical Maximum(%d)\n", field->physical_maximum);
405 } 461 }
406 if (field->unit_exponent) { 462 if (field->unit_exponent) {
407 tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); 463 tab(n, f); seq_printf(f, "Unit Exponent(%d)\n", field->unit_exponent);
408 } 464 }
409 if (field->unit) { 465 if (field->unit) {
410 static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; 466 static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
@@ -425,77 +481,75 @@ void hid_dump_field(struct hid_field *field, int n) {
425 data >>= 4; 481 data >>= 4;
426 482
427 if(sys > 4) { 483 if(sys > 4) {
428 tab(n); printk("Unit(Invalid)\n"); 484 tab(n, f); seq_printf(f, "Unit(Invalid)\n");
429 } 485 }
430 else { 486 else {
431 int earlier_unit = 0; 487 int earlier_unit = 0;
432 488
433 tab(n); printk("Unit(%s : ", systems[sys]); 489 tab(n, f); seq_printf(f, "Unit(%s : ", systems[sys]);
434 490
435 for (i=1 ; i<sizeof(__u32)*2 ; i++) { 491 for (i=1 ; i<sizeof(__u32)*2 ; i++) {
436 char nibble = data & 0xf; 492 char nibble = data & 0xf;
437 data >>= 4; 493 data >>= 4;
438 if (nibble != 0) { 494 if (nibble != 0) {
439 if(earlier_unit++ > 0) 495 if(earlier_unit++ > 0)
440 printk("*"); 496 seq_printf(f, "*");
441 printk("%s", units[sys][i]); 497 seq_printf(f, "%s", units[sys][i]);
442 if(nibble != 1) { 498 if(nibble != 1) {
443 /* This is a _signed_ nibble(!) */ 499 /* This is a _signed_ nibble(!) */
444 500
445 int val = nibble & 0x7; 501 int val = nibble & 0x7;
446 if(nibble & 0x08) 502 if(nibble & 0x08)
447 val = -((0x7 & ~val) +1); 503 val = -((0x7 & ~val) +1);
448 printk("^%d", val); 504 seq_printf(f, "^%d", val);
449 } 505 }
450 } 506 }
451 } 507 }
452 printk(")\n"); 508 seq_printf(f, ")\n");
453 } 509 }
454 } 510 }
455 tab(n); printk("Report Size(%u)\n", field->report_size); 511 tab(n, f); seq_printf(f, "Report Size(%u)\n", field->report_size);
456 tab(n); printk("Report Count(%u)\n", field->report_count); 512 tab(n, f); seq_printf(f, "Report Count(%u)\n", field->report_count);
457 tab(n); printk("Report Offset(%u)\n", field->report_offset); 513 tab(n, f); seq_printf(f, "Report Offset(%u)\n", field->report_offset);
458 514
459 tab(n); printk("Flags( "); 515 tab(n, f); seq_printf(f, "Flags( ");
460 j = field->flags; 516 j = field->flags;
461 printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); 517 seq_printf(f, "%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
462 printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); 518 seq_printf(f, "%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
463 printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); 519 seq_printf(f, "%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
464 printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); 520 seq_printf(f, "%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
465 printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); 521 seq_printf(f, "%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
466 printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : ""); 522 seq_printf(f, "%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : "");
467 printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); 523 seq_printf(f, "%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
468 printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); 524 seq_printf(f, "%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
469 printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); 525 seq_printf(f, "%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
470 printk(")\n"); 526 seq_printf(f, ")\n");
471} 527}
472EXPORT_SYMBOL_GPL(hid_dump_field); 528EXPORT_SYMBOL_GPL(hid_dump_field);
473 529
474void hid_dump_device(struct hid_device *device) { 530void hid_dump_device(struct hid_device *device, struct seq_file *f)
531{
475 struct hid_report_enum *report_enum; 532 struct hid_report_enum *report_enum;
476 struct hid_report *report; 533 struct hid_report *report;
477 struct list_head *list; 534 struct list_head *list;
478 unsigned i,k; 535 unsigned i,k;
479 static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; 536 static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
480 537
481 if (!hid_debug)
482 return;
483
484 for (i = 0; i < HID_REPORT_TYPES; i++) { 538 for (i = 0; i < HID_REPORT_TYPES; i++) {
485 report_enum = device->report_enum + i; 539 report_enum = device->report_enum + i;
486 list = report_enum->report_list.next; 540 list = report_enum->report_list.next;
487 while (list != &report_enum->report_list) { 541 while (list != &report_enum->report_list) {
488 report = (struct hid_report *) list; 542 report = (struct hid_report *) list;
489 tab(2); 543 tab(2, f);
490 printk("%s", table[i]); 544 seq_printf(f, "%s", table[i]);
491 if (report->id) 545 if (report->id)
492 printk("(%d)", report->id); 546 seq_printf(f, "(%d)", report->id);
493 printk("[%s]", table[report->type]); 547 seq_printf(f, "[%s]", table[report->type]);
494 printk("\n"); 548 seq_printf(f, "\n");
495 for (k = 0; k < report->maxfield; k++) { 549 for (k = 0; k < report->maxfield; k++) {
496 tab(4); 550 tab(4, f);
497 printk("Field(%d)\n", k); 551 seq_printf(f, "Field(%d)\n", k);
498 hid_dump_field(report->field[k], 6); 552 hid_dump_field(report->field[k], 6, f);
499 } 553 }
500 list = list->next; 554 list = list->next;
501 } 555 }
@@ -503,13 +557,37 @@ void hid_dump_device(struct hid_device *device) {
503} 557}
504EXPORT_SYMBOL_GPL(hid_dump_device); 558EXPORT_SYMBOL_GPL(hid_dump_device);
505 559
506void hid_dump_input(struct hid_usage *usage, __s32 value) { 560/* enqueue string to 'events' ring buffer */
507 if (hid_debug < 2) 561void hid_debug_event(struct hid_device *hdev, char *buf)
562{
563 int i;
564 struct hid_debug_list *list;
565
566 list_for_each_entry(list, &hdev->debug_list, node) {
567 for (i = 0; i <= strlen(buf); i++)
568 list->hid_debug_buf[(list->tail + i) % (HID_DEBUG_BUFSIZE - 1)] =
569 buf[i];
570 list->tail = (list->tail + i) % (HID_DEBUG_BUFSIZE - 1);
571 }
572}
573EXPORT_SYMBOL_GPL(hid_debug_event);
574
575void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value)
576{
577 char *buf;
578 int len;
579
580 buf = hid_resolv_usage(usage->hid, NULL);
581 if (!buf)
508 return; 582 return;
583 len = strlen(buf);
584 snprintf(buf + len, HID_DEBUG_BUFSIZE - len - 1, " = %d\n", value);
585
586 hid_debug_event(hdev, buf);
587
588 kfree(buf);
589 wake_up_interruptible(&hdev->debug_wait);
509 590
510 printk(KERN_DEBUG "hid-debug: input ");
511 hid_resolv_usage(usage->hid);
512 printk(" = %d\n", value);
513} 591}
514EXPORT_SYMBOL_GPL(hid_dump_input); 592EXPORT_SYMBOL_GPL(hid_dump_input);
515 593
@@ -786,12 +864,221 @@ static const char **names[EV_MAX + 1] = {
786 [EV_SND] = sounds, [EV_REP] = repeats, 864 [EV_SND] = sounds, [EV_REP] = repeats,
787}; 865};
788 866
789void hid_resolv_event(__u8 type, __u16 code) { 867void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) {
790 868
791 if (!hid_debug) 869 seq_printf(f, "%s.%s", events[type] ? events[type] : "?",
792 return;
793
794 printk("%s.%s", events[type] ? events[type] : "?",
795 names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); 870 names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
796} 871}
797EXPORT_SYMBOL_GPL(hid_resolv_event); 872
873void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f)
874{
875 int i, j, k;
876 struct hid_report *report;
877 struct hid_usage *usage;
878
879 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
880 list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
881 for (i = 0; i < report->maxfield; i++) {
882 for ( j = 0; j < report->field[i]->maxusage; j++) {
883 usage = report->field[i]->usage + j;
884 hid_resolv_usage(usage->hid, f);
885 seq_printf(f, " ---> ");
886 hid_resolv_event(usage->type, usage->code, f);
887 seq_printf(f, "\n");
888 }
889 }
890 }
891 }
892
893}
894
895
896static int hid_debug_rdesc_show(struct seq_file *f, void *p)
897{
898 struct hid_device *hdev = f->private;
899 int i;
900
901 /* dump HID report descriptor */
902 for (i = 0; i < hdev->rsize; i++)
903 seq_printf(f, "%02x ", hdev->rdesc[i]);
904 seq_printf(f, "\n\n");
905
906 /* dump parsed data and input mappings */
907 hid_dump_device(hdev, f);
908 seq_printf(f, "\n");
909 hid_dump_input_mapping(hdev, f);
910
911 return 0;
912}
913
914static int hid_debug_rdesc_open(struct inode *inode, struct file *file)
915{
916 return single_open(file, hid_debug_rdesc_show, inode->i_private);
917}
918
919static int hid_debug_events_open(struct inode *inode, struct file *file)
920{
921 int err = 0;
922 struct hid_debug_list *list;
923
924 if (!(list = kzalloc(sizeof(struct hid_debug_list), GFP_KERNEL))) {
925 err = -ENOMEM;
926 goto out;
927 }
928
929 if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
930 err = -ENOMEM;
931 kfree(list);
932 goto out;
933 }
934 list->hdev = (struct hid_device *) inode->i_private;
935 file->private_data = list;
936 mutex_init(&list->read_mutex);
937
938 list_add_tail(&list->node, &list->hdev->debug_list);
939
940out:
941 return err;
942}
943
944static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
945 size_t count, loff_t *ppos)
946{
947 struct hid_debug_list *list = file->private_data;
948 int ret = 0, len;
949 DECLARE_WAITQUEUE(wait, current);
950
951 while (ret == 0) {
952 mutex_lock(&list->read_mutex);
953 if (list->head == list->tail) {
954 add_wait_queue(&list->hdev->debug_wait, &wait);
955 set_current_state(TASK_INTERRUPTIBLE);
956
957 while (list->head == list->tail) {
958 if (file->f_flags & O_NONBLOCK) {
959 ret = -EAGAIN;
960 break;
961 }
962 if (signal_pending(current)) {
963 ret = -ERESTARTSYS;
964 break;
965 }
966
967 if (!list->hdev || !list->hdev->debug) {
968 ret = -EIO;
969 break;
970 }
971
972 /* allow O_NONBLOCK from other threads */
973 mutex_unlock(&list->read_mutex);
974 schedule();
975 mutex_lock(&list->read_mutex);
976 set_current_state(TASK_INTERRUPTIBLE);
977 }
978
979 set_current_state(TASK_RUNNING);
980 remove_wait_queue(&list->hdev->debug_wait, &wait);
981 }
982
983 if (ret)
984 goto out;
985
986 /* pass the ringbuffer contents to userspace */
987copy_rest:
988 if (list->tail == list->head)
989 goto out;
990 if (list->tail > list->head) {
991 len = list->tail - list->head;
992
993 if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
994 ret = -EFAULT;
995 goto out;
996 }
997 ret += len;
998 list->head += len;
999 } else {
1000 len = HID_DEBUG_BUFSIZE - list->head;
1001
1002 if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
1003 ret = -EFAULT;
1004 goto out;
1005 }
1006 list->head = 0;
1007 ret += len;
1008 goto copy_rest;
1009 }
1010
1011 }
1012out:
1013 mutex_unlock(&list->read_mutex);
1014 return ret;
1015}
1016
1017static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait)
1018{
1019 struct hid_debug_list *list = file->private_data;
1020
1021 poll_wait(file, &list->hdev->debug_wait, wait);
1022 if (list->head != list->tail)
1023 return POLLIN | POLLRDNORM;
1024 if (!list->hdev->debug)
1025 return POLLERR | POLLHUP;
1026 return 0;
1027}
1028
1029static int hid_debug_events_release(struct inode *inode, struct file *file)
1030{
1031 struct hid_debug_list *list = file->private_data;
1032
1033 list_del(&list->node);
1034 kfree(list->hid_debug_buf);
1035 kfree(list);
1036
1037 return 0;
1038}
1039
1040static const struct file_operations hid_debug_rdesc_fops = {
1041 .open = hid_debug_rdesc_open,
1042 .read = seq_read,
1043 .llseek = seq_lseek,
1044 .release = single_release,
1045};
1046
1047static const struct file_operations hid_debug_events_fops = {
1048 .owner = THIS_MODULE,
1049 .open = hid_debug_events_open,
1050 .read = hid_debug_events_read,
1051 .poll = hid_debug_events_poll,
1052 .release = hid_debug_events_release,
1053};
1054
1055
1056void hid_debug_register(struct hid_device *hdev, const char *name)
1057{
1058 hdev->debug_dir = debugfs_create_dir(name, hid_debug_root);
1059 hdev->debug_rdesc = debugfs_create_file("rdesc", 0400,
1060 hdev->debug_dir, hdev, &hid_debug_rdesc_fops);
1061 hdev->debug_events = debugfs_create_file("events", 0400,
1062 hdev->debug_dir, hdev, &hid_debug_events_fops);
1063 hdev->debug = 1;
1064}
1065
1066void hid_debug_unregister(struct hid_device *hdev)
1067{
1068 hdev->debug = 0;
1069 wake_up_interruptible(&hdev->debug_wait);
1070 debugfs_remove(hdev->debug_rdesc);
1071 debugfs_remove(hdev->debug_events);
1072 debugfs_remove(hdev->debug_dir);
1073}
1074
1075void hid_debug_init(void)
1076{
1077 hid_debug_root = debugfs_create_dir("hid", NULL);
1078}
1079
1080void hid_debug_exit(void)
1081{
1082 debugfs_remove_recursive(hid_debug_root);
1083}
1084
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f183b7147e1..5862b0f3b55d 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -159,17 +159,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
159 159
160 field->hidinput = hidinput; 160 field->hidinput = hidinput;
161 161
162 dbg_hid("Mapping: ");
163 hid_resolv_usage(usage->hid);
164 dbg_hid_line(" ---> ");
165
166 if (field->flags & HID_MAIN_ITEM_CONSTANT) 162 if (field->flags & HID_MAIN_ITEM_CONSTANT)
167 goto ignore; 163 goto ignore;
168 164
169 /* only LED usages are supported in output fields */ 165 /* only LED usages are supported in output fields */
170 if (field->report_type == HID_OUTPUT_REPORT && 166 if (field->report_type == HID_OUTPUT_REPORT &&
171 (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { 167 (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) {
172 dbg_hid_line(" [non-LED output field] ");
173 goto ignore; 168 goto ignore;
174 } 169 }
175 170
@@ -561,15 +556,9 @@ mapped:
561 set_bit(MSC_SCAN, input->mscbit); 556 set_bit(MSC_SCAN, input->mscbit);
562 } 557 }
563 558
564 hid_resolv_event(usage->type, usage->code);
565
566 dbg_hid_line("\n");
567
568 return;
569
570ignore: 559ignore:
571 dbg_hid_line("IGNORED\n");
572 return; 560 return;
561
573} 562}
574 563
575void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) 564void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 25f38a5af269..1b0e07a67d6d 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -4,8 +4,8 @@
4 * Copyright (c) 1999 Andreas Gal 4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7 * Copyright (c) 2006-2008 Jiri Kosina
8 * Copyright (c) 2007-2008 Oliver Neukum 7 * Copyright (c) 2007-2008 Oliver Neukum
8 * Copyright (c) 2006-2009 Jiri Kosina
9 */ 9 */
10 10
11/* 11/*
@@ -886,11 +886,6 @@ static int usbhid_parse(struct hid_device *hid)
886 goto err; 886 goto err;
887 } 887 }
888 888
889 dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
890 for (n = 0; n < rsize; n++)
891 dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
892 dbg_hid_line("\n");
893
894 ret = hid_parse_report(hid, rdesc, rsize); 889 ret = hid_parse_report(hid, rdesc, rsize);
895 kfree(rdesc); 890 kfree(rdesc);
896 if (ret) { 891 if (ret) {
@@ -1004,7 +999,6 @@ static int usbhid_start(struct hid_device *hid)
1004 usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); 999 usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
1005 1000
1006 usbhid_init_reports(hid); 1001 usbhid_init_reports(hid);
1007 hid_dump_device(hid);
1008 1002
1009 set_bit(HID_STARTED, &usbhid->iofl); 1003 set_bit(HID_STARTED, &usbhid->iofl);
1010 1004
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index d8f7423f363e..0d9045aa2c4b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -201,7 +201,7 @@ int usbhid_quirks_init(char **quirks_param)
201 u32 quirks; 201 u32 quirks;
202 int n = 0, m; 202 int n = 0, m;
203 203
204 for (; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) { 204 for (; n < MAX_USBHID_BOOT_QUIRKS && quirks_param[n]; n++) {
205 205
206 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", 206 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
207 &idVendor, &idProduct, &quirks); 207 &idVendor, &idProduct, &quirks);
diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h
index 50d568ec178a..53744fa1c8b7 100644
--- a/include/linux/hid-debug.h
+++ b/include/linux/hid-debug.h
@@ -2,7 +2,7 @@
2#define __HID_DEBUG_H 2#define __HID_DEBUG_H
3 3
4/* 4/*
5 * Copyright (c) 2007 Jiri Kosina 5 * Copyright (c) 2007-2009 Jiri Kosina
6 */ 6 */
7 7
8/* 8/*
@@ -22,24 +22,44 @@
22 * 22 *
23 */ 23 */
24 24
25#ifdef CONFIG_HID_DEBUG 25#define HID_DEBUG_BUFSIZE 512
26 26
27void hid_dump_input(struct hid_usage *, __s32); 27#ifdef CONFIG_DEBUG_FS
28void hid_dump_device(struct hid_device *); 28
29void hid_dump_field(struct hid_field *, int); 29void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
30void hid_resolv_usage(unsigned); 30void hid_dump_device(struct hid_device *, struct seq_file *);
31void hid_resolv_event(__u8, __u16); 31void hid_dump_field(struct hid_field *, int, struct seq_file *);
32char *hid_resolv_usage(unsigned, struct seq_file *);
33void hid_debug_register(struct hid_device *, const char *);
34void hid_debug_unregister(struct hid_device *);
35void hid_debug_init(void);
36void hid_debug_exit(void);
37void hid_debug_event(struct hid_device *, char *);
32 38
33#else
34 39
35#define hid_dump_input(a,b) do { } while (0) 40struct hid_debug_list {
36#define hid_dump_device(c) do { } while (0) 41 char *hid_debug_buf;
37#define hid_dump_field(a,b) do { } while (0) 42 int head;
38#define hid_resolv_usage(a) do { } while (0) 43 int tail;
39#define hid_resolv_event(a,b) do { } while (0) 44 struct fasync_struct *fasync;
45 struct hid_device *hdev;
46 struct list_head node;
47 struct mutex read_mutex;
48};
40 49
41#endif /* CONFIG_HID_DEBUG */ 50#else
42 51
52#define hid_dump_input(a,b,c) do { } while (0)
53#define hid_dump_device(a,b) do { } while (0)
54#define hid_dump_field(a,b,c) do { } while (0)
55#define hid_resolv_usage(a,b) do { } while (0)
56#define hid_debug_register(a, b) do { } while (0)
57#define hid_debug_unregister(a) do { } while (0)
58#define hid_debug_init() do { } while (0)
59#define hid_debug_exit() do { } while (0)
60#define hid_debug_event(a,b) do { } while (0)
61
62#endif
43 63
44#endif 64#endif
45 65
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 53489fd4d700..a0ebdace7baa 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -500,6 +500,14 @@ struct hid_device { /* device report descriptor */
500 500
501 /* handler for raw output data, used by hidraw */ 501 /* handler for raw output data, used by hidraw */
502 int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t); 502 int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
503
504 /* debugging support via debugfs */
505 unsigned short debug;
506 struct dentry *debug_dir;
507 struct dentry *debug_rdesc;
508 struct dentry *debug_events;
509 struct list_head debug_list;
510 wait_queue_head_t debug_wait;
503}; 511};
504 512
505static inline void *hid_get_drvdata(struct hid_device *hdev) 513static inline void *hid_get_drvdata(struct hid_device *hdev)
@@ -657,9 +665,7 @@ struct hid_ll_driver {
657 665
658/* HID core API */ 666/* HID core API */
659 667
660#ifdef CONFIG_HID_DEBUG
661extern int hid_debug; 668extern int hid_debug;
662#endif
663 669
664extern int hid_add_device(struct hid_device *); 670extern int hid_add_device(struct hid_device *);
665extern void hid_destroy_device(struct hid_device *); 671extern void hid_destroy_device(struct hid_device *);
@@ -815,21 +821,9 @@ int hid_pidff_init(struct hid_device *hid);
815#define hid_pidff_init NULL 821#define hid_pidff_init NULL
816#endif 822#endif
817 823
818#ifdef CONFIG_HID_DEBUG
819#define dbg_hid(format, arg...) if (hid_debug) \ 824#define dbg_hid(format, arg...) if (hid_debug) \
820 printk(KERN_DEBUG "%s: " format ,\ 825 printk(KERN_DEBUG "%s: " format ,\
821 __FILE__ , ## arg) 826 __FILE__ , ## arg)
822#define dbg_hid_line(format, arg...) if (hid_debug) \
823 printk(format, ## arg)
824#else
825static inline int __attribute__((format(printf, 1, 2)))
826dbg_hid(const char *fmt, ...)
827{
828 return 0;
829}
830#define dbg_hid_line dbg_hid
831#endif /* HID_DEBUG */
832
833#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ 827#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
834 __FILE__ , ## arg) 828 __FILE__ , ## arg)
835#endif /* HID_FF */ 829#endif /* HID_FF */