• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 };