Mapeie o caminho físico do dispositivo USB para o número de barramento / dispositivo retornado por lsusb

9

Preciso obter o título do dispositivo USB conectado. Eu posso fazer isso com lsusb.

O udev permite algumas substituições quando escrevo regras: digamos, podemos usar $kernelpara obter o nome do dispositivo ou $devpathpara encontrar o caminho para o dispositivo.

Mas o problema é que lsusbretorna uma string assim:

Bus 005 Device 032: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC

Mas o devpath do udev é:

/devices/pci0000:00/0000:00:1d.0/usb5/5-2 

O número do barramento é o mesmo ( 5), mas os números são diferentes: Device 032parece ser um número lógico (quando reconecto o dispositivo, esse número aumenta) e 2parece ser o número físico do dispositivo.

Então o udev retorna o número físico e preciso obter o número lógico. Então, eu posso recuperar dados como este:lsusb -D /dev/bus/usb/005/032

Então, como posso obter o número do dispositivo lógico 032por caminho físico /devices/pci0000:00/0000:00:1d.0/usb5/5-2?

Dmitry Frank
fonte

Respostas:

5

Em primeiro lugar, precisamos preceder /sysao caminho retornado por udev, de modo que caminho se torna algo como: /sys/devices/pci0000:00/0000:00:1d.0/usb5/5-2. Então vá para este diretório, e haverá vários arquivos nele. Entre outros, existem busnume devnumarquivos, eles contêm esses números "lógicos". Portanto, no script bash, podemos recuperá-los assim:

devpath='/devices/pci0000:00/0000:00:1d.0/usb5/5-2'

busnum=$(cat "/sys/$devpath/busnum")
devnum=$(cat "/sys/$devpath/devnum")

# we might want to make busnum and devnum have leading zeros
# (say, "003" instead of "3", and "012" instead of "12")
busnum=$(printf %03d $busnum)
devnum=$(printf %03d $devnum)

# now, we can retrieve device data by   lsusb -D /dev/bus/usb/$busnum/$devnum

echo "busnum=$busnum, devnum=$devnum"

Observe também que udevpodemos retornar estes busnume devnumdiretamente: in RUN+="..."podemos usar substituições $attr{busnum}e $attr{devnum}respectivamente.

Dmitry Frank
fonte
1
Estou confuso com os diferentes usos de udevvs. lsusbe sys/devices/..vs. /dev/bus/usb/..e, a julgar pela sua resposta, você parece ter conhecimento :) Talvez você possa lançar alguma luz sobre essas duas perguntas? askubuntu.com/questions/342061/power-on-off-usb-ports e askubuntu.com/questions/498950/...
noz sobre natty
@nuttyaboutnatty, infelizmente não posso lhe dar nenhuma pista sobre o seu problema (sobre como desligar o dispositivo). Estou apenas aprendendo coisas sobre Linux hoje em dia, e estou bem longe de qualquer tipo de guru. Muito pouco sobre o /sys/devices/...vs /dev/...: /sysé preenchido pelo kernel, é uma representação da hierarquia real dos dispositivos do kernel. O Udev é um daemon de espaço do usuário que lida com a /syshierarquia e preenche /dev/...(levando em conta as regras). Portanto, o udev é completamente responsável pelo /devconteúdo.
Dmitry Frank
1

A resposta aceita realmente não me ajudou muito. Finalmente descobri uma maneira de investigar o idProduct e o idVendor, se eles existirem. Aqui está um script de shell

#!/bin/bash
{ 
  cd /sys/bus/usb/devices
  for i in *; do 
    [ -e $i/idProduct ] && echo $(cat $i/idVendor $i/idProduct) $i
  done
}

Aqui está o que recebo no meu sistema.

$ ./script
0424 2514 1-3
8087 0024 2-1
0a5c 21e6 2-1.4
8087 0024 4-1
1d6b 0002 usb1
1d6b 0002 usb2
1d6b 0003 usb3
1d6b 0002 usb4

$ lsusb
Bus 004 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 006: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Aqui posso ver que, por exemplo 0a5c:21e6, que é um dispositivo bluetooth, mapeia para 2-1.4.

Para uma conveniência ainda maior, você pode definir isso como uma função em seu shell, algo como

$ cat >> ~/.bashrc << ENDL
gousb() {
  for i in /sys/bus/usb/devices/*; do 
    if [ -e \$i/idProduct ]; then
      if [ \$(cat \$i/idVendor):\$(cat \$i/idProduct) = \$1 ]; then 
        cd \$i
        return
      fi
    fi
  done

  echo "\$1 not found :-("
}
ENDL
$ source ~/.bashrc
$ gousb 0a5c:21e6
$ pwd 
/sys/bus/usb/devices/2-1.4
kristopolous
fonte