01signal.com

Linux 에서 USB 장치 재설정(및 전원 공급 장치 제어)

소개

완벽한 세상에서 USB 장치와 hubs는 잘 작동하며 발생하는 모든 문제를 해결합니다. 실제로는 온갖 종류의 이상한 일이 발생하며 이에 대해 조치를 취해야 합니다. 일반적인 해결책은 USB 플러그를 뽑고 장치를 다시 연결하는 것입니다. 그러나 이것이 자동으로 발생해야 하는 경우에는 어떻게 해야 합니까?

가장 극적인 해결책은 다른 웹 페이지 에 제시되어 있습니다. 이로 인해 USB hub의 drivers가 종료되고 다시 시작됩니다. 그 효과는 컴퓨터에서 모든 USB 장치를 분리했다가 다시 연결하는 것과 거의 같습니다. 그것은 가장 무거운 망치이며 때때로 필요합니다.

이 페이지에서는 하나의 특정 USB 장치를 재설정하는 두 가지 방법을 제시합니다. 몇 가지 최소한의 설명과 함께 각 방법을 수행하는 방법을 제시하는 것으로 시작하겠습니다. 그 후에 많은 기술적 세부 사항에 대해 설명하겠습니다.

여기에 제시된 두 번째 방법이 아마도 다른 플랫폼에서도 가능할지라도 전체 논의는 여기에서 Linux 로 제한됩니다.

여기에서 많은 정보는 Universal Serial Bus Specification Revision 2.0에서 가져온 것입니다. 이 문서의 파일 이름은 일반적으로 usb_20.pdf입니다.

방법 #1: Linux kernel 에 장치 재설정 요청

이를 위해 사용할 수 있는 몇 가지 도구가 있습니다. 가장 진보된 도구는 usbutils의 일부입니다. usbreset.c를 다운로드하고 compilation에 gcc를 사용하십시오.

$ gcc -O3 -Wall -g usbreset.c -o usbreset

그런 다음:

$ ./usbreset
Usage:
  usbreset PPPP:VVVV - reset by product and vendor id
  usbreset BBB/DDD   - reset by bus and device number
  usbreset "Product" - reset by product name

Devices:
  Number 001/004  ID 045e:07b2  Microsoft® Nano Transceiver v1.0
  Number 001/002  ID 04f3:0103
$ ./usbreset 001/004
Resetting Microsoft® Nano Transceiver v1.0 ... can't open [Permission denied]
$ sudo ./usbreset 001/004
Resetting Microsoft® Nano Transceiver v1.0 ... ok
$ sudo ./usbreset 045e:07b2
Resetting Microsoft® Nano Transceiver v1.0 ... ok

재설정에 대한 응답으로 kernel log에 다음이 나타납니다.

usb 1-6: reset full-speed USB device number 4 using xhci_hcd

이 세션에서 설명하는 내용:

그렇다면 usbreset은 무엇을 할까요? USB 장치의 device file에서 다음 명령으로 요약됩니다.

ioctl(fd, USBDEVFS_RESET, 0)

이것은 kernel의 usb_reset_device()에 대한 함수 호출로 끝납니다. 아이디어는 전체 프로세스를 원활하게 만드는 것입니다. 이 기능은 요청이 있는 경우 장치의 driver 에 재설정 전후에 대해 알려줍니다. 재설정하기 전에 driver를 바인딩 해제하고 나중에 다시 바인딩합니다. 재설정 후 장치의 configuration 도 로드됩니다. 이것이 없으면 장치는 bus address를 인식하지 못하고 데이터 교환을 위한 준비가 되지 않습니다.

따라서 거의 장치를 다시 연결하는 것과 같지만 자체 식별을 요청하지 않고(정보가 이미 알려져 있기 때문에) 새 주소를 할당하지 않습니다.

USB 3.x의 경우 덜 효율적인 유형인 hot reset입니다. 아래에서 hot reset 에 대해 자세히 알아보세요.

방법 #2: USB port의 power state 전환

이 목적을 위한 여러 도구도 있습니다. 이 방법을 hubpower로 시연하겠습니다. hubpower.c를 다운로드하고 compilation을 수행합니다.

$ gcc -O3 -Wall -g hubpower.c -o hubpower

명령이 USB 장치 자체로 전송되지 않기 때문에 이 도구를 사용하는 것은 다소 까다롭습니다. 대신 USB 장치가 연결된 USB hub 로 요청이 전송됩니다.

따라서 첫 번째 단계는 이것이 어떤 hub 인지 파악하는 것입니다. 먼저 USB 장치의 주소를 찾으십시오.

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 045e:07b2 Microsoft Corp.
Bus 001 Device 002: ID 04f3:0103 Elan Microelectronics Corp. ActiveJet K-2024 Multimedia Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

따라서 장치는 bus number 1 및 device number 4에 있습니다. device number는 USB 장치가 열거될 때마다 변경됩니다.

그렇다면 USB 장치는 어떤 hub 에 연결되어 있습니까? 그리고 어떤 port로?

$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
    |__ Port 6: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 6: Dev 4, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 6: Dev 4, If 2, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 11: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
    |__ Port 11: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M

따라서 장치 번호 4는 port #6에 연결됩니다. hub의 bus number는 1이고 device number는 1입니다( root hub로 기능하는 motherboard의 USB controller입니다).

hubpower가 이것에 대해 말하는 것을 보자:

$ sudo ./hubpower 1:1 status
Port  1 status: 0100  Power-On
Port  2 status: 0100  Power-On
Port  3 status: 0100  Power-On
Port  4 status: 0100  Power-On
Port  5 status: 0100  Power-On
Port  6 status: 0103  Power-On Enabled Connected
Port  7 status: 0100  Power-On
Port  8 status: 0100  Power-On
Port  9 status: 0100  Power-On
Port 10 status: 0100  Power-On
Port 11 status: 0303  Low-Speed Power-On Enabled Connected
Port 12 status: 0100  Power-On

"1:1" 부분은 hub의 bus address입니다. 외부 hub인 경우 이 address는 hub이 컴퓨터에 연결될 때마다 변경됩니다.

그러나 ports 의 번호는 절대 변경되지 않습니다(장치가 동일한 물리적 port에 연결되어 있는 한).

이제 기기의 port number를 알았으면 재설정해 보겠습니다.

$ sudo ./hubpower 1:1 power 6 off
Port  6 status: 0000  Power-Off
$ sudo ./hubpower 1:1 power 6 on
Port  6 status: 0100  Power-On

첫 번째 명령 후 장치는 kernel log에서 연결이 끊긴 것으로 보고됩니다.

usb 1-6: USB disconnect, device number 4

두 번째 명령 후 컴퓨터는 장치가 물리적으로 연결된 것처럼 동작합니다.

usb 1-6: new full-speed USB device number 5 using xhci_hcd
usb 1-6: New USB device found, idVendor=045e, idProduct=07b2, bcd Device= 7.04
usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-6: Product: Microsoft® Nano Transceiver v1.0
usb 1-6: Manufacturer: Microsoft
[ ... ]

이 re-enumeration로 인해 새 bus address가 장치에 할당됩니다.

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 045e:07b2 Microsoft Corp.
Bus 001 Device 002: ID 04f3:0103 Elan Microelectronics Corp. ActiveJet K-2024 Multimedia Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

그렇다면 이것은 USB 장치를 물리적으로 분리했다가 다시 연결하는 것과 같습니까? 대답은 아마도 다음과 같습니다. 대부분의 경우 hubpower 명령은 실제로 USB 장치의 전원 공급 장치를 끄지 않습니다. 따라서 장치는 계속해서 VBUS voltage (5V)를 수신합니다. 극소수의 USB hubs가 실제로 전원을 끕니다. 아래에서 이에 대해 자세히 알아보세요.

대부분의 hubs에서 첫 번째 명령("전원 끄기")은 port를 장치를 무시하는 상태로 만들기만 합니다. 두 번째 명령("전원 켜기")은 port를 원래 상태로 되돌립니다. 결과 장치가 감지되고 초기화 절차가 시작된다는 것입니다.무엇보다도 장치가 재설정되고 열거되며 driver가 초기화합니다.

따라서 특히 장치가 USB plug에서 전원 공급을 받는 경우 물리적 연결 해제가 일반적으로 이러한 명령보다 더 효과적입니다. 그러나 hub이 실제로 VBUS를 종료한다면 hubpower 도 그만큼 효과적입니다.

이 예에서 명령은 motherboard의 USB controller ( root hub)로 전송되었습니다. 그 이유는 USB 장치가 컴퓨터에 직접 연결되었기 때문입니다. 이 장치가 외부 hub을 통해 컴퓨터에 연결되어 있으면 이 외부 hub로 명령을 보내야 합니다. 두 경우 모두 hubpower는 같은 방식으로 사용됩니다.

불행히도hubpower는 USB 3.0 (SuperSpeed)를 지원하지 않습니다. 아래에서 자세히 알아보세요.

두 방법의 차이점

그렇다면 두 번째 방법( hubpower사용)은 첫 번째 방법( usbreset사용)과 어떻게 다릅니까? 장치의 문제를 해결하기 위해 두 방법 모두 기본적으로 동일한 작업을 수행합니다. 재설정 명령을 보냅니다. 이것이 일어나는 방식은 극적으로 다르지만 여전히 문제를 해결할 가능성이 있는 재설정 명령입니다.

그러나 몇 가지 중요한 차이점이 있습니다.

전기 장비 제어(?)

이 페이지의 주요 주제는 USB 장치의 문제를 해결하는 방법이지만 흥미로운 부작용도 있습니다. 때때로 USB port의 5V power supply을 제어할 수 있습니다. 즉, 간단하고 저렴한 USB hub을 사용하여 2.5 Watts를 처리할 수 있는 power supply을 켜고 끌 수 있습니다.

이것은 electromechanical relay를 제어하기에 충분합니다. 따라서 110V / 220V에서 실행되는 전기 제품을 제어하기 위해 하나의 구성 요소만 추가하면 됩니다. 음, USB hub이 손상되지 않도록 보호하기 위해 간단한 다이오드도 추가하는 것이 좋습니다. 하지만 그게 다야.

안타깝게도 power supply을 제어하는 기능은 선택 사항입니다. USB 2.0 사양의 섹션 11.11에 따르면 hub 에는 port가 Powered-Off 상태에 있을 때 5V power supply을 port 로 끄는 power switches가 있을 있습니다. 또는 power switch를 사용하여 여러 ports ("ganged power switching")의 전원 공급 장치를 제어할 수 있습니다. 전원 공급 장치를 제어하는 목적은 주로 너무 많은 전류를 소모하는 USB 장치를 차단하여 나머지 ports가 계속 정상적으로 작동할 수 있도록 하는 것입니다.

그러나 이미 언급했듯이 물리적 전원 제어는 선택 사항입니다. hubpower가 실제로 하는 일은 port의 PORT_POWER 속성( USB specifications에서는 "feature"라고 함)의 값을 변경하는 것입니다. 이 변경 사항은 hub의 port의 두 가지 다른 측면과 관련이 있습니다.

PORT_POWER는 아래에서 자세히 설명합니다.

내 hub이 전압을 제어합니까?

hub이 실제로 전압을 끄는지 어떻게 알 수 있습니까? 확실하게 알 수 있는 유일한 방법은 테스트하는 것입니다. USB 장치 가 아니지만 USB port에서 전력을 소비하는 모든 장치를 연결합니다. 실제 USB 장치는 혼란을 더할 수 있습니다. 예를 들어 광 마우스는 5V 전압이 남아 있더라도 일반적으로 전원 끄기 명령에 대한 응답으로 LED를 끕니다.

각 hub은 "lsusb -v"(사양의 섹션 11.23.2.1에 정의된 Hub Descriptor에서)로 표시되는 정보에서 전압 제어 여부와 세분성을 선언합니다. hub은 전압을 제어하지 않거나 ports ("gangs") 그룹의 전압을 제어하거나 각 port 의 전압을 개별적으로 제어한다고 선언할 수 있습니다. USB 2.0 사양의 섹션 11.11에 따르면 "a hub with power switches can switch power to all ports as a group/gang, to each port individually, or have an arbitrary number of gangs of one or more ports"입니다.

그러나 이 정보는 신뢰할 수 없습니다 . 나는 그들이 전압을 제어한다고 선언하는 여러 hubs를 만났지만 그들 중 누구도 그렇게 하지 않았습니다.

예를 들어, 이것은 "lsusb -v"의 출력입니다.

Bus 001 Device 073: ID 0bda:5411 Realtek Semiconductor Corp.
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass            9 Hub
  bDeviceSubClass         0 Unused
  bDeviceProtocol         2 TT per port
  bMaxPacketSize0        64
  idVendor           0x0bda Realtek Semiconductor Corp.
  idProduct          0x5411
  bcdDevice            1.23
  iManufacturer           1 Generic
  iProduct                2 4-Port USB 2.0 Hub
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:

[ ... ]

Hub Descriptor:
  bLength               9
  bDescriptorType      41
  nNbrPorts             4
  wHubCharacteristic 0x00a9
    Per-port power switching
    Per-port overcurrent protection
    TT think time 16 FS bits
    Port indicators
  bPwrOn2PwrGood        0 * 2 milli seconds
  bHubContrCurrent    100 milli Ampere
  DeviceRemovable    0x00
  PortPwrCtrlMask    0xff
 Hub Port Status:
   Port 1: 0000.0503 highspeed power enable connect
   Port 2: 0000.0503 highspeed power enable connect
   Port 3: 0000.0100 power
   Port 4: 0000.0100 power

낙관적으로 보이지 않습니까? 실제로 이 hub은 전압을 전혀 제어하지 않습니다.

대조적으로 이것은 일반 마더보드의 hub입니다.

Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 Unused
  bDeviceProtocol         1 Single TT
  bMaxPacketSize0        64
  idVendor           0x1d6b Linux Foundation
  idProduct          0x0002 2.0 root hub
  bcdDevice            4.15
  iManufacturer           3 Linux 4.15.0-20-generic xhci-hcd
  iProduct                2 xHCI Host Controller
  iSerial                 1 0000:06:00.0
  bNumConfigurations      1
  Configuration Descriptor:

[ ... ]

Hub Descriptor:
  bLength               9
  bDescriptorType      41
  nNbrPorts             2
  wHubCharacteristic 0x000a
    No power switching (usb 1.0)
    Per-port overcurrent protection
    TT think time 8 FS bits
  bPwrOn2PwrGood       10 * 2 milli seconds
  bHubContrCurrent      0 milli Ampere
  DeviceRemovable    0x00
  PortPwrCtrlMask    0xff
 Hub Port Status:
   Port 1: 0000.0100 power
   Port 2: 0000.0100 power
Device Status:     0x0001
  Self Powered

따라서 이 hub은 전압 제어를 지원하지 않는다는 점을 인정합니다.

전원 전환에 대한 정보 외에 "Hub Port Status"로 각 port 에 대한 상태 정보도 있습니다. 이러한 status bits는 USB 2.0 사양(섹션 11.24.2.7.1)의 표 11-21에 정의되어 있습니다. 이것은 hubpower에서 가져온 것과 동일한 정보입니다.

uhubctl 도구

USB hub 로 relay를 제어한다는 아이디어는 많은 이니셔티브의 동기가 되었습니다. 주로 이 프로젝트가 전압을 제어하는 USB hubs 목록을 유지하기 때문에 uhubctl을 살펴볼 가치가 있습니다.

이 도구는 분명히 전압 제어만을 위한 것이며 USB 장치의 문제를 해결하기 위한 것이 아닙니다. 예를 들어, 기본적으로 uhubctl은 각 port에 대해 개별적으로 전압을 제어하는 기능을 선언하지 않는 hubs를 무시합니다.

이러한 명령은 위의 hubpower 명령과 동일합니다.

$ sudo ./uhubctl -f -l 1 -p 6 -a 0
Current status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops]
  Port 6: 0103 power enable connect [045e:07b2 Microsoft Microsoft? Nano Transceiver v1.0]
Sent power off request
New status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops]
  Port 6: 0000 off
$ sudo ./uhubctl -f -l 1 -p 6 -a 1
Current status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops]
  Port 6: 0000 off
Sent power on request
New status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops]
  Port 6: 0100 power

명령 구문은 훨씬 덜 편리합니다. 아래에 간략하게 설명되어 있습니다.

uhubctl은 libusb를 기반으로 하므로 이 도구는 다른 운영 체제에서도 작동합니다. 반대로 hubpower는 /dev/bus/usb/ (또는 /proc/bus/usb/)에서 hub의 device file 에 직접 액세스하며 이는 Linux에서만 작동합니다.

uhubctl은 USB 3.x 도 지원합니다( git commit후속 조치 참조). 그러나 실제 USB 장치가 hub에 연결될 때 어떤 일이 발생하는지 아무도 신경 쓰지 않는 것 같습니다. SuperSpeed 장치를 재설정하려는 시도는 이상한 결과를 낳았습니다. power가 반환되었을 때 장치는 Polling 상태로 남아 있었고 열거되지 않았습니다. 또한 power가 꺼져 있는 동안 "lsusb -v"가 멈췄습니다. 그래서 거기에서 나쁜 일이 일어났습니다.

SuperSpeed port에서 전원을 껐다가 다시 켜는 명령입니다. SuperSpeed 에 대한 자세한 내용은 아래를 참조하십시오.

# ./uhubctl -f -e -l 2 -p 4 -a 0
# ./uhubctl -f -e -l 2 -p 4 -a 1

PORT_POWER 설명

host 에서 PORT_POWER를 0으로 변경하라는 명령이 도착하면 port는 무조건 Powered-off 상태로 들어갑니다. 이는 hub이 5V 전원 공급 장치를 장치에 계속 공급하는 경우에도 마찬가지입니다. PORT_POWER가 0이 되는 다른 이유, 특히 port 의 overcurrent 조건(장치가 너무 많은 전류를 소모함)이 있습니다.

PORT_POWER를 '1' 로 변경하는 유일한 방법은 host의 명령을 이용하는 것입니다. 이렇게 하면 port가 Disconnected 상태가 됩니다. 연결된 것이 없는 USB ports는 일반적으로 이 상태입니다. port에서 장치가 감지되면 잠시 후 상태가 Disabled 로 변경됩니다. 장치가 이미 연결되어 있고 PORT_POWER가 '1'로 변경되면 즉시 발생합니다.

이 상태에서 장치를 활성화하는 유일한 방법은 port를 재설정하는 것입니다( PORT_RESET사용, 아래 참조). host 만이 가능합니다. 따라서 hub이 할 수 있는 유일한 일은 주의가 필요한 연결된 장치가 있음을 host 에 알리는 것입니다.

이것은 port의 status bits 중 하나가 들어오는 곳입니다. PORT_CONNECTION. 이 bit은 port가 Powered-off 상태 또는 Disconnected 상태에 있을 때 0이어야 합니다. port가 Disconnected 상태에서 Disabled 상태로 전환될 때 PORT_CONNECTION은 '1' 로 변경됩니다. PORT_CONNECTION 의 변경 사항은 hub event를 생성하므로 driver 에 알립니다(즉, kernel의 hub.c 에서 port_event() 에 대한 함수 호출은 USB_PORT_FEAT_C_CONNECTION이 활성화된 상태에서 이루어짐). driver는 port를 재설정( port의 PORT_RESET 비트를 '1'로 변경)하고 연결된 장치를 열거하는 것으로 응답합니다.

이 모든 것은 USB 2.0와 관련이 있습니다. USB 2.0 사양의 그림 11-10은 hub의 port가 상태를 변경하는 방법을 보여줍니다.

PORT_RESET 및 PORT_ENABLE 직접 제어

hubpower 에는 두 가지 다른 속성을 직접 변경할 수 있는 기능도 있습니다. PORT_RESET 및 PORT_ENABLE. 사실 이 기능을 이 도구의 fork 에 추가했습니다. 그러나 이것으로 할 수 있는 일은 의도적으로 USB 장치를 고장나게 하는 것뿐입니다(따라서 컴퓨터가 장치를 재설정하여 문제를 해결하도록 함). 이제 더 자세히:

USB 2.0 사양의 섹션 11.5.1.5에 따라 port reset을 시작하려면 host 에서PORT_RESET을 '1' 로 설정해야 합니다. hub은 재설정을 완료한 후 PORT_RESET을 다시 '0' 로 변경합니다. hub은 자체 이니셔티브에서 port reset을 시작하지 않으며 host는 이 특성에 '0'을 쓸 수 없습니다(섹션 11.24.2.7.1.5).

이 hub은 port가 Powered-off 또는 Disconnected 상태인 경우 PORT_RESET을 무시합니다.

PORT_ENABLE관련: 이 속성이 '0'로 변경되면 port는 Disabled 상태로 변경됩니다. 이는 host의 요청, USB 장치의 연결 해제, port 의 전원이 꺼진 상태 또는 reset 프로세스 중 오류로 인해 발생할 수 있습니다.

PORT_ENABLE은 host 의 port reset 요청 결과로만 '1' 로 변경될 수 있습니다( USB 2.0 사양의 섹션 11.24.2.7.1.2).

따라서 host는 PORT_RESET을 '0' 로 변경하거나 PORT_ENABLE을 '1'로 변경할 수 없습니다. 이렇게 하면 hub 에서 오류 응답이 발생합니다(관련 ioctl() 명령은 error status를 반환함).

hubpower는 port의 PORT_RESET을 '1'로 변경하여 직접 재설정을 요청할 수 있습니다. 이렇게 하면 USB 장치가 재설정되고 결과적으로 장치에서 bus address가 지워집니다. 따라서 장치에 더 이상 액세스할 수 없습니다.

이 명령은 hub로 직접 전송되므로 Linux kernel 에 있는 hub의 driver는 이러한 일이 발생했음을 알 수 없습니다. 실제로 컴퓨터는 USB 장치에 액세스를 시도할 때까지 변경된 사항을 인식하지 못합니다. 다음에 일어날 일은 장치의 driver에 따라 다릅니다. 장치에 하드웨어 오류가 있는 것처럼 처리됩니다. 따라서 일종의 오류 정정 조치가 취해질 것입니다. 아마도 여기에는 재설정이 포함될 것입니다.

따라서 hubpower를 사용하여 직접 재설정하면 원하는 결과를 얻을 수 있지만 불필요한 드라마가 많이 있습니다. PORT_POWER는 이 작업을 보다 우아하게 수행합니다. 직접 PORT_RESET 의 유일한 장점은 driver가 "이 장치에 정말 문제가 있습니다. 문제를 해결하기 위해 과감한 조치를 취합시다"라고 말할 수 있다는 것입니다. 그리고 그것은 도움이 될 수 있습니다.

PORT_ENABLE을 조작하는 경우에도 마찬가지입니다. 장치가 갑자기 사라집니다. 이 경우에도 컴퓨터는 어떤 일이 발생했는지 즉시 알지 못합니다. USB 2.0 specification의 섹션 11.24.2.7.2.2에 따르면 PORT_ENABLE (예: C_PORT_ENABLE)에 대한 변경 알림은 링크 오류로 인해 port가 비활성화된 경우에만 트리거됩니다. 사양에는 이 알림이 다른 이유로 생성되지 않는다고 명시적으로 나와 있습니다.

따라서 PORT_ENABLE을 0으로 변경하면 PORT_RESET을 직접 변경하는 것과 대략 동일한 효과가 있습니다. 한 가지 단점: USB 3.0 사양의 섹션 10.14.2.6.1에 따르면 PORT_ENABLE "is not supported by SuperSpeed hubs"입니다.

SuperSpeed (USB 3.x)

맨 먼저: USB 3.x 장치에 문제가 있어서 이 글을 읽고 있다면 USB 3.x가 제공하는 data rate가 정말로 필요한지 자문해 보십시오. 대답이 부정적이면 USB 3.x를 지원하지 않는 USB hub (또는 짧은 USB 2.0 케이블)를 통해 장치를 컴퓨터에 연결해 보십시오. 이것만으로도 문제를 해결할 수 있습니다.

SuperSpeed USB ( USB 3.x와 같은 뜻)는 USB 2.0와 병렬로 공존한다. 모든 SuperSpeed 장치는 효과적으로 두 개의 장치로 구성됩니다. SuperSpeed를 위한 별도의 장치 하나와 USB 2.0을 위한 또 다른 장치. 이 두 USB versions는 각각 USB cable의 별도 와이어에 의존합니다. 이들은 전자적으로나 개념적으로 상호 독립적입니다.

USB 사양에서는 모든 SuperSpeed 장치가 이 두 장치로 구성되어야 하지만 실제로는 필요하지 않습니다. 즉, USB 2.0을 지원하지 않는 SuperSpeed 장치는 SuperSpeed port에 연결하면 제대로 작동합니다.

SuperSpeed 장치가 SuperSpeed port에 연결되면 첫 번째 시도는 SuperSpeed 인터페이스를 통해 연결하는 것입니다. 실패하면 USB 2.0을 통해 연결을 시도합니다. 실제로(및 사양에 따라) USB 장치는 동시에 두 버전을 통해 연결하지 않습니다. 그러나 이것은 가능하며 USB 장치가 두 개의 개별 장치인 것처럼 작동하도록 합니다.

SuperSpeed hub은 두 개의 hubs를 병렬로 구성합니다. 하나는 USB 2.0 용이고 다른 하나는 SuperSpeed용입니다. 외부 SuperSpeed USB hub을 컴퓨터에 연결하면 두 개의 hubs가 시스템에 추가됩니다. 두 개의 별도 장치로 나타납니다. 일반 USB 장치는 두 버전을 병렬로 사용할 수 없지만 hub은 이를 수행해야 합니다.

SuperSpeed hub이 USB 2.0 port에 연결되면 일반 USB 2.0 hub처럼 동작합니다.

일반적으로 이 두 hubs는 각각 서로 독립적으로 작동합니다. 각 hub 에는 자체 ports가 있으며 이러한 각 ports는 독립적으로 작동합니다. 특히, 이러한 병렬 hubs중 하나에서 port 의 매개변수가 변경되면 다른 hub의 ports에는 영향을 미치지 않습니다.

또 다른 결론은 "lsusb -t"가 SuperSpeed root hub을 통해 컴퓨터에 연결된 장치로 표시되면 SuperSpeed 장치로 작동한다는 것입니다. 즉, 데이터 속도는 5 Gbit/s 이상입니다. 마찬가지로 이 장치가 USB 2.0 root hub을 통해 연결되면 데이터 속도는 480 Mbit/s 이하입니다.

SuperSpeed 및 PORT_POWER

hubpower가 실제로 수행한 작업은 port의 PORT_POWER 특성을 변경한 것입니다.

그러나 SuperSpeed hub은 두 개의 hubs를 병렬로 구성합니다. 이 두 hubs 각각에는 각 port에 대한 고유한 독립적인 PORT_POWER 특성이 있습니다. 그렇다면 hub은 언제 VBUS power를 꺼야 할까요? 각각의 물리적 power switch는 각각의 병렬 hubs에서 하나씩 두 개의 PORT_POWER 속성에 의존합니다.

USB 3.0 specification 의 표 10-2는 hub이 전원 공급 장치를 활성화해야 하는지 여부에 대한 진리표를 제공합니다. 다음과 같이 요약할 수 있습니다. hub이 USB 2.0 hub 로만 작동하는 경우(예: SuperSpeed를 지원하지 않는 컴퓨터에 연결된 경우) USB 2.0의 PORT_POWER를 따릅니다. SuperSpeed hub 로 연결된 경우(또는 두 병렬 hubs가 연결된 경우) VBUS는 두 PORT_POWER가 모두 0인 경우에만 꺼집니다.

복잡하게 들린다면 실제로는 쉬운 부분이었습니다. hub 의 SuperSpeed 부분은 내부 state machine이 다릅니다. link training은 다르게 수행되기 때문에 상당히 예상됩니다. 그러나 이 state machine 에는 PORT_POWER가 0일 때 적합한 세 가지 상태( USB 2.0와 같은 하나 대신)가 있습니다.

마지막 두 상태의 목적은 자체 전원 공급 장치가 있는 SuperSpeed 장치가 port에 연결된 경우 연결이 USB 2.0로 폴백되지 않도록 하는 것입니다. 이는 장치가 SuperSpeed port에 연결되어 있음을 인식할 방법이 없기 때문에 발생합니다.

그래서 우리는 이것으로부터 무엇을 배웠습니까? 주로 SuperSpeed hub 에서 PORT_POWER를 변경하여 장치를 재설정하는 것은 USB 2.0 hub만큼 간단하지 않습니다.

SuperSpeed: warm reset 및 hot reset

USB 2.0 에는 장치를 재설정하는 한 가지 간단한 방법이 있습니다. 두 와이어 모두 hub 에서 ground (SE0)로 10ms 동안 연결됩니다. 반면에 SuperSpeed 장치에는 장치를 reset 하는 두 가지 방법이 있습니다. warm reset 및 hot reset. 재설정 이유를 정의하는 데 사용되는 용어인 PowerOn Reset 및 Inband Reset와 혼동해서는 안 됩니다. Inband Reset은 host의 요청으로 인해 재설정이 발생했음을 의미합니다. 요청 유형에 따라 warm reset 또는 hot reset이 될 수 있습니다(자세한 내용은 아래 참조).

warm reset 와 hot reset을 구별하는 것이 중요합니다. 특히 warm reset은 data stream을 중지하고 처음부터 다시 불러오는 작업을 포함합니다. hot reset은 data stream 자체에서 전송되며 이 data stream을 계속 실행합니다. 따라서 hot reset은 훨씬 빠르지만 data stream을 다시 시작하여 해결할 수 있는 문제가 있는 경우 warm reset이 필요합니다. 이러한 문제의 예는 physical layer에 bit errors가 있는 경우입니다. bitstream을 중단하고 다시 시작하면 equalizer의 최적이 아닌 튜닝을 수정할 수 있기 때문에 이 문제를 해결할 수 있습니다.

usbreset은 USBDEVFS_RESET와 함께 ioctl()을 수행합니다. 발생하는 다른 모든 일 중에서 장치의 USB 버전( Linux kernel v5.16기준)에 관계없이 PORT_RESET이 0으로 변경됩니다.

USB 3.0 사양 섹션 7.4.2에 따르면 PORT_RESET 요청은 Hot Reset이 됩니다. 즉, data stream이 활성 상태이면 분해되지 않지만 이 data stream에서 재설정 명령이 전송됩니다. 이 사양은 또한 BH_PORT_RESET (feature 번호 28)를 정의하며, 이는 warm reset을 강제 실행합니다( port가 비활성화되지 않은 경우). 이 재설정은 더 근본적입니다. data stream을 종료하고 다시 시작하는 절차를 다시 시작합니다( LFPS signaling덕분에). 중요한 차이점은 data stream을 다시 시작해야 하는 경우 BH_PORT_RESET은 다시 시작하지만 PORT_RESET은 다시 시작하지 않는다는 것입니다.

새 SuperSpeed 장치 연결에는 Warm Reset이 포함됩니다. 따라서 SuperSpeed port에서 PORT_POWER 로 트릭을 수행할 수 있는 도구가 없다는 것은 안타까운 일입니다. 위에서 언급했듯이 uhubctl은 기술적으로 이를 수행할 수 있지만 장치는 지저분한 상태로 끝납니다.


남은 점

유용할 수 있지만 적절한 컨텍스트가 없는 임의의 정보입니다.

이 페이지는 영어에서 자동으로 번역됩니다. 불분명한 사항이 있으면 원본 페이지를 참조하십시오.
Copyright © 2021-2024. All rights reserved. (38a9d8fd)