info.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Vojtech Horky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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                  * Probably useless, hub descriptor shall not be part of
00211                  * configuration descriptor.
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         /*printf("Found string in %s->%s: %zu\n",
00257             #descr_struct, #descr_item, __str_index); */
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         /* Get supported languages. */
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         /* Find used indexes. Device with more than 64 strings are very rare.
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         /* Get all strings and dump them. */
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         /* Device status first. */
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         /* Interface is not interesting, skipping ;-). */
00372 
00373         /* Control endpoint zero. */
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 

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7