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 // #undef NDEBUG
17
18 #include "guest/commands/usbforward/usb_server.h"
19
20 #include <string>
21 #include <vector>
22 #include <strings.h>
23 #include <log/log.h>
24 #include <libusb/libusb.h>
25 #include "common/libs/fs/shared_select.h"
26 #include "common/libs/usbforward/protocol.h"
27 #include "guest/commands/usbforward/transport_request.h"
28
29 namespace usb_forward {
30 namespace {
31 // USBServer exports device kExportedVendorID:kExportedProductID to the server.
32 // We will not support exporting multiple USB devices as there's no practical
33 // need for this.
34 constexpr uint16_t kExportedVendorID = 0x18d1;
35 constexpr uint16_t kExportedProductID = 0x4ee7;
36
37 // Use default BUS and DEVICE IDs so that it's easier to attach over USB/IP.
38 constexpr uint8_t kDefaultBusID = 1;
39 constexpr uint8_t kDefaultDevID = 1;
40
GetDevice()41 std::shared_ptr<libusb_device_handle> GetDevice() {
42 std::shared_ptr<libusb_device_handle> res(
43 libusb_open_device_with_vid_pid(nullptr, kExportedVendorID,
44 kExportedProductID),
45 [](libusb_device_handle* h) {
46 // Apparently, deleter is called even on an uninitialized shared_ptr.
47 if (h != nullptr) {
48 libusb_release_interface(h, 0);
49 libusb_close(h);
50 }
51 });
52
53 if (res) libusb_claim_interface(res.get(), 0);
54
55 return res;
56 }
57
58 } // anonymous namespace
59
GetDeviceInfo(DeviceInfo * info,std::vector<InterfaceInfo> * ifaces)60 bool USBServer::GetDeviceInfo(
61 DeviceInfo* info, std::vector<InterfaceInfo>* ifaces) {
62 if (!handle_) return false;
63
64 // This function does not modify the reference count of the returned device,
65 // so do not feel compelled to unreference it when you are done.
66 libusb_device* dev = libusb_get_device(handle_.get());
67
68 libusb_device_descriptor desc;
69 libusb_config_descriptor* conf;
70 memset(info, 0, sizeof(*info));
71
72 int res = libusb_get_device_descriptor(dev, &desc);
73 if (res < 0) {
74 // This shouldn't really happen.
75 ALOGE("libusb_get_device_descriptor failed %d", res);
76 return false;
77 }
78
79 res = libusb_get_active_config_descriptor(dev, &conf);
80 if (res < 0) {
81 // This shouldn't really happen.
82 ALOGE("libusb_get_active_config_descriptor failed %d", res);
83 libusb_free_config_descriptor(conf);
84 return false;
85 }
86
87 info->vendor_id = desc.idVendor;
88 info->product_id = desc.idProduct;
89 info->dev_version = desc.bcdDevice;
90 info->dev_class = desc.bDeviceClass;
91 info->dev_subclass = desc.bDeviceSubClass;
92 info->dev_protocol = desc.bDeviceProtocol;
93 info->speed = libusb_get_device_speed(dev);
94 info->num_configurations = desc.bNumConfigurations;
95 info->num_interfaces = conf->bNumInterfaces;
96 info->cur_configuration = conf->bConfigurationValue;
97 info->bus_id = kDefaultBusID;
98 info->dev_id = kDefaultDevID;
99
100 if (ifaces != nullptr) {
101 for (int ifidx = 0; ifidx < conf->bNumInterfaces; ++ifidx) {
102 const libusb_interface& iface = conf->interface[ifidx];
103 for (int altidx = 0; altidx < iface.num_altsetting; ++altidx) {
104 const libusb_interface_descriptor& alt = iface.altsetting[altidx];
105 ifaces->push_back(InterfaceInfo{alt.bInterfaceClass,
106 alt.bInterfaceSubClass,
107 alt.bInterfaceProtocol, 0});
108 }
109 }
110 }
111 libusb_free_config_descriptor(conf);
112 return true;
113 }
114
USBServer(const cvd::SharedFD & fd)115 USBServer::USBServer(const cvd::SharedFD& fd)
116 : fd_{fd},
117 device_event_fd_{cvd::SharedFD::Event(0, 0)},
118 thread_event_fd_{cvd::SharedFD::Event(0, 0)} {}
119
HandleDeviceList(uint32_t tag)120 void USBServer::HandleDeviceList(uint32_t tag) {
121 // Iterate all devices and send structure for every found device.
122 // Write header: number of devices.
123 DeviceInfo info;
124 std::vector<InterfaceInfo> ifaces;
125 bool found = GetDeviceInfo(&info, &ifaces);
126
127 cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
128 ResponseHeader rsp{StatusSuccess, tag};
129 fd_->Write(&rsp, sizeof(rsp));
130 if (found) {
131 uint32_t cnt = 1;
132 fd_->Write(&cnt, sizeof(cnt));
133 fd_->Write(&info, sizeof(info));
134 fd_->Write(ifaces.data(), ifaces.size() * sizeof(InterfaceInfo));
135 } else {
136 // No devices.
137 uint32_t cnt = 0;
138 fd_->Write(&cnt, sizeof(cnt));
139 }
140 }
141
HandleAttach(uint32_t tag)142 void USBServer::HandleAttach(uint32_t tag) {
143 // We read the request, but it no longer plays any significant role here.
144 AttachRequest req;
145 if (fd_->Read(&req, sizeof(req)) != sizeof(req)) return;
146
147 cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
148 ResponseHeader rsp{handle_ ? StatusSuccess : StatusFailure, tag};
149 fd_->Write(&rsp, sizeof(rsp));
150 }
151
HandleHeartbeat(uint32_t tag)152 void USBServer::HandleHeartbeat(uint32_t tag) {
153 cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
154 ResponseHeader rsp{handle_ ? StatusSuccess : StatusFailure, tag};
155 fd_->Write(&rsp, sizeof(rsp));
156 }
157
HandleControlTransfer(uint32_t tag)158 void USBServer::HandleControlTransfer(uint32_t tag) {
159 ControlTransfer req;
160 // If disconnected prematurely, don't send response.
161 if (fd_->Read(&req, sizeof(req)) != sizeof(req)) return;
162
163 // Technically speaking this isn't endpoint, but names, masks, values and
164 // meaning here is exactly same.
165 bool is_data_in =
166 ((req.type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN);
167
168 std::unique_ptr<TransportRequest> treq(new TransportRequest(
169 handle_,
170 [this, is_data_in, tag](bool is_success, const uint8_t* data,
171 int32_t length) {
172 OnTransferComplete(tag, is_data_in, is_success, data, length);
173 },
174 req));
175
176 if (!is_data_in && req.length) {
177 // If disconnected prematurely, don't send response.
178 int32_t got = 0;
179 while (got < req.length) {
180 auto read = fd_->Read(&treq->Buffer()[got], req.length - got);
181 if (fd_->GetErrno() != 0) {
182 ALOGE("Failed to read from client: %s", fd_->StrError());
183 return;
184 } else if (read == 0) {
185 ALOGE("Failed to read from client: short read");
186 return;
187 }
188 got += read;
189 }
190 }
191
192 // At this point we store transport request internally until it completes.
193 TransportRequest* treq_ptr = treq.get();
194 {
195 cvd::LockGuard<cvd::Mutex> lock(requests_mutex_);
196 requests_in_flight_[tag] = std::move(treq);
197 }
198
199 if (!treq_ptr->Submit()) {
200 OnTransferComplete(tag, is_data_in, false, nullptr, 0);
201 }
202 }
203
HandleDataTransfer(uint32_t tag)204 void USBServer::HandleDataTransfer(uint32_t tag) {
205 DataTransfer req;
206 // If disconnected prematurely, don't send response.
207 if (fd_->Read(&req, sizeof(req)) != sizeof(req)) return;
208
209 bool is_data_in = !req.is_host_to_device;
210
211 std::unique_ptr<TransportRequest> treq(new TransportRequest(
212 handle_,
213 [this, is_data_in, tag](bool is_success, const uint8_t* data,
214 int32_t length) {
215 OnTransferComplete(tag, is_data_in, is_success, data, length);
216 },
217 req));
218
219 if (!is_data_in && req.length) {
220 // If disconnected prematurely, don't send response.
221 int32_t got = 0;
222 while (got < req.length) {
223 auto read = fd_->Read(&treq->Buffer()[got], req.length - got);
224 if (fd_->GetErrno() != 0) {
225 ALOGE("Failed to read from client: %s", fd_->StrError());
226 return;
227 } else if (read == 0) {
228 ALOGE("Failed to read from client: short read");
229 return;
230 }
231 got += read;
232 }
233 }
234
235 // At this point we store transport request internally until it completes.
236 TransportRequest* treq_ptr = treq.get();
237 {
238 cvd::LockGuard<cvd::Mutex> lock(requests_mutex_);
239 requests_in_flight_[tag] = std::move(treq);
240 }
241
242 if (!treq_ptr->Submit()) {
243 OnTransferComplete(tag, is_data_in, false, nullptr, 0);
244 }
245 }
246
OnTransferComplete(uint32_t tag,bool is_data_in,bool is_success,const uint8_t * buffer,int32_t actual_length)247 void USBServer::OnTransferComplete(uint32_t tag, bool is_data_in,
248 bool is_success, const uint8_t* buffer,
249 int32_t actual_length) {
250 ResponseHeader rsp{is_success ? StatusSuccess : StatusFailure, tag};
251
252 cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
253 fd_->Write(&rsp, sizeof(rsp));
254 if (is_success && is_data_in) {
255 fd_->Write(&actual_length, sizeof(actual_length));
256 if (actual_length > 0) {
257 // NOTE: don't use buffer_ here directly, as libusb uses first few bytes
258 // to store control data there.
259 int32_t sent = 0;
260 while (sent < actual_length) {
261 int packet_size = fd_->Write(&buffer[sent], actual_length - sent);
262 sent += packet_size;
263 ALOGV("Sending response, %d / %d bytes sent", sent, actual_length);
264 if (fd_->GetErrno() != 0) {
265 ALOGE("Send failed: %s", fd_->StrError());
266 return;
267 }
268 }
269 }
270 }
271
272 {
273 cvd::LockGuard<cvd::Mutex> lock(requests_mutex_);
274 requests_in_flight_.erase(tag);
275 }
276 }
277
HandleDeviceEvent(libusb_context *,libusb_device *,libusb_hotplug_event event,void * self_raw)278 int USBServer::HandleDeviceEvent(libusb_context*, libusb_device*,
279 libusb_hotplug_event event, void* self_raw) {
280 auto self = reinterpret_cast<USBServer*>(self_raw);
281 int64_t dummy = 1;
282 self->device_event_fd_->Write(&dummy, sizeof(dummy));
283 return 0;
284 }
285
ProcessLibUSBRequests(void * self_raw)286 void* USBServer::ProcessLibUSBRequests(void* self_raw) {
287 USBServer* self = reinterpret_cast<USBServer*>(self_raw);
288 ALOGI("Starting hotplug thread.");
289
290 cvd::SharedFDSet rset;
291 while (true) {
292 // Do not wait if there's no event.
293 timeval select_timeout{0, 0};
294 rset.Zero();
295 rset.Set(self->thread_event_fd_);
296 int ret = cvd::Select(&rset, nullptr, nullptr, &select_timeout);
297 if (ret > 0) break;
298
299 timeval libusb_timeout{1, 0};
300 libusb_handle_events_timeout_completed(nullptr, &libusb_timeout, nullptr);
301 }
302
303 int64_t dummy;
304 self->thread_event_fd_->Read(&dummy, sizeof(dummy));
305 ALOGI("Shutting down hotplug thread.");
306 return nullptr;
307 }
308
InitLibUSB()309 void USBServer::InitLibUSB() {
310 if (libusb_init(nullptr) != 0) return;
311 libusb_hotplug_register_callback(
312 nullptr,
313 libusb_hotplug_event(LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
314 libusb_hotplug_flag(0), kExportedVendorID, kExportedProductID,
315 LIBUSB_HOTPLUG_MATCH_ANY, &USBServer::HandleDeviceEvent, this,
316 &hotplug_handle_);
317 handle_ = GetDevice();
318 libusb_thread_.reset(new cvd::ScopedThread(&ProcessLibUSBRequests, this));
319 }
320
ExitLibUSB()321 void USBServer::ExitLibUSB() {
322 if (!libusb_thread_) return;
323 libusb_hotplug_deregister_callback(nullptr, hotplug_handle_);
324 int64_t dummy = 1;
325 thread_event_fd_->Write(&dummy, sizeof(dummy));
326 libusb_thread_.reset();
327 handle_.reset();
328 libusb_exit(nullptr);
329 }
330
Serve()331 void USBServer::Serve() {
332 cvd::SharedFDSet rset;
333 while (true) {
334 timeval retry_timeout{1, 0};
335 timeval* select_timeout = nullptr;
336 if (!handle_) {
337 select_timeout = &retry_timeout;
338 }
339
340 rset.Zero();
341 rset.Set(fd_);
342 rset.Set(device_event_fd_);
343 int ret = cvd::Select(&rset, nullptr, nullptr, select_timeout);
344
345 // device_event_fd_ is reset each time libusb notices device has re-appeared
346 // or is gone. In both cases, the existing handle is no longer valid.
347 if (rset.IsSet(device_event_fd_)) {
348 int64_t dummy;
349 device_event_fd_->Read(&dummy, sizeof(dummy));
350 handle_.reset();
351 }
352
353 if (!handle_) {
354 ExitLibUSB();
355 InitLibUSB();
356 if (handle_) {
357 ALOGI("Device present.");
358 }
359 }
360
361 if (ret < 0) continue;
362
363 if (rset.IsSet(fd_)) {
364 RequestHeader req;
365 if (fd_->Read(&req, sizeof(req)) != sizeof(req)) {
366 // There's nobody on the other side.
367 sleep(3);
368 continue;
369 }
370
371 switch (req.command) {
372 case CmdDeviceList:
373 ALOGV("Processing DeviceList command, tag=%d", req.tag);
374 HandleDeviceList(req.tag);
375 break;
376
377 case CmdAttach:
378 ALOGV("Processing Attach command, tag=%d", req.tag);
379 HandleAttach(req.tag);
380 break;
381
382 case CmdControlTransfer:
383 ALOGV("Processing ControlTransfer command, tag=%d", req.tag);
384 HandleControlTransfer(req.tag);
385 break;
386
387 case CmdDataTransfer:
388 ALOGV("Processing DataTransfer command, tag=%d", req.tag);
389 HandleDataTransfer(req.tag);
390 break;
391
392 case CmdHeartbeat:
393 ALOGV("Processing Heartbeat command, tag=%d", req.tag);
394 HandleHeartbeat(req.tag);
395 break;
396
397 default:
398 ALOGE("Discarding unknown command %08x, tag=%d", req.command,
399 req.tag);
400 }
401 }
402 }
403 }
404
405 } // namespace usb_forward
406