¿Cómo se asignaron el número de bus USB y el número de dispositivo?

19

Cuando lo uso, lsusbme doy cuenta de que el número de bus y el número de dispositivo de un dispositivo USB pueden cambiar de vez en cuando. Por lo que entiendo, el número de bus se puede cambiar en cada reinicio. El número de dispositivo cambiará en cada reconexión.

Mi pregunta es qué algoritmo utilizó el sistema para obtener el número de bus y el número de dispositivo. Especialmente el número de dispositivo, ¿es monótono? ¿Alguna vez habrá un caso en el que: sin reiniciar el sistema operativo, un dispositivo reconectado está usando el número de bus y el número de dispositivo antiguo de otro dispositivo reconectado?

Conan
fuente
66
Una cosa me hizo sentir curiosidad por tu pregunta: ¿realmente viste los números de BUS cambiar después de un reinicio? Siempre tuve la certeza de que, a menos que cambie el hardware o actualice el BIOS, los números de BUS no cambiarán. Los buses USB son simplemente concentradores / controladores conectados a los buses PCI (en todos los casos que vi al menos), y la información del bus PCI proviene del BIOS. Pero podría estar equivocado, no quiero dar una respuesta y hablar mal.
grochmal
bien, solo cuando tengo cambio de hardware parece.
Conan

Respuestas:

23

Nota: Esta es una respuesta de Linux ; otros núcleos tendrán una forma ligeramente diferente de lidiar con esto.

Contexto

Es difícil hablar de buses USB sin hablar de buses PCI. Una CPU no puede hablar con un bus USB, lo que sucede es que la CPU habla con un bus PCI que tiene un controlador USB conectado (y un controlador / hub USB es lo que lsusbllama un bus USB). Los buses PCI están numerados en función de qué tan lejos están de la CPU, por ejemplo:

    +-----+
    | CPU |
    +-----+
       |              PCI Bus 0
 ---+--+-----------------------------+
    |                                |
+---+----+                      +----+---+
| Bridge |                      | Bridge |
+---+----+                      +----+---+
    |  PCI bus 1                     |  PCI bus 2
  --+--------+               +-------+-------------+
             |               |                     |
       Disk Controller    USB Controller      Network Card
         (Device 00)       (Device 00)         (Device 01)

Mirando hacia adentro man lspcivemos lo siguiente:

   Slot   The  name of the slot where the device resides
          ([domain:]bus:device.function).  This tag is
          always the first in a record.

Por lo tanto, ahora sabemos cómo interpretar los números PCI. A continuación, veremos los controladores USB conectados a los buses PCI. La máquina en la que estoy actualmente tiene una configuración USB interesante, así que la usaré como ejemplo:

$ lspci -tv
-[0000:00]-+-00.0  Advanced Micro Devices, Inc. [AMD] RS780 Host Bridge
           +-01.0-[01]----05.0  Advanced Micro Devices, Inc. [AMD/ATI] RS780M [Mobility Radeon HD 3200]
           +-04.0-[02]----00.0  Qualcomm Atheros AR928X Wireless Network Adapter (PCI-Express)
           +-05.0-[03]----00.0  Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
           +-06.0-[04-06]--
           +-11.0  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode]
           +-12.0  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
           +-12.1  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
           +-12.2  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
           +-13.0  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
           +-13.1  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
           +-13.2  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
           +-14.0  Advanced Micro Devices, Inc. [AMD/ATI] SBx00 SMBus Controller
           +-14.1  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 IDE Controller
           +-14.2  Advanced Micro Devices, Inc. [AMD/ATI] SBx00 Azalia (Intel HDA)
           +-14.3  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 LPC host controller
           +-14.4-[07]--
           +-14.5  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
           +-18.0  Advanced Micro Devices, Inc. [AMD] Family 11h Processor HyperTransport Configuration
           +-18.1  Advanced Micro Devices, Inc. [AMD] Family 11h Processor Address Map
           +-18.2  Advanced Micro Devices, Inc. [AMD] Family 11h Processor DRAM Controller
           +-18.3  Advanced Micro Devices, Inc. [AMD] Family 11h Processor Miscellaneous Control
           \-18.4  Advanced Micro Devices, Inc. [AMD] Family 11h Processor Link Control

Espera espera espera, ¿cuáles son todas esas ventajas? En la parte superior tenemos el dominio y el bus PCI -[0000:00](esta máquina solo tiene un bus PCI). Y luego tenemos varios dispositivos conectados a ese bus. Veamos cuáles son dispositivos USB:

$ lspci -tv | grep -i usb
       +-12.0  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
       +-12.1  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
       +-12.2  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
       +-13.0  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
       +-13.1  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
       +-13.2  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
       +-14.5  Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI2 Controller

Bien, ahora comparemos eso con lsusb(lo uso sortsolo para facilitar la búsqueda en la lista más adelante):

$ lsusb | sort
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 174f:5a31 Syntek Sonix USB 2.0 Camera
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 002: ID 046d:c019 Logitech, Inc. Optical Tilt Wheel Mouse
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 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 002: ID 0b05:1751 ASUSTek Computer, Inc. BT-253 Bluetooth Adapter

Espera otra vez. Tenemos 7 dispositivos USB según lspcipero 10 dispositivos según lsusb! lspcisolo enumera los controladores USB; Un controlador puede tener más de un dispositivo USB conectado. Exploremos /sys/bus/para ver cómo sucede esto.

$ ls -l /sys/bus/usb/devices/
... 1-0:1.0 -> ../../../devices/pci0000:00/0000:00:12.2/usb1/1-0:1.0
... 2-0:1.0 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-0:1.0
... 2-1 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-1
... 2-1:1.0 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-1/2-1:1.0
... 2-1:1.1 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-1/2-1:1.1
... 3-0:1.0 -> ../../../devices/pci0000:00/0000:00:12.0/usb3/3-0:1.0
... 3-1 -> ../../../devices/pci0000:00/0000:00:12.0/usb3/3-1
... 3-1:1.0 -> ../../../devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0
... 4-0:1.0 -> ../../../devices/pci0000:00/0000:00:12.1/usb4/4-0:1.0
... 5-0:1.0 -> ../../../devices/pci0000:00/0000:00:13.0/usb5/5-0:1.0
... 6-0:1.0 -> ../../../devices/pci0000:00/0000:00:13.1/usb6/6-0:1.0
... 7-0:1.0 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-0:1.0
... 7-1 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1
... 7-1:1.0 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.0
... 7-1:1.1 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.1
... 7-1:1.2 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.2
... 7-1:1.3 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.3
... usb1 -> ../../../devices/pci0000:00/0000:00:12.2/usb1
... usb2 -> ../../../devices/pci0000:00/0000:00:13.2/usb2
... usb3 -> ../../../devices/pci0000:00/0000:00:12.0/usb3
... usb4 -> ../../../devices/pci0000:00/0000:00:12.1/usb4
... usb5 -> ../../../devices/pci0000:00/0000:00:13.0/usb5
... usb6 -> ../../../devices/pci0000:00/0000:00:13.1/usb6
... usb7 -> ../../../devices/pci0000:00/0000:00:14.5/usb7

Ahora esto está comenzando a tener sentido, tenemos 7 controladores USB que están conectados en el bus PCI como dispositivos. Por ejemplo, el bus USB 001 corresponde al dispositivo PCI 0000:00:12.2y el bus USB 007 corresponde al 0000:00:14.5dispositivo.

Numeración del dispositivo

Los directorios que comienzan con el número de bus USB (p 7-1:1.2. Ej. ) Son los dispositivos reales conectados al controlador USB. Al igual que un bus PCI puede tener varios dispositivos conectados, un controlador USB (un concentrador) puede tener varios dispositivos USB conectados.

Los números de dispositivo son simplemente contadores: el primer dispositivo conectado obtiene un 1, el siguiente obtiene un 2, y así sucesivamente. Pero hay un poco más: USB fue diseñado para ser conectable en caliente; por lo tanto, puede conectar y desconectar dispositivos. Cuando desconecte un dispositivo USB, el núcleo no volverá a utilizar el número de dispositivo para ningún otro dispositivo en ese controlador USB. Por ejemplo, si conecta y desconecta un pen drive y sigue haciéndolo lsusb, verá el número de dispositivo de su pen drive subiendo.

Numeración de bus

Si ha leído lo anterior con atención, es posible que se pregunte sobre una cosa que no toqué. ¡El orden de numeración de PCI no corresponde al orden en que se numeraron los controladores USB! Veamos eso de nuevo:

USB  | PCI
-----+----
usb1 | 0000:00/0000:00:12.2
usb2 | 0000:00/0000:00:13.2
usb3 | 0000:00/0000:00:12.0
usb4 | 0000:00/0000:00:12.1
usb5 | 0000:00/0000:00:13.0
usb6 | 0000:00/0000:00:13.1
usb7 | 0000:00/0000:00:14.5

La lista está en orden, pero no del todo. Los primeros dos controladores USB parecen estar fuera de servicio. Sin embargo, hay una razón por la cual: si observa lspciarriba, verá que son EHCIUSB (USB 2.0), mientras que todos los demás controladores OHCIUSB son USB (USB 1.x).

Por lo tanto, podemos volver a dibujar esta tabla como:

USB  | PCI
-----+----
usb1 | 0000:00/0000:00:12.2
usb2 | 0000:00/0000:00:13.2     USB 2.0
-----+---------------------------------
usb3 | 0000:00/0000:00:12.0     USB 1.x
usb4 | 0000:00/0000:00:12.1
usb5 | 0000:00/0000:00:13.0
usb6 | 0000:00/0000:00:13.1
usb7 | 0000:00/0000:00:14.5

Y la asignación de números se vuelve clara.

grochmal
fuente
Entonces, ¿qué sucederá cuando se use el número máximo de dispositivos? Digamos que sigo volviendo a conectar mi dispositivo. El número de dispositivo pronto llegará al máximo. Realmente hice una prueba, parece que no es un simple contador. No está volviendo a 001, sino que el núcleo está reutilizando el número de dispositivo más grande. ¿Hay una manera fácil de cambiar este comportamiento?
Conan
@Conan - Hmm ... bueno, ¿cómo puedo decirlo? Simplemente no lo sé. Nunca intenté desbordar el contador del dispositivo como lo hiciste. Por otra parte, apenas es necesario saber de antemano un número de dispositivo. Por ejemplo, si está tratando de encontrar una unidad USB cuando se conecta, debe hacerlo por etiqueta del sistema de archivos o UUID (que incluso udevcomprende más o menos). En cuanto a entender la numeración en aras del aprendizaje, creo que el único lugar que tiene la información es el código del núcleo.
grochmal
Gracias @grochmal, creo que cometí un error al desbordar la prueba. Las pruebas posteriores me mostraron cuando se desbordó, el contador de hecho buscó desde el número más bajo.
Conan