Home | History | Annotate | Download | only in usbforward
      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