]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
usbtest: Fix issue when multiple devices are sharing same USB vendor and product ID.
authorHans Petter Selasky <hselasky@FreeBSD.org>
Sun, 13 Mar 2022 14:17:06 +0000 (15:17 +0100)
committerHans Petter Selasky <hselasky@FreeBSD.org>
Thu, 17 Mar 2022 12:26:10 +0000 (13:26 +0100)
When there are multiple devices sharing the same USB vendor and product ID,
the wrong device may be selected. Fix this by also matching the bus and
device address, ugen<X>.<Y> .

Sponsored by: NVIDIA Networking
Approved by: re (gjb)

(cherry picked from commit 16346e1401b8b369e251bc70781349fb9b813cef)
(cherry picked from commit 90afe1886f5250dc32134b5851adf6cffa4a46d4)

tools/tools/usbtest/usb_control_ep_test.c
tools/tools/usbtest/usb_modem_test.c
tools/tools/usbtest/usb_msc_test.c
tools/tools/usbtest/usbtest.c
tools/tools/usbtest/usbtest.h

index 87c5fc16a83cb7f35a402640692cff0af4d59a17..4ee3bf3e05b6b65ec5c0852d2d382d7f2e2d19f8 100644 (file)
@@ -1,6 +1,6 @@
 /* $FreeBSD$ */
 /*-
- * Copyright (c) 2007-2010 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2007-2022 Hans Petter Selasky
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -75,7 +75,7 @@ emissing:
 }
 
 void
-usb_control_ep_error_test(uint16_t vid, uint16_t pid)
+usb_control_ep_error_test(struct uaddr uaddr)
 {
        struct LIBUSB20_CONTROL_SETUP_DECODED req;
        struct libusb20_device *pdev;
@@ -86,7 +86,7 @@ usb_control_ep_error_test(uint16_t vid, uint16_t pid)
        int dev;
        int cfg;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -161,7 +161,7 @@ usb_control_ep_error_test(uint16_t vid, uint16_t pid)
 }
 
 void
-usb_get_string_desc_test(uint16_t vid, uint16_t pid)
+usb_get_string_desc_test(struct uaddr uaddr)
 {
        struct libusb20_device *pdev;
        uint32_t x;
@@ -170,7 +170,7 @@ usb_get_string_desc_test(uint16_t vid, uint16_t pid)
        uint8_t *buf;
        int error;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -190,7 +190,7 @@ usb_get_string_desc_test(uint16_t vid, uint16_t pid)
        valid = 0;
 
        printf("Starting string descriptor test for "
-           "VID=0x%04x PID=0x%04x\n", vid, pid);
+           "VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
 
        for (x = 0; x != 256; x++) {
 
@@ -236,7 +236,7 @@ usb_get_string_desc_test(uint16_t vid, uint16_t pid)
 }
 
 void
-usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration)
+usb_port_reset_test(struct uaddr uaddr, uint32_t duration)
 {
        struct timeval sub_tv;
        struct timeval ref_tv;
@@ -252,7 +252,7 @@ usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration)
 
        /* sysctl() - no set config */
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -306,7 +306,7 @@ usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration)
 }
 
 void
-usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration)
+usb_set_config_test(struct uaddr uaddr, uint32_t duration)
 {
        struct libusb20_device *pdev;
        struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
@@ -315,7 +315,7 @@ usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration)
        int failed;
        int exp;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -329,7 +329,7 @@ usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration)
        failed = 0;
 
        printf("Starting set config test for "
-           "VID=0x%04x PID=0x%04x\n", vid, pid);
+           "VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
 
        for (x = 255; x > -1; x--) {
 
@@ -365,11 +365,11 @@ usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration)
 }
 
 void
-usb_get_descriptor_test(uint16_t vid, uint16_t pid, uint32_t duration)
+usb_get_descriptor_test(struct uaddr uaddr, uint32_t duration)
 {
        struct libusb20_device *pdev;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -378,7 +378,7 @@ usb_get_descriptor_test(uint16_t vid, uint16_t pid, uint32_t duration)
 }
 
 void
-usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration)
+usb_suspend_resume_test(struct uaddr uaddr, uint32_t duration)
 {
        struct timeval sub_tv;
        struct timeval ref_tv;
@@ -403,7 +403,7 @@ usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration)
                printf("WARNING: Could not set power "
                    "timeout to 1 (error=%d) \n", errno);
        }
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -417,7 +417,7 @@ usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration)
        power_old = libusb20_dev_get_power_mode(pdev);
 
        printf("Starting suspend and resume "
-           "test for VID=0x%04x PID=0x%04x\n", vid, pid);
+           "test for VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
 
        iter = 0;
        errcnt = 0;
@@ -468,7 +468,7 @@ usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration)
 }
 
 void
-usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid)
+usb_set_and_clear_stall_test(struct uaddr uaddr)
 {
        struct libusb20_device *pdev;
        struct libusb20_transfer *pxfer;
@@ -478,7 +478,7 @@ usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid)
        int errcnt;
        int ep;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -490,7 +490,7 @@ usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid)
                return;
        }
        printf("Starting set and clear stall test "
-           "for VID=0x%04x PID=0x%04x\n", vid, pid);
+           "for VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
 
        iter = 0;
        errcnt = 0;
@@ -604,7 +604,7 @@ usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid)
 }
 
 void
-usb_set_alt_interface_test(uint16_t vid, uint16_t pid)
+usb_set_alt_interface_test(struct uaddr uaddr)
 {
        struct libusb20_device *pdev;
        struct libusb20_config *config;
@@ -615,13 +615,13 @@ usb_set_alt_interface_test(uint16_t vid, uint16_t pid)
        int n;
        int m;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
        }
        printf("Starting set alternate setting test "
-           "for VID=0x%04x PID=0x%04x\n", vid, pid);
+           "for VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
 
        config = libusb20_dev_alloc_config(pdev,
            libusb20_dev_get_config_index(pdev));
index 74406fc6b2183b9e68e35420d1ce7773dce83134..0ac7ac594601d1dae48f64ac085252d8399fd7b5 100644 (file)
@@ -1,6 +1,6 @@
 /* $FreeBSD$ */
 /*-
- * Copyright (c) 2007-2010 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2007-2022 Hans Petter Selasky
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -428,7 +428,7 @@ fail:
 }
 
 static void
-exec_host_modem_test(struct modem *p, uint16_t vid, uint16_t pid)
+exec_host_modem_test(struct modem *p, struct uaddr uaddr)
 {
        struct libusb20_device *pdev;
 
@@ -440,7 +440,7 @@ exec_host_modem_test(struct modem *p, uint16_t vid, uint16_t pid)
 
        int error;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -513,7 +513,7 @@ exec_host_modem_test(struct modem *p, uint16_t vid, uint16_t pid)
 }
 
 void
-show_host_modem_test(uint8_t level, uint16_t vid, uint16_t pid, uint32_t duration)
+show_host_modem_test(uint8_t level, struct uaddr uaddr, uint32_t duration)
 {
        uint8_t retval;
 
@@ -542,7 +542,7 @@ show_host_modem_test(uint8_t level, uint16_t vid, uint16_t pid, uint32_t duratio
                    (modem.use_vendor_specific ? "YES" : "NO"),
                    (modem.loop_data ? "YES" : "NO"),
                    (int)(modem.duration),
-                   (int)vid, (int)pid);
+                   (int)uaddr.vid, (int)uaddr.pid);
 
                switch (retval) {
                case 0:
@@ -573,10 +573,10 @@ show_host_modem_test(uint8_t level, uint16_t vid, uint16_t pid, uint32_t duratio
                        set_defaults(&modem);
                        break;
                case 30:
-                       exec_host_modem_test(&modem, vid, pid);
+                       exec_host_modem_test(&modem, uaddr);
                        break;
                case 40:
-                       show_host_device_selection(level + 1, &vid, &pid);
+                       show_host_device_selection(level + 1, &uaddr);
                        break;
                default:
                        return;
index db2ab257baab4f109d05bfbace0c55929ac6ccbf..8a67d040f63ce0f68484ed39d6e95d88bd42af0c 100644 (file)
@@ -1,6 +1,6 @@
 /* $FreeBSD$ */
 /*-
- * Copyright (c) 2007-2012 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2007-2022 Hans Petter Selasky
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -857,14 +857,13 @@ fail:
 }
 
 void
-show_host_device_selection(uint8_t level, uint16_t *pvid, uint16_t *ppid)
+show_host_device_selection(uint8_t level, struct uaddr *puaddr)
 {
        struct libusb20_backend *pbe;
        struct libusb20_device *pdev;
        struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
 
-       uint16_t vid[USB_DEVICES_MAX];
-       uint16_t pid[USB_DEVICES_MAX];
+       struct uaddr uaddr[USB_DEVICES_MAX];
 
        int index;
        int sel;
@@ -887,8 +886,10 @@ top:
                        ddesc = libusb20_dev_get_device_desc(pdev);
                        ptr = libusb20_dev_get_desc(pdev);
                        printf("%s%d) %s\n", indent[level], index, ptr);
-                       vid[index] = ddesc->idVendor;
-                       pid[index] = ddesc->idProduct;
+                       uaddr[index].vid = ddesc->idVendor;
+                       uaddr[index].pid = ddesc->idProduct;
+                       uaddr[index].bus = libusb20_dev_get_bus_number(pdev);
+                       uaddr[index].addr = libusb20_dev_get_address(pdev);
                        index++;
                } else {
                        break;
@@ -907,16 +908,14 @@ top:
                goto top;
 
        if ((sel < 0) || (sel >= index)) {
-               *pvid = 0;
-               *ppid = 0;
-               return;
+               memset(puaddr, 0, sizeof(*puaddr));
+       } else {
+               *puaddr = uaddr[sel];
        }
-       *pvid = vid[sel];
-       *ppid = pid[sel];
 }
 
 struct libusb20_device *
-find_usb_device(uint16_t vid, uint16_t pid)
+find_usb_device(struct uaddr uaddr)
 {
        struct libusb20_backend *pbe = libusb20_be_alloc_default();
        struct libusb20_device *pdev = NULL;
@@ -929,8 +928,11 @@ find_usb_device(uint16_t vid, uint16_t pid)
 
                ddesc = libusb20_dev_get_device_desc(pdev);
 
-               if ((vid == ddesc->idVendor) &&
-                   (pid == ddesc->idProduct)) {
+               if ((uaddr.vid == ddesc->idVendor) &&
+                   (uaddr.pid == ddesc->idProduct) &&
+                   (uaddr.addr == 0 ||
+                    (uaddr.addr == libusb20_dev_get_address(pdev) &&
+                     uaddr.bus == libusb20_dev_get_bus_number(pdev)))) {
                        libusb20_be_dequeue_device(pbe, pdev);
                        break;
                }
@@ -1004,7 +1006,7 @@ find_usb_endpoints(struct libusb20_device *pdev, uint8_t class,
 }
 
 static void
-exec_host_msc_test(struct usb_msc_params *p, uint16_t vid, uint16_t pid)
+exec_host_msc_test(struct usb_msc_params *p, struct uaddr uaddr)
 {
        struct libusb20_device *pdev;
 
@@ -1019,7 +1021,7 @@ exec_host_msc_test(struct usb_msc_params *p, uint16_t vid, uint16_t pid)
        xfer_current_id = 0;
        xfer_wrapper_sig = CBWSIGNATURE;
 
-       pdev = find_usb_device(vid, pid);
+       pdev = find_usb_device(uaddr);
        if (pdev == NULL) {
                printf("USB device not found\n");
                return;
@@ -1199,8 +1201,7 @@ get_io_area(const struct usb_msc_params *p)
 }
 
 void
-show_host_msc_test(uint8_t level, uint16_t vid,
-    uint16_t pid, uint32_t duration)
+show_host_msc_test(uint8_t level, struct uaddr uaddr, uint32_t duration)
 {
        struct usb_msc_params params;
        uint8_t retval;
@@ -1251,7 +1252,7 @@ show_host_msc_test(uint8_t level, uint16_t vid,
                    (params.try_sense_on_error ? "YES" : "NO"),
                    (params.try_all_lun ? "YES" : "NO"),
                    (params.try_shorter_wrapper_block ? "YES" : "NO"),
-                   vid, pid);
+                   uaddr.vid, uaddr.pid);
                switch (retval) {
                case 0:
                        break;
@@ -1317,10 +1318,10 @@ show_host_msc_test(uint8_t level, uint16_t vid,
                        set_defaults(&params);
                        break;
                case 30:
-                       exec_host_msc_test(&params, vid, pid);
+                       exec_host_msc_test(&params, uaddr);
                        break;
                case 40:
-                       show_host_device_selection(level + 1, &vid, &pid);
+                       show_host_device_selection(level + 1, &uaddr);
                        break;
                default:
                        return;
index 725b9ead9718ba372af418d24b1e287b528e09df..40d67589c5a91abca20fdeaa66abcb436cbc16ed 100644 (file)
@@ -1,6 +1,6 @@
 /* $FreeBSD$ */
 /*-
- * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2010-2022 Hans Petter Selasky
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -688,8 +688,8 @@ show_host_select(uint8_t level)
        int error;
        uint32_t duration = 60;
 
-       uint16_t dev_vid = 0;
-       uint16_t dev_pid = 0;
+       struct uaddr uaddr = {};
+
        uint8_t retval;
 
        while (1) {
@@ -702,7 +702,7 @@ show_host_select(uint8_t level)
                            "to %d (error=%d)\n", force_fs, errno);
                }
                retval = usb_ts_show_menu(level, "Select Host Mode Test (via LibUSB)",
-                   " 1) Select USB device (VID=0x%04x, PID=0x%04x)\n"
+                   " 1) Select USB device (VID=0x%04x, PID=0x%04x, ugen%u.%u)\n"
                    " 2) Manually enter USB vendor and product ID\n"
                    " 3) Force FULL speed operation: <%s>\n"
                    " 4) Mass Storage (UMASS)\n"
@@ -717,7 +717,7 @@ show_host_select(uint8_t level)
                    "17) Start Invalid Control Request Test\n"
                    "30) Duration: <%d> seconds\n"
                    "x) Return to previous menu\n",
-                   dev_vid, dev_pid,
+                   uaddr.vid, uaddr.pid, uaddr.bus, uaddr.addr,
                    force_fs ? "YES" : "NO",
                    (int)duration);
 
@@ -725,44 +725,47 @@ show_host_select(uint8_t level)
                case 0:
                        break;
                case 1:
-                       show_host_device_selection(level + 1, &dev_vid, &dev_pid);
+                       show_host_device_selection(level + 1, &uaddr);
                        break;
                case 2:
-                       dev_vid = get_integer() & 0xFFFF;
-                       dev_pid = get_integer() & 0xFFFF;
+                       /* only match VID and PID */
+                       uaddr.vid = get_integer() & 0xFFFF;
+                       uaddr.pid = get_integer() & 0xFFFF;
+                       uaddr.bus = 0;
+                       uaddr.addr = 0;
                        break;
                case 3:
                        force_fs ^= 1;
                        break;
                case 4:
-                       show_host_msc_test(level + 1, dev_vid, dev_pid, duration);
+                       show_host_msc_test(level + 1, uaddr, duration);
                        break;
                case 5:
-                       show_host_modem_test(level + 1, dev_vid, dev_pid, duration);
+                       show_host_modem_test(level + 1, uaddr, duration);
                        break;
                case 10:
-                       usb_get_string_desc_test(dev_vid, dev_pid);
+                       usb_get_string_desc_test(uaddr);
                        break;
                case 11:
-                       usb_port_reset_test(dev_vid, dev_pid, duration);
+                       usb_port_reset_test(uaddr, duration);
                        break;
                case 12:
-                       usb_set_config_test(dev_vid, dev_pid, duration);
+                       usb_set_config_test(uaddr, duration);
                        break;
                case 13:
-                       usb_get_descriptor_test(dev_vid, dev_pid, duration);
+                       usb_get_descriptor_test(uaddr, duration);
                        break;
                case 14:
-                       usb_suspend_resume_test(dev_vid, dev_pid, duration);
+                       usb_suspend_resume_test(uaddr, duration);
                        break;
                case 15:
-                       usb_set_and_clear_stall_test(dev_vid, dev_pid);
+                       usb_set_and_clear_stall_test(uaddr);
                        break;
                case 16:
-                       usb_set_alt_interface_test(dev_vid, dev_pid);
+                       usb_set_alt_interface_test(uaddr);
                        break;
                case 17:
-                       usb_control_ep_error_test(dev_vid, dev_pid);
+                       usb_control_ep_error_test(uaddr);
                        break;
                case 30:
                        duration = get_integer();
index 3d6643cd58f7c11f32bde67f24f9df31958f7686..f274bebc848b81ce5455e75b3f74c0b7717fec7e 100644 (file)
@@ -1,6 +1,6 @@
 /* $FreeBSD$ */
 /*-
- * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2010-2022 Hans Petter Selasky
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,21 +37,28 @@ struct bps {
        time_t  time;
 };
 
-extern void usb_get_string_desc_test(uint16_t, uint16_t);
-extern void usb_port_reset_test(uint16_t, uint16_t, uint32_t);
-extern void usb_set_config_test(uint16_t, uint16_t, uint32_t);
-extern void usb_get_descriptor_test(uint16_t, uint16_t, uint32_t);
-extern void usb_control_ep_error_test(uint16_t, uint16_t);
-extern void usb_set_and_clear_stall_test(uint16_t, uint16_t);
-extern void usb_set_alt_interface_test(uint16_t, uint16_t);
+struct uaddr {
+       uint16_t vid;
+       uint16_t pid;
+       uint8_t bus;
+       uint8_t addr;
+};
+
+extern void usb_get_string_desc_test(struct uaddr);
+extern void usb_port_reset_test(struct uaddr, uint32_t);
+extern void usb_set_config_test(struct uaddr, uint32_t);
+extern void usb_get_descriptor_test(struct uaddr, uint32_t);
+extern void usb_control_ep_error_test(struct uaddr);
+extern void usb_set_and_clear_stall_test(struct uaddr);
+extern void usb_set_alt_interface_test(struct uaddr);
 
-extern void usb_suspend_resume_test(uint16_t, uint16_t, uint32_t);
+extern void usb_suspend_resume_test(struct uaddr, uint32_t);
 extern void do_bps(const char *, struct bps *, uint32_t len);
 extern const char *indent[USB_TS_MAX_LEVELS];
-extern void show_host_msc_test(uint8_t, uint16_t, uint16_t, uint32_t);
-extern void show_host_modem_test(uint8_t, uint16_t, uint16_t, uint32_t);
-extern void show_host_device_selection(uint8_t, uint16_t *, uint16_t *);
-extern struct libusb20_device *find_usb_device(uint16_t, uint16_t);
+extern void show_host_msc_test(uint8_t, struct uaddr, uint32_t);
+extern void show_host_modem_test(uint8_t, struct uaddr, uint32_t);
+extern void show_host_device_selection(uint8_t, struct uaddr *);
+extern struct libusb20_device *find_usb_device(struct uaddr);
 extern void find_usb_endpoints(struct libusb20_device *, uint8_t, uint8_t,
     uint8_t, uint8_t, uint8_t *, uint8_t *, uint8_t *, uint8_t);
 extern void get_string(char *, int);