• 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 #include "usb_libusb_device.h"
18 
19 #include <stdint.h>
20 #include <stdlib.h>
21 
22 #include <atomic>
23 #include <chrono>
24 #include <condition_variable>
25 #include <format>
26 #include <memory>
27 #include <mutex>
28 #include <thread>
29 #include <unordered_map>
30 #include <vector>
31 
32 #include <libusb/libusb.h>
33 
34 #include <android-base/file.h>
35 #include <android-base/logging.h>
36 #include <android-base/stringprintf.h>
37 #include <android-base/strings.h>
38 #include <android-base/thread_annotations.h>
39 
40 #include "adb.h"
41 #include "adb_trace.h"
42 #include "adb_utils.h"
43 #include "fdevent/fdevent.h"
44 #include "transport.h"
45 #include "usb.h"
46 
47 using namespace std::chrono_literals;
48 
49 using android::base::ScopedLockAssertion;
50 using android::base::StringPrintf;
51 
endpoint_is_output(uint8_t endpoint)52 static bool endpoint_is_output(uint8_t endpoint) {
53     return (endpoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT;
54 }
55 
LibUsbDevice(libusb_device * device)56 LibUsbDevice::LibUsbDevice(libusb_device* device)
57     : device_(device), device_address_(GetDeviceAddress()) {
58     libusb_ref_device(device);
59     Init();
60 }
61 
~LibUsbDevice()62 LibUsbDevice::~LibUsbDevice() {
63     ReleaseInterface();
64     CloseDeviceHandle();
65     CloseDevice();
66 }
67 
IsInitialized() const68 bool LibUsbDevice::IsInitialized() const {
69     return initialized_;
70 }
71 
Init()72 void LibUsbDevice::Init() {
73     initialized_ = OpenDeviceHandle();
74     session_ = GenerateSessionId(device_);
75 }
76 
ReleaseInterface()77 void LibUsbDevice::ReleaseInterface() {
78     if (interface_claimed_) {
79         libusb_release_interface(device_handle_, interface_num_);
80         interface_claimed_ = false;
81     }
82 }
83 
CloseDeviceHandle()84 void LibUsbDevice::CloseDeviceHandle() {
85     if (device_handle_ != nullptr) {
86         libusb_close(device_handle_);
87         device_handle_ = nullptr;
88     }
89 }
90 
CloseDevice()91 void LibUsbDevice::CloseDevice() {
92     if (device_ != nullptr) {
93         libusb_unref_device(device_);
94         device_ = nullptr;
95     }
96 }
97 
Write(apacket * packet)98 bool LibUsbDevice::Write(apacket* packet) {
99     VLOG(USB) << "Write " << command_to_string(packet->msg.command)
100               << " payload=" << packet->msg.data_length;
101     int transferred;
102     int data_size = sizeof(packet->msg);
103     auto r = libusb_bulk_transfer(device_handle_, write_endpoint_, (unsigned char*)&packet->msg,
104                                   data_size, &transferred, 0);
105     if ((r != 0) || (transferred != data_size)) {
106         VLOG(USB) << "LibUsbDevice::Write failed at header " << libusb_error_name(r);
107         return false;
108     }
109 
110     data_size = packet->payload.size();
111     if (data_size == 0) {
112         return true;
113     }
114     r = libusb_bulk_transfer(device_handle_, write_endpoint_,
115                              (unsigned char*)packet->payload.data(), data_size, &transferred, 0);
116     if ((r != 0) || (transferred != data_size)) {
117         VLOG(USB) << "LibUsbDevice::Write failed at payload " << libusb_error_name(r);
118         return false;
119     }
120 
121     if ((data_size & zlp_mask_) == 0) {
122         VLOG(USB) << "Sending zlp (payload_size=" << data_size
123                   << ", endpoint_size=" << out_endpoint_size_
124                   << ", modulo=" << data_size % out_endpoint_size_ << ")";
125         libusb_bulk_transfer(device_handle_, write_endpoint_,
126                              (unsigned char*)packet->payload.data(), 0, &transferred, 0);
127     }
128 
129     return true;
130 }
131 
Read(apacket * packet)132 bool LibUsbDevice::Read(apacket* packet) {
133     VLOG(USB) << "LibUsbDevice Read()";
134     int transferred;
135     int data_size = sizeof(packet->msg);
136     auto r = libusb_bulk_transfer(device_handle_, read_endpoint_, (unsigned char*)&packet->msg,
137                                   data_size, &transferred, 0);
138     if ((r != 0) || (transferred != data_size)) {
139         VLOG(USB) << "LibUsbDevice::READ failed at header " << libusb_error_name(r);
140         return false;
141     }
142     VLOG(USB) << "Read " << command_to_string(packet->msg.command)
143               << " header, now expecting=" << packet->msg.data_length;
144     if (packet->msg.data_length == 0) {
145         packet->payload.resize(0);
146         return true;
147     }
148 
149     packet->payload.resize(packet->msg.data_length);
150     data_size = packet->msg.data_length;
151     r = libusb_bulk_transfer(device_handle_, read_endpoint_, (unsigned char*)packet->payload.data(),
152                              data_size, &transferred, 0);
153     if ((r != 0) || (transferred != data_size)) {
154         VLOG(USB) << "LibUsbDevice::READ failed at payload << " << libusb_error_name(r);
155         return false;
156     }
157     VLOG(USB) << "Read " << command_to_string(packet->msg.command) << " got =" << transferred;
158 
159     return true;
160 }
161 
Reset()162 void LibUsbDevice::Reset() {
163     if (device_handle_ == nullptr) {
164         return;
165     }
166     int rc = libusb_reset_device(device_handle_);
167     if (rc != 0) {
168         LOG(ERROR) << "libusb_reset_device failed: " << libusb_error_name(rc);
169     }
170 }
171 
GetDeviceAddress()172 std::string LibUsbDevice::GetDeviceAddress() {
173     uint8_t ports[7];
174     int port_count = libusb_get_port_numbers(device_, ports, 7);
175     if (port_count < 0) return "";
176 
177     std::string address =
178             android::base::StringPrintf("%d-%d", libusb_get_bus_number(device_), ports[0]);
179     for (int port = 1; port < port_count; ++port) {
180         address += android::base::StringPrintf(".%d", ports[port]);
181     }
182 
183     return address;
184 }
185 
GetDeviceDescriptor()186 std::optional<libusb_device_descriptor> LibUsbDevice::GetDeviceDescriptor() {
187     libusb_device_descriptor device_desc;
188     int rc = libusb_get_device_descriptor(device_, &device_desc);
189     if (rc != 0) {
190         LOG(WARNING) << "failed to get device descriptor for device :" << libusb_error_name(rc);
191         return {};
192     }
193     return device_desc;
194 }
195 
GetSerial()196 std::string LibUsbDevice::GetSerial() {
197     return serial_;
198 }
199 
FindAdbInterface()200 bool LibUsbDevice::FindAdbInterface() {
201     std::optional<libusb_device_descriptor> device_desc = GetDeviceDescriptor();
202     if (!device_desc.has_value()) {
203         return false;
204     }
205 
206     if (device_desc->bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) {
207         // Assume that all Android devices have the device class set to per interface.
208         // TODO: Is this assumption valid?
209         VLOG(USB) << "skipping device with incorrect class at " << device_address_;
210         return false;
211     }
212 
213     libusb_config_descriptor* config;
214     int rc = libusb_get_active_config_descriptor(device_, &config);
215     if (rc != 0) {
216         LOG(WARNING) << "failed to get active config descriptor for device at " << device_address_
217                      << ": " << libusb_error_name(rc);
218         return false;
219     }
220 
221     // Use size_t for interface_num so <iostream>s don't mangle it.
222     size_t interface_num;
223     uint8_t bulk_in = 0, bulk_out = 0;
224     size_t packet_size = 0;
225     bool found_adb = false;
226 
227     for (interface_num = 0; interface_num < config->bNumInterfaces; ++interface_num) {
228         const libusb_interface& interface = config->interface[interface_num];
229 
230         if (interface.num_altsetting == 0) {
231             continue;
232         }
233 
234         const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
235         if (!is_adb_interface(interface_desc.bInterfaceClass, interface_desc.bInterfaceSubClass,
236                               interface_desc.bInterfaceProtocol)) {
237             VLOG(USB) << "skipping non-adb interface at " << device_address_ << " (interface "
238                       << interface_num << ")";
239             continue;
240         }
241 
242         VLOG(USB) << "found potential adb interface at " << device_address_ << " (interface "
243                   << interface_num << ")";
244 
245         bool found_in = false;
246         bool found_out = false;
247         for (size_t endpoint_num = 0; endpoint_num < interface_desc.bNumEndpoints; ++endpoint_num) {
248             const auto& endpoint_desc = interface_desc.endpoint[endpoint_num];
249             const uint8_t endpoint_addr = endpoint_desc.bEndpointAddress;
250             const uint8_t endpoint_attr = endpoint_desc.bmAttributes;
251             VLOG(USB) << "Scanning endpoint=" << endpoint_num
252                       << ", addr=" << std::format("{:#02x}", endpoint_addr)
253                       << ", attr=" << std::format("{:#02x}", endpoint_attr);
254 
255             const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;
256 
257             if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
258                 continue;
259             }
260 
261             if (endpoint_is_output(endpoint_addr) && !found_out) {
262                 found_out = true;
263                 out_endpoint_size_ = endpoint_desc.wMaxPacketSize;
264                 VLOG(USB) << "Device " << GetSerial()
265                           << " uses wMaxPacketSize=" << out_endpoint_size_;
266                 zlp_mask_ = out_endpoint_size_ - 1;
267                 bulk_out = endpoint_addr;
268             } else if (!endpoint_is_output(endpoint_addr) && !found_in) {
269                 found_in = true;
270                 bulk_in = endpoint_addr;
271             }
272 
273             size_t endpoint_packet_size = endpoint_desc.wMaxPacketSize;
274             CHECK(endpoint_packet_size != 0);
275             if (packet_size == 0) {
276                 packet_size = endpoint_packet_size;
277             } else {
278                 CHECK(packet_size == endpoint_packet_size);
279             }
280         }
281 
282         if (found_in && found_out) {
283             found_adb = true;
284             break;
285         } else {
286             VLOG(USB) << "rejecting potential adb interface at " << device_address_ << "(interface "
287                       << interface_num << "): missing bulk endpoints "
288                       << "(found_in = " << found_in << ", found_out = " << found_out << ")";
289         }
290     }
291 
292     libusb_free_config_descriptor(config);
293 
294     if (!found_adb) {
295         VLOG(USB) << "ADB interface missing endpoints: bulk_out=" << bulk_out
296                   << " and bulk_in=" << bulk_in;
297         return false;
298     }
299 
300     interface_num_ = interface_num;
301     write_endpoint_ = bulk_out;
302     read_endpoint_ = bulk_in;
303 
304     VLOG(USB) << "Found ADB interface=" << interface_num_
305               << " bulk_in=" << std::format("{:#02x}", bulk_in)
306               << " bulk_out=" << std::format("{:#02x}", bulk_out);
307     return true;
308 }
309 
GetAddress() const310 std::string LibUsbDevice::GetAddress() const {
311     return std::string("usb:") + device_address_;
312 }
313 
RetrieveSerial()314 bool LibUsbDevice::RetrieveSerial() {
315     auto device_desc = GetDeviceDescriptor();
316 
317     serial_.resize(512);
318     int rc = libusb_get_string_descriptor_ascii(device_handle_, device_desc->iSerialNumber,
319                                                 reinterpret_cast<unsigned char*>(&serial_[0]),
320                                                 serial_.length());
321     if (rc == 0) {
322         LOG(WARNING) << "received empty serial from device at " << device_address_;
323         return false;
324     } else if (rc < 0) {
325         VLOG(USB) << "failed to get serial from device " << device_address_ << " :"
326                   << libusb_error_name(rc);
327         return false;
328     }
329     serial_.resize(rc);
330     return true;
331 }
332 
333 // libusb gives us an int which is a value from 'enum libusb_speed'
ToConnectionSpeed(int speed)334 static uint64_t ToConnectionSpeed(int speed) {
335     switch (speed) {
336         case LIBUSB_SPEED_LOW:
337             return 1;
338         case LIBUSB_SPEED_FULL:
339             return 12;
340         case LIBUSB_SPEED_HIGH:
341             return 480;
342         case LIBUSB_SPEED_SUPER:
343             return 5000;
344         case LIBUSB_SPEED_SUPER_PLUS:
345             return 10000;
346         case LIBUSB_SPEED_SUPER_PLUS_X2:
347             return 20000;
348         case LIBUSB_SPEED_UNKNOWN:
349         default:
350             return 0;
351     }
352 }
353 
354 // libusb gives us a bitfield made of 'enum libusb_supported_speed' values
ExtractMaxSuperSpeed(uint16_t wSpeedSupported)355 static uint64_t ExtractMaxSuperSpeed(uint16_t wSpeedSupported) {
356     if (wSpeedSupported == 0) {
357         return 0;
358     }
359 
360     int msb = 0;
361     while (wSpeedSupported >>= 1) {
362         msb++;
363     }
364 
365     switch (1 << msb) {
366         case LIBUSB_LOW_SPEED_OPERATION:
367             return 1;
368         case LIBUSB_FULL_SPEED_OPERATION:
369             return 12;
370         case LIBUSB_HIGH_SPEED_OPERATION:
371             return 480;
372         case LIBUSB_SUPER_SPEED_OPERATION:
373             return 5000;
374         default:
375             return 0;
376     }
377 }
378 
ExtractMaxSuperSpeedPlus(libusb_ssplus_usb_device_capability_descriptor * cap)379 static uint64_t ExtractMaxSuperSpeedPlus(libusb_ssplus_usb_device_capability_descriptor* cap) {
380     // The exponents is one of {bytes, kB, MB, or GB}. We express speed in MB so we use a 0
381     // multiplier for value which would result in 0MB anyway.
382     static uint64_t exponent[] = {0, 0, 1, 1000};
383     uint64_t max_speed = 0;
384     for (uint8_t i = 0; i < cap->numSublinkSpeedAttributes; i++) {
385         libusb_ssplus_sublink_attribute* attr = &cap->sublinkSpeedAttributes[i];
386         uint64_t speed = attr->mantissa * exponent[attr->exponent];
387         max_speed = std::max(max_speed, speed);
388     }
389     return max_speed;
390 }
391 
RetrieveSpeeds()392 void LibUsbDevice::RetrieveSpeeds() {
393     negotiated_speed_ = ToConnectionSpeed(libusb_get_device_speed(device_));
394 
395     // To discover the maximum speed supported by an USB device, we walk its capability
396     // descriptors.
397     struct libusb_bos_descriptor* bos = nullptr;
398     if (libusb_get_bos_descriptor(device_handle_, &bos)) {
399         return;
400     }
401 
402     for (int i = 0; i < bos->bNumDeviceCaps; i++) {
403         switch (bos->dev_capability[i]->bDevCapabilityType) {
404             case LIBUSB_BT_SS_USB_DEVICE_CAPABILITY: {
405                 libusb_ss_usb_device_capability_descriptor* cap = nullptr;
406                 if (!libusb_get_ss_usb_device_capability_descriptor(nullptr, bos->dev_capability[i],
407                                                                     &cap)) {
408                     max_speed_ = std::max(max_speed_, ExtractMaxSuperSpeed(cap->wSpeedSupported));
409                     libusb_free_ss_usb_device_capability_descriptor(cap);
410                 }
411             } break;
412             case LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY: {
413                 libusb_ssplus_usb_device_capability_descriptor* cap = nullptr;
414                 if (!libusb_get_ssplus_usb_device_capability_descriptor(
415                             nullptr, bos->dev_capability[i], &cap)) {
416                     max_speed_ = std::max(max_speed_, ExtractMaxSuperSpeedPlus(cap));
417                     libusb_free_ssplus_usb_device_capability_descriptor(cap);
418                 }
419             } break;
420             default:
421                 break;
422         }
423     }
424     libusb_free_bos_descriptor(bos);
425 }
426 
OpenDeviceHandle()427 bool LibUsbDevice::OpenDeviceHandle() {
428     if (device_handle_) {
429         VLOG(USB) << "device already open";
430         return true;
431     }
432 
433     int rc = libusb_open(device_, &device_handle_);
434     if (rc != 0) {
435         VLOG(USB) << "Unable to open device: " << GetSerial() << " :" << libusb_strerror(rc);
436         return false;
437     }
438 
439     if (!RetrieveSerial()) {
440         return false;
441     }
442 
443     if (!FindAdbInterface()) {
444         return false;
445     }
446 
447     RetrieveSpeeds();
448     return true;
449 }
450 
ClaimInterface()451 bool LibUsbDevice::ClaimInterface() {
452     VLOG(USB) << "ClaimInterface for " << GetSerial();
453     if (interface_claimed_) {
454         VLOG(USB) << "Interface already open";
455         return true;
456     }
457 
458     if (!FindAdbInterface()) {
459         VLOG(USB) << "Unable to open interface for " << GetSerial();
460         return false;
461     }
462 
463     int rc = libusb_claim_interface(device_handle_, interface_num_);
464     if (rc != 0) {
465         VLOG(USB) << "failed to claim adb interface for device " << serial_.c_str() << ":"
466                   << libusb_error_name(rc);
467         return false;
468     }
469 
470     for (uint8_t endpoint : {read_endpoint_, write_endpoint_}) {
471         rc = libusb_clear_halt(device_handle_, endpoint);
472         if (rc != 0) {
473             VLOG(USB) << "failed to clear halt on device " << serial_ << " endpoint" << endpoint
474                       << ": " << libusb_error_name(rc);
475             libusb_release_interface(device_handle_, interface_num_);
476             return false;
477         }
478     }
479 
480     VLOG(USB) << "Claimed interface for " << GetSerial() << ", "
481               << StringPrintf("bulk_in = %#x, bulk_out = %#x", read_endpoint_, write_endpoint_);
482     interface_claimed_ = true;
483     return true;
484 }
485 
Open()486 bool LibUsbDevice::Open() {
487     if (!OpenDeviceHandle()) {
488         VLOG(USB) << "Unable to attach, cannot open device";
489         return false;
490     }
491 
492     if (!ClaimInterface()) {
493         VLOG(USB) << "failed to claim interface " << GetSerial();
494         return false;
495     }
496 
497     VLOG(USB) << "Attached device " << GetSerial();
498     return true;
499 }
500 
Close()501 bool LibUsbDevice::Close() {
502     ReleaseInterface();
503     CloseDeviceHandle();
504     return true;
505 }
506 
MaxSpeedMbps()507 uint64_t LibUsbDevice::MaxSpeedMbps() {
508     return max_speed_;
509 }
510 
NegotiatedSpeedMbps()511 uint64_t LibUsbDevice::NegotiatedSpeedMbps() {
512     return negotiated_speed_;
513 }
514 
GenerateSessionId(libusb_device * dev)515 USBSessionID LibUsbDevice::GenerateSessionId(libusb_device* dev) {
516     libusb_device_descriptor desc{};
517     auto result = libusb_get_device_descriptor(dev, &desc);
518     if (result != LIBUSB_SUCCESS) {
519         LOG(WARNING) << "Unable to retrieve device descriptor: " << libusb_error_name(result);
520         return USBSessionID{};
521     }
522 
523     USBSessionID session{};
524     session.fields.vendor = desc.idVendor;
525     session.fields.product = desc.idProduct;
526     session.fields.port = libusb_get_port_number(dev);
527     session.fields.address = libusb_get_device_address(dev);
528     return session;
529 }
530 
GetSessionId() const531 USBSessionID LibUsbDevice::GetSessionId() const {
532     return session_;
533 }
534