Depurar problemas de conexão USB com Android

A depuração USB do meu telefone Google Nexus 4 costumava funcionar bem na minha área de trabalho Debian. Até que um dia simplesmente parou de funcionar. Os sintomas eram assim:

$ adb logcat
- waiting for device -
^C
$ adb devices

List of devices attached
???????????? no permissions

Ou seja, adb logcat estava esperando uma eternidade, embora meu telefone estivesse conectado e os dispositivos adb fornecessem erros de permissão. Não houve uma resposta fácil sobre stackoverflow, mas muitas respostas desajeitadas, sugerindo fazer o setuid binário adb ou adicionar regras de udev com permissões 0666. Eu realmente tinha que chegar ao fundo disso sozinho.

Estas são as etapas para depurar, compreender e resolver o problema adequadamente.

Primeiro, encontre o barramento e a id do dispositivo atribuídos pelo kernel:

$ lsusb 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 002: ID 045e:0053 Microsoft Corp. Optical Mouse
Bus 004 Device 003: ID 0566:3002 Monterey International Corp.
Bus 001 Device 008: ID 18d1:d002 Google Inc.

Comprei meu dispositivo do Google, provavelmente é o último.

Em seguida, verifique as permissões do arquivo do dispositivo

$ ls -l /dev/bus/usb/001/008
crw
-rw-r-T 1 root root 189, 8 Nov 10 18:34 /dev/bus/usb/001/008

O caminho vem da saída de lsusb: 001 é o barramento e 008 é o dispositivo.

O problema é claro: o arquivo pertence ao usuário root e ao grupo root, que eu também não sou. A solução elegante é adicionar uma regra udev para que o dispositivo pertença a um grupo razoável, como plugdev, do qual sou membro.

Finalmente, crie um arquivo de regras do udev, digamos: /etc/udev/rules.d/51-android.rules

SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="d002", MODE="0660", 
GROUP
="plugdev", SYMLINK+="android%n"

Aqui, idVendor e idProduct vêm da saída de lsusb: 18d1: d002. Faça o mesmo com o seu próprio dispositivo. A regra especifica que um dispositivo USB correspondente deve ser criado com as permissões 0660, com o grupo plugdev e um link simbólico convenientemente apontando para ele.

Agora que tudo está pronto, basta conectar o dispositivo e conectá-lo novamente para confirmar o resultado:

$ lsusb | grep oogle
Bus 001 Device 010: ID 18d1:d002 Google Inc.
$ ls
-l /dev/bus/usb/001/010
crw
-rw-r-T 1 root plugdev 189, 9 Nov 10 18:37 /dev/bus/usb/001/010
$ ls
-l /dev/android7
lrwxrwxrwx
1 root root 15 Nov 10 18:37 /dev/android7 -> bus/usb/001/010
$ adb devices

List of devices attached
01d1e2510d9c6d28 device

PS: não há necessidade de reiniciar o udev, a regra alterada deve ser selecionada automaticamente.