Skip to content

Commit ceb7cbf

Browse files
committed
Add derived UsbTransport class with USB reset method
For testing there needs to be a way to simulate unplugging and replugging a device. This change adds support for a USB reset method that does this. Also add timeouts, so USB reads/writes don't block forever on an unresponsive device. Test: glinux, fastboot tool still works Test: Reset confirmed working via wireshark Linux URB captures Change-Id: I7213a2395d4ef1c0238810e4929ab966e78c8b55
1 parent 767506f commit ceb7cbf

File tree

4 files changed

+59
-18
lines changed

4 files changed

+59
-18
lines changed

fastboot/usb.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ struct usb_ifc_info {
5252
char device_path[256];
5353
};
5454

55+
class UsbTransport : public Transport {
56+
// Resets the underlying transport. Returns 0 on success.
57+
// This effectively simulates unplugging and replugging
58+
virtual int Reset() = 0;
59+
};
60+
5561
typedef int (*ifc_match_func)(usb_ifc_info *ifc);
5662

57-
Transport* usb_open(ifc_match_func callback);
63+
// 0 is non blocking
64+
UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms = 0);

fastboot/usb_linux.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
using namespace std::chrono_literals;
5454

55-
#define MAX_RETRIES 5
55+
#define MAX_RETRIES 2
5656

5757
/* Timeout in seconds for usb_wait_for_disconnect.
5858
* It doesn't usually take long for a device to disconnect (almost always
@@ -91,18 +91,21 @@ struct usb_handle
9191
unsigned char ep_out;
9292
};
9393

94-
class LinuxUsbTransport : public Transport {
94+
class LinuxUsbTransport : public UsbTransport {
9595
public:
96-
explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
96+
explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
97+
: handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
9798
~LinuxUsbTransport() override = default;
9899

99100
ssize_t Read(void* data, size_t len) override;
100101
ssize_t Write(const void* data, size_t len) override;
101102
int Close() override;
103+
int Reset() override;
102104
int WaitForDisconnect() override;
103105

104106
private:
105107
std::unique_ptr<usb_handle> handle_;
108+
const uint32_t ms_timeout_;
106109

107110
DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport);
108111
};
@@ -402,7 +405,7 @@ ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
402405
bulk.ep = handle_->ep_out;
403406
bulk.len = xfer;
404407
bulk.data = data;
405-
bulk.timeout = 0;
408+
bulk.timeout = ms_timeout_;
406409

407410
n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk);
408411
if(n != xfer) {
@@ -436,7 +439,7 @@ ssize_t LinuxUsbTransport::Read(void* _data, size_t len)
436439
bulk.ep = handle_->ep_in;
437440
bulk.len = xfer;
438441
bulk.data = data;
439-
bulk.timeout = 0;
442+
bulk.timeout = ms_timeout_;
440443
retry = 0;
441444

442445
do {
@@ -447,7 +450,7 @@ ssize_t LinuxUsbTransport::Read(void* _data, size_t len)
447450
if (n < 0) {
448451
DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno));
449452
if (++retry > MAX_RETRIES) return -1;
450-
std::this_thread::sleep_for(1s);
453+
std::this_thread::sleep_for(100ms);
451454
}
452455
} while (n < 0);
453456

@@ -477,10 +480,19 @@ int LinuxUsbTransport::Close()
477480
return 0;
478481
}
479482

480-
Transport* usb_open(ifc_match_func callback)
481-
{
483+
int LinuxUsbTransport::Reset() {
484+
int ret = 0;
485+
// We reset the USB connection
486+
if ((ret = ioctl(handle_->desc, USBDEVFS_RESET, 0))) {
487+
return ret;
488+
}
489+
490+
return 0;
491+
}
492+
493+
UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
482494
std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback);
483-
return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr;
495+
return handle ? new LinuxUsbTransport(std::move(handle), timeout_ms) : nullptr;
484496
}
485497

486498
/* Wait for the system to notice the device is gone, so that a subsequent

fastboot/usb_osx.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,20 @@ struct usb_handle
6565
unsigned int zero_mask;
6666
};
6767

68-
class OsxUsbTransport : public Transport {
68+
class OsxUsbTransport : public UsbTransport {
6969
public:
70-
OsxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
70+
OsxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout)
71+
: handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
7172
~OsxUsbTransport() override = default;
7273

7374
ssize_t Read(void* data, size_t len) override;
7475
ssize_t Write(const void* data, size_t len) override;
7576
int Close() override;
77+
int Reset() override;
7678

7779
private:
7880
std::unique_ptr<usb_handle> handle_;
81+
const uint32_t ms_timeout_;
7982

8083
DISALLOW_COPY_AND_ASSIGN(OsxUsbTransport);
8184
};
@@ -456,22 +459,33 @@ static int init_usb(ifc_match_func callback, std::unique_ptr<usb_handle>* handle
456459
* Definitions of this file's public functions.
457460
*/
458461

459-
Transport* usb_open(ifc_match_func callback) {
462+
UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
460463
std::unique_ptr<usb_handle> handle;
461464

462465
if (init_usb(callback, &handle) < 0) {
463466
/* Something went wrong initializing USB. */
464467
return nullptr;
465468
}
466469

467-
return new OsxUsbTransport(std::move(handle));
470+
return new OsxUsbTransport(std::move(handle), timeout_ms);
468471
}
469472

470473
int OsxUsbTransport::Close() {
471474
/* TODO: Something better here? */
472475
return 0;
473476
}
474477

478+
int OsxUsbTransport::Reset() {
479+
IOReturn result = (*handle_->interface)->ResetDevice(handle_->interface);
480+
481+
if (result == 0) {
482+
return 0;
483+
} else {
484+
ERR("usb_reset failed with status %x\n", result);
485+
return -1;
486+
}
487+
}
488+
475489
ssize_t OsxUsbTransport::Read(void* data, size_t len) {
476490
IOReturn result;
477491
UInt32 numBytes = len;
@@ -494,7 +508,9 @@ ssize_t OsxUsbTransport::Read(void* data, size_t len) {
494508
return -1;
495509
}
496510

497-
result = (*handle_->interface)->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
511+
result = (*handle_->interface)
512+
->ReadPipeTO(handle_->interface, handle_->bulkIn, data, &numBytes,
513+
USB_TRANSACTION_TIMEOUT, USB_TRANSACTION_TIMEOUT);
498514

499515
if (result == 0) {
500516
return (int) numBytes;

fastboot/usb_windows.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ struct usb_handle {
6666
std::string interface_name;
6767
};
6868

69-
class WindowsUsbTransport : public Transport {
69+
class WindowsUsbTransport : public UsbTransport {
7070
public:
7171
WindowsUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
7272
~WindowsUsbTransport() override = default;
7373

7474
ssize_t Read(void* data, size_t len) override;
7575
ssize_t Write(const void* data, size_t len) override;
7676
int Close() override;
77+
int Reset() override;
7778

7879
private:
7980
std::unique_ptr<usb_handle> handle_;
@@ -261,6 +262,12 @@ int WindowsUsbTransport::Close() {
261262
return 0;
262263
}
263264

265+
int WindowsUsbTransport::Reset() {
266+
DBG("usb_reset currently unsupported\n\n");
267+
// TODO, this is a bit complicated since it is using ADB
268+
return -1;
269+
}
270+
264271
int recognized_device(usb_handle* handle, ifc_match_func callback) {
265272
struct usb_ifc_info info;
266273
USB_DEVICE_DESCRIPTOR device_desc;
@@ -366,8 +373,7 @@ static std::unique_ptr<usb_handle> find_usb_device(ifc_match_func callback) {
366373
return handle;
367374
}
368375

369-
Transport* usb_open(ifc_match_func callback)
370-
{
376+
UsbTransport* usb_open(ifc_match_func callback, uint32_t) {
371377
std::unique_ptr<usb_handle> handle = find_usb_device(callback);
372378
return handle ? new WindowsUsbTransport(std::move(handle)) : nullptr;
373379
}

0 commit comments

Comments
 (0)