aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-debug.c')
-rw-r--r--drivers/hid/hid-debug.c239
1 files changed, 220 insertions, 19 deletions
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
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