4 #include "usb_device.h"
10 #include <linux/usbdevice_fs.h>
13 #include "usbdev_utils.h"
16 static constexpr
unsigned PORT_SUSPEND = 2u;
17 static constexpr
unsigned PORT_RESET = 4u;
18 static constexpr
unsigned PORT_POWER = 8u;
25 int rc = libusb_init(&ctx_);
27 return ErrorUSB(
"ERROR: Initializing libusb", rc);
33 productID_ = productID;
36 addrSpec_ = devAddress;
47 libusb_close(parenth_);
64 std::cout <<
"Locating USB device" << std::endl;
65 unsigned numTries = 30u;
74 libusb_device **dev_list;
75 ssize_t num_devs = libusb_get_device_list(ctx_, &dev_list);
77 for (idx = 0; idx < num_devs; idx++) {
78 int rc = libusb_get_device_descriptor(dev_list[idx], &devDesc_);
81 std::cout <<
"Device: "
82 <<
"VendorID: " << std::hex << devDesc_.idVendor
83 <<
" ProductID: " << devDesc_.idProduct << std::dec
86 if (devDesc_.idVendor == vendorID_ &&
87 devDesc_.idProduct == productID_) {
90 uint8_t addr = libusb_get_device_address(dev_list[idx]);
91 uint8_t bus = libusb_get_bus_number(dev_list[idx]);
100 if (!addrSpec_ || (addrSpec_ == addr && busSpec_ == bus)) {
106 libusb_device *dev = dev_list[idx];
107 rc = libusb_open(dev, &devh_);
109 std::cerr <<
"Error opening device " << (int)bus <<
":"
110 << (
int)addr <<
" - " << libusb_error_name(rc)
117 libusb_device *parent = libusb_get_parent(dev);
119 rc = libusb_open(parent, &parenth_);
121 std::cerr <<
"Failed to open parent device - "
122 << libusb_error_name(rc) << std::endl;
125 std::cout <<
"Opened parent\n";
130 uint8_t bus = libusb_get_bus_number(dev);
132 std::cout <<
"Device path: " << (unsigned)bus <<
"-";
134 devPath_ = std::to_string(bus) +
'-';
136 int rc = libusb_get_port_numbers(dev, ports,
sizeof(ports));
138 unsigned num_ports = (unsigned)rc;
139 for (
unsigned idx = 0u; idx < num_ports; idx++) {
141 std::cout << (unsigned)ports[idx];
143 devPath_ += std::to_string(ports[idx]);
144 if (idx + 1 < num_ports) {
149 portNumber_ = ports[idx];
151 std::cout << std::endl;
153 std::cerr <<
"Error getting port list: "
154 << libusb_error_name(rc) << std::endl;
166 libusb_free_device_list(dev_list, 1u);
171 busSpec_ = busNumber_;
172 addrSpec_ = devAddress_;
174 }
else if (numTries-- > 0u) {
176 std::cout <<
'.' << std::flush;
179 std::cerr <<
"Unable to locate USB device" << std::endl;
185 std::cout <<
"Device found (Bus " << (int)busNumber_ <<
" Device "
186 << (
int)devAddress_ <<
")" << std::endl;
188 std::cout <<
" - Path: " << devPath_ << std::endl;
193 int rc = libusb_set_auto_detach_kernel_driver(devh_, 1u);
195 std::cerr <<
"Error detaching kernel driver: " << libusb_error_name(rc)
203 rc = libusb_get_configuration(devh_, &config);
205 std::cerr <<
"Error getting configuration: " << libusb_error_name(rc)
209 std::cout <<
"Configuration: " << config << std::endl;
211 std::cout <<
"Running without libusb" << std::endl;
219 #if STREAMTEST_LIBUSB
231 #if STREAMTEST_LIBUSB
232 struct timeval tv = {0};
233 int rc = libusb_handle_events_timeout(ctx_, &tv);
235 return ErrorUSB(
"ERROR: Handling events", rc);
247 return "SleepResume";
248 case kSuspendPhaseSleepReset:
251 return "SleepDisconnect";
257 return "DeepDisconnect";
266 std::cout <<
"Reading Test Descriptor" << std::endl;
271 #if STREAMTEST_LIBUSB
272 uint8_t bmRequestType = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR |
273 LIBUSB_RECIPIENT_ENDPOINT;
274 std::cout <<
"req type " << (int)bmRequestType << std::endl;
276 uint8_t testDesc[0x10u];
277 int rc = libusb_control_transfer(devh_, bmRequestType, kVendorTestConfig, 0u,
278 0u, testDesc,
sizeof(testDesc),
279 kControlTransferTimeout);
281 std::cerr <<
"Error reading test descriptor: " << libusb_error_name(rc)
287 std::cout <<
"Test Descriptor:" << std::endl;
288 for (
unsigned idx = 0u; idx <
sizeof(testDesc); idx++) {
289 printf(
"%u: 0x%02x\n", idx, testDesc[idx]);
294 const uint8_t test_sig_head[] = {0x7eu, 0x57u, 0xc0u, 0xf1u};
295 const uint8_t test_sig_tail[] = {0x1fu, 0x0cu, 0x75u, 0xe7u};
296 const uint8_t *dp = testDesc;
297 if (!
memcmp(dp, test_sig_head, 4) && 0x10u == get_le16(&dp[4]) &&
298 !
memcmp(&dp[12], test_sig_tail, 4)) {
299 usb_testutils_test_number_t testNum =
300 (usb_testutils_test_number_t)get_le16(&dp[6]);
303 std::cout <<
"Test number: " << testNum <<
" args " << std::hex
304 << (int)dp[8] <<
" " << (
int)dp[9] <<
" " << (int)dp[10] <<
" "
305 << (
int)dp[11] << std::dec << std::endl;
313 testNumber_ = testNum;
316 testArg_[2] = dp[10];
317 testArg_[3] = dp[11];
319 std::cout <<
"Test number: " << testNum <<
" Test Phase: "
329 testNumber_ = USBDevice::kUsbTestNumberStreams;
340 while (time_us > 0) {
341 uint32_t delay_us = time_us;
343 std::cout <<
"Delaying " << time_us <<
"us "
344 << (with_traffic ?
" - with traffic" :
"no traffic")
358 std::cout <<
"Resetting Device" << std::endl;
366 const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT |
367 LIBUSB_REQUEST_TYPE_CLASS |
368 LIBUSB_RECIPIENT_OTHER;
370 std::cout <<
"Resetting port " << portNumber_ << std::endl;
373 int rc = libusb_control_transfer(parenth_, bmRequestType,
374 LIBUSB_REQUEST_SET_FEATURE, PORT_RESET,
375 portNumber_, NULL, 0u, 0u);
377 std::cerr <<
"Failed to reset device - " << libusb_error_name(rc)
382 std::cout <<
"Done port reset" << std::endl;
389 int rc = libusb_reset_device(devh_);
398 std::cout <<
"Suspending Device " << devPath_ << std::endl;
402 const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT |
403 LIBUSB_REQUEST_TYPE_CLASS |
404 LIBUSB_RECIPIENT_OTHER;
406 std::cout <<
"Suspending port " << portNumber_ << std::endl;
409 int rc = libusb_control_transfer(parenth_, bmRequestType,
410 LIBUSB_REQUEST_SET_FEATURE, PORT_SUSPEND,
411 portNumber_, NULL, 0u, 0u);
413 std::cerr <<
"Failed to suspend device - " << libusb_error_name(rc)
418 std::cout <<
"Done suspend" << std::endl;
425 std::string powerPath =
"/sys/bus/usb/devices/" + devPath_ +
"/power/";
426 std::string filename = powerPath +
"autosuspend_delay_ms";
428 int fd = open(filename.c_str(), O_WRONLY);
430 std::cerr <<
"Failed to open '" << filename <<
"'" << std::endl;
431 std::cerr <<
" (Note: this requires super user permissions)"
435 int rc = write(fd,
"0", 1);
437 std::cerr <<
"Write failed" << std::endl;
441 std::cerr <<
"Close failed" << std::endl;
445 filename = powerPath +
"control";
446 fd = open(filename.c_str(), O_WRONLY);
448 std::cerr <<
"Failed to open '" << filename <<
"'" << std::endl;
449 std::cerr <<
" (Note: this requires super user permissions)"
453 rc = write(fd,
"auto", 4);
455 std::cerr <<
"Write failed" << std::endl;
459 std::cerr <<
"Close failed" << std::endl;
468 std::cout <<
"Resuming Device" << std::endl;
472 const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT |
473 LIBUSB_REQUEST_TYPE_CLASS |
474 LIBUSB_RECIPIENT_OTHER;
476 std::cout <<
"Resuming port " << portNumber_ << std::endl;
479 int rc = libusb_control_transfer(parenth_, bmRequestType,
480 LIBUSB_REQUEST_CLEAR_FEATURE, PORT_SUSPEND,
481 portNumber_, NULL, 0u, 0u);
483 std::cerr <<
"Failed to resume device - " << libusb_error_name(rc)
488 std::cout <<
"Done resume" << std::endl;
491 std::string powerPath =
"/sys/bus/usb/devices/" + devPath_ +
"/power/";
492 std::string filename = powerPath +
"control";
494 int fd = open(filename.c_str(), O_WRONLY);
496 std::cerr <<
"Failed to open '" << filename <<
"'" << std::endl;
499 int rc = write(fd,
"on", 2);
501 std::cerr <<
"Write failed" << std::endl;
523 std::cout <<
"Connecting Device " << devPath_ << std::endl;
527 const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT |
528 LIBUSB_REQUEST_TYPE_CLASS |
529 LIBUSB_RECIPIENT_OTHER;
531 std::cout <<
"Connecting port " << portNumber_ << std::endl;
534 int rc = libusb_control_transfer(parenth_, bmRequestType,
535 LIBUSB_REQUEST_SET_FEATURE, PORT_POWER,
536 portNumber_, NULL, 0u, 0u);
538 std::cerr <<
"Failed to connect device - " << libusb_error_name(rc)
543 std::cout <<
"Done connect" << std::endl;
546 std::cout <<
"Connect operation not available" << std::endl;
554 std::cout <<
"Disconnecting Device " << devPath_ << std::endl;
558 const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT |
559 LIBUSB_REQUEST_TYPE_CLASS |
560 LIBUSB_RECIPIENT_OTHER;
562 std::cout <<
"Disconnecting port " << portNumber_ << std::endl;
565 int rc = libusb_control_transfer(parenth_, bmRequestType,
566 LIBUSB_REQUEST_CLEAR_FEATURE, PORT_POWER,
567 portNumber_, NULL, 0u, 0u);
569 std::cerr <<
"Failed to disconnect device - " << libusb_error_name(rc)
574 std::cout <<
"Done disconnect" << std::endl;
577 std::cout <<
"Disconnect operation not available" << std::endl;