aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2009-06-12 09:20:55 -0400
committerJiri Kosina <jkosina@suse.cz>2009-06-12 09:20:55 -0400
commita635f9dd83f3382577f4544a96df12356e951a40 (patch)
treec6fa27df6d01c34e304a32c9f423d569f7358346
parent8ebf975608aaebd7feb33d77f07ba21a6380e086 (diff)
HID: use debugfs for report dumping descriptor
It is a little bit inconvenient for people who have some non-standard HID hardware (usually violating the HID specification) to have to recompile kernel with CONFIG_HID_DEBUG to be able to see kernel's perspective of the HID report descriptor and observe the parsed events. Plus the messages are then mixed up inconveniently with the rest of the dmesg stuff. This patch implements /sys/kernel/debug/hid/<device>/rdesc file, which represents the kernel's view of report descriptor (both the raw report descriptor data and parsed contents). With all the device-specific debug data being available through debugfs, there is no need for keeping CONFIG_HID_DEBUG, as the 'debug' parameter to the hid module will now only output only driver-specific debugging options, which has absolutely minimal memory footprint, just a few error messages and one global flag (hid_debug). We use the current set of output formatting functions. The ones that need to be used both for one-shot rdesc seq_file and also for continuous flow of data (individual reports, as being sent by the device) distinguish according to the passed seq_file parameter, and if it is NULL, it still output to kernel ringbuffer, otherwise the corresponding seq_file is used for output. The format of the output is preserved. Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/Kconfig15
-rw-r--r--drivers/hid/Makefile5
-rw-r--r--drivers/hid/hid-core.c13
-rw-r--r--drivers/hid/hid-debug.c227
-rw-r--r--drivers/hid/hid-input.c13
-rw-r--r--drivers/hid/usbhid/hid-core.c8
-rw-r--r--include/linux/hid-debug.h32
-rw-r--r--include/linux/hid.h4
8 files changed, 195 insertions, 122 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7e67dcb3d4f6..05950a783560 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 1f7cb0fd4505..cf3687d1ed63 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 8551693d645f..d4317db85b54 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, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)");
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.
@@ -987,7 +985,6 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 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) {
@@ -1721,6 +1718,8 @@ int hid_add_device(struct hid_device *hdev)
1721 if (!ret) 1718 if (!ret)
1722 hdev->status |= HID_STAT_ADDED; 1719 hdev->status |= HID_STAT_ADDED;
1723 1720
1721 hid_debug_register(hdev, dev_name(&hdev->dev));
1722
1724 return ret; 1723 return ret;
1725} 1724}
1726EXPORT_SYMBOL_GPL(hid_add_device); 1725EXPORT_SYMBOL_GPL(hid_add_device);
@@ -1768,6 +1767,7 @@ static void hid_remove_device(struct hid_device *hdev)
1768{ 1767{
1769 if (hdev->status & HID_STAT_ADDED) { 1768 if (hdev->status & HID_STAT_ADDED) {
1770 device_del(&hdev->dev); 1769 device_del(&hdev->dev);
1770 hid_debug_unregister(hdev);
1771 hdev->status &= ~HID_STAT_ADDED; 1771 hdev->status &= ~HID_STAT_ADDED;
1772 } 1772 }
1773} 1773}
@@ -1843,6 +1843,10 @@ static int __init hid_init(void)
1843{ 1843{
1844 int ret; 1844 int ret;
1845 1845
1846 if (hid_debug)
1847 printk(KERN_WARNING "HID: hid_debug parameter has been deprecated. "
1848 "Debugging data are now provided via debugfs\n");
1849
1846 ret = bus_register(&hid_bus_type); 1850 ret = bus_register(&hid_bus_type);
1847 if (ret) { 1851 if (ret) {
1848 printk(KERN_ERR "HID: can't register hid bus\n"); 1852 printk(KERN_ERR "HID: can't register hid bus\n");
@@ -1853,6 +1857,8 @@ static int __init hid_init(void)
1853 if (ret) 1857 if (ret)
1854 goto err_bus; 1858 goto err_bus;
1855 1859
1860 hid_debug_init();
1861
1856 return 0; 1862 return 0;
1857err_bus: 1863err_bus:
1858 bus_unregister(&hid_bus_type); 1864 bus_unregister(&hid_bus_type);
@@ -1862,6 +1868,7 @@ err:
1862 1868
1863static void __exit hid_exit(void) 1869static void __exit hid_exit(void)
1864{ 1870{
1871 hid_debug_exit();
1865 hidraw_exit(); 1872 hidraw_exit();
1866 bus_unregister(&hid_bus_type); 1873 bus_unregister(&hid_bus_type);
1867} 1874}
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 47ac1a7d66e1..067e173aa3e4 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,13 @@
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>
29#include <linux/hid.h> 31#include <linux/hid.h>
30#include <linux/hid-debug.h> 32#include <linux/hid-debug.h>
31 33
34static struct dentry *hid_debug_root;
35
32struct hid_usage_entry { 36struct hid_usage_entry {
33 unsigned page; 37 unsigned page;
34 unsigned usage; 38 unsigned usage;
@@ -331,72 +335,83 @@ static const struct hid_usage_entry hid_usage_table[] = {
331 { 0, 0, NULL } 335 { 0, 0, NULL }
332}; 336};
333 337
334static void resolv_usage_page(unsigned page) { 338static void resolv_usage_page(unsigned page, struct seq_file *f) {
335 const struct hid_usage_entry *p; 339 const struct hid_usage_entry *p;
336 340
337 for (p = hid_usage_table; p->description; p++) 341 for (p = hid_usage_table; p->description; p++)
338 if (p->page == page) { 342 if (p->page == page) {
339 printk("%s", p->description); 343 if (!f)
344 printk("%s", p->description);
345 else
346 seq_printf(f, "%s", p->description);
340 return; 347 return;
341 } 348 }