From 1e126edff1611abf495f64aba852c66232218dda Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Sun, 13 Mar 2022 15:17:06 +0100 Subject: [PATCH] usbtest: Fix issue when multiple devices are sharing same USB vendor and product ID. 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. . 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 | 44 +++++++++++------------ tools/tools/usbtest/usb_modem_test.c | 14 ++++---- tools/tools/usbtest/usb_msc_test.c | 43 +++++++++++----------- tools/tools/usbtest/usbtest.c | 39 ++++++++++---------- tools/tools/usbtest/usbtest.h | 33 ++++++++++------- 5 files changed, 92 insertions(+), 81 deletions(-) diff --git a/tools/tools/usbtest/usb_control_ep_test.c b/tools/tools/usbtest/usb_control_ep_test.c index 87c5fc16a83c..4ee3bf3e05b6 100644 --- a/tools/tools/usbtest/usb_control_ep_test.c +++ b/tools/tools/usbtest/usb_control_ep_test.c @@ -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 @@ set_ctrl_ep_fail(int bus, int dev, int ds_fail, int ss_fail) } 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)); diff --git a/tools/tools/usbtest/usb_modem_test.c b/tools/tools/usbtest/usb_modem_test.c index 74406fc6b218..0ac7ac594601 100644 --- a/tools/tools/usbtest/usb_modem_test.c +++ b/tools/tools/usbtest/usb_modem_test.c @@ -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 @@ usb_modem_data_stress_test(struct modem *p, uint32_t duration) } 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; diff --git a/tools/tools/usbtest/usb_msc_test.c b/tools/tools/usbtest/usb_msc_test.c index db2ab257baab..8a67d040f63c 100644 --- a/tools/tools/usbtest/usb_msc_test.c +++ b/tools/tools/usbtest/usb_msc_test.c @@ -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 @@ usb_msc_test(struct usb_msc_params *p) } 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 @@ show_host_device_selection(uint8_t level, uint16_t *pvid, uint16_t *ppid) 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 @@ show_host_device_selection(uint8_t level, uint16_t *pvid, uint16_t *ppid) 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(¶ms); break; case 30: - exec_host_msc_test(¶ms, vid, pid); + exec_host_msc_test(¶ms, uaddr); break; case 40: - show_host_device_selection(level + 1, &vid, &pid); + show_host_device_selection(level + 1, &uaddr); break; default: return; diff --git a/tools/tools/usbtest/usbtest.c b/tools/tools/usbtest/usbtest.c index 725b9ead9718..40d67589c5a9 100644 --- a/tools/tools/usbtest/usbtest.c +++ b/tools/tools/usbtest/usbtest.c @@ -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(); diff --git a/tools/tools/usbtest/usbtest.h b/tools/tools/usbtest/usbtest.h index 3d6643cd58f7..f274bebc848b 100644 --- a/tools/tools/usbtest/usbtest.h +++ b/tools/tools/usbtest/usbtest.h @@ -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_suspend_resume_test(uint16_t, uint16_t, uint32_t); +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(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);