"Fossies" - the Fresh Open Source Software Archive

Member "usbutils-015/usbhid-dump/src/iface.c" (22 Feb 2021, 5555 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 "iface.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  * usbhid-dump - interface
    4  *
    5  * Copyright (C) 2010 Nikolai Kondrashov <spbnick@gmail.com>
    6  */
    7 
    8 #include "config.h"
    9 
   10 #include "iface.h"
   11 #include <assert.h>
   12 #include <stdlib.h>
   13 #include <stdio.h>
   14 #include <string.h>
   15 
   16 bool
   17 uhd_iface_valid(const uhd_iface *iface)
   18 {
   19     return iface != NULL &&
   20            uhd_dev_valid(iface->dev) &&
   21            iface->number < UINT8_MAX &&
   22            strlen(iface->addr_str) == (sizeof(iface->addr_str) - 1);
   23 }
   24 
   25 uhd_iface *
   26 uhd_iface_new(const uhd_dev    *dev,
   27               uint8_t           number,
   28               uint8_t           int_in_ep_addr,
   29               uint16_t          int_in_ep_maxp,
   30               uint16_t          rd_len)
   31 {
   32     uhd_iface      *iface;
   33     libusb_device  *lusb_dev;
   34     int             rc;
   35 
   36     iface = malloc(sizeof(*iface));
   37     if (iface == NULL)
   38         return NULL;
   39 
   40     iface->next             = NULL;
   41     iface->dev              = dev;
   42     iface->number           = number;
   43     iface->int_in_ep_addr   = int_in_ep_addr;
   44     iface->int_in_ep_maxp   = int_in_ep_maxp;
   45     iface->rd_len           = rd_len;
   46     iface->detached         = false;
   47     iface->claimed          = false;
   48     iface->submitted        = false;
   49 
   50     /* Format address string */
   51     lusb_dev = libusb_get_device(dev->handle);
   52     rc = snprintf(iface->addr_str, sizeof(iface->addr_str),
   53                   "%.3hhu:%.3hhu:%.3hhu",
   54                   libusb_get_bus_number(lusb_dev),
   55                   libusb_get_device_address(lusb_dev),
   56                   number);
   57     (void)rc;
   58     assert(rc == (sizeof(iface->addr_str) - 1));
   59 
   60     assert(uhd_iface_valid(iface));
   61 
   62     return iface;
   63 }
   64 
   65 
   66 void
   67 uhd_iface_free(uhd_iface *iface)
   68 {
   69     if (iface == NULL)
   70         return;
   71 
   72     assert(uhd_iface_valid(iface));
   73 
   74     free(iface);
   75 }
   76 
   77 
   78 enum libusb_error
   79 uhd_iface_detach(uhd_iface *iface)
   80 {
   81     enum libusb_error   err;
   82 
   83     assert(uhd_iface_valid(iface));
   84 
   85     err = libusb_detach_kernel_driver(iface->dev->handle, iface->number);
   86     if (err == LIBUSB_SUCCESS)
   87         iface->detached = true;
   88     else if (err != LIBUSB_ERROR_NOT_FOUND)
   89         return err;
   90 
   91     return LIBUSB_SUCCESS;
   92 }
   93 
   94 
   95 enum libusb_error
   96 uhd_iface_attach(uhd_iface *iface)
   97 {
   98     enum libusb_error   err;
   99 
  100     assert(uhd_iface_valid(iface));
  101 
  102     if (iface->detached)
  103     {
  104         err = libusb_attach_kernel_driver(iface->dev->handle,
  105                                           iface->number);
  106         if (err != LIBUSB_SUCCESS)
  107             return err;
  108         iface->detached = false;
  109     }
  110 
  111     return LIBUSB_SUCCESS;
  112 }
  113 
  114 
  115 enum libusb_error
  116 uhd_iface_claim(uhd_iface *iface)
  117 {
  118     enum libusb_error   err;
  119 
  120     assert(uhd_iface_valid(iface));
  121 
  122     err = libusb_claim_interface(iface->dev->handle, iface->number);
  123     if (err != LIBUSB_SUCCESS)
  124         return err;
  125 
  126     iface->claimed = true;
  127 
  128     return LIBUSB_SUCCESS;
  129 }
  130 
  131 
  132 enum libusb_error
  133 uhd_iface_release(uhd_iface *iface)
  134 {
  135     enum libusb_error   err;
  136 
  137     assert(uhd_iface_valid(iface));
  138 
  139     err = libusb_release_interface(iface->dev->handle, iface->number);
  140     if (err != LIBUSB_SUCCESS)
  141         return err;
  142 
  143     iface->claimed = false;
  144 
  145     return LIBUSB_SUCCESS;
  146 }
  147 
  148 
  149 enum libusb_error
  150 uhd_iface_clear_halt(uhd_iface *iface)
  151 {
  152     enum libusb_error   err;
  153 
  154     assert(uhd_iface_valid(iface));
  155 
  156     err = libusb_clear_halt(iface->dev->handle, iface->int_in_ep_addr);
  157     if (err != LIBUSB_SUCCESS)
  158         return err;
  159 
  160     return LIBUSB_SUCCESS;
  161 }
  162 
  163 
  164 enum libusb_error
  165 uhd_iface_set_idle(const uhd_iface    *iface,
  166                    uint8_t             duration,
  167                    unsigned int        timeout)
  168 {
  169     int rc;
  170 
  171     assert(uhd_iface_valid(iface));
  172 
  173     rc = libusb_control_transfer(iface->dev->handle,
  174                                  /* host->device, class, interface */
  175                                  0x21,
  176                                  /* Set_Idle */
  177                                  0x0A,
  178                                  /* duration for all report IDs */
  179                                  duration << 8,
  180                                  /* interface */
  181                                  iface->number,
  182                                  NULL, 0,
  183                                  timeout);
  184     /*
  185      * Ignoring EPIPE, which means a STALL handshake, which is OK on
  186      * control pipes and indicates request is not supported.
  187      * See USB 2.0 spec, 8.4.5 Handshake Packets
  188      */
  189     if (rc < 0 && rc != LIBUSB_ERROR_PIPE)
  190         return rc;
  191 
  192     return LIBUSB_SUCCESS;
  193 }
  194 
  195 
  196 enum libusb_error
  197 uhd_iface_set_protocol(const uhd_iface    *iface,
  198                        bool                report,
  199                        unsigned int        timeout)
  200 {
  201     int rc;
  202 
  203     assert(uhd_iface_valid(iface));
  204 
  205     rc = libusb_control_transfer(iface->dev->handle,
  206                                  /* host->device, class, interface */
  207                                  0x21,
  208                                  /* Set_Protocol */
  209                                  0x0B,
  210                                  /* 0 - boot, 1 - report */
  211                                  report ? 1 : 0,
  212                                  /* interface */
  213                                  iface->number,
  214                                  NULL, 0,
  215                                  timeout);
  216     /*
  217      * Ignoring EPIPE, which means a STALL handshake, which is OK on
  218      * control pipes and indicates request is not supported.
  219      * See USB 2.0 spec, 8.4.5 Handshake Packets
  220      */
  221     if (rc < 0 && rc != LIBUSB_ERROR_PIPE)
  222         return rc;
  223 
  224     return LIBUSB_SUCCESS;
  225 }
  226 
  227