<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/16830">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">usb: Add osmo_libusb_find_matching_dev_{path,serial}<br><br>Thise two helper functions allow the user application to find<br>a unique match among the existing USB devices, using either a user-<br>provided iSerial string, or a user-provided physical USB path.<br><br>Change-Id: I8ff3fb3e1a77e10cb313473480ce5e7673749a93<br>---<br>M include/osmocom/usb/libusb.h<br>M src/usb/osmo_libusb.c<br>2 files changed, 154 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/30/16830/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 382c86e..2220e03 100644</span><br><span>--- a/include/osmocom/usb/libusb.h</span><br><span>+++ b/include/osmocom/usb/libusb.h</span><br><span>@@ -62,6 +62,14 @@</span><br><span> libusb_device **osmo_libusb_find_matching_usb_devs(void *ctx, struct libusb_context *luctx,</span><br><span>                                                  const struct dev_id *dev_ids);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device *osmo_libusb_find_matching_dev_path(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%);">+                                                 const char *path);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device *osmo_libusb_find_matching_dev_serial(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%);">+                                                 const char *serial);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int osmo_libusb_dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class,</span><br><span>                                          int protocol, struct usb_interface_match *out,</span><br><span>                                       unsigned int out_len);</span><br><span>diff --git a/src/usb/osmo_libusb.c b/src/usb/osmo_libusb.c</span><br><span>index b10f5be..9ad6240 100644</span><br><span>--- a/src/usb/osmo_libusb.c</span><br><span>+++ b/src/usb/osmo_libusb.c</span><br><span>@@ -220,6 +220,152 @@</span><br><span>         return out;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Find a USB device of matching VendorID/ProductID at given path.</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 zer-oterminated array of VendorId/ProductId tuples</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] path string representation of USB path</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns libusb_device if there was exactly one match; NULL otherwise */</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device *osmo_libusb_find_matching_dev_path(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%);">+                                                 const char *path)</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 *match = NULL;</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%);">+     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%);">+               return NULL;</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%);">+         char pathbuf[128];</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%);">+                      LOGP(DLUSB, LOGL_ERROR, "couldn't get device descriptor\n");</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%);">+           /* check if device doesn't match */</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%);">+                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* check if path doesn't match */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (path) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_libusb_dev_get_path_buf(pathbuf, sizeof(pathbuf), dev);</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (strcmp(pathbuf, path))</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) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* we already have a match, but now found a second -> FAIL */</span><br><span style="color: hsl(120, 100%, 40%);">+                      libusb_free_device_list(list, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGP(DLUSB, LOGL_ERROR, "Found more than one matching USB device\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                       return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        match = 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%);">+   if (!match) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* no match: free the list with automatic unref of all devices */</span><br><span style="color: hsl(120, 100%, 40%);">+             libusb_free_device_list(list, 1);</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%);">+   /* unref all devices *except* the match we found */</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%);">+           libusb_device *dev = list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+         if (dev != match)</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%);">+     /* free the list *without* automatic unref of all devices */</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 match;</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 USB device of matching VendorID/ProductID and given iSerial string.</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 zer-oterminated array of VendorId/ProductId tuples</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] serial string representation of serial number</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns libusb_device if there was exactly one match; NULL otherwise */</span><br><span style="color: hsl(120, 100%, 40%);">+libusb_device *osmo_libusb_find_matching_dev_serial(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%);">+                                                 const char *serial)</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 *match = NULL;</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%);">+     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%);">+               return NULL;</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%);">+                      LOGP(DLUSB, LOGL_ERROR, "couldn't get device descriptor\n");</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%);">+           /* check if device doesn't match */</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%);">+                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* check if serial number string doesn't match */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (serial) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 char strbuf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+                     libusb_device_handle *devh;</span><br><span style="color: hsl(120, 100%, 40%);">+                   rc = libusb_open(dev, &devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              LOGP(DLUSB, LOGL_ERROR, "Cannot open USB Device: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     libusb_strerror(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                         /* there's no point in continuing here, as we don't know if there</span><br><span style="color: hsl(120, 100%, 40%);">+                              * are multiple matches if we cannot read the iSerial string of all</span><br><span style="color: hsl(120, 100%, 40%);">+                            * devices with matching vid/pid */</span><br><span style="color: hsl(120, 100%, 40%);">+                           libusb_free_device_list(list, 1);</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_string_descriptor_ascii(devh, dev_desc.iSerialNumber,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                         (uint8_t *) strbuf, sizeof(strbuf));</span><br><span style="color: hsl(120, 100%, 40%);">+                  libusb_close(devh);</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (strcmp(strbuf, serial))</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) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* we already have a match, but now found a second -> FAIL */</span><br><span style="color: hsl(120, 100%, 40%);">+                      libusb_free_device_list(list, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGP(DLUSB, LOGL_ERROR, "Found more than one matching USB device\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                       return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        match = 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%);">+   if (!match) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* no match: free the list with automatic unref of all devices */</span><br><span style="color: hsl(120, 100%, 40%);">+             libusb_free_device_list(list, 1);</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%);">+   /* unref all devices *except* the match we found */</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%);">+           libusb_device *dev = list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+         if (dev != match)</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%);">+     /* free the list *without* automatic unref of all devices */</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 match;</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> /*! find a matching interface among all interfaces of the given USB device.</span><br><span>  *  \param[in] dev USB device in which we shall search</span><br><span>  *  \param[in] class USB Interface Class to look for</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/16830">change 16830</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/+/16830"/><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: I8ff3fb3e1a77e10cb313473480ce5e7673749a93 </div>
<div style="display:none"> Gerrit-Change-Number: 16830 </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>