1 /* 2 * Copyright (C) 2025 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 17 #pragma once 18 19 #include "sysdeps.h" 20 #include "transport.h" 21 #include "types.h" 22 23 #include <stdint.h> 24 #include <optional> 25 #include <string> 26 27 #include "libusb/libusb.h" 28 29 // A session is started when a device is connected to a workstation. It ends upon its 30 // disconnection. For in-house hotplug, we generate a unique identifier based on the device 31 // invariants vendor, product (adb vs mtp...), the USB port, and the address (the location 32 // in the USB chain). On Windows, the address is always incremented, even if the same device 33 // is unplugged and plugged immediately. 34 union USBSessionID { 35 uint64_t id; 36 struct { 37 uint8_t address; 38 uint8_t port; 39 uint16_t product; 40 uint16_t vendor; 41 } fields; 42 }; 43 44 // Abstraction layer simplifying libusb_device management 45 struct LibUsbDevice { 46 public: 47 explicit LibUsbDevice(libusb_device* device); 48 ~LibUsbDevice(); 49 50 // Device must have been Opened prior to calling this method. 51 // This method blocks until a packet is available on the USB. 52 // Calling Close will make it return even if not packet was 53 // read. 54 bool Read(apacket* packet); 55 56 // Device must have been Opened prior to calling this method. 57 // This method blocks until the packet has been submitted to 58 // the USB. 59 bool Write(apacket* packet); 60 61 // Reset the device. This will cause the OS to issue a disconnect 62 // and the device will re-connect. 63 void Reset(); 64 65 uint64_t NegotiatedSpeedMbps(); 66 uint64_t MaxSpeedMbps(); 67 68 // Return the Android serial 69 std::string GetSerial(); 70 71 // Acquire all resources necessary for USB transfer. 72 bool Open(); 73 74 // Release all resources necessary for USB transfer. 75 bool Close(); 76 77 // Get the OS address (e.g.: usb:4.0.1) 78 std::string GetAddress() const; 79 80 // Call immediately after creating this object to check that the device can be interacted 81 // with (this also makes sure this is an Android device). 82 bool IsInitialized() const; 83 84 USBSessionID GetSessionId() const; 85 86 static USBSessionID GenerateSessionId(libusb_device* device); 87 88 private: 89 // Make sure device is and Android device, retrieve OS address, retrieve Android serial. 90 void Init(); 91 92 std::optional<libusb_device_descriptor> GetDeviceDescriptor(); 93 94 bool ClaimInterface(); 95 void ReleaseInterface(); 96 97 bool OpenDeviceHandle(); 98 void CloseDeviceHandle(); 99 100 void CloseDevice(); 101 std::string GetDeviceAddress(); 102 bool RetrieveSerial(); 103 void RetrieveSpeeds(); 104 105 bool FindAdbInterface(); 106 107 libusb_device* device_ = nullptr; 108 libusb_device_handle* device_handle_ = nullptr; 109 std::string device_address_{}; 110 std::string serial_{}; 111 112 // The mask used to determine if we should send a Zero Length Packet 113 int zlp_mask_{}; 114 int out_endpoint_size_{}; 115 116 int interface_num_ = 0; 117 unsigned char write_endpoint_{}; 118 unsigned char read_endpoint_{}; 119 std::atomic<bool> interface_claimed_ = false; 120 121 uint64_t negotiated_speed_{}; 122 uint64_t max_speed_{}; 123 124 bool initialized_ = false; 125 126 USBSessionID session_; 127 };