Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adb fails to find devices over USB with libusb (android-tools 35.0.1) #153

Open
omasanori opened this issue Aug 1, 2024 · 10 comments
Open
Labels
bug Something isn't working

Comments

@omasanori
Copy link

omasanori commented Aug 1, 2024

android-tools 35.0.0 and later uses libusb by default on Linux. (See also: https://developer.android.com/tools/releases/platform-tools)

On Fedora Linux 40 x86_64 and postmarketOS v24.06 aarch64 (based on Alpine Linux v3.20) which packages android-tools 35.0.1, adb fails to detect devices over USB.

A workaround is adding ADB_LIBUSB=0 to the environment. (ex. ADB_LIBUSB=0 adb devices -l)

Downstream report: https://gitlab.alpinelinux.org/alpine/aports/-/issues/16326

@Biswa96
Copy link
Collaborator

Biswa96 commented Aug 1, 2024

I am using adb in ArchLinux without any issue. Please let me know if there is any way I could help to troubleshoot the issue. ADB_TRACE environment variable may help to show any debug output.

@Biswa96 Biswa96 added the bug Something isn't working label Aug 1, 2024
@Arnavion
Copy link

Arnavion commented Aug 1, 2024

Looking at ADB_TRACE=all adb server nodaemon, I see:

08-01 00:25:08.657 16626 16626 D adb     : adb_trace.cpp:187 Android Debug Bridge version 1.0.41
08-01 00:25:08.657 16626 16626 D adb     : adb_trace.cpp:187 Version 35.0.1-android-tools
08-01 00:25:08.657 16626 16626 D adb     : adb_trace.cpp:187 Installed as /usr/bin/adb
08-01 00:25:08.657 16626 16626 D adb     : adb_trace.cpp:187 Running on Linux 6.9.10 (aarch64)
08-01 00:25:08.657 16626 16626 D adb     : adb_trace.cpp:187 
08-01 00:25:08.657 16626 16626 D adb     : commandline.cpp:1646 Using server socket: tcp:5037
08-01 00:25:08.658 16626 16626 D adb     : usb_libusb.cpp:1029 initializing libusb...
08-01 00:25:08.660 16626 16626 D adb     : transport_local.cpp:233 transport: local client init
08-01 00:25:08.661 16626 16630 D adb     : transport_local.cpp:191 transport: client_socket_thread() starting
08-01 00:25:08.661 16626 16626 I adb     : auth.cpp:416 adb_auth_init...
08-01 00:25:08.663 16626 16626 I adb     : auth.cpp:152 loaded new key from '/root/.android/adbkey' with fingerprint 7085CFED43D7E255B15677E4FD60E5FC24D9F3535188265308C2330D0D3D9177
08-01 00:25:08.663 16626 16626 I adb     : auth.cpp:391 adb_auth_inotify_init...
08-01 00:25:08.665 16626 16626 D adb     : main.cpp:232 Event loop starting
08-01 00:25:11.665 16626 16626 D adb     : fdevent_epoll.cpp:165 (fdevent 0: fd 4 R) got events 0x1

According to adb/client/usb_libusb.cpp, after initializing libusb... log, it calls libusb_init, then calls libusb_hotplug_register_callback(LIBUSB_HOTPLUG_ENUMERATE, hotplug_callback). (libusb_hotplug_register_callback(LIBUSB_HOTPLUG_ENUMERATE) is expected to call the callback with all existing devices.) hotplug_callback spawns a thread to run the hotplug_thread function. The first thing the hotplug_thread thread does is log libusb hotplug thread started and set its name to libusb hotplug, but this log does not appear above. Furthermore I do not see a thread named libusb hotplug in the list of threads of adb process.

$ pidof adb

16626

$ ls -l /proc/16626/task/

total 0
dr-xr-xr-x    7 root     root             0 Aug  1 00:25 ./
dr-xr-xr-x    9 root     root             0 Aug  1 00:25 ../
dr-xr-xr-x    7 root     root             0 Aug  1 00:25 16626/
dr-xr-xr-x    7 root     root             0 Aug  1 00:25 16627/
dr-xr-xr-x    7 root     root             0 Aug  1 00:25 16628/
dr-xr-xr-x    7 root     root             0 Aug  1 00:25 16629/
dr-xr-xr-x    7 root     root             0 Aug  1 00:25 16630/

$ ps -T

...

16626 root      0:00 adb server nodaemon
16627 root      0:00 adb server nodaemon
16628 root      0:00 {libusb_event} adb server nodaemon
16629 root      0:00 {libusb} adb server nodaemon
16630 root      0:00 {client_socket_t} adb server nodaemon

(libusb_event is started internally by libusb itself.)

So it would seem that the problem is libusb isn't sending any events to the hotplug_callback. atm I can't check in gdb to be sure because the Alpine package of android-tools doesn't have debug symbols; I'll need to recompile with symbols enabled.

@Arnavion
Copy link

Arnavion commented Aug 1, 2024

Forgot to say, according to strace it certainly seems to be enumerating all the USB devices. But again I don't have debug symbols right now to see what exactly libusb is doing.

$ ADB_TRACE=all strace -fe file,read,readv,write,writev -- adb server nodaemon

...

[pid 20695] writev(2, [{iov_base="", iov_len=0}, {iov_base="08-01 00:41:41.531 20695 20695 D"..., iov_len=86}], 208-01 00:41:41.531 20695 20695 D adb     : usb_libusb.cpp:1029 initializing libusb...
) = 86
[pid 20695] write(6, "\1\0\0\0\0\0\0\0", 8) = 8
[pid 20695] openat(AT_FDCWD, "/dev/bus/usb", O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_DIRECTORY) = 8
[pid 20695] statfs("/sys", {f_type=SYSFS_MAGIC, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={val=[0x52a078e6, 0xe4a7715]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV|ST_NOEXEC|ST_RELATIME}) = 0
strace: Process 20697 attached
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices", O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_DIRECTORY) = 10
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb3/busnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "3\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb3/devnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "1\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb3/speed", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "12\n", 19)        = 3
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb3/descriptors", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "\22\1\20\1\t\0\0@k\35\1\0\t\6\3\2\1\1\t\2\31\0\1\1\0\340\0\t\4\0\0\1"..., 256) = 43
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb1/busnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "1\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb1/devnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "1\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb1/speed", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "480\n", 19)       = 4
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb1/descriptors", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "\22\1\0\2\t\0\0@k\35\2\0\t\6\3\2\1\1\t\2\31\0\1\1\0\340\0\t\4\0\0\1"..., 256) = 43
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/1-1/busnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "1\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/1-1/devnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "5\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/1-1/speed", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "480\n", 19)       = 4
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/1-1/descriptors", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "\22\1\0\2\357\2\1@|,%\1\30\3\1\2\3\1\t\2\350\0\6\1\0\240\372\t\4\0\0\2"..., 256) = 250
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb4/busnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "4\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb4/devnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "1\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb4/speed", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "12\n", 19)        = 3
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb4/descriptors", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "\22\1\20\1\t\0\0@k\35\1\0\t\6\3\2\1\1\t\2\31\0\1\1\0\340\0\t\4\0\0\1"..., 256) = 43
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb2/busnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "2\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb2/devnum", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "1\n", 19)         = 2
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb2/speed", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "480\n", 19)       = 4
[pid 20695] openat(AT_FDCWD, "/sys/bus/usb/devices/usb2/descriptors", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 11
[pid 20695] read(11, "\22\1\0\2\t\0\0@k\35\2\0\t\6\3\2\1\1\t\2\31\0\1\1\0\340\0\t\4\0\0\1"..., 256) = 43

...

@omasanori
Copy link
Author

omasanori commented Aug 4, 2024

I neither have prepared for proper debugging yet, but I found that, ADB_TRACE=all adb server nodaemon on Fedora 40 receives hotplug events for any my USB devices (flash memory, headset, keyboard) but my Fx0, while dmesg showed that it is recognized by the kernel too.

@Arnavion
Copy link

Arnavion commented Aug 4, 2024

I built debug packages of adb and libusb and found the issue.

adb calls:

    rc = libusb_hotplug_register_callback(
            nullptr,
            static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
                                              LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
            LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
            LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, nullptr);

where LIBUSB_CLASS_PER_INTERFACE will be used to match the device class. The problem is the PinePhone modem at least does not have this device class, only LIBUSB_CLASS_MISCELLANEOUS, so libusb filters it out.

This patch fixes it:

From d349fae010f6c780d76e89c5d6b81d45119137c0 Mon Sep 17 00:00:00 2001
From: Arnav Singh <[email protected]>
Date: Sat, 3 Aug 2024 21:55:23 -0700
Subject: [PATCH] Fix libusb enumeration to handle PINE64 PinePhone modem.

The PINE64 PinePhone modem exposes itself as an adb-accessible device over USB
but its device class is LIBUSB_CLASS_MISCELLANEOUS, so allow that too.
---
 vendor/adb/client/usb_libusb.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/vendor/adb/client/usb_libusb.cpp b/vendor/adb/client/usb_libusb.cpp
index 6133e7c8..9af91eb7 100644
--- a/vendor/adb/client/usb_libusb.cpp
+++ b/vendor/adb/client/usb_libusb.cpp
@@ -364,8 +364,8 @@ struct LibusbConnection : public Connection {
     }
 
     bool FindInterface(libusb_device_descriptor* device_desc) {
-        if (device_desc->bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) {
-            // Assume that all Android devices have the device class set to per interface.
+        if (device_desc->bDeviceClass != LIBUSB_CLASS_PER_INTERFACE && device_desc->bDeviceClass != LIBUSB_CLASS_MISCELLANEOUS) {
+            // Assume that all Android devices have the device class set to per interface or miscellaneous.
             // TODO: Is this assumption valid?
             VLOG(USB) << "skipping device with incorrect class at " << device_address_;
             return false;
@@ -1039,7 +1039,7 @@ void usb_init() {
             static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
                                               LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
             LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
-            LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, nullptr);
+            LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, nullptr, nullptr);
 
     if (rc != LIBUSB_SUCCESS) {
         LOG(FATAL) << "failed to register libusb hotplug callback";
-- 
2.46.0

Edit: And the reason this is only an issue with libusb backend is that the original "Linux" backend does not try to filter devices based on device class. It just checks every interface of every device looking for the adb interface.

@omasanori
Copy link
Author

Indeed, LGL25 is also a device with the 239 (Miscellaneous) device class!

@Arnavion
Copy link

Arnavion commented Aug 8, 2024

(Just to repeat what I wrote in the Alpine issue, I don't plan to talk to Android upstream about this bug or the patch myself. omasanori brought it up in https://issuetracker.google.com/issues/341439962#comment3 )

@nmeum
Copy link
Owner

nmeum commented Aug 30, 2024

I don't plan to talk to Android upstream about this bug or the patch myself.

Should we just include this patch in our downstream patchset for the time being then? I personally wouldn't mind doing so.

@omasanori
Copy link
Author

It would be nice.

@fabiensanglard
Copy link

fabiensanglard commented Sep 6, 2024

I don't plan to talk to Android upstream about this bug or the patch myself.

(Upstream maintainer here) Sorry about this oversight. The issue has been reported here and we will work on a fix ASAP. It will ship in 35.0.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants