C++程序  |  99行  |  2.97 KB

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <map>
#include <memory>
#include <string>
#include <libusb/libusb.h>

#include "common/libs/fs/shared_fd.h"
#include "common/libs/threads/cuttlefish_thread.h"
#include "guest/commands/usbforward/transport_request.h"

namespace usb_forward {

// USBServer exposes access to USB devices over pipe (virtio channel etc).
// Usage:
//
//     cvd::SharedFD pipe = cvd::SharedFD::Open(pipe_path, O_RDWR);
//     USBServer server(pipe);
//     CHECK(server.Init());
//     server.Serve();
class USBServer final {
 public:
  USBServer(const cvd::SharedFD& fd);
  ~USBServer() = default;

  // Serve incoming USB requests.
  void Serve();

 private:
  // HandleDeviceEvent opens and closes Android Gadget device, whenever it
  // appears / disappears.
  static int HandleDeviceEvent(libusb_context*, libusb_device*,
                                libusb_hotplug_event event, void* self_raw);

  // Handle CmdDeviceList request.
  void HandleDeviceList(uint32_t tag);

  // Handle CmdAttach request.
  void HandleAttach(uint32_t tag);

  // Handle CmdControlTransfer request.
  void HandleControlTransfer(uint32_t tag);

  // Handle CmdDataTransfer request.
  void HandleDataTransfer(uint32_t tag);

  // Handle CmdHeartbeat request.
  void HandleHeartbeat(uint32_t tag);

  // OnAsyncDataTransferComplete handles end of asynchronous data transfer cycle
  // and sends response back to caller.
  void OnTransferComplete(uint32_t tag, bool is_data_in, bool is_success,
                          const uint8_t* buffer, int32_t actual_length);

  // Initialize, Configure and start libusb.
  void InitLibUSB();

  // Stop, Deconfigure and Clean up libusb.
  void ExitLibUSB();

  // Extract device info, if device is available.
  bool GetDeviceInfo(DeviceInfo* info, std::vector<InterfaceInfo>* ifaces);

  // Handle asynchronous libusb events.
  static void* ProcessLibUSBRequests(void* self_ptr);

  std::shared_ptr<libusb_device_handle> handle_;
  libusb_hotplug_callback_handle hotplug_handle_;

  std::unique_ptr<cvd::ScopedThread> libusb_thread_;
  cvd::Mutex write_mutex_;
  cvd::SharedFD fd_;
  cvd::SharedFD device_event_fd_;
  cvd::SharedFD thread_event_fd_;

  cvd::Mutex requests_mutex_;
  std::map<uint32_t, std::unique_ptr<TransportRequest>> requests_in_flight_;

  USBServer(const USBServer& other) = delete;
  USBServer& operator=(const USBServer& other) = delete;
};

}  // namespace usb_forward