diff --git a/adb/adb.cpp b/adb/adb.cpp index 29d6e6597..8b6b2b5ed 100644 --- a/adb/adb.cpp +++ b/adb/adb.cpp @@ -1089,6 +1089,31 @@ int handle_host_request(const char* service, TransportType type, return 1; } + if (!strcmp(service, "reconnect-offline")) { + std::string response; + close_usb_devices([&response](const atransport* transport) { + switch (transport->connection_state) { + case kCsOffline: + case kCsUnauthorized: + response += "reconnecting "; + if (transport->serial) { + response += transport->serial; + } else { + response += ""; + } + response += "\n"; + return true; + default: + return false; + } + }); + if (!response.empty()) { + response.resize(response.size() - 1); + } + SendOkay(reply_fd, response); + return 0; + } + if (!strcmp(service, "features")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); diff --git a/adb/commandline.cpp b/adb/commandline.cpp index 1f03c1ac9..e15bcad8f 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -1950,10 +1950,17 @@ int adb_commandline(int argc, const char** argv) { } else if (!strcmp(argv[0], "reconnect")) { if (argc == 1) { return adb_query_command("host:reconnect"); - } else if (argc == 2 && !strcmp(argv[1], "device")) { - std::string err; - adb_connect("reconnect", &err); - return 0; + } else if (argc == 2) { + if (!strcmp(argv[1], "device")) { + std::string err; + adb_connect("reconnect", &err); + return 0; + } else if (!strcmp(argv[1], "offline")) { + std::string err; + return adb_query_command("host:reconnect-offline"); + } else { + return usage(); + } } } diff --git a/adb/sockets.cpp b/adb/sockets.cpp index 3a5717488..c05903f9e 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -791,11 +791,14 @@ static int smart_socket_enqueue(asocket* s, apacket* p) { } #endif - if (!(s->transport) || (s->transport->connection_state == kCsOffline)) { + if (!s->transport) { + SendFail(s->peer->fd, "device offline (no transport)"); + goto fail; + } else if (s->transport->connection_state == kCsOffline) { /* if there's no remote we fail the connection ** right here and terminate it */ - SendFail(s->peer->fd, "device offline (x)"); + SendFail(s->peer->fd, "device offline (transport offline)"); goto fail; } diff --git a/adb/transport.cpp b/adb/transport.cpp index 7b4bb1c75..132702d31 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -908,12 +908,18 @@ std::string list_transports(bool long_listing) { return result; } +void close_usb_devices(std::function predicate) { + std::lock_guard lock(transport_lock); + for (auto& t : transport_list) { + if (predicate(t)) { + t->Kick(); + } + } +} + /* hack for osx */ void close_usb_devices() { - std::lock_guard lock(transport_lock); - for (const auto& t : transport_list) { - t->Kick(); - } + close_usb_devices([](const atransport*) { return true; }); } #endif // ADB_HOST diff --git a/adb/transport.h b/adb/transport.h index 621516cdc..b2df838b6 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -199,8 +200,8 @@ void unregister_usb_transport(usb_handle* usb); int check_header(apacket* p, atransport* t); int check_data(apacket* p); -/* for MacOS X cleanup */ void close_usb_devices(); +void close_usb_devices(std::function predicate); void send_packet(apacket* p, atransport* t);