Asigne la ruta física del dispositivo USB al número de Bus / Dispositivo devuelto por lsusb

9

Necesito obtener el título del dispositivo USB conectado. Puedo hacer eso con lsusb.

udev permite algunas sustituciones cuando escribo reglas: por ejemplo, podemos usar $kernelpara obtener el nombre del dispositivo o $devpathpara obtener la ruta al dispositivo.

Pero el problema es que lsusbdevuelve una cadena así:

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

Pero el devpath de udev es:

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

El número de bus es el mismo ( 5), pero los números son diferentes: Device 032parece ser un número lógico (cuando vuelvo a conectar el dispositivo, este número aumenta) y 2parece ser un número de dispositivo físico.

Entonces udev devuelve un número físico, y necesito obtener un número lógico. Entonces, puedo recuperar datos como este:lsusb -D /dev/bus/usb/005/032

Entonces, ¿cómo puedo obtener el número de dispositivo lógico 032por ruta física como /devices/pci0000:00/0000:00:1d.0/usb5/5-2?

Dmitry Frank
fuente

Respuestas:

5

En primer lugar, tenemos que anteponer /sysa la ruta que devuelve udev, por lo que ese camino se convierte en algo así como: /sys/devices/pci0000:00/0000:00:1d.0/usb5/5-2. Luego vaya a este directorio y habrá varios archivos en él. Entre otros, hay busnumy devnumarchivos, contienen estos números "lógicos". Entonces, en bash script, podemos recuperarlos así:

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"

También tenga en cuenta que udevpuede devolver estos busnumy devnumdirectamente: en RUN+="..."podemos usar sustituciones $attr{busnum}y $attr{devnum}respectivamente.

Dmitry Frank
fuente
1
Estoy confundido por los diferentes usos de udevvs. lsusby sys/devices/..vs. /dev/bus/usb/..y, a juzgar por su respuesta, parece saberlo :) ¿Quizás pueda arrojar algo de luz sobre estas dos preguntas? askubuntu.com/questions/342061/power-on-off-usb-ports y askubuntu.com/questions/498950/…
chiflado sobre
@nuttyaboutnatty, desafortunadamente no puedo darte ninguna pista sobre tu problema (sobre apagar el dispositivo). Solo estoy aprendiendo cosas de Linux en estos días, y estoy bastante lejos de cualquier tipo de gurú. Muy poco sobre /sys/devices/...vs /dev/...: /sysestá poblado por el núcleo, es una representación de la jerarquía real de los dispositivos del núcleo. Udev es un demonio de espacio de usuario que maneja la /sysjerarquía y las poblaciones /dev/...(teniendo en cuenta las reglas). Entonces, udev es completamente responsable de los /devcontenidos.
Dmitry Frank
1

La respuesta aceptada realmente no me ayudó mucho. Finalmente descubrí una forma probando idProduct e idVendor si existen. Aquí hay un 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
}

Esto es lo que obtengo en mi 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

Aquí puedo ver que, por ejemplo 0a5c:21e6, que es un dispositivo bluetooth, se asigna a 2-1.4.

Para una mayor conveniencia, podría definir esto como una función en su shell, algo así 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
fuente