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<X>.<Y> .

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

(cherry picked from commit 16346e1401)
(cherry picked from commit 90afe1886f)
This commit is contained in:
Hans Petter Selasky 2022-03-13 15:17:06 +01:00
parent 0520911be8
commit 1e126edff1
5 changed files with 92 additions and 81 deletions

View 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 @@ 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));

View 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 @@ 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;

View 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 @@ 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(&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;

View 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();

View 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_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);