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#pragma once
17
18#include <map>
19#include <memory>
20#include <string>
21#include <libusb/libusb.h>
22
23#include "common/libs/fs/shared_fd.h"
24#include "common/libs/threads/cuttlefish_thread.h"
25#include "guest/commands/usbforward/transport_request.h"
26
27namespace usb_forward {
28
29// USBServer exposes access to USB devices over pipe (virtio channel etc).
30// Usage:
31//
32//     cvd::SharedFD pipe = cvd::SharedFD::Open(pipe_path, O_RDWR);
33//     USBServer server(pipe);
34//     CHECK(server.Init());
35//     server.Serve();
36class USBServer final {
37 public:
38  USBServer(const cvd::SharedFD& fd);
39  ~USBServer() = default;
40
41  // Serve incoming USB requests.
42  void Serve();
43
44 private:
45  // HandleDeviceEvent opens and closes Android Gadget device, whenever it
46  // appears / disappears.
47  static int HandleDeviceEvent(libusb_context*, libusb_device*,
48                                libusb_hotplug_event event, void* self_raw);
49
50  // Handle CmdDeviceList request.
51  void HandleDeviceList(uint32_t tag);
52
53  // Handle CmdAttach request.
54  void HandleAttach(uint32_t tag);
55
56  // Handle CmdControlTransfer request.
57  void HandleControlTransfer(uint32_t tag);
58
59  // Handle CmdDataTransfer request.
60  void HandleDataTransfer(uint32_t tag);
61
62  // Handle CmdHeartbeat request.
63  void HandleHeartbeat(uint32_t tag);
64
65  // OnAsyncDataTransferComplete handles end of asynchronous data transfer cycle
66  // and sends response back to caller.
67  void OnTransferComplete(uint32_t tag, bool is_data_in, bool is_success,
68                          const uint8_t* buffer, int32_t actual_length);
69
70  // Initialize, Configure and start libusb.
71  void InitLibUSB();
72
73  // Stop, Deconfigure and Clean up libusb.
74  void ExitLibUSB();
75
76  // Extract device info, if device is available.
77  bool GetDeviceInfo(DeviceInfo* info, std::vector<InterfaceInfo>* ifaces);
78
79  // Handle asynchronous libusb events.
80  static void* ProcessLibUSBRequests(void* self_ptr);
81
82  std::shared_ptr<libusb_device_handle> handle_;
83  libusb_hotplug_callback_handle hotplug_handle_;
84
85  std::unique_ptr<cvd::ScopedThread> libusb_thread_;
86  cvd::Mutex write_mutex_;
87  cvd::SharedFD fd_;
88  cvd::SharedFD device_event_fd_;
89  cvd::SharedFD thread_event_fd_;
90
91  cvd::Mutex requests_mutex_;
92  std::map<uint32_t, std::unique_ptr<TransportRequest>> requests_in_flight_;
93
94  USBServer(const USBServer& other) = delete;
95  USBServer& operator=(const USBServer& other) = delete;
96};
97
98}  // namespace usb_forward
99