"Fossies" - the Fresh Open Source Software Archive

Member "usbutils-015/desc-dump.c" (22 Feb 2021, 16959 Bytes) of package /linux/misc/usbutils-015.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "desc-dump.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 013_vs_014.

    1 // SPDX-License-Identifier: GPL-2.0-or-later
    2 /*
    3  * USB descriptor dumping
    4  *
    5  * Copyright (C) 2017-2018 Michael Drake <michael.drake@codethink.co.uk>
    6  */
    7 
    8 #include "config.h"
    9 
   10 #include <stdbool.h>
   11 #include <assert.h>
   12 #include <string.h>
   13 #include <stdlib.h>
   14 #include <stdio.h>
   15 
   16 #include <libusb.h>
   17 
   18 #include "desc-defs.h"
   19 #include "desc-dump.h"
   20 #include "usbmisc.h"
   21 #include "names.h"
   22 
   23 /**
   24  * Print a description of a bmControls field value, using a given string array.
   25  *
   26  * Handles the DESC_BMCONTROL_1 and DESC_BMCONTROL_2 field types.  The former
   27  * is one bit per string, and the latter is 2 bits per string, with the
   28  * additional bit specifying whether the control is read-only.
   29  *
   30  * \param[in] bmcontrols  The value to dump a human-readable representation of.
   31  * \param[in] strings     Array of human-readable strings, must be NULL terminated.
   32  * \param[in] type        The type of the value in bmcontrols.
   33  * \param[in] indent      The current indent level.
   34  */
   35 static void desc_bmcontrol_dump(
   36         unsigned long long bmcontrols,
   37         const char * const * strings,
   38         enum desc_type type,
   39         unsigned int indent)
   40 {
   41     static const char * const setting[] = {
   42         "read-only",
   43         "ILLEGAL VALUE (0b10)",
   44         "read/write"
   45     };
   46     unsigned int count = 0;
   47     unsigned int control;
   48 
   49     assert((type == DESC_BMCONTROL_1) ||
   50            (type == DESC_BMCONTROL_2));
   51 
   52     while (strings[count] != NULL) {
   53         if (strings[count][0] != '\0') {
   54             if (type == DESC_BMCONTROL_1) {
   55                 if ((bmcontrols >> count) & 0x1) {
   56                     printf("%*s%s Control\n",
   57                             indent * 2, "",
   58                             strings[count]);
   59                 }
   60             } else {
   61                 control = (bmcontrols >> (count * 2)) & 0x3;
   62                 if (control) {
   63                     printf("%*s%s Control (%s)\n",
   64                             indent * 2, "",
   65                             strings[count],
   66                             setting[control-1]);
   67                 }
   68             }
   69         }
   70         count++;
   71     }
   72 }
   73 
   74 /**
   75  * Read N bytes from descriptor data buffer into a value.
   76  *
   77  * Only supports values of up to 8 bytes.
   78  *
   79  * \param[in] buf     Buffer containing the bytes to read.
   80  * \param[in] offset  Offset in buffer to start reading bytes from.
   81  * \param[in] bytes   Number of bytes to read.
   82  * \return Value contained within the given bytes.
   83  */
   84 static unsigned long long get_n_bytes_as_ull(
   85         const unsigned char *buf,
   86         unsigned int offset,
   87         unsigned int bytes)
   88 {
   89     unsigned long long ret = 0;
   90 
   91     if (bytes > 8) {
   92         fprintf(stderr, "Bad descriptor definition; Field size > 8.\n");
   93         exit(EXIT_FAILURE);
   94     }
   95 
   96     buf += offset;
   97 
   98     switch (bytes) {
   99     case 8: ret |= ((unsigned long long)buf[7]) << 56; /* fall-through */
  100     case 7: ret |= ((unsigned long long)buf[6]) << 48; /* fall-through */
  101     case 6: ret |= ((unsigned long long)buf[5]) << 40; /* fall-through */
  102     case 5: ret |= ((unsigned long long)buf[4]) << 32; /* fall-through */
  103     case 4: ret |= ((unsigned long long)buf[3]) << 24; /* fall-through */
  104     case 3: ret |= ((unsigned long long)buf[2]) << 16; /* fall-through */
  105     case 2: ret |= ((unsigned long long)buf[1]) <<  8; /* fall-through */
  106     case 1: ret |= ((unsigned long long)buf[0]);
  107     }
  108 
  109     return ret;
  110 }
  111 
  112 /**
  113  * Get the size of a descriptor field in bytes.
  114  *
  115  * Normally the size is provided in the entry's size parameter, but some
  116  * fields have a variable size, with the actual size being stored in as
  117  * the value of another field.
  118  *
  119  * \param[in] buf    Descriptor data.
  120  * \param[in] desc   First field in the descriptor definition array.
  121  * \param[in] entry  The descriptor definition field to get size for.
  122  * \return Size of the field in bytes.
  123  */
  124 static unsigned int get_entry_size(
  125         const unsigned char *buf,
  126         const struct desc *desc,
  127         const struct desc *entry);
  128 
  129 /**
  130  * Read a value from a field of given name.
  131  *
  132  * \param[in] buf    Descriptor data.
  133  * \param[in] desc   First field in the descriptor definition array.
  134  * \param[in] field  The name of the field to get the value for.
  135  * \return The value from the given field.
  136  */
  137 static unsigned long long get_value_from_field(
  138         const unsigned char *buf,
  139         const struct desc *desc,
  140         const char *field)
  141 {
  142     size_t offset = 0;
  143     const struct desc *current;
  144     unsigned long long value = 0;
  145 
  146     /* Search descriptor definition array for the field who's value
  147      * gives the value of the entry we're interested in. */
  148     for (current = desc; current->field != NULL; current++) {
  149         if (strcmp(current->field, field) == 0) {
  150             value = get_n_bytes_as_ull(buf, offset,
  151                     current->size);
  152             break;
  153         }
  154 
  155         /* Keep track of our offset in the descriptor data
  156          * as we look for the field we want. */
  157         offset += get_entry_size(buf, desc, current);
  158     }
  159 
  160     return value;
  161 }
  162 
  163 /**
  164  * Dump a number as hex to stdout.
  165  *
  166  * \param[in] buf     Descriptor buffer to get values to render from.
  167  * \param[in] width   Character width to right-align value inside.
  168  * \param[in] offset  Offset in buffer to start of value to render.
  169  * \param[in] bytes   Byte length of value to render.
  170  */
  171 static void hex_renderer(
  172         const unsigned char *buf,
  173         unsigned int width,
  174         unsigned int offset,
  175         unsigned int bytes)
  176 {
  177     unsigned int align = (width >= bytes * 2) ? width - bytes * 2 : 0;
  178     printf(" %*s0x%0*llx", align, "", bytes * 2,
  179             get_n_bytes_as_ull(buf, offset, bytes));
  180 }
  181 
  182 /**
  183  * Dump a number to stdout.
  184  *
  185  * Single-byte numbers a rendered as decimal, otherwise hexadecimal is used.
  186  *
  187  * \param[in] buf     Descriptor buffer to get values to render from.
  188  * \param[in] width   Character width to right-align value inside.
  189  * \param[in] offset  Offset in buffer to start of value to render.
  190  * \param[in] bytes   Byte length of value to render.
  191  */
  192 static void number_renderer(
  193         const unsigned char *buf,
  194         unsigned int width,
  195         unsigned int offset,
  196         unsigned int bytes)
  197 {
  198     if (bytes == 1) {
  199         /* Render small numbers as decimal */
  200         printf("   %*u", width, buf[offset]);
  201     } else {
  202         /* Otherwise render as hexadecimal */
  203         hex_renderer(buf, width, offset, bytes);
  204     }
  205 }
  206 
  207 /**
  208  * Render a field's value to stdout.
  209  *
  210  * The manner of rendering the value is dependant on the value type.
  211  *
  212  * \param[in] dev           LibUSB device handle.
  213  * \param[in] current       Descriptor definition field to render.
  214  * \param[in] current_size  Size of value to render.
  215  * \param[in] buf           Byte array containing the descriptor date to dump.
  216  * \param[in] buf_len       Byte length of `buf`.
  217  * \param[in] desc          First field in the descriptor definition.
  218  * \param[in] indent        Current indent level.
  219  * \param[in] offset        Offset to current value in `buf`.
  220  */
  221 static void value_renderer(
  222         libusb_device_handle *dev,
  223         const struct desc *current,
  224         unsigned int current_size,
  225         const unsigned char *buf,
  226         unsigned int buf_len,
  227         const struct desc *desc,
  228         unsigned int indent,
  229         size_t offset)
  230 {
  231     /** Maximum amount of characters to right align numerical values by. */
  232     const unsigned int size_chars = 4;
  233 
  234     switch (current->type) {
  235     case DESC_NUMBER: /* fall-through */
  236     case DESC_CONSTANT:
  237         number_renderer(buf, size_chars, offset, current_size);
  238         printf("\n");
  239         break;
  240     case DESC_NUMBER_POSTFIX:
  241         number_renderer(buf, size_chars, offset, current_size);
  242         printf("%s\n", current->number_postfix);
  243         break;
  244     case DESC_NUMBER_STRINGS: {
  245         unsigned int i;
  246         unsigned long long value = get_n_bytes_as_ull(buf, offset, current_size);
  247         number_renderer(buf, size_chars, offset, current_size);
  248         for (i = 0; i <= value; i++) {
  249             if (current->number_strings[i] == NULL) {
  250                 break;
  251             }
  252             if (value == i) {
  253                 printf(" %s", current->number_strings[i]);
  254             }
  255         }
  256         printf("\n");
  257         break;
  258     }
  259     case DESC_BCD: {
  260         unsigned int i;
  261         printf("  %2x", buf[offset + current_size - 1]);
  262         for (i = 1; i < current_size; i++) {
  263             printf(".%02x", buf[offset + current_size - 1 - i]);
  264         }
  265         printf("\n");
  266         break;
  267     }
  268     case DESC_BITMAP:
  269         hex_renderer(buf, size_chars, offset, current_size);
  270         printf("\n");
  271         break;
  272     case DESC_BMCONTROL_1: /* fall-through */
  273     case DESC_BMCONTROL_2:
  274         hex_renderer(buf, size_chars, offset, current_size);
  275         printf("\n");
  276         desc_bmcontrol_dump(
  277                 get_n_bytes_as_ull(buf, offset, current_size),
  278                 current->bmcontrol, current->type, indent + 1);
  279         break;
  280     case DESC_BITMAP_STRINGS: {
  281         unsigned int i;
  282         unsigned long long value = get_n_bytes_as_ull(buf, offset, current_size);
  283         hex_renderer(buf, size_chars, offset, current_size);
  284         printf("\n");
  285         for (i = 0; i < current->bitmap_strings.count; i++) {
  286             if (current->bitmap_strings.strings[i] == NULL) {
  287                 continue;
  288             }
  289             if (((value >> i) & 0x1) == 0) {
  290                 continue;
  291             }
  292             printf("%*s%s\n", (indent + 1) * 2, "",
  293                     current->bitmap_strings.strings[i]);
  294         }
  295         break;
  296     }
  297     case DESC_STR_DESC_INDEX: {
  298         char *string;
  299         number_renderer(buf, size_chars, offset, current_size);
  300         string = get_dev_string(dev, buf[offset]);
  301         if (string) {
  302             printf(" %s\n", string);
  303             free(string);
  304         } else {
  305             printf("\n");
  306         }
  307         break;
  308     }
  309     case DESC_CS_STR_DESC_ID:
  310         number_renderer(buf, size_chars, offset, current_size);
  311         /* TODO: Add support for UAC3 class-specific String descriptor */
  312         printf("\n");
  313         break;
  314     case DESC_TERMINAL_STR:
  315         number_renderer(buf, size_chars, offset, current_size);
  316         printf(" %s\n", names_audioterminal(
  317                 get_n_bytes_as_ull(buf, offset, current_size)));
  318         break;
  319     case DESC_EXTENSION: {
  320         unsigned int type = get_value_from_field(buf, desc,
  321                 current->extension.type_field);
  322         const struct desc *ext_desc;
  323         const struct desc_ext *ext;
  324 
  325         /* Lookup the extention descriptor definitions to use, */
  326         for (ext = current->extension.d; ext->desc != NULL; ext++) {
  327             if (ext->type == type) {
  328                 ext_desc = ext->desc;
  329                 break;
  330             }
  331         }
  332 
  333         /* If the type didn't match a known type, use the
  334          * undefined descriptor. */
  335         if (ext->desc == NULL) {
  336             ext_desc = desc_undefined;
  337         }
  338 
  339         desc_dump(dev, ext_desc, buf + offset,
  340                 buf_len - offset, indent);
  341 
  342         break;
  343     }
  344     case DESC_SNOWFLAKE:
  345         number_renderer(buf, size_chars, offset, current_size);
  346         current->snowflake(
  347                 get_n_bytes_as_ull(buf, offset, current_size),
  348                 indent + 1);
  349         break;
  350     }
  351 }
  352 
  353 /* Documented at forward declaration above. */
  354 static unsigned int get_entry_size(
  355         const unsigned char *buf,
  356         const struct desc *desc,
  357         const struct desc *entry)
  358 {
  359     unsigned int size = entry->size;
  360 
  361     if (entry->size_field != NULL) {
  362         /* Variable field length, given by `size_field`'s value. */
  363         size = get_value_from_field(buf, desc, entry->size_field);
  364     }
  365 
  366     if (size == 0) {
  367         fprintf(stderr, "Bad descriptor definition; "
  368                 "'%s' field has zero size.\n", entry->field);
  369         exit(EXIT_FAILURE);
  370     }
  371 
  372     return size;
  373 }
  374 
  375 /**
  376  * Get the number of entries needed by an descriptor definition array field.
  377  *
  378  * The number of entries is either calculated from length_field parameters,
  379  * which indicate which other field(s) contain values representing the
  380  * array length, or the array length is calculated from the buf_len parameter,
  381  * which should ultimately have been derived from the bLength field in the raw
  382  * descriptor data.
  383  *
  384  * \param[in] buf          Descriptor data.
  385  * \param[in] buf_len      Byte length of `buf`.
  386  * \param[in] desc         First field in the descriptor definition.
  387  * \param[in] array_entry  Array field to get entry count for.
  388  * \return Number of entries in array.
  389  */
  390 static unsigned int get_array_entry_count(
  391         const unsigned char *buf,
  392         unsigned int buf_len,
  393         const struct desc *desc,
  394         const struct desc *array_entry)
  395 {
  396     const struct desc *current;
  397     unsigned int entries = 0;
  398 
  399     if (array_entry->array.length_field1) {
  400         /* We can get the array size from the length_field1. */
  401         entries = get_value_from_field(buf, desc,
  402                 array_entry->array.length_field1);
  403 
  404         if (array_entry->array.length_field2 != NULL) {
  405             /* There's a second field specifying length.  The two
  406              * lengths are multiplied. */
  407             entries *= get_value_from_field(buf, desc,
  408                     array_entry->array.length_field2);
  409         }
  410 
  411         /* If the bits flag is set, then the entry count so far
  412          * was a bit count, and we need to get a byte count. */
  413         if (array_entry->array.bits) {
  414             entries = (entries / 8) + (entries & 0x7) ? 1 : 0;
  415         }
  416     } else {
  417         /* Inferred array length.  We haven't been given a field to get
  418          * length from; start with the descriptor's byte-length, and
  419          * subtract the sizes of all the other fields. */
  420         unsigned int size = buf_len;
  421 
  422         for (current = desc; current->field != NULL; current++) {
  423             if (current == array_entry)
  424                 continue;
  425 
  426             if (current->array.array) {
  427                 unsigned int count;
  428                 /* We can't deal with two inferred-length arrays
  429                  * in one descriptor definition, because its
  430                  * an unresolvable ambiguity.  If this
  431                  * happens it's a flaw in the descriptor
  432                  * definition. */
  433                 if (current->array.length_field1 == NULL) {
  434                     return 0xffffffff;
  435                 }
  436                 count = get_array_entry_count(buf, buf_len,
  437                         desc, current);
  438                 if (count == 0xffffffff) {
  439                     fprintf(stderr, "Bad descriptor definition; "
  440                         "multiple inferred-length arrays.\n");
  441                     exit(EXIT_FAILURE);
  442                 }
  443                 size -= get_entry_size(buf, desc, current) *
  444                         count;
  445             } else {
  446                 size -= get_entry_size(buf, desc, current);
  447             }
  448         }
  449 
  450         entries = size / get_entry_size(buf, desc, array_entry);
  451     }
  452 
  453     return entries;
  454 }
  455 
  456 /**
  457  * Get the number of characters needed to dump an array index
  458  *
  459  * \param[in] array_entries  Number of entries in array.
  460  * \return number of characters required to render largest possible index.
  461  */
  462 static unsigned int get_char_count_for_array_index(unsigned int array_entries)
  463 {
  464     /* Arrays are zero-indexed, so largest index is array_entries - 1. */
  465     if (array_entries > 100) {
  466         /* [NNN] */
  467         return 5;
  468     } else if (array_entries > 10) {
  469         /* [NN] */
  470         return 4;
  471     }
  472 
  473     /* [N] */
  474     return 3;
  475 }
  476 
  477 /**
  478  * Render a field's name.
  479  *
  480  * \param[in] entry       Current entry number (for arrays).
  481  * \param[in] entries     Entry count (for arrays).
  482  * \param[in] field_len   Character width of field name space for alignment.
  483  * \param[in] current     Descriptor definition of field to render.
  484  * \param[in] indent      Current indent level.
  485  */
  486 static void field_render(
  487         unsigned int entry,
  488         unsigned int entries,
  489         unsigned int field_len,
  490         const struct desc *current,
  491         unsigned int indent)
  492 {
  493     if (current->array.array) {
  494         unsigned int needed_chars = field_len -
  495                 get_char_count_for_array_index(entries) -
  496                 strlen(current->field);
  497         printf("%*s%s(%u)%*s", indent * 2, "",
  498                 current->field, entry,
  499                 needed_chars, "");
  500     } else {
  501         printf("%*s%-*s", indent * 2, "",
  502                 field_len, current->field);
  503     }
  504 }
  505 
  506 /* Function documented in desc-dump.h */
  507 void desc_dump(
  508         libusb_device_handle *dev,
  509         const struct desc *desc,
  510         const unsigned char *buf,
  511         unsigned int buf_len,
  512         unsigned int indent)
  513 {
  514     unsigned int entry;
  515     unsigned int entries;
  516     unsigned int needed_chars;
  517     unsigned int current_size;
  518     unsigned int field_len = 18;
  519     const struct desc *current;
  520     size_t offset = 0;
  521 
  522     /* Find the buffer length, if we've been instructed to read it from
  523      * the first field. */
  524     if ((buf_len == DESC_BUF_LEN_FROM_BUF) && (desc != NULL)) {
  525         buf_len = get_n_bytes_as_ull(buf, offset, desc->size);
  526     }
  527 
  528     /* Increase `field_len` to be sufficient for character length of
  529      * longest field name for this descriptor. */
  530     for (current = desc; current->field != NULL; current++) {
  531         needed_chars = 0;
  532         if (current->array.array) {
  533             entries = get_array_entry_count(buf, buf_len,
  534                     desc, current);
  535             needed_chars = get_char_count_for_array_index(entries);
  536         }
  537         if (strlen(current->field) + needed_chars > field_len) {
  538             field_len = strlen(current->field) + needed_chars;
  539         }
  540     }
  541 
  542     /* Step through each field, and dump it. */
  543     for (current = desc; current->field != NULL; current++) {
  544         entries = 1;
  545         if (current->array.array) {
  546             /* Array type fields may have more than one entry. */
  547             entries = get_array_entry_count(buf, buf_len,
  548                     desc, current);
  549         }
  550 
  551         current_size = get_entry_size(buf, desc, current);
  552 
  553         for (entry = 0; entry < entries; entry++) {
  554             /* Check there's enough data in buf for this entry. */
  555             if (offset + current_size > buf_len) {
  556                 unsigned int i;
  557                 printf("%*sWarning: Length insufficient for "
  558                         "descriptor type.\n",
  559                         (indent - 1) * 2, "");
  560                 for (i = offset; i < buf_len; i++) {
  561                     printf("%02x ", buf[i]);
  562                 }
  563                 printf("\n");
  564                 return;
  565             }
  566 
  567             /* Dump the field name */
  568             if (current->type != DESC_EXTENSION) {
  569                 field_render(entry, entries, field_len,
  570                         current, indent);
  571             }
  572 
  573             /* Dump the value */
  574             value_renderer(dev, current, current_size, buf, buf_len,
  575                     desc, indent, offset);
  576 
  577             if (current->type == DESC_EXTENSION) {
  578                 /* A desc extension consumes all remaining
  579                  * value buffer. */
  580                 offset = buf_len;
  581             } else {
  582                 /* Advance offset in buffer */
  583                 offset += current_size;
  584             }
  585         }
  586     }
  587 
  588     /* Check for junk at end of descriptor. */
  589     if (offset < buf_len) {
  590         unsigned int i;
  591         printf("%*sWarning: Junk at end of descriptor (%zu bytes):\n",
  592                 (indent - 1) * 2, "", buf_len - offset);
  593         printf("%*s", indent * 2, "");
  594         for (i = offset; i < buf_len; i++) {
  595             printf("%02x ", buf[i]);
  596         }
  597         printf("\n");
  598     }
  599 }