"Fossies" - the Fresh Open Source Software Archive

Member "usbutils-014/usbhid-dump/src/iface_list.c" (22 Feb 2021, 6250 Bytes) of package /linux/misc/usbutils-014.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 "iface_list.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 013_vs_014.

    1 // SPDX-License-Identifier: GPL-2.0-or-later
    2 /*
    3  * usbhid-dump - interface list
    4  *
    5  * Copyright (C) 2010 Nikolai Kondrashov <spbnick@gmail.com>
    6  */
    7 
    8 #include "config.h"
    9 
   10 #include "iface_list.h"
   11 #include "misc.h"
   12 #include <assert.h>
   13 #include <stdlib.h>
   14 #include <stdio.h>
   15 
   16 bool
   17 uhd_iface_list_valid(const uhd_iface *list)
   18 {
   19     UHD_IFACE_LIST_FOR_EACH(list, list)
   20         if (!uhd_iface_valid(list))
   21             return false;
   22 
   23     return true;
   24 }
   25 
   26 
   27 size_t
   28 uhd_iface_list_len(const uhd_iface *list)
   29 {
   30     size_t  len = 0;
   31 
   32     UHD_IFACE_LIST_FOR_EACH(list, list)
   33         len++;
   34 
   35     return len;
   36 }
   37 
   38 
   39 void
   40 uhd_iface_list_free(uhd_iface *list)
   41 {
   42     uhd_iface *next;
   43 
   44     for (; list != NULL; list = next)
   45     {
   46         next = list->next;
   47         uhd_iface_free(list);
   48     }
   49 }
   50 
   51 
   52 enum libusb_error
   53 uhd_iface_list_new(uhd_dev     *dev_list,
   54                    uhd_iface  **plist)
   55 {
   56     enum libusb_error   err = LIBUSB_ERROR_OTHER;
   57 
   58     uhd_dev                                    *dev;
   59     struct libusb_config_descriptor            *config          = NULL;
   60     const struct libusb_interface              *lusb_iface;
   61     const struct libusb_interface_descriptor   *iface_desc;
   62     const uhd_hid_descriptor                   *hid_desc;
   63     const uhd_hid_descriptor_extra             *hid_desc_extra;
   64     uint16_t                                    rd_len;
   65     const struct libusb_endpoint_descriptor    *ep_list;
   66     uint8_t                                     ep_num;
   67     const struct libusb_endpoint_descriptor    *ep;
   68     uhd_iface                                  *list            = NULL;
   69     uhd_iface                                  *iface;
   70 
   71     assert(uhd_dev_list_valid(dev_list));
   72 
   73     UHD_DEV_LIST_FOR_EACH(dev, dev_list)
   74     {
   75         /* Retrieve active configuration descriptor */
   76         err = libusb_get_active_config_descriptor(libusb_get_device(dev->handle),
   77                                                   &config);
   78         if (err != LIBUSB_SUCCESS)
   79             goto cleanup;
   80 
   81         /*
   82          * Build the matching interface list
   83          */
   84 
   85         /* For each interface */
   86         for (lusb_iface = config->interface;
   87              lusb_iface - config->interface < config->bNumInterfaces;
   88              lusb_iface++)
   89         {
   90             /* Skip interfaces with altsettings */
   91             if (lusb_iface->num_altsetting != 1)
   92                 continue;
   93 
   94             iface_desc = lusb_iface->altsetting;
   95 
   96             /* Skip non-HID interfaces */
   97             if (iface_desc->bInterfaceClass != LIBUSB_CLASS_HID)
   98                 continue;
   99 
  100             /*
  101              * Try to retrieve report descriptor length
  102              */
  103             rd_len = UHD_MAX_DESCRIPTOR_SIZE;
  104             /* If interface descriptor has space for a HID descriptor */
  105             if (iface_desc->extra_length >= (int)sizeof(uhd_hid_descriptor))
  106             {
  107                 hid_desc = (const uhd_hid_descriptor *)iface_desc->extra;
  108                 /* If this is truly a HID class descriptor */
  109                 if (hid_desc->bDescriptorType == LIBUSB_DT_HID)
  110                 {
  111                     /* For each extra HID descriptor entry */
  112                     for (hid_desc_extra = hid_desc->extra;
  113                          hid_desc_extra <
  114                             hid_desc->extra + hid_desc->bNumDescriptors &&
  115                          (uint8_t *)hid_desc_extra <
  116                             (uint8_t *)hid_desc + hid_desc->bLength &&
  117                          (unsigned char *)hid_desc_extra <
  118                             iface_desc->extra +
  119                             iface_desc->extra_length;
  120                          hid_desc_extra++) {
  121                         /* If this is a report descriptor entry */
  122                         if (hid_desc_extra->bDescriptorType ==
  123                                 LIBUSB_DT_REPORT)
  124                         {
  125                             rd_len = hid_desc_extra->wDescriptorLength;
  126                             break;
  127                         }
  128                     }
  129                 }
  130             }
  131 
  132             /* Retrieve endpoint list */
  133             ep_list = iface_desc->endpoint;
  134             ep_num = iface_desc->bNumEndpoints;
  135 
  136             /* For each endpoint */
  137             for (ep = ep_list; (ep - ep_list) < ep_num; ep++)
  138             {
  139                 /* Skip non-interrupt and non-in endpoints */
  140                 if ((ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) !=
  141                     LIBUSB_TRANSFER_TYPE_INTERRUPT ||
  142                     (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) !=
  143                     LIBUSB_ENDPOINT_IN)
  144                     continue;
  145 
  146                 /* Create the interface */
  147                 iface = uhd_iface_new(
  148                             dev,
  149                             iface_desc->bInterfaceNumber,
  150                             ep->bEndpointAddress, ep->wMaxPacketSize,
  151                             rd_len);
  152                 if (iface == NULL)
  153                 {
  154                     err = LIBUSB_ERROR_NO_MEM;
  155                     goto cleanup;
  156                 }
  157 
  158                 /* Add the interface */
  159                 iface->next = list;
  160                 list = iface;
  161 
  162                 break;
  163             }
  164         }
  165 
  166         /* Free the config descriptor */
  167         libusb_free_config_descriptor(config);
  168         config = NULL;
  169     }
  170 
  171     /* Output the resulting list, if requested */
  172     assert(uhd_iface_list_valid(list));
  173     if (plist != NULL)
  174     {
  175         *plist = list;
  176         list = NULL;
  177     }
  178 
  179     /* Done! */
  180     err = LIBUSB_SUCCESS;
  181 
  182 cleanup:
  183 
  184     libusb_free_config_descriptor(config);
  185     uhd_iface_list_free(list);
  186 
  187     return err;
  188 }
  189 
  190 
  191 uhd_iface *
  192 uhd_iface_list_fltr_by_num(uhd_iface   *list,
  193                            uint8_t      number)
  194 {
  195     uhd_iface  *prev;
  196     uhd_iface  *iface;
  197     uhd_iface  *next;
  198 
  199     assert(uhd_iface_list_valid(list));
  200     assert(number < UINT8_MAX);
  201 
  202     for (prev = NULL, iface = list; iface != NULL; iface = next)
  203     {
  204         next = iface->next;
  205         if (iface->number == number)
  206             prev = iface;
  207         else
  208         {
  209             if (prev == NULL)
  210                 list = next;
  211             else
  212                 prev->next = next;
  213             uhd_iface_free(iface);
  214         }
  215     }
  216 
  217     return list;
  218 }
  219 
  220