00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <errno.h>
00040 #include <str_error.h>
00041 #include <bool.h>
00042
00043 #include <usb/usb.h>
00044 #include <usb/descriptor.h>
00045 #include <usb/debug.h>
00046 #include <usb/classes/classes.h>
00047
00048 #include "usbinfo.h"
00049 #include <usb/dev/dp.h>
00050
00051 #define INDENT " "
00052 #define BYTES_PER_LINE 12
00053
00054
00055 const char *get_indent(size_t level)
00056 {
00057 static const char *indents[] = {
00058 INDENT,
00059 INDENT INDENT,
00060 INDENT INDENT INDENT,
00061 INDENT INDENT INDENT INDENT,
00062 INDENT INDENT INDENT INDENT INDENT
00063 };
00064 static size_t indents_count = sizeof(indents)/sizeof(indents[0]);
00065 if (level >= indents_count) {
00066 return indents[indents_count - 1];
00067 }
00068 return indents[level];
00069 }
00070
00071 void dump_buffer(const char *msg, size_t indent,
00072 const uint8_t *buffer, size_t length)
00073 {
00074 if (msg != NULL) {
00075 printf("%s\n", msg);
00076 }
00077
00078 size_t i;
00079 if (length > 0) {
00080 printf("%s", get_indent(indent));
00081 }
00082 for (i = 0; i < length; i++) {
00083 printf("0x%02X", buffer[i]);
00084 if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0))
00085 || (i + 1 == length)) {
00086 printf("\n");
00087 if (i + 1 < length) {
00088 printf("%s", get_indent(indent));
00089 }
00090 } else {
00091 printf(" ");
00092 }
00093 }
00094 }
00095
00096 void dump_usb_descriptor(uint8_t *descriptor, size_t size)
00097 {
00098 printf("Device descriptor:\n");
00099 usb_dump_standard_descriptor(stdout, get_indent(0), "\n",
00100 descriptor, size);
00101 }
00102
00103 void dump_match_ids(match_id_list_t *matches, const char *line_prefix)
00104 {
00105 link_t *link;
00106 for (link = matches->ids.next;
00107 link != &matches->ids;
00108 link = link->next) {
00109 match_id_t *match = list_get_instance(link, match_id_t, link);
00110
00111 printf("%s%3d %s\n", line_prefix, match->score, match->id);
00112 }
00113 }
00114
00115 static void dump_tree_descriptor(uint8_t *descriptor, size_t depth)
00116 {
00117 if (descriptor == NULL) {
00118 return;
00119 }
00120 int type = (int) *(descriptor + 1);
00121 const char *name = "unknown";
00122 switch (type) {
00123 #define _TYPE(descriptor_type) \
00124 case USB_DESCTYPE_##descriptor_type: name = #descriptor_type; break
00125 _TYPE(DEVICE);
00126 _TYPE(CONFIGURATION);
00127 _TYPE(STRING);
00128 _TYPE(INTERFACE);
00129 _TYPE(ENDPOINT);
00130 _TYPE(HID);
00131 _TYPE(HID_REPORT);
00132 _TYPE(HID_PHYSICAL);
00133 _TYPE(HUB);
00134 #undef _TYPE
00135 }
00136 printf("%s%s (0x%02X):\n", get_indent(depth), name, type);
00137 usb_dump_standard_descriptor(stdout, get_indent(depth), "\n",
00138 descriptor, descriptor[0]);
00139 }
00140
00141 static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
00142 uint8_t *root, size_t depth)
00143 {
00144 if (root == NULL) {
00145 return;
00146 }
00147 dump_tree_descriptor(root, depth);
00148 uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
00149 do {
00150 dump_tree_internal(parser, data, child, depth + 1);
00151 child = usb_dp_get_sibling_descriptor(parser, data, root, child);
00152 } while (child != NULL);
00153 }
00154
00155 static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
00156 {
00157 uint8_t *ptr = data->data;
00158 printf("Descriptor tree:\n");
00159 dump_tree_internal(parser, data, ptr, 0);
00160 }
00161
00162 #define NESTING(parentname, childname) \
00163 { \
00164 .child = USB_DESCTYPE_##childname, \
00165 .parent = USB_DESCTYPE_##parentname, \
00166 }
00167 #define LAST_NESTING { -1, -1 }
00168
00169 static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
00170 NESTING(CONFIGURATION, INTERFACE),
00171 NESTING(INTERFACE, ENDPOINT),
00172 NESTING(INTERFACE, HUB),
00173 NESTING(INTERFACE, HID),
00174 NESTING(HID, HID_REPORT),
00175 LAST_NESTING
00176 };
00177
00178 static usb_dp_parser_t parser = {
00179 .nesting = descriptor_nesting
00180 };
00181
00182 void dump_descriptor_tree(uint8_t *descriptors, size_t length)
00183 {
00184 usb_dp_parser_data_t data = {
00185 .data = descriptors,
00186 .size = length,
00187 .arg = NULL
00188 };
00189
00190 dump_tree(&parser, &data);
00191 }
00192