• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <algorithm>
17 #include <memory>
18 #include <gflags/gflags.h>
19 
20 #include "common/libs/fs/shared_select.h"
21 #include "host/commands/virtual_usb_manager/vadb/usb_cmd_attach.h"
22 #include "host/commands/virtual_usb_manager/vadb/usb_cmd_control_transfer.h"
23 #include "host/commands/virtual_usb_manager/vadb/usb_cmd_data_transfer.h"
24 #include "host/commands/virtual_usb_manager/vadb/usb_cmd_device_list.h"
25 #include "host/commands/virtual_usb_manager/vadb/usb_cmd_heartbeat.h"
26 #include "host/commands/virtual_usb_manager/vadb/virtual_adb_client.h"
27 
28 DEFINE_bool(debug_adb_client, false, "Turn on verbose logging in the virtual_adb_client.cpp");
29 
30 #define VLOG(X) if (FLAGS_debug_adb_client) LOG(VERBOSE)
31 
32 namespace vadb {
33 namespace {
34 constexpr int kHeartbeatTimeoutSeconds = 3;
35 }  // namespace
36 
VirtualADBClient(usbip::DevicePool * pool,cvd::SharedFD fd,int vhci_port,const std::string & usbip_socket_name)37 VirtualADBClient::VirtualADBClient(usbip::DevicePool* pool, cvd::SharedFD fd,
38                                    int vhci_port,
39                                    const std::string& usbip_socket_name)
40     : pool_{pool}, fd_{fd}, vhci_{vhci_port, usbip_socket_name} {
41   CHECK(vhci_.Init());
42   timer_ = cvd::SharedFD::TimerFD(CLOCK_MONOTONIC, 0);
43   SendHeartbeat();
44 }
45 
RegisterDevice(const usb_forward::DeviceInfo & dev,const std::vector<usb_forward::InterfaceInfo> & ifaces)46 void VirtualADBClient::RegisterDevice(
47     const usb_forward::DeviceInfo& dev,
48     const std::vector<usb_forward::InterfaceInfo>& ifaces) {
49   auto d = std::unique_ptr<usbip::Device>(new usbip::Device);
50   d->vendor_id = dev.vendor_id;
51   d->product_id = dev.product_id;
52   d->dev_version = dev.dev_version;
53   d->dev_class = dev.dev_class;
54   d->dev_subclass = dev.dev_subclass;
55   d->dev_protocol = dev.dev_protocol;
56   d->speed = dev.speed;
57   d->configurations_count = dev.num_configurations;
58   d->configuration_number = dev.cur_configuration;
59 
60   for (const auto& iface : ifaces) {
61     d->interfaces.push_back(usbip::Device::Interface{
62         iface.if_class, iface.if_subclass, iface.if_protocol});
63   }
64 
65   uint8_t bus_id = dev.bus_id;
66   uint8_t dev_id = dev.dev_id;
67 
68   d->handle_attach = [this, bus_id, dev_id]() -> bool {
69     return HandleAttach(bus_id, dev_id);
70   };
71 
72   d->handle_control_transfer =
73       [this, bus_id, dev_id](
74           const usbip::CmdRequest& r, uint32_t deadline,
75           std::vector<uint8_t> data,
76           usbip::Device::AsyncTransferReadyCB callback) -> bool {
77     return HandleDeviceControlRequest(bus_id, dev_id, r, deadline,
78                                       std::move(data), std::move(callback));
79   };
80 
81   d->handle_data_transfer =
82       [this, bus_id, dev_id](
83           uint8_t endpoint, bool is_host_to_device, uint32_t deadline,
84           std::vector<uint8_t> data,
85           usbip::Device::AsyncTransferReadyCB callback) -> bool {
86     return HandleDeviceDataRequest(bus_id, dev_id, endpoint, is_host_to_device,
87                                    deadline, std::move(data),
88                                    std::move(callback));
89   };
90 
91   pool_->AddDevice(usbip::DevicePool::BusDevNumber{bus_id, dev_id},
92                    std::move(d));
93 
94   // Attach this device.
95   HandleAttach(bus_id, dev_id);
96 }
97 
PopulateRemoteDevices()98 bool VirtualADBClient::PopulateRemoteDevices() {
99   return ExecuteCommand(std::unique_ptr<USBCommand>(new USBCmdDeviceList(
100       [this](const usb_forward::DeviceInfo& info,
101              const std::vector<usb_forward::InterfaceInfo>& ifaces) {
102         RegisterDevice(info, ifaces);
103       })));
104 }
105 
HandleDeviceControlRequest(uint8_t bus_id,uint8_t dev_id,const usbip::CmdRequest & r,uint32_t timeout,std::vector<uint8_t> data,usbip::Device::AsyncTransferReadyCB callback)106 bool VirtualADBClient::HandleDeviceControlRequest(
107     uint8_t bus_id, uint8_t dev_id, const usbip::CmdRequest& r,
108     uint32_t timeout, std::vector<uint8_t> data,
109     usbip::Device::AsyncTransferReadyCB callback) {
110   return ExecuteCommand(std::unique_ptr<USBCommand>(new USBCmdControlTransfer(
111       bus_id, dev_id, r.type, r.cmd, r.value, r.index, timeout, std::move(data),
112       std::move(callback))));
113 }
114 
HandleDeviceDataRequest(uint8_t bus_id,uint8_t dev_id,uint8_t endpoint,bool is_host_to_device,uint32_t deadline,std::vector<uint8_t> data,usbip::Device::AsyncTransferReadyCB callback)115 bool VirtualADBClient::HandleDeviceDataRequest(
116     uint8_t bus_id, uint8_t dev_id, uint8_t endpoint, bool is_host_to_device,
117     uint32_t deadline, std::vector<uint8_t> data,
118     usbip::Device::AsyncTransferReadyCB callback) {
119   return ExecuteCommand(std::unique_ptr<USBCommand>(
120       new USBCmdDataTransfer(bus_id, dev_id, endpoint, is_host_to_device,
121                              deadline, std::move(data), std::move(callback))));
122 }
123 
HandleAttach(uint8_t bus_id,uint8_t dev_id)124 bool VirtualADBClient::HandleAttach(uint8_t bus_id, uint8_t dev_id) {
125   return ExecuteCommand(
126       std::unique_ptr<USBCommand>(new USBCmdAttach(bus_id, dev_id)));
127 }
128 
SendHeartbeat()129 bool VirtualADBClient::SendHeartbeat() {
130   VLOG(1) << "Sending heartbeat...";
131   struct itimerspec spec {};
132   spec.it_value.tv_sec = kHeartbeatTimeoutSeconds;
133   timer_->TimerSet(0, &spec, nullptr);
134 
135   heartbeat_tag_ = tag_;
136 
137   return ExecuteCommand(std::unique_ptr<USBCommand>(
138       new USBCmdHeartbeat([this](bool success) { HandleHeartbeat(success); })));
139 }
140 
HandleHeartbeat(bool is_ready)141 void VirtualADBClient::HandleHeartbeat(bool is_ready) {
142   VLOG(1) << "Remote server status: " << is_ready;
143   if (is_ready && !is_remote_server_ready_) {
144     LOG(INFO) << "Remote server is now ready.";
145     PopulateRemoteDevices();
146     vhci_.TriggerAttach();
147   } else if (is_remote_server_ready_ && !is_ready) {
148     vhci_.TriggerDetach();
149     LOG(WARNING) << "Remote server connection lost.";
150     // It makes perfect sense to cancel all outstanding USB requests, as device
151     // is not going to answer any of these anyway.
152     for (const auto& pair : commands_) {
153       pair.second->OnResponse(false, fd_);
154     }
155     commands_.clear();
156   }
157   is_remote_server_ready_ = is_ready;
158 }
159 
HandleHeartbeatTimeout()160 bool VirtualADBClient::HandleHeartbeatTimeout() {
161   uint64_t timer_result;
162   timer_->Read(&timer_result, sizeof(timer_result));
163 
164   auto iter = commands_.find(heartbeat_tag_);
165   if (iter != commands_.end()) {
166     // Make sure to erase the value from list of commands prior to running
167     // callback. Particularly important for heartbeat, which cancels all
168     // outstanding USB commands (including self, if found), if device goes
169     // away (eg. reboots).
170     auto command = std::move(iter->second);
171     commands_.erase(iter);
172     command->OnResponse(false, fd_);
173   }
174 
175   return SendHeartbeat();
176 }
177 
ExecuteCommand(std::unique_ptr<USBCommand> cmd)178 bool VirtualADBClient::ExecuteCommand(std::unique_ptr<USBCommand> cmd) {
179   uint32_t this_tag = tag_;
180   tag_++;
181   usb_forward::RequestHeader hdr{cmd->Command(), this_tag};
182   if (fd_->Write(&hdr, sizeof(hdr)) != sizeof(hdr)) {
183     LOG(ERROR) << "Could not contact USB Forwarder: " << fd_->StrError();
184     return false;
185   }
186 
187   if (!cmd->OnRequest(fd_)) return false;
188 
189   commands_[this_tag] = std::move(cmd);
190   return true;
191 }
192 
193 // BeforeSelect is Called right before Select() to populate interesting
194 // SharedFDs.
BeforeSelect(cvd::SharedFDSet * fd_read) const195 void VirtualADBClient::BeforeSelect(cvd::SharedFDSet* fd_read) const {
196   fd_read->Set(fd_);
197   fd_read->Set(timer_);
198 }
199 
200 // AfterSelect is Called right after Select() to detect and respond to changes
201 // on affected SharedFDs.
202 // Return value indicates whether this client is still valid.
AfterSelect(const cvd::SharedFDSet & fd_read)203 bool VirtualADBClient::AfterSelect(const cvd::SharedFDSet& fd_read) {
204   if (fd_read.IsSet(timer_)) {
205     HandleHeartbeatTimeout();
206   }
207   if (fd_read.IsSet(fd_)) {
208     usb_forward::ResponseHeader rhdr;
209     if (fd_->Read(&rhdr, sizeof(rhdr)) != sizeof(rhdr)) {
210       LOG(ERROR) << "Could not read from USB Forwarder: " << fd_->StrError();
211       // TODO(ender): it is very likely the connection has been dropped by QEmu.
212       // Should we cancel all pending commands now?
213       return false;
214     }
215 
216     auto iter = commands_.find(rhdr.tag);
217     if (iter == commands_.end()) {
218       // This is likely a late heartbeat response, but could very well be any of
219       // the remaining commands.
220       LOG(INFO) << "Received response for discarded tag " << rhdr.tag;
221     } else {
222       // Make sure to erase the value from list of commands prior to running
223       // callback. Particularly important for heartbeat, which cancels all
224       // outstanding USB commands (including self, if found), if device goes
225       // away (eg. reboots).
226       auto command = std::move(iter->second);
227       commands_.erase(iter);
228       command->OnResponse(rhdr.status == usb_forward::StatusSuccess, fd_);
229     }
230   }
231 
232   return true;
233 }
234 
235 }  // namespace vadb
236