Comment le numéro de bus USB et le numéro de périphérique ont-ils été attribués?

19

Lors de l'utilisation, lsusbje me rends compte que le numéro de bus et le numéro de périphérique d'un périphérique USB peuvent changer de temps en temps. D'après ce que je comprends, le numéro de bus peut être changé à chaque redémarrage. Le numéro d'appareil change à chaque reconnexion.

Ma question est quel algorithme le système a utilisé pour obtenir le numéro de bus et le numéro de périphérique? Surtout le numéro d'appareil, est-il monotone? Y aura-t-il un cas où: sans redémarrer le système d'exploitation, un périphérique reconnecté utilise l'ancien numéro de bus et le numéro de périphérique d'un autre périphérique reconnecté?

Conan
la source
6
Une chose m'a rendu curieux à propos de votre question, avez-vous vraiment vu les numéros de BUS changer après un redémarrage? J'étais toujours convaincu qu'à moins que vous ne changiez le matériel ou mettiez à jour le BIOS, les numéros de BUS ne changeront pas. Les bus USB sont simplement des concentrateurs / contrôleurs connectés aux bus PCI (dans tous les cas, j'ai vu au moins), et les informations de bus PCI proviennent du BIOS. Mais je peux me tromper, je ne veux pas répondre et parler de merde dedans.
grochmal
à droite, seulement quand j'ai un changement de matériel ressemble.
Conan

Réponses:

23

Remarque: il s'agit d'une réponse Linux ; les autres noyaux auront une manière légèrement différente de gérer cela.

Le contexte

Il est difficile de parler de bus USB sans parler de bus PCI. Un CPU ne peut pas parler à un bus USB, ce qui se passe est que le CPU parle à un bus PCI auquel est connecté un contrôleur USB (et un contrôleur / concentrateur USB est ce qu'on lsusbappelle un bus USB). Les bus PCI sont numérotés en fonction de leur distance par rapport au CPU, par exemple:

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

En regardant, man lspcinous voyons ce qui suit:

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

Par conséquent, nous savons maintenant comment interpréter les numéros PCI. Ensuite, nous examinerons les contrôleurs USB connectés aux bus PCI. La machine sur laquelle je suis actuellement a une configuration USB intéressante, je vais donc l'utiliser comme exemple:

$ 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

Attendez, attendez, quels sont tous ces avantages? En haut, nous avons le domaine et le bus PCI -[0000:00](cette machine n'a qu'un seul bus PCI). Et puis nous avons plusieurs appareils connectés à ce bus. Voyons quels sont les périphériques 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

Bon, comparons maintenant cela lsusb(j'utilise sortjuste pour faciliter la recherche dans la liste plus tard):

$ 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

Attends encore. Nous avons 7 appareils USB selon lspcimais 10 appareils selon lsusb! lspcirépertorie uniquement les contrôleurs USB; un contrôleur peut avoir plusieurs périphériques USB connectés. Explorons /sys/bus/pour voir comment cela se produit.

$ 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

Maintenant, cela commence à avoir un sens, nous avons 7 contrôleurs USB qui sont branchés sur le bus PCI en tant que périphériques. Par exemple, le bus USB 001 correspond au périphérique PCI 0000:00:12.2et le bus USB 007 correspond au 0000:00:14.5périphérique.

Numérotation des appareils

Les répertoires commençant par le numéro de bus USB (par exemple 7-1:1.2) sont les périphériques réels connectés au contrôleur USB. Tout comme un bus PCI peut avoir plusieurs périphériques connectés, un contrôleur USB (un concentrateur) peut avoir plusieurs périphériques USB connectés.

Les numéros d'appareil sont simplement des compteurs: le premier appareil connecté obtient un 1, le suivant obtient un 2, etc. Mais il y a un peu plus: l'USB a été conçu pour être enfichable à chaud; vous pouvez donc connecter et déconnecter des appareils. Lorsque vous déconnectez un périphérique USB, le numéro de périphérique ne sera plus utilisé par le noyau pour tout autre périphérique sur ce contrôleur USB. Par exemple, si vous connectez et déconnectez une clé USB et continuez, lsusbvous verrez le numéro de périphérique de votre clé USB augmenter.

Numérotation des bus

Si vous avez lu ce qui précède avec attention, vous vous demandez peut-être une chose que je n'ai pas touchée. L'ordre de numérotation PCI ne correspond pas à l'ordre de numérotation des contrôleurs USB! Voyons cela à nouveau:

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 liste est en ordre, mais pas tout à fait. Les deux premiers contrôleurs USB semblent être hors service. Pourtant, il y a une raison: si vous regardez lspcici-dessus, vous verrez que ce sont des EHCIports USB (USB 2.0), tandis que tous les autres contrôleurs OHCIUSB sont USB (USB 1.x).

Par conséquent, nous pouvons redessiner ce tableau comme:

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

Et l'attribution des numéros devient claire.

grochmal
la source
alors que se passera-t-il lorsque le nombre maximum de numéros de périphérique sera utilisé. disons que je continue de reconnecter mon appareil. Le numéro d'appareil va bientôt atteindre le maximum. J'ai fait un test, on dirait que ce n'est pas un simple compteur. Il ne revient pas à 001, mais le noyau réutilise le plus grand nombre de périphériques. Existe-t-il un moyen simple de modifier ce comportement?
Conan
@Conan - Hmm ... eh bien, comment puis-je le dire: je ne sais pas. Je n'ai jamais essayé de déborder le compteur d'appareil comme vous l'avez fait. Là encore, il n'est guère nécessaire de connaître un numéro d'appareil au préalable. Par exemple, si vous essayez de trouver un lecteur USB lorsqu'il se connecte, vous devez le faire par étiquette de système de fichiers ou UUID (ce qui est encore udevplus ou moins compris). Quant à comprendre la numérotation dans un souci d'apprentissage, je pense que le seul endroit qui contient les informations est le code du noyau.
grochmal
Merci @grochmal, je pense que j'ai fait une erreur lors du débordement du test. Les tests ultérieurs m'ont montré lors du débordement, le compteur cherchait en effet à partir du chiffre le plus bas.
Conan