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