<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/16607">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">usb: Import a variety of libusb utility functions from simtrace<br><br>Those functions were originally developed as part of simtrace; let's<br>import them to libosmousb as they are truly generic.<br><br>Change-Id: I2c18b938e4e1ea5b8a521a386f00db3a7389e47a<br>---<br>M include/osmocom/usb/libusb.h<br>M src/usb/osmo_libusb.c<br>2 files changed, 384 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/07/16607/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/usb/libusb.h b/include/osmocom/usb/libusb.h</span><br><span>index 7f10f74..5b01847 100644</span><br><span>--- a/include/osmocom/usb/libusb.h</span><br><span>+++ b/include/osmocom/usb/libusb.h</span><br><span>@@ -1,6 +1,77 @@</span><br><span> #pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+/* libusb utilities</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2010-2019 by Harald Welte <hwelte@hmw-consulting.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> </span><br><span> #include <libusb.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define USB_MAX_PATH_LEN 20</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct dev_id {</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t vendor_id;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t product_id;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* structure describing a single matching interface found */</span><br><span style="color: hsl(120, 100%, 40%);">+struct usb_interface_match {</span><br><span style="color: hsl(120, 100%, 40%);">+        /* libusb device E*/</span><br><span style="color: hsl(120, 100%, 40%);">+  libusb_device *usb_dev;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Vendor ID of the device running matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t vendor;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Product ID of the device running matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t product;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* USB Bus Address */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* physical path */</span><br><span style="color: hsl(120, 100%, 40%);">+   char path[USB_MAX_PATH_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+  /* configuration of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t configuration;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* interface number of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t interface;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* altsetting of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t altsetting;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* bInterfaceClass of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t class;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* bInterfaceSubClass of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t sub_class;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* bInterfaceProtocol of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t protocol;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* index of string descriptor of matching interface */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t string_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_libusb_dev_get_path_buf(char *buf, size_t bufsize, libusb_device *dev);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_libusb_dev_get_path_c(void *ctx, libusb_device *dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device **osmo_libusb_find_matching_usb_devs(void *ctx, struct libusb_context *luctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 const struct dev_id *dev_ids);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_libusb_dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class,</span><br><span style="color: hsl(120, 100%, 40%);">+                                            int protocol, struct usb_interface_match *out,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        unsigned int out_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device_handle *osmo_libusb_open_claim_interface(void *ctx, libusb_context *luctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       const struct usb_interface_match *ifm);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_libusb_get_ep_addrs(libusb_device_handle *devh, unsigned int if_num,</span><br><span style="color: hsl(120, 100%, 40%);">+                           uint8_t *out, uint8_t *in, uint8_t *irq);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int osmo_libusb_init(libusb_context **luctx);</span><br><span> void osmo_libusb_exit(libusb_context *luctx);</span><br><span>diff --git a/src/usb/osmo_libusb.c b/src/usb/osmo_libusb.c</span><br><span>index 79ab0ff..c8633b3 100644</span><br><span>--- a/src/usb/osmo_libusb.c</span><br><span>+++ b/src/usb/osmo_libusb.c</span><br><span>@@ -1,6 +1,6 @@</span><br><span> /* libosmocore integration with libusb-1.0</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019-2019 by Harald Welte <laforge@gnumonks.org></span><br><span>  * All Rights Reserved.</span><br><span>  *</span><br><span>  * SPDX-License-Identifier: GPL-2.0+</span><br><span>@@ -33,6 +33,8 @@</span><br><span> </span><br><span> #include <libusb.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/usb/libusb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /***********************************************************************</span><br><span>  * logging integration</span><br><span>  ***********************************************************************/</span><br><span>@@ -104,7 +106,317 @@</span><br><span>     talloc_free(ofd);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * utility functions</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! obtain the string representation of the USB device path of given device.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] buf Output string buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bufsize Size of output string buffer in bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dev USB device whose bus path we want to obtain</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns pointer to 'buf' in case of success; NULL in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_libusb_dev_get_path_buf(char *buf, size_t bufsize, libusb_device *dev)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+#if (defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000102) || \</span><br><span style="color: hsl(120, 100%, 40%);">+    (defined(LIBUSBX_API_VERSION) && LIBUSBX_API_VERSION >= 0x01000102)</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_strbuf sb = { .buf = buf, .len = bufsize };</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t path[8];</span><br><span style="color: hsl(120, 100%, 40%);">+      int r,j;</span><br><span style="color: hsl(120, 100%, 40%);">+      r = libusb_get_port_numbers(dev, path, sizeof(path));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (r > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               OSMO_STRBUF_PRINTF(sb, "%d-%d", libusb_get_bus_number(dev), path[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+               for (j = 1; j < r; j++){</span><br><span style="color: hsl(120, 100%, 40%);">+                   OSMO_STRBUF_PRINTF(sb, ".%d", path[j]);</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span style="color: hsl(120, 100%, 40%);">+# warning "libusb too old - building without USB path support!"</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! obtain the string representation of the USB device path of given device.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] talloc context from which to dynamically allocate output string buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dev USB device whose bus path we want to obtain</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns pointer to 'buf' in case of success; NULL in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_libusb_dev_get_path_c(void *ctx, libusb_device *dev)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char *buf = talloc_zero_size(ctx, USB_MAX_PATH_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_libusb_dev_get_path_buf(buf, USB_MAX_PATH_LEN, dev);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int match_dev_id(const struct libusb_device_descriptor *desc, const struct dev_id *id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if ((desc->idVendor == id->vendor_id) && (desc->idProduct == id->product_id))</span><br><span style="color: hsl(120, 100%, 40%);">+             return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int match_dev_ids(const struct libusb_device_descriptor *desc, const struct dev_id *ids)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct dev_id *id;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    for (id = ids; id->vendor_id || id->product_id; id++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (match_dev_id(desc, id))</span><br><span style="color: hsl(120, 100%, 40%);">+                   return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Find USB devices matching the specified list of USB VendorID/ProductIDs</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context from which to allocate output data</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] luctx libusb context on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dev_ids zero-terminated array of VendorId/ProductId tuples</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns array of up to 256 libusb_device pointers; NULL in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device **osmo_libusb_find_matching_usb_devs(void *ctx, struct libusb_context *luctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             const struct dev_id *dev_ids)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   libusb_device **list;</span><br><span style="color: hsl(120, 100%, 40%);">+ libusb_device **out = talloc_array(ctx, libusb_device *, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+        libusb_device **cur = out;</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!out)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = libusb_get_device_list(luctx, &list);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             perror("No USB devices found");</span><br><span style="color: hsl(120, 100%, 40%);">+             talloc_free(out);</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; list[i] != NULL; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           struct libusb_device_descriptor dev_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+             libusb_device *dev = list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = libusb_get_device_descriptor(dev, &dev_desc);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      perror("Couldn't get device descriptor\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     libusb_unref_device(dev);</span><br><span style="color: hsl(120, 100%, 40%);">+                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (match_dev_ids(&dev_desc, dev_ids)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  *cur = dev;</span><br><span style="color: hsl(120, 100%, 40%);">+                   cur++;</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* overflow check */</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (cur >= out + 256)</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        libusb_unref_device(dev);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (cur == out) {</span><br><span style="color: hsl(120, 100%, 40%);">+             libusb_free_device_list(list, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+             talloc_free(out);</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   libusb_free_device_list(list, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     return out;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! find a matching interface among all interfaces of the given USB device.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dev USB device in which we shall search</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] class USB Interface Class to look for</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] sub_class USB Interface Subclass to look for</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] protocol USB Interface Protocol to look for</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] out User-allocated array for storing matches</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] out_len Length of out array</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns number of matching interfaces; negative in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_libusb_dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       int protocol, struct usb_interface_match *out,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        unsigned int out_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct libusb_device_descriptor dev_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc, i, out_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ char pathbuf[USB_MAX_PATH_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+       char *path;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = libusb_get_device_descriptor(dev, &dev_desc);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              perror("Couldn't get device descriptor\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   addr = libusb_get_device_address(dev);</span><br><span style="color: hsl(120, 100%, 40%);">+        path = osmo_libusb_dev_get_path_buf(pathbuf, sizeof(pathbuf), dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* iterate over all configurations */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < dev_desc.bNumConfigurations; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct libusb_config_descriptor *conf_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+           int j;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = libusb_get_config_descriptor(dev, i, &conf_desc);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      fprintf(stderr, "Couldn't get config descriptor %u\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+                      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             /* iterate over all interfaces */</span><br><span style="color: hsl(120, 100%, 40%);">+             for (j = 0; j < conf_desc->bNumInterfaces; j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       const struct libusb_interface *intf = &conf_desc->interface[j];</span><br><span style="color: hsl(120, 100%, 40%);">+                        int k;</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* iterate over all alternate settings */</span><br><span style="color: hsl(120, 100%, 40%);">+                     for (k = 0; k < intf->num_altsetting; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            const struct libusb_interface_descriptor *if_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+                            if_desc = &intf->altsetting[k];</span><br><span style="color: hsl(120, 100%, 40%);">+                                if (class >= 0 && if_desc->bInterfaceClass != class)</span><br><span style="color: hsl(120, 100%, 40%);">+                                    continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (sub_class >= 0 && if_desc->bInterfaceSubClass != sub_class)</span><br><span style="color: hsl(120, 100%, 40%);">+                                 continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (protocol >= 0 && if_desc->bInterfaceProtocol != protocol)</span><br><span style="color: hsl(120, 100%, 40%);">+                                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             /* MATCH! */</span><br><span style="color: hsl(120, 100%, 40%);">+                          out[out_idx].usb_dev = dev;</span><br><span style="color: hsl(120, 100%, 40%);">+                           out[out_idx].vendor = dev_desc.idVendor;</span><br><span style="color: hsl(120, 100%, 40%);">+                              out[out_idx].product = dev_desc.idProduct;</span><br><span style="color: hsl(120, 100%, 40%);">+                            out[out_idx].addr = addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                             strncpy(out[out_idx].path, path, sizeof(out[out_idx].path)-1);</span><br><span style="color: hsl(120, 100%, 40%);">+                                out[out_idx].path[sizeof(out[out_idx].path)-1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                                out[out_idx].configuration = conf_desc->bConfigurationValue;</span><br><span style="color: hsl(120, 100%, 40%);">+                               out[out_idx].interface = if_desc->bInterfaceNumber;</span><br><span style="color: hsl(120, 100%, 40%);">+                                out[out_idx].altsetting = if_desc->bAlternateSetting;</span><br><span style="color: hsl(120, 100%, 40%);">+                              out[out_idx].class = if_desc->bInterfaceClass;</span><br><span style="color: hsl(120, 100%, 40%);">+                             out[out_idx].sub_class = if_desc->bInterfaceSubClass;</span><br><span style="color: hsl(120, 100%, 40%);">+                              out[out_idx].protocol = if_desc->bInterfaceProtocol;</span><br><span style="color: hsl(120, 100%, 40%);">+                               out[out_idx].string_idx = if_desc->iInterface;</span><br><span style="color: hsl(120, 100%, 40%);">+                             out_idx++;</span><br><span style="color: hsl(120, 100%, 40%);">+                            if (out_idx >= out_len)</span><br><span style="color: hsl(120, 100%, 40%);">+                                    return out_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return out_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! open matching USB device and claim interface</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context to use for related allocations</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] luctx libusb context on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ifm interface match describing interface to claim</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns libusb device chandle on success; NULL on error */</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device_handle *osmo_libusb_open_claim_interface(void *ctx, libusb_context *luctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                        const struct usb_interface_match *ifm)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc, config;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct dev_id dev_ids[] = { { ifm->vendor, ifm->product }, { 0, 0 } };</span><br><span style="color: hsl(120, 100%, 40%);">+  libusb_device **list;</span><br><span style="color: hsl(120, 100%, 40%);">+ libusb_device **dev;</span><br><span style="color: hsl(120, 100%, 40%);">+  libusb_device_handle *usb_devh = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      list = osmo_libusb_find_matching_usb_devs(ctx, luctx, dev_ids);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          perror("No USB device with matching VID/PID");</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (dev = list; *dev; dev++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               int addr;</span><br><span style="color: hsl(120, 100%, 40%);">+             char pathbuf[USB_MAX_PATH_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+               char *path;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         addr = libusb_get_device_address(*dev);</span><br><span style="color: hsl(120, 100%, 40%);">+               path = osmo_libusb_dev_get_path_buf(pathbuf, sizeof(pathbuf), *dev);</span><br><span style="color: hsl(120, 100%, 40%);">+          if ((ifm->addr && addr == ifm->addr) ||</span><br><span style="color: hsl(120, 100%, 40%);">+             (strlen(ifm->path) && !strcmp(path, ifm->path))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  rc = libusb_open(*dev, &usb_devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              fprintf(stderr, "Cannot open device: %s\n", libusb_error_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                         usb_devh = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = libusb_get_configuration(usb_devh, &config);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              fprintf(stderr, "Cannot get current configuration: %s\n", libusb_error_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                           libusb_close(usb_devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                               usb_devh = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (config != ifm->configuration) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                rc = libusb_set_configuration(usb_devh, ifm->configuration);</span><br><span style="color: hsl(120, 100%, 40%);">+                               if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      fprintf(stderr, "Cannot set configuration: %s\n", libusb_error_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                                   libusb_close(usb_devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                                       usb_devh = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                                }</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = libusb_claim_interface(usb_devh, ifm->interface);</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              fprintf(stderr, "Cannot claim interface: %s\n", libusb_error_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                             libusb_close(usb_devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                               usb_devh = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = libusb_set_interface_alt_setting(usb_devh, ifm->interface, ifm->altsetting);</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              fprintf(stderr, "Cannot set interface altsetting: %s\n", libusb_error_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                            libusb_release_interface(usb_devh, ifm->interface);</span><br><span style="color: hsl(120, 100%, 40%);">+                                libusb_close(usb_devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                               usb_devh = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* unref / free list */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (dev = list; *dev; dev++)</span><br><span style="color: hsl(120, 100%, 40%);">+         libusb_unref_device(*dev);</span><br><span style="color: hsl(120, 100%, 40%);">+    free(list);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return usb_devh;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! obtain the endpoint addresses for a given USB interface.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] devh USB device handle on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] if_num USB Interface number on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] out user-provided storage for OUT endpoint number</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] in user-provided storage for IN endpoint number</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] irq user-provided storage for IRQ endpoint number</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 in case of success; negative in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_libusb_get_ep_addrs(libusb_device_handle *devh, unsigned int if_num,</span><br><span style="color: hsl(120, 100%, 40%);">+                      uint8_t *out, uint8_t *in, uint8_t *irq)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      libusb_device *dev = libusb_get_device(devh);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct libusb_config_descriptor *cdesc;</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct libusb_interface_descriptor *idesc;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct libusb_interface *iface;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc, l;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = libusb_get_active_config_descriptor(dev, &cdesc);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  iface = &cdesc->interface[if_num];</span><br><span style="color: hsl(120, 100%, 40%);">+     /* FIXME: we assume there's no altsetting */</span><br><span style="color: hsl(120, 100%, 40%);">+      idesc = &iface->altsetting[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (l = 0; l < idesc->bNumEndpoints; l++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            const struct libusb_endpoint_descriptor *edesc = &idesc->endpoint[l];</span><br><span style="color: hsl(120, 100%, 40%);">+          switch (edesc->bmAttributes & 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+             case LIBUSB_TRANSFER_TYPE_BULK:</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (edesc->bEndpointAddress & 0x80) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (in)</span><br><span style="color: hsl(120, 100%, 40%);">+                                       *in = edesc->bEndpointAddress;</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (out)</span><br><span style="color: hsl(120, 100%, 40%);">+                                      *out = edesc->bEndpointAddress;</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case LIBUSB_TRANSFER_TYPE_INTERRUPT:</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (irq)</span><br><span style="color: hsl(120, 100%, 40%);">+                              *irq = edesc->bEndpointAddress;</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> /***********************************************************************</span><br><span>  * initialization</span><br><span>  ***********************************************************************/</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/16607">change 16607</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/16607"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I2c18b938e4e1ea5b8a521a386f00db3a7389e47a </div>
<div style="display:none"> Gerrit-Change-Number: 16607 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>