Add support for fastboot transport timeouts and USB Reset() on linux
USB Reset() allows simulating unplugging and replugging device.
Test: build and run fastboot on mac 10.13.3
Test: glinux build and run fastboot
Change-Id: Id924d063e549a4cca9dda03afd8f8fe266f6d2ab
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index e95b049..4d48f6e 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -65,17 +65,21 @@
unsigned int zero_mask;
};
-class OsxUsbTransport : public Transport {
+class OsxUsbTransport : public UsbTransport {
public:
- OsxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
+ // A timeout of 0 is blocking
+ OsxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
+ : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
~OsxUsbTransport() override = default;
ssize_t Read(void* data, size_t len) override;
ssize_t Write(const void* data, size_t len) override;
int Close() override;
+ int Reset() override;
private:
std::unique_ptr<usb_handle> handle_;
+ const uint32_t ms_timeout_;
DISALLOW_COPY_AND_ASSIGN(OsxUsbTransport);
};
@@ -456,7 +460,7 @@
* Definitions of this file's public functions.
*/
-Transport* usb_open(ifc_match_func callback) {
+UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
std::unique_ptr<usb_handle> handle;
if (init_usb(callback, &handle) < 0) {
@@ -464,7 +468,7 @@
return nullptr;
}
- return new OsxUsbTransport(std::move(handle));
+ return new OsxUsbTransport(std::move(handle), timeout_ms);
}
int OsxUsbTransport::Close() {
@@ -472,6 +476,19 @@
return 0;
}
+/*
+ TODO: this SHOULD be easy to do with ResetDevice() from IOUSBDeviceInterface.
+ However to perform operations that manipulate the state of the device, you must
+ claim ownership of the device with USBDeviceOpenSeize(). However, this operation
+ always fails with kIOReturnExclusiveAccess.
+ It seems that the kext com.apple.driver.usb.AppleUSBHostCompositeDevice
+ always loads and claims ownership of the device and refuses to give it up.
+*/
+int OsxUsbTransport::Reset() {
+ ERR("USB reset is currently unsupported on osx\n");
+ return -1;
+}
+
ssize_t OsxUsbTransport::Read(void* data, size_t len) {
IOReturn result;
UInt32 numBytes = len;
@@ -494,7 +511,14 @@
return -1;
}
- result = (*handle_->interface)->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
+ if (!ms_timeout_) {
+ result = (*handle_->interface)
+ ->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
+ } else {
+ result = (*handle_->interface)
+ ->ReadPipeTO(handle_->interface, handle_->bulkIn, data, &numBytes,
+ ms_timeout_, ms_timeout_);
+ }
if (result == 0) {
return (int) numBytes;
@@ -541,8 +565,16 @@
int lenToSend = lenRemaining > maxLenToSend
? maxLenToSend : lenRemaining;
- result = (*handle_->interface)->WritePipe(
- handle_->interface, handle_->bulkOut, (void *)data, lenToSend);
+ if (!ms_timeout_) { // blocking
+ result = (*handle_->interface)
+ ->WritePipe(handle_->interface, handle_->bulkOut, (void*)data,
+ lenToSend);
+ } else {
+ result = (*handle_->interface)
+ ->WritePipeTO(handle_->interface, handle_->bulkOut, (void*)data,
+ lenToSend, ms_timeout_, ms_timeout_);
+ }
+
if (result != 0) break;
lenRemaining -= lenToSend;