VirtualADB: allow usbip to reconnect
Change-Id: Iee81a81a3844f0b603d9d4cfc168007403ba9b6c
(cherry picked from commit 72270a9e2332bcfdec49e99cbd211ca6922541da)
diff --git a/vadb/BUILD b/vadb/BUILD
index 05d9b58..614630a 100644
--- a/vadb/BUILD
+++ b/vadb/BUILD
@@ -11,8 +11,6 @@
"usb_cmd_data_transfer.h",
"usb_cmd_device_list.cpp",
"usb_cmd_device_list.h",
- "vhci_instrument.cpp",
- "vhci_instrument.h",
"virtual_adb.cpp",
"virtual_adb.h",
],
diff --git a/vadb/main.cpp b/vadb/main.cpp
index be81f73..c981f17 100644
--- a/vadb/main.cpp
+++ b/vadb/main.cpp
@@ -20,7 +20,6 @@
#include "common/libs/fs/shared_fd.h"
#include "host/vadb/usbip/server.h"
-#include "host/vadb/vhci_instrument.h"
#include "host/vadb/virtual_adb.h"
DEFINE_string(socket, "", "Socket to use to talk to USBForwarder.");
@@ -33,9 +32,6 @@
vadb::VirtualADB adb(FLAGS_socket);
CHECK(adb.Init());
- vadb::VHCIInstrument vhci(FLAGS_usbip_socket_name);
- CHECK(vhci.Init());
-
vadb::usbip::Server s(FLAGS_usbip_socket_name, adb.Pool());
CHECK(s.Init()) << "Could not start server";
s.Serve();
diff --git a/vadb/usbip/BUILD b/vadb/usbip/BUILD
index 5f0bc66..dcbd6fc 100644
--- a/vadb/usbip/BUILD
+++ b/vadb/usbip/BUILD
@@ -10,6 +10,8 @@
"messages.h",
"server.cpp",
"server.h",
+ "vhci_instrument.cpp",
+ "vhci_instrument.h",
],
hdrs = [
"client.h",
diff --git a/vadb/usbip/server.cpp b/vadb/usbip/server.cpp
index 3c9cd00..c55eaf8 100644
--- a/vadb/usbip/server.cpp
+++ b/vadb/usbip/server.cpp
@@ -32,9 +32,9 @@
} // namespace
Server::Server(const std::string &name, const DevicePool &devices)
- : name_(name), device_pool_(devices) {}
+ : name_{name}, device_pool_{devices}, vhci_{name} {}
-bool Server::Init() { return CreateServerSocket(); }
+bool Server::Init() { return CreateServerSocket() && vhci_.Init(); }
// Open new listening server socket.
// Returns false, if listening socket could not be created.
@@ -68,6 +68,7 @@
// If client conversation failed, hang up.
if (!iter->HandleIncomingMessage()) {
iter = clients_.erase(iter);
+ vhci_.TriggerAttach();
continue;
}
}
diff --git a/vadb/usbip/server.h b/vadb/usbip/server.h
index 7bcb076..b3acafd 100644
--- a/vadb/usbip/server.h
+++ b/vadb/usbip/server.h
@@ -21,6 +21,7 @@
#include "common/libs/fs/shared_fd.h"
#include "host/vadb/usbip/device_pool.h"
#include "host/vadb/usbip/client.h"
+#include "host/vadb/usbip/vhci_instrument.h"
namespace vadb {
namespace usbip {
@@ -50,7 +51,9 @@
std::string name_;
avd::SharedFD server_;
std::list<Client> clients_;
+
const DevicePool& device_pool_;
+ VHCIInstrument vhci_;
Server(const Server&) = delete;
Server& operator=(const Server&) = delete;
diff --git a/vadb/vhci_instrument.cpp b/vadb/usbip/vhci_instrument.cpp
similarity index 82%
rename from vadb/vhci_instrument.cpp
rename to vadb/usbip/vhci_instrument.cpp
index 1e89fc3..9a2b8a2 100644
--- a/vadb/vhci_instrument.cpp
+++ b/vadb/usbip/vhci_instrument.cpp
@@ -21,11 +21,13 @@
#include <fstream>
#include <sstream>
#include <glog/logging.h>
+#include "common/libs/fs/shared_select.h"
#include "common/libs/fs/shared_fd.h"
#include "host/vadb/vhci_instrument.h"
namespace vadb {
+namespace usbip {
namespace {
// Device ID is specified as a concatenated pair of BUS and DEVICE id.
// Since we only export one device and our server doesn't care much about
@@ -54,6 +56,8 @@
name_(name) {}
bool VHCIInstrument::Init() {
+ wake_event_ = avd::SharedFD::Event(0, 0);
+
udev_.reset(udev_new());
CHECK(udev_) << "Could not create libudev context.";
@@ -107,12 +111,34 @@
return false;
}
+void VHCIInstrument::TriggerAttach() {
+ uint64_t count = 1;
+ wake_event_->Write(&count, sizeof(count));
+}
+
void VHCIInstrument::AttachThread() {
+ avd::SharedFDSet rset;
+ // If we're attempting connection, make sure to re-try every second until
+ // we're successful.
+ timeval period = {1, 0};
+ // Trigger attach upon start.
+ bool want_attach = true;
+
while (true) {
- sleep(3);
+ rset.Zero();
+ rset.Set(wake_event_);
+ // Wait until poked.
+ if (0 != avd::Select(&rset, nullptr, nullptr,
+ (want_attach ? &period : nullptr))) {
+ uint64_t ignore;
+ wake_event_->Read(&ignore, sizeof(ignore));
+ LOG(INFO) << "Attach triggered.";
+ want_attach = true;
+ }
+
+ // Make an attempt to re-attach. If successful, clear pending attach flag.
if (Attach()) {
- LOG(INFO) << "Attach successful.";
- break;
+ want_attach = false;
}
}
}
@@ -140,4 +166,5 @@
return attach.rdstate() == std::ios_base::goodbit;
}
+} // namespace usbip
} // namespace vadb
diff --git a/vadb/vhci_instrument.h b/vadb/usbip/vhci_instrument.h
similarity index 64%
rename from vadb/vhci_instrument.h
rename to vadb/usbip/vhci_instrument.h
index ea2a6da..107e140 100644
--- a/vadb/vhci_instrument.h
+++ b/vadb/usbip/vhci_instrument.h
@@ -21,15 +21,33 @@
#include <libudev.h>
+#include "common/libs/fs/shared_fd.h"
+
namespace vadb {
+namespace usbip {
+// VHCIInstrument class configures VHCI-HCD on local kernel.
class VHCIInstrument {
public:
VHCIInstrument(const std::string& name);
virtual ~VHCIInstrument() = default;
+ // Init opens vhci-hcd driver and allocates port to which remote USB device
+ // will be attached.
+ // Returns false, if vhci-hcd driver could not be opened, or if no free port
+ // was found.
bool Init();
+ // TriggerAttach tells underlying thread to make attempt to re-attach USB
+ // device.
+ void TriggerAttach();
+
+ private:
+ // Attach makes an attempt to configure VHCI to enable virtual USB device.
+ // Returns true, if configuration attempt was successful.
bool Attach();
+
+ // AttachThread is a background thread that responds to configuration
+ // requests.
void AttachThread();
bool FindFreePort();
@@ -39,9 +57,11 @@
std::string name_;
std::unique_ptr<std::thread> attach_thread_;
std::string syspath_;
+ avd::SharedFD wake_event_;
int port_;
VHCIInstrument(const VHCIInstrument& other) = delete;
VHCIInstrument& operator=(const VHCIInstrument& other) = delete;
};
+} // namespace usbip
} // namespace vadb
diff --git a/vadb/virtual_adb.h b/vadb/virtual_adb.h
index edbee8d..76a6f31 100644
--- a/vadb/virtual_adb.h
+++ b/vadb/virtual_adb.h
@@ -25,7 +25,6 @@
#include "host/vadb/usbip/device.h"
#include "host/vadb/usbip/device_pool.h"
#include "host/vadb/usbip/messages.h"
-#include "host/vadb/vhci_instrument.h"
namespace vadb {
// VirtualADB is a companion class for USBForwarder, running on Cuttlefish.