I'm using a Raspberry with two similar devices but different antennas.
Specifying the device via index didn't work, because the enumeration of
devices changed from time to time. Therefore I implemented functions to
give a USB path instead. This path looks the same as the Linux kernel
uses (eg. "4-1.2") and contains the USB bus and port numbers.

I'll hope you'll find my patch acceptable.

Best Regards,
Alex


Add functions to query devices via path, and path from a device.
The path is formatted similar to Linux USB device names (bus number,
hyphen, ports separated by dots, eg. "4-1.2").
---
 include/rtl-sdr.h             |  25 +++++++
 src/convenience/convenience.c |  10 +++
 src/librtlsdr.c               | 121 ++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+)

diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index d64701e..e6ce33a 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -49,6 +49,31 @@ RTLSDR_API int rtlsdr_get_device_usb_strings(uint32_t index,
                                             char *product,
                                             char *serial);

+/*!
+ * Get device index by USB path string.
+ *
+ * The path string has the format "bus-port.port..."
+ * (i.e. the bus number, followed by a hyphen, then
+ * followed by the port numbers separated by dots).
+ *
+ * \param path path string of the device
+ * \return device index of the device with the given path
+ * \return -1 if no matching device was found.
+ */
+RTLSDR_API int rtlsdr_get_index_by_path(const char *path);
+
+/*!
+ * Get the USB path.
+ *
+ * NOTE: The buffer should provide space for at least 32 bytes.
+ *
+ * \param index the device index
+ * \param buf buffer where the path will be written
+ * \param len size of the buffer
+ * \return 0 on success
+ */
+RTLSDR_API int rtlsdr_get_device_path(uint32_t index, char *buf, size_t len);
+
 /*!
  * Get device index by USB serial string descriptor.
  *
diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c
index 00cc2cc..55f82e2 100644
--- a/src/convenience/convenience.c
+++ b/src/convenience/convenience.c
@@ -268,6 +268,16 @@ int verbose_device_search(char *s)
                        device, rtlsdr_get_device_name((uint32_t)device));
                return device;
        }
+       /* does string match a path */
+       if (s2[0] == '-') {
+               i = rtlsdr_get_index_by_path(s);
+               if (i >= 0) {
+                       device = i;
+                       fprintf(stderr, "Using device %d: %s\n",
+                               device, 
rtlsdr_get_device_name((uint32_t)device));
+                       return device;
+               }
+       }
        /* does string exact match a serial */
        for (i = 0; i < device_count; i++) {
                rtlsdr_get_device_usb_strings(i, vendor, product, serial);
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 0146298..e3f03d7 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -1414,6 +1414,127 @@ int rtlsdr_get_device_usb_strings(uint32_t index, char 
*manufact,
        return r;
 }

+static void get_device_path(libusb_device *dev, char *buf, size_t len)
+{
+       uint8_t port_numbers[16];
+       int port_entries;
+       int i, count;
+
+       count = snprintf(buf, len, "%d-", (int)libusb_get_bus_number(dev));
+       if (count < 0) {
+               buf[0] = 0;
+               return;
+       }
+       else if ((size_t)count >= len) {
+               buf[len-1] = 0;
+               return;
+       }
+
+       len -= count;
+       buf += count;
+
+       port_entries = libusb_get_port_numbers(dev, port_numbers, 
sizeof(port_numbers)/sizeof(port_numbers[0]));
+       if (port_entries < 0)
+               return;
+
+       for (i = 0; i < port_entries; i++) {
+               count = snprintf(buf, len, i ? ".%d" : "%d", (int) 
port_numbers[i]);
+
+               if (count < 0) {
+                       buf[0] = 0;
+                       break;
+               }
+               else if ((size_t)count >= len) {
+                       buf[len-1] = 0;
+                       break;
+               }
+
+               len -= count;
+               buf += count;
+       }
+
+       if (!port_entries && len > 1) {
+               buf[0] = '0';
+               buf[1] = 0;
+       }
+}
+
+int rtlsdr_get_index_by_path(const char *path)
+{
+       libusb_context *ctx;
+       libusb_device **list;
+       struct libusb_device_descriptor dd;
+       ssize_t cnt;
+       int i,r,pos;
+
+       r = libusb_init(&ctx);
+
+       if(r < 0)
+               return -1;
+
+       cnt = libusb_get_device_list(ctx, &list);
+
+       pos = 0;
+       for (i = 0; i < cnt; i++) {
+               libusb_get_device_descriptor(list[i], &dd);
+
+               if (find_known_device(dd.idVendor, dd.idProduct)) {
+                       char buf[64];
+                       get_device_path(list[i], buf, sizeof(buf));
+
+                       if (!strncmp(path, buf, sizeof(buf))) {
+                               libusb_free_device_list(list, 1);
+                               libusb_exit(ctx);
+
+                               return pos;
+                       }
+
+                       pos++;
+               }
+       }
+
+       libusb_free_device_list(list, 1);
+       libusb_exit(ctx);
+
+       return -1;
+}
+
+int rtlsdr_get_device_path(uint32_t index, char *buf, size_t len)
+{
+       libusb_context *ctx;
+       libusb_device **list;
+       struct libusb_device_descriptor dd;
+       int i,r;
+       uint32_t device_count = 0;
+       ssize_t cnt;
+
+       r = libusb_init(&ctx);
+       if(r < 0)
+               return r;
+
+       cnt = libusb_get_device_list(ctx, &list);
+
+       r = LIBUSB_ERROR_NO_DEVICE;
+       for (i = 0; i < cnt; i++) {
+               libusb_get_device_descriptor(list[i], &dd);
+
+               if (find_known_device(dd.idVendor, dd.idProduct)) {
+                       device_count++;
+
+                       if (index == device_count - 1) {
+                               get_device_path(list[i], buf, len);
+                               r = 0;
+                               break;
+                       }
+               }
+       }
+
+       libusb_free_device_list(list, 1);
+       libusb_exit(ctx);
+
+       return r;
+}
+
 int rtlsdr_get_index_by_serial(const char *serial)
 {
        int i, cnt, r;
--
2.20.1

Reply via email to