adb: make adb reconnect
perform a USB reset.
Bug: http://b/128941083 Test: manual Change-Id: Iaf46d2c46cc82b590768004486d119244591c8e2
This commit is contained in:
parent
ee9ba3efe7
commit
3705b346b9
12 changed files with 104 additions and 12 deletions
|
@ -1114,7 +1114,7 @@ HostRequestResult handle_host_request(std::string_view service, TransportType ty
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}, true);
|
||||
if (!response.empty()) {
|
||||
response.resize(response.size() - 1);
|
||||
}
|
||||
|
@ -1229,7 +1229,7 @@ HostRequestResult handle_host_request(std::string_view service, TransportType ty
|
|||
std::string response;
|
||||
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &response, true);
|
||||
if (t != nullptr) {
|
||||
kick_transport(t);
|
||||
kick_transport(t, true);
|
||||
response =
|
||||
"reconnecting " + t->serial_name() + " [" + t->connection_state_name() + "]\n";
|
||||
}
|
||||
|
|
|
@ -52,6 +52,11 @@ int usb_close(usb_handle* h) {
|
|||
: native::usb_close(reinterpret_cast<native::usb_handle*>(h));
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle* h) {
|
||||
should_use_libusb() ? libusb::usb_reset(reinterpret_cast<libusb::usb_handle*>(h))
|
||||
: native::usb_reset(reinterpret_cast<native::usb_handle*>(h));
|
||||
}
|
||||
|
||||
void usb_kick(usb_handle* h) {
|
||||
should_use_libusb() ? libusb::usb_kick(reinterpret_cast<libusb::usb_handle*>(h))
|
||||
: native::usb_kick(reinterpret_cast<native::usb_handle*>(h));
|
||||
|
|
|
@ -622,6 +622,11 @@ int usb_close(usb_handle* h) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle* h) {
|
||||
libusb_reset_device(h->device_handle);
|
||||
usb_kick(h);
|
||||
}
|
||||
|
||||
void usb_kick(usb_handle* h) {
|
||||
h->Close();
|
||||
}
|
||||
|
|
|
@ -458,6 +458,11 @@ int usb_read(usb_handle *h, void *_data, int len)
|
|||
return orig_len - len;
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle* h) {
|
||||
ioctl(h->fd, USBDEVFS_RESET);
|
||||
usb_kick(h);
|
||||
}
|
||||
|
||||
void usb_kick(usb_handle* h) {
|
||||
std::lock_guard<std::mutex> lock(h->mutex);
|
||||
D("[ kicking %p (fd = %d) ]", h, h->fd);
|
||||
|
|
|
@ -556,6 +556,13 @@ int usb_close(usb_handle *handle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle* handle) {
|
||||
if (!handle->dead) {
|
||||
(*handle->interface)->USBDeviceReEnumerate(handle->interface, 0);
|
||||
}
|
||||
usb_kick(handle);
|
||||
}
|
||||
|
||||
static void usb_kick_locked(usb_handle *handle)
|
||||
{
|
||||
LOG(INFO) << "Kicking handle";
|
||||
|
|
|
@ -448,6 +448,11 @@ void usb_cleanup_handle(usb_handle* handle) {
|
|||
}
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle* handle) {
|
||||
// Unimplemented on Windows.
|
||||
usb_kick(handle);
|
||||
}
|
||||
|
||||
static void usb_kick_locked(usb_handle* handle) {
|
||||
// The reason the lock must be acquired before calling this function is in
|
||||
// case multiple threads are trying to kick the same device at the same time.
|
||||
|
|
|
@ -33,6 +33,10 @@ int usb_close(usb_handle*) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle*) {
|
||||
LOG(FATAL) << "unimplemented";
|
||||
}
|
||||
|
||||
void usb_kick(usb_handle*) {
|
||||
LOG(FATAL) << "unimplemented";
|
||||
}
|
||||
|
|
|
@ -307,6 +307,10 @@ int usb_close(usb_handle* h) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void usb_reset(usb_handle* h) {
|
||||
usb_close(h);
|
||||
}
|
||||
|
||||
void usb_kick(usb_handle* h) {
|
||||
h->kick(h);
|
||||
}
|
||||
|
|
|
@ -257,6 +257,11 @@ TransportId NextTransportId() {
|
|||
return next++;
|
||||
}
|
||||
|
||||
void Connection::Reset() {
|
||||
LOG(INFO) << "Connection::Reset(): stopping";
|
||||
Stop();
|
||||
}
|
||||
|
||||
BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
|
||||
: underlying_(std::move(connection)) {}
|
||||
|
||||
|
@ -312,6 +317,26 @@ void BlockingConnectionAdapter::Start() {
|
|||
started_ = true;
|
||||
}
|
||||
|
||||
void BlockingConnectionAdapter::Reset() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!started_) {
|
||||
LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): not started";
|
||||
return;
|
||||
}
|
||||
|
||||
if (stopped_) {
|
||||
LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_
|
||||
<< "): already stopped";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): resetting";
|
||||
this->underlying_->Reset();
|
||||
Stop();
|
||||
}
|
||||
|
||||
void BlockingConnectionAdapter::Stop() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
@ -424,14 +449,18 @@ void send_packet(apacket* p, atransport* t) {
|
|||
}
|
||||
}
|
||||
|
||||
void kick_transport(atransport* t) {
|
||||
void kick_transport(atransport* t, bool reset) {
|
||||
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||
// As kick_transport() can be called from threads without guarantee that t is valid,
|
||||
// check if the transport is in transport_list first.
|
||||
//
|
||||
// TODO(jmgao): WTF? Is this actually true?
|
||||
if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
|
||||
t->Kick();
|
||||
if (reset) {
|
||||
t->Reset();
|
||||
} else {
|
||||
t->Kick();
|
||||
}
|
||||
}
|
||||
|
||||
#if ADB_HOST
|
||||
|
@ -942,9 +971,16 @@ int atransport::Write(apacket* p) {
|
|||
return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
|
||||
}
|
||||
|
||||
void atransport::Reset() {
|
||||
if (!kicked_.exchange(true)) {
|
||||
LOG(INFO) << "resetting transport " << this << " " << this->serial;
|
||||
this->connection()->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void atransport::Kick() {
|
||||
if (!kicked_.exchange(true)) {
|
||||
D("kicking transport %p %s", this, this->serial.c_str());
|
||||
LOG(INFO) << "kicking transport " << this << " " << this->serial;
|
||||
this->connection()->Stop();
|
||||
}
|
||||
}
|
||||
|
@ -1173,18 +1209,22 @@ std::string list_transports(bool long_listing) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void close_usb_devices(std::function<bool(const atransport*)> predicate) {
|
||||
void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset) {
|
||||
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||
for (auto& t : transport_list) {
|
||||
if (predicate(t)) {
|
||||
t->Kick();
|
||||
if (reset) {
|
||||
t->Reset();
|
||||
} else {
|
||||
t->Kick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* hack for osx */
|
||||
void close_usb_devices() {
|
||||
close_usb_devices([](const atransport*) { return true; });
|
||||
void close_usb_devices(bool reset) {
|
||||
close_usb_devices([](const atransport*) { return true; }, reset);
|
||||
}
|
||||
#endif // ADB_HOST
|
||||
|
||||
|
|
|
@ -99,6 +99,9 @@ struct Connection {
|
|||
virtual void Start() = 0;
|
||||
virtual void Stop() = 0;
|
||||
|
||||
// Stop, and reset the device if it's a USB connection.
|
||||
virtual void Reset();
|
||||
|
||||
std::string transport_name_;
|
||||
ReadCallback read_callback_;
|
||||
ErrorCallback error_callback_;
|
||||
|
@ -124,6 +127,9 @@ struct BlockingConnection {
|
|||
// This method must be thread-safe, and must cause concurrent Reads/Writes to terminate.
|
||||
// Formerly known as 'Kick' in atransport.
|
||||
virtual void Close() = 0;
|
||||
|
||||
// Terminate a connection, and reset it.
|
||||
virtual void Reset() = 0;
|
||||
};
|
||||
|
||||
struct BlockingConnectionAdapter : public Connection {
|
||||
|
@ -136,6 +142,8 @@ struct BlockingConnectionAdapter : public Connection {
|
|||
virtual void Start() override final;
|
||||
virtual void Stop() override final;
|
||||
|
||||
virtual void Reset() override final;
|
||||
|
||||
bool started_ GUARDED_BY(mutex_) = false;
|
||||
bool stopped_ GUARDED_BY(mutex_) = false;
|
||||
|
||||
|
@ -157,6 +165,7 @@ struct FdConnection : public BlockingConnection {
|
|||
bool Write(apacket* packet) override final;
|
||||
|
||||
void Close() override;
|
||||
virtual void Reset() override final { Close(); }
|
||||
|
||||
private:
|
||||
unique_fd fd_;
|
||||
|
@ -170,6 +179,7 @@ struct UsbConnection : public BlockingConnection {
|
|||
bool Write(apacket* packet) override final;
|
||||
|
||||
void Close() override final;
|
||||
virtual void Reset() override final;
|
||||
|
||||
usb_handle* handle_;
|
||||
};
|
||||
|
@ -235,6 +245,7 @@ class atransport {
|
|||
virtual ~atransport();
|
||||
|
||||
int Write(apacket* p);
|
||||
void Reset();
|
||||
void Kick();
|
||||
bool kicked() const { return kicked_; }
|
||||
|
||||
|
@ -364,7 +375,7 @@ class atransport {
|
|||
atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
|
||||
bool* is_ambiguous, std::string* error_out,
|
||||
bool accept_any_state = false);
|
||||
void kick_transport(atransport* t);
|
||||
void kick_transport(atransport* t, bool reset = false);
|
||||
void update_transports(void);
|
||||
|
||||
// Iterates across all of the current and pending transports.
|
||||
|
@ -395,8 +406,8 @@ void unregister_usb_transport(usb_handle* usb);
|
|||
|
||||
bool check_header(apacket* p, atransport* t);
|
||||
|
||||
void close_usb_devices();
|
||||
void close_usb_devices(std::function<bool(const atransport*)> predicate);
|
||||
void close_usb_devices(bool reset = false);
|
||||
void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset = false);
|
||||
|
||||
void send_packet(apacket* p, atransport* t);
|
||||
|
||||
|
|
|
@ -171,6 +171,11 @@ bool UsbConnection::Write(apacket* packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void UsbConnection::Reset() {
|
||||
usb_reset(handle_);
|
||||
usb_kick(handle_);
|
||||
}
|
||||
|
||||
void UsbConnection::Close() {
|
||||
usb_kick(handle_);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
int usb_write(handle_ref_type h, const void* data, int len); \
|
||||
int usb_read(handle_ref_type h, void* data, int len); \
|
||||
int usb_close(handle_ref_type h); \
|
||||
void usb_reset(handle_ref_type h); \
|
||||
void usb_kick(handle_ref_type h); \
|
||||
size_t usb_get_max_packet_size(handle_ref_type)
|
||||
|
||||
|
|
Loading…
Reference in a new issue