You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UEFI程序如何读取实际USB端口数?使用GetCapability获额外端口

读取UEFI环境下实际USB端口数量的实现方法

你遇到的问题是因为GetCapability方法返回的是USB控制器硬件支持的最大端口数,其中包含了未物理部署的虚端口,并非实际存在的物理端口数量。要获取真实的物理端口数,需要遍历每个端口并检查其物理存在状态。

核心实现思路

通过USB控制器协议提供的GetPortStatus接口,逐个检查每个端口的PortExists状态位——该位为TRUE时表示此端口是物理存在的。

具体实现步骤

  1. 获取系统中的USB控制器句柄(可通过LocateHandleBuffer枚举所有支持USB HC协议的句柄)
  2. 对每个控制器句柄,获取对应的USB协议(兼容USB 1.1和USB 2.0版本)
  3. 调用GetCapability获取控制器支持的最大端口数
  4. 遍历每个端口,调用GetPortStatus检查PortExists位,统计物理存在的端口数量

示例代码

#include <Uefi.h>
#include <Protocol/UsbHc.h>
#include <Protocol/Usb2Hc.h>

UINTN GetPhysicalUsbPortCount(EFI_HANDLE UsbHcHandle) {
    EFI_STATUS Status;
    UINTN PortCount = 0;
    EFI_USB_HC_CAPABILITY HcCapability;
    EFI_USB_PORT_STATUS PortStatus;

    // 优先尝试获取USB 2.0控制器协议
    EFI_USB2_HC_PROTOCOL *Usb2Hc = NULL;
    Status = gBS->HandleProtocol(UsbHcHandle, &gEfiUsb2HcProtocolGuid, (VOID**)&Usb2Hc);
    if (!EFI_ERROR(Status)) {
        Status = Usb2Hc->GetCapability(Usb2Hc, &HcCapability);
        if (EFI_ERROR(Status)) return 0;

        for (UINTN PortNum = 1; PortNum <= HcCapability.MaxPortNumber; PortNum++) {
            Status = Usb2Hc->GetPortStatus(Usb2Hc, PortNum, &PortStatus);
            if (!EFI_ERROR(Status) && PortStatus.PortExists) {
                PortCount++;
            }
        }
        return PortCount;
    }

    // 兼容USB 1.1控制器协议
    EFI_USB_HC_PROTOCOL *UsbHc = NULL;
    Status = gBS->HandleProtocol(UsbHcHandle, &gEfiUsbHcProtocolGuid, (VOID**)&UsbHc);
    if (EFI_ERROR(Status)) return 0;

    Status = UsbHc->GetCapability(UsbHc, &HcCapability);
    if (EFI_ERROR(Status)) return 0;

    for (UINTN PortNum = 1; PortNum <= HcCapability.MaxPortNumber; PortNum++) {
        Status = UsbHc->GetPortStatus(UsbHc, PortNum, &PortStatus);
        if (!EFI_ERROR(Status) && PortStatus.PortExists) {
            PortCount++;
        }
    }
    return PortCount;
}

// 枚举所有USB控制器并计算总端口数
UINTN GetTotalPhysicalUsbPorts() {
    EFI_HANDLE *UsbHcHandles = NULL;
    UINTN HandleCount = 0;
    EFI_STATUS Status;
    UINTN TotalPorts = 0;

    // 枚举所有支持USB HC协议的控制器句柄
    Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiUsbHcProtocolGuid, NULL, &HandleCount, &UsbHcHandles);
    if (!EFI_ERROR(Status)) {
        for (UINTN i = 0; i < HandleCount; i++) {
            TotalPorts += GetPhysicalUsbPortCount(UsbHcHandles[i]);
        }
        gBS->FreePool(UsbHcHandles);
    }

    // 补充枚举USB 2.0控制器(部分设备可能仅注册此协议)
    Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiUsb2HcProtocolGuid, NULL, &HandleCount, &UsbHcHandles);
    if (!EFI_ERROR(Status)) {
        for (UINTN i = 0; i < HandleCount; i++) {
            TotalPorts += GetPhysicalUsbPortCount(UsbHcHandles[i]);
        }
        gBS->FreePool(UsbHcHandles);
    }

    return TotalPorts;
}

关键注意事项

  • 端口存在判断:必须依赖PortExists位,而非PortConnectStatus(后者仅表示是否有设备连接)或PortEnabledStatus(后者表示端口是否启用)
  • 协议兼容性:需同时处理USB 1.1和USB 2.0控制器协议,避免遗漏设备
  • 控制器初始化:调用上述函数前,确保USB控制器已通过Initialize接口完成初始化,否则可能无法正确获取端口状态

内容的提问来源于stack exchange,提问作者yiii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:02:24