Como o número do barramento USB e o número do dispositivo foram atribuídos?

19

Quando uso lsusb, percebo que o número do barramento e o número do dispositivo de um dispositivo USB podem mudar de tempos em tempos. Pelo que entendi, o número do barramento pode ser alterado a cada reinicialização. O número do dispositivo será alterado a cada reconexão.

Minha pergunta é qual algoritmo o sistema usou para obter o número do barramento e o número do dispositivo? Especialmente o número do dispositivo, é monotônico? Alguma vez haverá um caso em que: sem reiniciar o sistema operacional, um dispositivo reconectado está usando o número do barramento e o número do dispositivo antigo de outro dispositivo reconectado?

Conan
fonte
6
Uma coisa me deixou curiosa sobre sua pergunta: você realmente viu os números dos ônibus mudarem após uma reinicialização? Eu sempre tive certeza de que, a menos que você altere o hardware ou atualize o BIOS, os números do barramento não serão alterados. Os barramentos USB são simplesmente hubs / controladores conectados aos barramentos PCI (em todos os casos que vi pelo menos), e as informações sobre barramentos PCI vêm do BIOS. Mas eu posso estar errado, não quero responder e falar porcaria.
grochmal 21/07
certo, apenas quando eu tenho alterações de hardware se parece.
Conan

Respostas:

23

Nota: Esta é uma resposta do Linux ; outros kernels terão uma maneira ligeiramente diferente de lidar com isso.

Contexto

É difícil falar sobre barramentos USB sem falar sobre barramentos PCI. Uma CPU não pode falar com um barramento USB, o que acontece é que a CPU conversa com um barramento PCI que possui um controlador USB conectado a ela (e um controlador / hub USB é o que lsusbchama de barramento USB). Os barramentos PCI são numerados com base na distância da CPU, por exemplo:

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

Observando man lspci, vemos o seguinte:

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

Portanto, agora sabemos como interpretar números PCI. A seguir, veremos os controladores USB conectados aos barramentos PCI. A máquina em que estou atualmente possui uma configuração USB interessante, então vou usá-la como exemplo:

$ 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

Espere, espere, espere, quais são todas essas vantagens? No topo, temos o domínio e o barramento PCI -[0000:00](esta máquina possui apenas um barramento PCI). E então temos vários dispositivos conectados a esse barramento. Vamos ver quais são os 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

Bom, agora vamos comparar isso lsusb(eu uso sortapenas para facilitar a pesquisa na lista posteriormente):

$ 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

Aguarde de novo. Temos 7 dispositivos USB de acordo com, lspcimas 10 dispositivos de acordo com lsusb! lspcilista apenas os controladores USB; um controlador pode ter mais de um dispositivo USB conectado a ele. Vamos explorar /sys/bus/para ver como isso acontece.

$ 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

Agora, isso está começando a fazer sentido, temos 7 controladores USB conectados ao barramento PCI como dispositivos. Por exemplo, o barramento USB 001 corresponde ao dispositivo PCI 0000:00:12.2e o barramento USB 007 corresponde ao 0000:00:14.5dispositivo.

Numeração do dispositivo

Os diretórios que começam com o número do barramento USB (por exemplo 7-1:1.2) são os dispositivos reais conectados ao controlador USB. Assim como um barramento PCI pode ter vários dispositivos conectados, um controlador USB (um hub) pode ter vários dispositivos USB conectados a ele.

Os números dos dispositivos são simplesmente contadores: o primeiro dispositivo conectado recebe 1, o próximo recebe 2 e assim por diante. Mas há um pouco mais: o USB foi projetado para ser plugável a quente; portanto, você pode conectar e desconectar dispositivos. Quando você desconecta um dispositivo USB, o número do dispositivo não será usado novamente pelo kernel para nenhum outro dispositivo nesse controlador USB. Por exemplo, se você conectar e desconectar um pen drive e continuar fazendo lsusb, verá o número do dispositivo do seu pen drive subindo.

Numeração de barramento

Se você leu o texto acima com atenção, pode estar se perguntando sobre uma coisa que eu não toquei. A ordem da numeração PCI não corresponde à ordem em que os controladores USB foram numerados! Vamos ver isso de novo:

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

A lista está em ordem, mas não completamente. Os dois primeiros controladores USB parecem estar fora de ordem. No entanto, há uma razão para: Se você examinar lspciacima, verá que eles são EHCIUSB (USB 2.0), enquanto todos os outros controladores OHCIUSB são USB (USB 1.x).

Portanto, podemos redesenhar esta tabela 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

E a atribuição de números fica clara.

grochmal
fonte
Então, o que acontecerá quando o número máximo de dispositivos for usado. digamos que eu continuo reconectando meu dispositivo. O número do dispositivo logo chegará ao máximo. Na verdade, eu fiz um teste, parece que não é um contador simples. Ele não está retornando 001, mas o kernel está reutilizando o maior número de dispositivos. Existe uma maneira fácil de mudar esse comportamento?
Conan
@Conan - Hmm ... bem, como posso dizer: eu simplesmente não sei. Eu nunca tentei estourar o contador do dispositivo como você fez. Por outro lado, dificilmente é necessário conhecer um número de dispositivo com antecedência. Por exemplo, se você está tentando encontrar uma unidade USB quando ela se conecta, deve fazê-lo por etiqueta do sistema de arquivos ou UUID (que compreende udevmais ou menos). Para entender a numeração em prol da aprendizagem, acredito que o único local que possui essa informação é o código do kernel.
grochmal
Obrigado @grochmal, acho que cometi um erro quando estouro de teste. Os testes posteriores mostraram-me quando estouraram, o contador de fato procurando pelo número mais baixo.
Conan