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 <cutils/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 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 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 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 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 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 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 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 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 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 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 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 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 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 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