AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1543042
Accepted
BZab
BZab
Asked: 2025-03-06 18:42:39 +0800 CST2025-03-06 18:42:39 +0800 CST 2025-03-06 18:42:39 +0800 CST

USB 集线器对下游端口具有独立的电源控制 - 系统可使其重新开启

  • 772

我正在编写一个小型 Python 模块,用于控制使用Cypress CY7C65631 (EZ-USB HX2LP) 芯片的 USB HUB。它所在的电路板有用于 VBUS 控制的外部 IC(所有启用和过流信号都连接到 HUB IC)和 GPIO Expander,让我可以监控上述线路上设置的逻辑值。

它运行在 Ubuntu 20.04.6 LTS 上,内核为 5.8(由 x86 主板制造商提供)。集线器由 PyUSB 的 ctrl 传输控制。与集线器的通信正常,系统正确识别集线器:

:~$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 04b4:6560 Cypress Semiconductor Corp. CY7C65640 USB-2.0 "TetraHub"
Bus 001 Device 017: ID 0781:55b1 SanDisk Corp. Dell KB216 Wired Keyboard
Bus 001 Device 003: ID 04b4:6560 Cypress Semiconductor Corp. CY7C65640 USB-2.0 "TetraHub"
Bus 001 Device 002: ID 413c:2113 Dell Computer Corp. Dell KB216 Wired Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

为了测试目的,我将一个 U 盘(包含一些数据)连接到其中一个端口。我现在想要实现的是:

  1. 启用一切并读取数据
  2. 只关闭单个端口,然后观察操作系统是否没有看到 U 盘设备
  3. 重新启用端口,查看设备自动识别并重新读取数据。

当我尝试进行上述测试时,我可以观察到端口已正确关闭,但一段时间后(时间会有所不同,但一般在 0.5 秒到 2 秒之间)端口又打开了。我怀疑这与 USB 驱动程序或负责 USB 设备电源管理的内核模块有关,但我不知道它到底是什么以及如何禁用它(或更改我控制端口的方式)。

我从测试中删除了第 3 点,首先验证我是否能够成功关闭端口。以下是我用来运行测试的日志和部分代码。

Hub 的描述符:

:~$ lsusb -vvv -d 04b4:6560

Bus 001 Device 003: ID 04b4:6560 Cypress Semiconductor Corp. CY7C65640 USB-2.0 "TetraHub"
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 
  bDeviceProtocol         1 Single TT
  bMaxPacketSize0        64
  idVendor           0x04b4 Cypress Semiconductor Corp.
  idProduct          0x6560 CY7C65640 USB-2.0 "TetraHub"
  bcdDevice            9.15
  iManufacturer           0 
  iProduct                2 EXTERNAL USB HUB
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0019
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              174mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         9 Hub
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 Full speed (or root) hub
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0001  1x 1 bytes
        bInterval              12
Hub Descriptor:
  bLength               9
  bDescriptorType      41
  nNbrPorts             4
  wHubCharacteristic 0x0089
    Per-port power switching
    Per-port overcurrent protection
    TT think time 8 FS bits
    Port indicators
  bPwrOn2PwrGood       50 * 2 milli seconds
  bHubContrCurrent    100 milli Ampere
  DeviceRemovable    0x00
  PortPwrCtrlMask    0xff
 Hub Port Status:
   Port 1: 0000.0100 power
   Port 2: 0000.0503 highspeed power enable connect
   Port 3: 0000.0100 power
   Port 4: 0000.0100 power
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 
  bDeviceProtocol         0 Full speed (or root) hub
  bMaxPacketSize0        64
  bNumConfigurations      1
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0001
  Self Powered

测试相关的部分dmesg(端口断电瞬间):

usb 1-3.2: USB disconnect, device number 16
[  +0.763930] usb 1-3.2: new high-speed USB device number 17 using xhci_hcd
[  +0.102990] usb 1-3.2: New USB device found, idVendor=0781, idProduct=55b1, bcdDevice= 1.10
[  +0.000009] usb 1-3.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0.000005] usb 1-3.2: Product: SanDisk 3.2 Gen1
[  +0.000004] usb 1-3.2: Manufacturer: SanDisk
[  +0.000004] usb 1-3.2: SerialNumber: A20019FE2628A724
[  +0.001528] usb-storage 1-3.2:1.0: USB Mass Storage device detected
[  +0.000650] scsi host2: usb-storage 1-3.2:1.0
[  +1.012410] scsi 2:0:0:0: Direct-Access     SanDisk  SanDisk 3.2 Gen1 DL17 PQ: 0 ANSI: 6
[  +0.000876] sd 2:0:0:0: Attached scsi generic sg0 type 0
[  +0.000414] sd 2:0:0:0: [sda] 126124032 512-byte logical blocks: (64.6 GB/60.1 GiB)
[  +0.000524] sd 2:0:0:0: [sda] Write Protect is off
[  +0.000006] sd 2:0:0:0: [sda] Mode Sense: 45 00 00 00
[  +0.000618] sd 2:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[  +0.082726]  sda: sda1 sda2
[  +0.002845] sd 2:0:0:0: [sda] Attached SCSI removable disk

测试代码的部分内容:

# b is the instance of the object abstracing the connected board
port_num = 2
print(b.external_usb_hub.get_port_status(port_num))
b.external_usb_hub.set_port_power(port_num, is_up=False)
print(b.external_usb_hub.get_port_status(port_num))
t = 0.
dt = 0.1
for _ in range(25):
    # read_hub_port_sig_n_ena reads the state of the input bit corresponding
    # to the ENA_n signal connecting the HUB Controller and the IC managing
    # the power on downstream ports. Signal ACTIVE means VBUS output is present.
    print(f"T = {round(t, 2)}: ", b.read_hub_port_sig_n_ena("external",port_num))
    sleep(dt)
    t += dt

class HUB:
    # get_port_status(...) is a beautified version of hub's method:
    def get_port_status_raw(self, port_num):
        return self.ctrl_transfer(
            bmRequestType=0xA3,
            bRequest=BRequest.GET_STATUS,
            wValue=0x0,
            wIndex=port_num,
            wLength=0x4,
        )
    
     def ctrl_transfer(
        self,
        bmRequestType,
        bRequest,
        wValue,
        wIndex,
        wLength=None,
        data=None,
        data_or_wLength=None,
    ):
        # Args verification omitted for clarity
        
        # self.dev is the instance returned by the usb.core.find(...)
        resp = self.dev.ctrl_transfer(
            bmRequestType=bmRequestType,
            bRequest=bRequest,
            wValue=wValue,
            wIndex=wIndex,
            data_or_wLength=data_or_wLength,
        )
        # Prevent timeouts with stacked xfers -- quick 'n dirty fix
        sleep(0.2)
        return resp

输出:

# Before disabling the port:
{'PortStatus.PORT_CONNECTION': 1, 'PortStatus.PORT_ENABLE': 0, 'PortStatus.PORT_SUSPEND': 1, 'PortStatus.PORT_OVER_CURRENT': 0, 'PortStatus.PORT_RESET': 0, 'PortStatus.PORT_POWER': 1, 'PortStatus.PORT_LOW_SPEED': 1, 'PortStatus.PORT_HIGH_SPEED': 0, 'PortStatus.PORT_TEST': 0, 'PortStatus.PORT_INDICATOR': 0, 'PortChange.C_PORT_CONNECTION': 0, 'PortChange.C_PORT_ENABLE': 0, 'PortChange.C_PORT_SUSPEND': 0, 'PortChange.C_PORT_OVER_CURRENT': 0, 'PortChange.C_PORT_RESET': 0}
# Right after disabling the port:
{'PortStatus.PORT_CONNECTION': 0, 'PortStatus.PORT_ENABLE': 0, 'PortStatus.PORT_SUSPEND': 0, 'PortStatus.PORT_OVER_CURRENT': 0, 'PortStatus.PORT_RESET': 0, 'PortStatus.PORT_POWER': 0, 'PortStatus.PORT_LOW_SPEED': 0, 'PortStatus.PORT_HIGH_SPEED': 0, 'PortStatus.PORT_TEST': 0, 'PortStatus.PORT_INDICATOR': 0, 'PortChange.C_PORT_CONNECTION': 0, 'PortChange.C_PORT_ENABLE': 0, 'PortChange.C_PORT_SUSPEND': 0, 'PortChange.C_PORT_OVER_CURRENT': 0, 'PortChange.C_PORT_RESET': 0}
T = 0.0:  GPIOExpState.INACTIVE
(...)
T = 1.2:  GPIOExpState.INACTIVE
# Here something toggles behind my back the power back on, port becomes enabled and device discovered
T = 1.3:  GPIOExpState.ACTIVE
(...)
drivers
  • 1 1 个回答
  • 58 Views

1 个回答

  • Voted
  1. Best Answer
    BZab
    2025-03-15T02:07:48+08:002025-03-15T02:07:48+08:00

    要在 Python 下执行此操作,无需提升权限:

    import usb.core
    
    # 'hub' is an instance of usb.core.Device
    connected = {
        d.port_number: d
        for d in usb.core.find(find_all=True)
        if d.parent == hub
    }
    connected[port_num].detach_kernel_driver(0)
    # Wrapper around the usb.core.Device.ctrl_transfer(...):
    clear_port_feature(hub, port_num, PortFeature.PORT_POWER) 
    
    • 0

相关问题

  • Ubuntu 中的科胜讯调制解调器

  • 如何解决联想笔记本电脑上恢复/电源问题时禁用的蓝牙?

  • 如何为 LG X130 上网本安装 relink 无线驱动程序

  • 类似于 Eyefinity 的东西?

  • 在哪里可以找到 Brother HL-2170W 64 位打印机驱动程序?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve