From 275f907e2bad87021cb18ae080068a5b4815b9f5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 26 Jun 2009 15:27:49 +1000 Subject: Revert "HID: use debugfs for report dumping descriptor" This reverts commit a635f9dd83f3382577f4544a96df12356e951a40. --- drivers/hid/Kconfig | 15 +++ drivers/hid/Makefile | 5 +- drivers/hid/hid-core.c | 13 +-- drivers/hid/hid-debug.c | 227 +++++++++++++----------------------------- drivers/hid/hid-input.c | 13 ++- drivers/hid/usbhid/hid-core.c | 8 +- include/linux/hid-debug.h | 32 +++--- include/linux/hid.h | 4 - 8 files changed, 122 insertions(+), 195 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 56c1656e057a..d3910c64bf01 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -31,6 +31,21 @@ config HID If unsure, say Y. +config HID_DEBUG + bool "HID debugging support" + default y + depends on HID + ---help--- + This option lets the HID layer output diagnostics about its internal + state, resolve HID usages, dump HID fields, etc. Individual HID drivers + use this debugging facility to output information about individual HID + devices, etc. + + This feature is useful for those who are either debugging the HID parser + or any HID hardware device. + + If unsure, say Y. + config HIDRAW bool "/dev/hidraw raw HID device support" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index a06525d6b0f9..db35151673b1 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -3,12 +3,9 @@ # hid-objs := hid-core.o hid-input.o -ifdef CONFIG_DEBUG_FS - hid-objs += hid-debug.o -endif - obj-$(CONFIG_HID) += hid.o +hid-$(CONFIG_HID_DEBUG) += hid-debug.o hid-$(CONFIG_HIDRAW) += hidraw.o hid-logitech-objs := hid-lg.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 17190653785c..3f2e5852272d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -44,10 +44,12 @@ #define DRIVER_DESC "HID core driver" #define DRIVER_LICENSE "GPL" +#ifdef CONFIG_HID_DEBUG int hid_debug = 0; module_param_named(debug, hid_debug, int, 0600); MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)"); EXPORT_SYMBOL_GPL(hid_debug); +#endif /* * Register a new report for a device. @@ -985,6 +987,7 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) if (offset >= field->report_count) { dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count); + hid_dump_field(field, 8); return -1; } if (field->logical_minimum < 0) { @@ -1721,8 +1724,6 @@ int hid_add_device(struct hid_device *hdev) if (!ret) hdev->status |= HID_STAT_ADDED; - hid_debug_register(hdev, dev_name(&hdev->dev)); - return ret; } EXPORT_SYMBOL_GPL(hid_add_device); @@ -1770,7 +1771,6 @@ static void hid_remove_device(struct hid_device *hdev) { if (hdev->status & HID_STAT_ADDED) { device_del(&hdev->dev); - hid_debug_unregister(hdev); hdev->status &= ~HID_STAT_ADDED; } } @@ -1846,10 +1846,6 @@ static int __init hid_init(void) { int ret; - if (hid_debug) - printk(KERN_WARNING "HID: hid_debug parameter has been deprecated. " - "Debugging data are now provided via debugfs\n"); - ret = bus_register(&hid_bus_type); if (ret) { printk(KERN_ERR "HID: can't register hid bus\n"); @@ -1860,8 +1856,6 @@ static int __init hid_init(void) if (ret) goto err_bus; - hid_debug_init(); - return 0; err_bus: bus_unregister(&hid_bus_type); @@ -1871,7 +1865,6 @@ err: static void __exit hid_exit(void) { - hid_debug_exit(); hidraw_exit(); bus_unregister(&hid_bus_type); } diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 6561d7d87276..04359ed64b87 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -1,9 +1,9 @@ /* * (c) 1999 Andreas Gal * (c) 2000-2001 Vojtech Pavlik - * (c) 2007-2009 Jiri Kosina + * (c) 2007 Jiri Kosina * - * HID debugging support + * Some debug stuff for the HID parser. */ /* @@ -26,13 +26,9 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#include -#include #include #include -static struct dentry *hid_debug_root; - struct hid_usage_entry { unsigned page; unsigned usage; @@ -343,83 +339,72 @@ static const struct hid_usage_entry hid_usage_table[] = { { 0, 0, NULL } }; -static void resolv_usage_page(unsigned page, struct seq_file *f) { +static void resolv_usage_page(unsigned page) { const struct hid_usage_entry *p; for (p = hid_usage_table; p->description; p++) if (p->page == page) { - if (!f) - printk("%s", p->description); - else - seq_printf(f, "%s", p->description); + printk("%s", p->description); return; } - if (!f) - printk("%04x", page); - else - seq_printf(f, "%04x", page); + printk("%04x", page); } -void hid_resolv_usage(unsigned usage, struct seq_file *f) { +void hid_resolv_usage(unsigned usage) { const struct hid_usage_entry *p; - resolv_usage_page(usage >> 16, f); - if (!f) - printk("."); - else - seq_printf(f, "."); + if (!hid_debug) + return; + + resolv_usage_page(usage >> 16); + printk("."); for (p = hid_usage_table; p->description; p++) if (p->page == (usage >> 16)) { for(++p; p->description && p->usage != 0; p++) if (p->usage == (usage & 0xffff)) { - if (!f) - printk("%s", p->description); - else - seq_printf(f, - "%s", - p->description); + printk("%s", p->description); return; } break; } - if (!f) - printk("%04x", usage & 0xffff); - else - seq_printf(f, "%04x", usage & 0xffff); + printk("%04x", usage & 0xffff); } EXPORT_SYMBOL_GPL(hid_resolv_usage); -static void tab(int n, struct seq_file *f) { - seq_printf(f, "%*s", n, ""); +static void tab(int n) { + printk(KERN_DEBUG "%*s", n, ""); } -void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) { +void hid_dump_field(struct hid_field *field, int n) { int j; + if (!hid_debug) + return; + if (field->physical) { - tab(n, f); - seq_printf(f, "Physical("); - hid_resolv_usage(field->physical, f); seq_printf(f, ")\n"); + tab(n); + printk("Physical("); + hid_resolv_usage(field->physical); printk(")\n"); } if (field->logical) { - tab(n, f); - seq_printf(f, "Logical("); - hid_resolv_usage(field->logical, f); seq_printf(f, ")\n"); + tab(n); + printk("Logical("); + hid_resolv_usage(field->logical); printk(")\n"); } - tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage); + tab(n); printk("Usage(%d)\n", field->maxusage); for (j = 0; j < field->maxusage; j++) { - tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n"); + tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n"); } if (field->logical_minimum != field->logical_maximum) { - tab(n, f); seq_printf(f, "Logical Minimum(%d)\n", field->logical_minimum); - tab(n, f); seq_printf(f, "Logical Maximum(%d)\n", field->logical_maximum); + tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); + tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); } if (field->physical_minimum != field->physical_maximum) { - tab(n, f); seq_printf(f, "Physical Minimum(%d)\n", field->physical_minimum); - tab(n, f); seq_printf(f, "Physical Maximum(%d)\n", field->physical_maximum); + tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); + tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); } if (field->unit_exponent) { - tab(n, f); seq_printf(f, "Unit Exponent(%d)\n", field->unit_exponent); + tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); } if (field->unit) { static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; @@ -440,75 +425,77 @@ void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) { data >>= 4; if(sys > 4) { - tab(n, f); seq_printf(f, "Unit(Invalid)\n"); + tab(n); printk("Unit(Invalid)\n"); } else { int earlier_unit = 0; - tab(n, f); seq_printf(f, "Unit(%s : ", systems[sys]); + tab(n); printk("Unit(%s : ", systems[sys]); for (i=1 ; i>= 4; if (nibble != 0) { if(earlier_unit++ > 0) - seq_printf(f, "*"); - seq_printf(f, "%s", units[sys][i]); + printk("*"); + printk("%s", units[sys][i]); if(nibble != 1) { /* This is a _signed_ nibble(!) */ int val = nibble & 0x7; if(nibble & 0x08) val = -((0x7 & ~val) +1); - seq_printf(f, "^%d", val); + printk("^%d", val); } } } - seq_printf(f, ")\n"); + printk(")\n"); } } - tab(n, f); seq_printf(f, "Report Size(%u)\n", field->report_size); - tab(n, f); seq_printf(f, "Report Count(%u)\n", field->report_count); - tab(n, f); seq_printf(f, "Report Offset(%u)\n", field->report_offset); + tab(n); printk("Report Size(%u)\n", field->report_size); + tab(n); printk("Report Count(%u)\n", field->report_count); + tab(n); printk("Report Offset(%u)\n", field->report_offset); - tab(n, f); seq_printf(f, "Flags( "); + tab(n); printk("Flags( "); j = field->flags; - seq_printf(f, "%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); - seq_printf(f, "%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); - seq_printf(f, "%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); - seq_printf(f, ")\n"); + printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); + printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); + printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); + printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); + printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); + printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : ""); + printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); + printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); + printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); + printk(")\n"); } EXPORT_SYMBOL_GPL(hid_dump_field); -void hid_dump_device(struct hid_device *device, struct seq_file *f) -{ +void hid_dump_device(struct hid_device *device) { struct hid_report_enum *report_enum; struct hid_report *report; struct list_head *list; unsigned i,k; static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; + if (!hid_debug) + return; + for (i = 0; i < HID_REPORT_TYPES; i++) { report_enum = device->report_enum + i; list = report_enum->report_list.next; while (list != &report_enum->report_list) { report = (struct hid_report *) list; - tab(2, f); - seq_printf(f, "%s", table[i]); + tab(2); + printk("%s", table[i]); if (report->id) - seq_printf(f, "(%d)", report->id); - seq_printf(f, "[%s]", table[report->type]); - seq_printf(f, "\n"); + printk("(%d)", report->id); + printk("[%s]", table[report->type]); + printk("\n"); for (k = 0; k < report->maxfield; k++) { - tab(4, f); - seq_printf(f, "Field(%d)\n", k); - hid_dump_field(report->field[k], 6, f); + tab(4); + printk("Field(%d)\n", k); + hid_dump_field(report->field[k], 6); } list = list->next; } @@ -521,7 +508,7 @@ void hid_dump_input(struct hid_usage *usage, __s32 value) { return; printk(KERN_DEBUG "hid-debug: input "); - hid_resolv_usage(usage->hid, NULL); + hid_resolv_usage(usage->hid); printk(" = %d\n", value); } EXPORT_SYMBOL_GPL(hid_dump_input); @@ -799,84 +786,12 @@ static const char **names[EV_MAX + 1] = { [EV_SND] = sounds, [EV_REP] = repeats, }; -void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) { - - seq_printf(f, "%s.%s", events[type] ? events[type] : "?", - names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); -} - -void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f) -{ - int i, j, k; - struct hid_report *report; - struct hid_usage *usage; - - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { - list_for_each_entry(report, &hid->report_enum[k].report_list, list) { - for (i = 0; i < report->maxfield; i++) { - for ( j = 0; j < report->field[i]->maxusage; j++) { - usage = report->field[i]->usage + j; - hid_resolv_usage(usage->hid, f); - seq_printf(f, " ---> "); - hid_resolv_event(usage->type, usage->code, f); - seq_printf(f, "\n"); - } - } - } - } - -} +void hid_resolv_event(__u8 type, __u16 code) { -static int hid_debug_rdesc_show(struct seq_file *f, void *p) -{ - struct hid_device *hdev = f->private; - int i; - - /* dump HID report descriptor */ - for (i = 0; i < hdev->rsize; i++) - seq_printf(f, "%02x ", hdev->rdesc[i]); - seq_printf(f, "\n\n"); - - /* dump parsed data and input mappings */ - hid_dump_device(hdev, f); - seq_printf(f, "\n"); - hid_dump_input_mapping(hdev, f); - - return 0; -} - -static int hid_debug_rdesc_open(struct inode *inode, struct file *file) -{ - return single_open(file, hid_debug_rdesc_show, inode->i_private); -} - -static const struct file_operations hid_debug_rdesc_fops = { - .open = hid_debug_rdesc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -void hid_debug_register(struct hid_device *hdev, const char *name) -{ - hdev->debug_dir = debugfs_create_dir(name, hid_debug_root); - hdev->debug_rdesc = debugfs_create_file("rdesc", 0400, - hdev->debug_dir, hdev, &hid_debug_rdesc_fops); -} - -void hid_debug_unregister(struct hid_device *hdev) -{ - debugfs_remove(hdev->debug_rdesc); - debugfs_remove(hdev->debug_dir); -} - -void hid_debug_init(void) -{ - hid_debug_root = debugfs_create_dir("hid", NULL); -} + if (!hid_debug) + return; -void hid_debug_exit(void) -{ - debugfs_remove_recursive(hid_debug_root); + printk("%s.%s", events[type] ? events[type] : "?", + names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); } - +EXPORT_SYMBOL_GPL(hid_resolv_event); diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 5862b0f3b55d..7f183b7147e1 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -159,12 +159,17 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel field->hidinput = hidinput; + dbg_hid("Mapping: "); + hid_resolv_usage(usage->hid); + dbg_hid_line(" ---> "); + if (field->flags & HID_MAIN_ITEM_CONSTANT) goto ignore; /* only LED usages are supported in output fields */ if (field->report_type == HID_OUTPUT_REPORT && (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { + dbg_hid_line(" [non-LED output field] "); goto ignore; } @@ -556,9 +561,15 @@ mapped: set_bit(MSC_SCAN, input->mscbit); } -ignore: + hid_resolv_event(usage->type, usage->code); + + dbg_hid_line("\n"); + return; +ignore: + dbg_hid_line("IGNORED\n"); + return; } void 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 a72e3149810f..c654b896eac0 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -4,8 +4,8 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2006-2008 Jiri Kosina * Copyright (c) 2007-2008 Oliver Neukum - * Copyright (c) 2006-2009 Jiri Kosina */ /* @@ -886,6 +886,11 @@ static int usbhid_parse(struct hid_device *hid) goto err; } + dbg_hid("report descriptor (size %u, read %d) = ", rsize, n); + for (n = 0; n < rsize; n++) + dbg_hid_line(" %02x", (unsigned char) rdesc[n]); + dbg_hid_line("\n"); + ret = hid_parse_report(hid, rdesc, rsize); kfree(rdesc); if (ret) { @@ -999,6 +1004,7 @@ static int usbhid_start(struct hid_device *hid) usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); usbhid_init_reports(hid); + hid_dump_device(hid); set_bit(HID_STARTED, &usbhid->iofl); diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h index 516e12c33235..50d568ec178a 100644 --- a/include/linux/hid-debug.h +++ b/include/linux/hid-debug.h @@ -2,7 +2,7 @@ #define __HID_DEBUG_H /* - * Copyright (c) 2007-2009 Jiri Kosina + * Copyright (c) 2007 Jiri Kosina */ /* @@ -22,30 +22,24 @@ * */ -#ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_HID_DEBUG void hid_dump_input(struct hid_usage *, __s32); -void hid_dump_device(struct hid_device *, struct seq_file *); -void hid_dump_field(struct hid_field *, int, struct seq_file *); -void hid_resolv_usage(unsigned, struct seq_file *); -void hid_debug_register(struct hid_device *, const char *); -void hid_debug_unregister(struct hid_device *); -void hid_debug_init(void); -void hid_debug_exit(void); +void hid_dump_device(struct hid_device *); +void hid_dump_field(struct hid_field *, int); +void hid_resolv_usage(unsigned); +void hid_resolv_event(__u8, __u16); #else -#define hid_dump_input(a,b) do { } while (0) -#define hid_dump_device(c) do { } while (0) -#define hid_dump_field(a,b) do { } while (0) -#define hid_resolv_usage(a) do { } while (0) -#define hid_resolv_event(a,b) do { } while (0) -#define hid_debug_register(a, b) do { } while (0) -#define hid_debug_unregister(a) do { } while (0) -#define hid_debug_init() do { } while (0) -#define hid_debug_exit() do { } while (0) +#define hid_dump_input(a,b) do { } while (0) +#define hid_dump_device(c) do { } while (0) +#define hid_dump_field(a,b) do { } while (0) +#define hid_resolv_usage(a) do { } while (0) +#define hid_resolv_event(a,b) do { } while (0) + +#endif /* CONFIG_HID_DEBUG */ -#endif #endif diff --git a/include/linux/hid.h b/include/linux/hid.h index ca5935df9fa6..53489fd4d700 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -487,10 +487,6 @@ struct hid_device { /* device report descriptor */ char phys[64]; /* Device physical location */ char uniq[64]; /* Device unique identifier (serial #) */ - /* debugfs */ - struct dentry *debug_dir; - struct dentry *debug_rdesc; - void *driver_data; /* temporary hid_ff handling (until moved to the drivers) */ -- cgit v1.2.3