diff options
| -rw-r--r-- | drivers/hid/hid-core.c | 42 | ||||
| -rw-r--r-- | drivers/hid/hid-debug.c | 239 | ||||
| -rw-r--r-- | include/linux/hid-debug.h | 18 | ||||
| -rw-r--r-- | include/linux/hid.h | 26 |
4 files changed, 276 insertions, 49 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d4317db85b54..449bd747d116 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | int hid_debug = 0; | 47 | int hid_debug = 0; |
| 48 | module_param_named(debug, hid_debug, int, 0600); | 48 | module_param_named(debug, hid_debug, int, 0600); |
| 49 | MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)"); | 49 | MODULE_PARM_DESC(debug, "toggle HID debugging messages"); |
| 50 | EXPORT_SYMBOL_GPL(hid_debug); | 50 | EXPORT_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 | ||
| 1119 | nomem: | ||
| 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; |
| 1760 | err: | 1782 | err: |
| 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 067e173aa3e4..a331a1821e85 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 | ||
| 338 | static 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 | */ | ||
| 351 | static 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 | ||
| 355 | void hid_resolv_usage(unsigned usage, struct seq_file *f) { | 380 | char *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 | } |
| 382 | EXPORT_SYMBOL_GPL(hid_resolv_usage); | 423 | EXPORT_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 | } |
| 509 | EXPORT_SYMBOL_GPL(hid_dump_device); | 550 | EXPORT_SYMBOL_GPL(hid_dump_device); |
| 510 | 551 | ||
| 511 | void hid_dump_input(struct hid_usage *usage, __s32 value) { | 552 | /* enqueue string to 'events' ring buffer */ |
| 512 | if (hid_debug < 2) | 553 | void 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 | } | ||
| 565 | EXPORT_SYMBOL_GPL(hid_debug_event); | ||
| 566 | |||
| 567 | void 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 | } |
| 519 | EXPORT_SYMBOL_GPL(hid_dump_input); | 584 | EXPORT_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 | |||
| 811 | static int hid_debug_rdesc_show(struct seq_file *f, void *p) | 877 | static 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 | ||
| 900 | static 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 | |||
| 920 | out: | ||
| 921 | return err; | ||
| 922 | } | ||
| 923 | |||
| 924 | static 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 */ | ||
| 967 | copy_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 | } | ||
| 992 | out: | ||
| 993 | mutex_unlock(&list->read_mutex); | ||
| 994 | return ret; | ||
| 995 | } | ||
| 996 | |||
| 997 | static 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 | |||
| 1009 | static 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 | |||
| 834 | static const struct file_operations hid_debug_rdesc_fops = { | 1020 | static 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 | ||
| 1027 | static 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 | |||
| 841 | void hid_debug_register(struct hid_device *hdev, const char *name) | 1036 | void 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 | ||
| 848 | void hid_debug_unregister(struct hid_device *hdev) | 1046 | void 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 516e12c33235..ec08ac1ad687 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 | ||
| 27 | void hid_dump_input(struct hid_usage *, __s32); | 27 | void hid_dump_input(struct hid_device *, struct hid_usage *, __s32); |
| 28 | void hid_dump_device(struct hid_device *, struct seq_file *); | 28 | void hid_dump_device(struct hid_device *, struct seq_file *); |
| 29 | void hid_dump_field(struct hid_field *, int, struct seq_file *); | 29 | void hid_dump_field(struct hid_field *, int, struct seq_file *); |
| 30 | void hid_resolv_usage(unsigned, struct seq_file *); | 30 | char *hid_resolv_usage(unsigned, struct seq_file *); |
| 31 | void hid_debug_register(struct hid_device *, const char *); | 31 | void hid_debug_register(struct hid_device *, const char *); |
| 32 | void hid_debug_unregister(struct hid_device *); | 32 | void hid_debug_unregister(struct hid_device *); |
| 33 | void hid_debug_init(void); | 33 | void hid_debug_init(void); |
| 34 | void hid_debug_exit(void); | 34 | void hid_debug_exit(void); |
| 35 | void hid_debug_event(struct hid_device *, char *); | ||
| 36 | |||
| 37 | #define HID_DEBUG_BUFSIZE 512 | ||
| 38 | |||
| 39 | struct 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 da09ab140ef1..60fa52913f89 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 | ||
| 473 | static inline void *hid_get_drvdata(struct hid_device *hdev) | 477 | static 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 | ||
| 629 | extern int hid_debug; | 632 | extern int hid_debug; |
| 630 | #endif | ||
| 631 | 633 | ||
| 632 | extern int hid_add_device(struct hid_device *); | 634 | extern int hid_add_device(struct hid_device *); |
| 633 | extern void hid_destroy_device(struct hid_device *); | 635 | extern 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 | ||
| 793 | static inline int __attribute__((format(printf, 1, 2))) | ||
| 794 | dbg_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 */ |
