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
00036 #include <stdio.h>
00037 #include <str_error.h>
00038 #include <errno.h>
00039 #include <usb/dev/pipes.h>
00040 #include <usb/dev/recognise.h>
00041 #include <usb/dev/request.h>
00042 #include <usb/classes/classes.h>
00043 #include <usb/classes/hub.h>
00044 #include "usbinfo.h"
00045
00046 void dump_short_device_identification(usbinfo_device_t *dev)
00047 {
00048 printf("%sDevice 0x%04x by vendor 0x%04x\n", get_indent(0),
00049 (int) dev->device_descriptor.product_id,
00050 (int) dev->device_descriptor.vendor_id);
00051 }
00052
00053 static void dump_match_ids_from_interface(uint8_t *descriptor, size_t depth,
00054 void *arg)
00055 {
00056 if (depth != 1) {
00057 return;
00058 }
00059 size_t descr_size = descriptor[0];
00060 if (descr_size < sizeof(usb_standard_interface_descriptor_t)) {
00061 return;
00062 }
00063 int descr_type = descriptor[1];
00064 if (descr_type != USB_DESCTYPE_INTERFACE) {
00065 return;
00066 }
00067
00068 usbinfo_device_t *dev = (usbinfo_device_t *) arg;
00069
00070 usb_standard_interface_descriptor_t *iface
00071 = (usb_standard_interface_descriptor_t *) descriptor;
00072
00073 printf("%sInterface #%d match ids (%s, 0x%02x, 0x%02x)\n",
00074 get_indent(0),
00075 (int) iface->interface_number,
00076 usb_str_class(iface->interface_class),
00077 (int) iface->interface_subclass,
00078 (int) iface->interface_protocol);
00079
00080 match_id_list_t matches;
00081 init_match_ids(&matches);
00082 usb_device_create_match_ids_from_interface(&dev->device_descriptor,
00083 iface, &matches);
00084 dump_match_ids(&matches, get_indent(1));
00085 clean_match_ids(&matches);
00086 }
00087
00088 void dump_device_match_ids(usbinfo_device_t *dev)
00089 {
00090 match_id_list_t matches;
00091 init_match_ids(&matches);
00092 usb_device_create_match_ids_from_device_descriptor(
00093 &dev->device_descriptor, &matches);
00094 printf("%sDevice match ids (0x%04x by 0x%04x, %s)\n", get_indent(0),
00095 (int) dev->device_descriptor.product_id,
00096 (int) dev->device_descriptor.vendor_id,
00097 usb_str_class(dev->device_descriptor.device_class));
00098 dump_match_ids(&matches, get_indent(1));
00099 clean_match_ids(&matches);
00100
00101 usb_dp_walk_simple(dev->full_configuration_descriptor,
00102 dev->full_configuration_descriptor_size,
00103 usb_dp_standard_descriptor_nesting,
00104 dump_match_ids_from_interface,
00105 dev);
00106 }
00107
00108 static void dump_descriptor_tree_brief_device(const char *prefix,
00109 usb_standard_device_descriptor_t *descriptor)
00110 {
00111 printf("%sDevice (0x%04x by 0x%04x, %s, %zu configurations)\n", prefix,
00112 (int) descriptor->product_id,
00113 (int) descriptor->vendor_id,
00114 usb_str_class(descriptor->device_class),
00115 (size_t) descriptor->configuration_count);
00116 }
00117
00118 static void dump_descriptor_tree_brief_configuration(const char *prefix,
00119 usb_standard_configuration_descriptor_t *descriptor)
00120 {
00121 printf("%sConfiguration #%d (%zu interfaces, total %zuB)\n", prefix,
00122 (int) descriptor->configuration_number,
00123 (size_t) descriptor->interface_count,
00124 (size_t) descriptor->total_length);
00125 }
00126
00127 static void dump_descriptor_tree_brief_interface(const char *prefix,
00128 usb_standard_interface_descriptor_t *descriptor)
00129 {
00130 printf("%sInterface #%d (%s, 0x%02x, 0x%02x), alternate %d\n", prefix,
00131 (int) descriptor->interface_number,
00132 usb_str_class(descriptor->interface_class),
00133 (int) descriptor->interface_subclass,
00134 (int) descriptor->interface_protocol,
00135 (int) descriptor->alternate_setting);
00136 }
00137
00138 static void dump_descriptor_tree_brief_endpoint(const char *prefix,
00139 usb_standard_endpoint_descriptor_t *descriptor)
00140 {
00141 usb_endpoint_t endpoint_no = descriptor->endpoint_address & 0xF;
00142 usb_transfer_type_t transfer = descriptor->attributes & 0x3;
00143 usb_direction_t direction = descriptor->endpoint_address & 0x80
00144 ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
00145 printf("%sEndpoint #%d (%s %s, %zu)\n", prefix,
00146 endpoint_no, usb_str_transfer_type(transfer),
00147 direction == USB_DIRECTION_IN ? "in" : "out",
00148 (size_t) descriptor->max_packet_size);
00149 }
00150
00151 static void dump_descriptor_tree_brief_hid(const char *prefix,
00152 usb_standard_hid_descriptor_t *descriptor)
00153 {
00154 printf("%sHID (country %d, %d descriptors)\n", prefix,
00155 (int) descriptor->country_code,
00156 (int) descriptor->class_desc_count);
00157 }
00158
00159 static void dump_descriptor_tree_brief_hub(const char *prefix,
00160 usb_hub_descriptor_header_t *descriptor)
00161 {
00162 printf("%shub (%d ports)\n", prefix,
00163 (int) descriptor->port_count);
00164 }
00165
00166
00167 static void dump_descriptor_tree_callback(uint8_t *descriptor,
00168 size_t depth, void *arg)
00169 {
00170 const char *indent = get_indent(depth + 1);
00171
00172 int descr_type = -1;
00173 size_t descr_size = descriptor[0];
00174 if (descr_size > 0) {
00175 descr_type = descriptor[1];
00176 }
00177
00178 switch (descr_type) {
00179
00180 #define _BRANCH(type_enum, descriptor_type, callback) \
00181 case type_enum: \
00182 if (descr_size >= sizeof(descriptor_type)) { \
00183 callback(indent, (descriptor_type *) descriptor); \
00184 if (arg != NULL) { \
00185 usb_dump_standard_descriptor(stdout, \
00186 get_indent(depth +2), "\n", \
00187 descriptor, descr_size); \
00188 } \
00189 } else { \
00190 descr_type = -1; \
00191 } \
00192 break;
00193
00194 _BRANCH(USB_DESCTYPE_DEVICE,
00195 usb_standard_device_descriptor_t,
00196 dump_descriptor_tree_brief_device);
00197 _BRANCH(USB_DESCTYPE_CONFIGURATION,
00198 usb_standard_configuration_descriptor_t,
00199 dump_descriptor_tree_brief_configuration);
00200 _BRANCH(USB_DESCTYPE_INTERFACE,
00201 usb_standard_interface_descriptor_t,
00202 dump_descriptor_tree_brief_interface);
00203 _BRANCH(USB_DESCTYPE_ENDPOINT,
00204 usb_standard_endpoint_descriptor_t,
00205 dump_descriptor_tree_brief_endpoint);
00206 _BRANCH(USB_DESCTYPE_HID,
00207 usb_standard_hid_descriptor_t,
00208 dump_descriptor_tree_brief_hid);
00209
00210
00211
00212
00213 _BRANCH(USB_DESCTYPE_HUB,
00214 usb_hub_descriptor_header_t,
00215 dump_descriptor_tree_brief_hub);
00216
00217 default:
00218 break;
00219 }
00220
00221 if (descr_type == -1) {
00222 printf("%sInvalid descriptor.\n", indent);
00223 }
00224 }
00225
00226 void dump_descriptor_tree_brief(usbinfo_device_t *dev)
00227 {
00228 dump_descriptor_tree_callback((uint8_t *)&dev->device_descriptor,
00229 (size_t) -1, NULL);
00230 usb_dp_walk_simple(dev->full_configuration_descriptor,
00231 dev->full_configuration_descriptor_size,
00232 usb_dp_standard_descriptor_nesting,
00233 dump_descriptor_tree_callback,
00234 NULL);
00235 }
00236
00237 void dump_descriptor_tree_full(usbinfo_device_t *dev)
00238 {
00239 dump_descriptor_tree_callback((uint8_t *)&dev->device_descriptor,
00240 (size_t) -1, dev);
00241 usb_dp_walk_simple(dev->full_configuration_descriptor,
00242 dev->full_configuration_descriptor_size,
00243 usb_dp_standard_descriptor_nesting,
00244 dump_descriptor_tree_callback,
00245 dev);
00246 }
00247
00248 static void find_string_indexes_callback(uint8_t *descriptor,
00249 size_t depth, void *arg)
00250 {
00251 size_t descriptor_length = descriptor[0];
00252 if (descriptor_length <= 1) {
00253 return;
00254 }
00255
00256
00257
00258 #define SET_STRING_INDEX(descr, mask, descr_type, descr_struct, descr_item) \
00259 do { \
00260 if ((descr)[1] == (descr_type)) { \
00261 descr_struct *__type_descr = (descr_struct *) (descr); \
00262 size_t __str_index = __type_descr->descr_item; \
00263 if ((__str_index > 0) && (__str_index < 64)) { \
00264 mask = (mask) | (1 << __str_index); \
00265 } \
00266 } \
00267 } while (0)
00268
00269 uint64_t *mask = arg;
00270
00271 #define SET_STR(descr_type, descr_struct, descr_item) \
00272 SET_STRING_INDEX(descriptor, (*mask), descr_type, descr_struct, descr_item)
00273
00274 SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
00275 str_manufacturer);
00276 SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
00277 str_product);
00278 SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
00279 str_serial_number);
00280 SET_STR(USB_DESCTYPE_CONFIGURATION, usb_standard_configuration_descriptor_t,
00281 str_configuration);
00282 SET_STR(USB_DESCTYPE_INTERFACE, usb_standard_interface_descriptor_t,
00283 str_interface);
00284 }
00285
00286
00287 void dump_strings(usbinfo_device_t *dev)
00288 {
00289
00290 l18_win_locales_t *langs;
00291 size_t langs_count;
00292 int rc = usb_request_get_supported_languages(&dev->ctrl_pipe,
00293 &langs, &langs_count);
00294 if (rc != EOK) {
00295 fprintf(stderr,
00296 NAME ": failed to get list of supported languages: %s.\n",
00297 str_error(rc));
00298 return;
00299 }
00300
00301 printf("%sString languages (%zu):", get_indent(0), langs_count);
00302 size_t i;
00303 for (i = 0; i < langs_count; i++) {
00304 printf(" 0x%04x", (int) langs[i]);
00305 }
00306 printf(".\n");
00307
00308
00309
00310 uint64_t str_mask = 0;
00311 find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
00312 &str_mask);
00313 usb_dp_walk_simple(dev->full_configuration_descriptor,
00314 dev->full_configuration_descriptor_size,
00315 usb_dp_standard_descriptor_nesting,
00316 find_string_indexes_callback,
00317 &str_mask);
00318
00319
00320 for (i = 0; i < langs_count; i++) {
00321 l18_win_locales_t lang = langs[i];
00322
00323 printf("%sStrings in %s:\n", get_indent(0),
00324 str_l18_win_locale(lang));
00325
00326 size_t idx;
00327 for (idx = 1; idx < 64; idx++) {
00328 if ((str_mask & ((uint64_t)1 << idx)) == 0) {
00329 continue;
00330 }
00331 char *string = NULL;
00332 rc = usb_request_get_string(&dev->ctrl_pipe, idx, lang,
00333 &string);
00334 if ((rc != EOK) && (rc != EEMPTY)) {
00335 printf("%sWarn: failed to retrieve string #%zu: %s.\n",
00336 get_indent(1), idx, str_error(rc));
00337 continue;
00338 }
00339 printf("%sString #%zu: \"%s\"\n", get_indent(1),
00340 idx, rc == EOK ? string : "");
00341 if (string != NULL) {
00342 free(string);
00343 }
00344 }
00345 }
00346 }
00347
00348
00349 void dump_status(usbinfo_device_t *dev)
00350 {
00351 int rc;
00352 uint16_t device_status = 0;
00353 uint16_t ctrl_pipe_status = 0;
00354
00355
00356 rc = usb_request_get_status(&dev->ctrl_pipe,
00357 USB_REQUEST_RECIPIENT_DEVICE, 0,
00358 &device_status);
00359 if (rc != EOK) {
00360 printf("%sFailed to get device status: %s.\n",
00361 get_indent(0), str_error(rc));
00362 goto try_ctrl_pipe_status;
00363 }
00364
00365 printf("%sDevice status 0x%04x: power=%s, remote-wakeup=%s.\n",
00366 get_indent(0),
00367 device_status,
00368 device_status & USB_DEVICE_STATUS_SELF_POWERED ? "self" : "bus",
00369 device_status & USB_DEVICE_STATUS_REMOTE_WAKEUP ? "yes" : "no");
00370
00371
00372
00373
00374 try_ctrl_pipe_status:
00375 rc = usb_request_get_status(&dev->ctrl_pipe,
00376 USB_REQUEST_RECIPIENT_ENDPOINT, 0,
00377 &ctrl_pipe_status);
00378 if (rc != EOK) {
00379 printf("%sFailed to get control endpoint status: %s.\n",
00380 get_indent(0), str_error(rc));
00381 goto leave;
00382 }
00383
00384 printf("%sControl endpoint zero status %04X: halted=%s.\n",
00385 get_indent(0),
00386 ctrl_pipe_status,
00387 ctrl_pipe_status & USB_ENDPOINT_STATUS_HALTED ? "yes" : "no");
00388
00389 leave:
00390 return;
00391 }
00392