什么是IOCTL_USB_GET_ROOT_HUB_NAME的目标设备(USB驱动程序特定的IOCTL IRQ)

时间:2011-03-28 09:03:53

标签: windows winapi usb driver wdk

我对USB IOCTL IOCTL_USB_GET_ROOT_HUB_NAME 感到有些困惑。它的目标设备是什么?虽然MSDN WDK文档清楚地表明了目标设备,但我仍然对WDK提供的USBVIEW示例感到困惑。我困惑的原因如下:

我不熟悉Windows中的内核模式和USB驱动程序,现在正在研究Windows驱动程序工具包http://msdn.microsoft.com/en-us/library/ff558728(v=vs.85).aspx中的USBVIEW示例。 MSDN描述了USBVIEW示例执行的第一步:

  

枚举主机控制器和root   集线器。主机控制器具有象征性   链接名称“HCDx”,其中x   从0开始。

     

使用CreateFile()打开每个主机   控制器符号链接。

     

在树视图中创建一个节点   代表每个主机控制器。

     

主控制器出现后   打开,发送主机控制器   IOCTL_USB_GET_ROOT_HUB_NAME请求   获取根的符号链接名称   作为主机一部分的集线器   控制器

但是,我在MSDN http://msdn.microsoft.com/en-us/library/ff537326(v=VS.85).aspx中仔细检查了IOCTL_USB_GET_ROOT_HUB_NAME的使用情况 其中说:

  

IOCTL_USB_GET_ROOT_HUB_NAME是一个   用户模式I / O控制请求。这个   请求的目标是 USB集线器FDO

请注意,IOCTL_USB_GET_ROOT_HUB_NAME IRP的目标是USB Hub FDO。但是,如USBVIEW示例所述,我们只是检索了主机控制器符号链接,这意味着设备对象是主机控制器设备对象。我们怎样才能发送IOCTL_USB_GET_ROOT_HUB_NAME个IRP?我们应该首先以某种方式检索USB集线器FDO吗?

2 个答案:

答案 0 :(得分:2)

我猜这是一个不幸的复制粘贴错误。 IOCTL_USB_GET_ROOT_HUB_NAME确实已发送到主机控制器,因此由USB主机控制器FDO处理。

顺便说一句,只是为了让你进入上下文: 术语“FDO”只是松散地涉及用户模式 ​​- 它不像你可以访问任何其他“xDO”。如果您要在内核模式下发送此IOCTL,那么您可以将IOCTL发送到设备堆栈中的任何特定设备对象(“可以”并不意味着“应该”,请注意)。但是,来自用户模式应用程序的DeviceIoControl总是将IOCTL发送到设备堆栈的顶部(因此它会将所有过滤器,FDO和下行链路传递给PDO)。

这个问题是在3月28日被问到的,所以我真的希望你现在已经解决了这个问题:)

答案 1 :(得分:0)

正如文档所述,您需要一个USB主控制器的句柄,但不清楚您应该如何获得这样的句柄。在USBView中,类似于此函数的内容用于通过传递GUID_DEVINTERFACE_USB_HOST_CONTROLLER(包括initguid.husbiodef.h)获取设备路径名称:

vector<wstring> EnumDevices(
    _In_    const GUID Guid
)
{
    vector<wstring> r;

    int index = 0;
    HDEVINFO hDevInfo = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    SP_DEVINFO_DATA DevInfoData;
    memset(&DevInfoData, 0, sizeof(SP_DEVINFO_DATA));
    DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    while (SetupDiEnumDeviceInfo(hDevInfo, index, &DevInfoData)) {
        index++;

        int jndex = 0;
        SP_DEVICE_INTERFACE_DATA DevIntData;
        memset(&DevIntData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
        DevIntData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

        while (SetupDiEnumDeviceInterfaces(
            hDevInfo,
            &DevInfoData, &Guid, jndex, &DevIntData
        )) {
            jndex++;

            // Get the size required for the structure.
            DWORD RequiredSize;
            SetupDiGetDeviceInterfaceDetail(
                hDevInfo, &DevIntData, NULL, NULL, &RequiredSize, NULL
            );

            PSP_DEVICE_INTERFACE_DETAIL_DATA pDevIntDetData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(
                sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + RequiredSize
            );
            memset(pDevIntDetData, 0, sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + RequiredSize);
            pDevIntDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

            SetupDiGetDeviceInterfaceDetail(
                hDevInfo,
                &DevIntData,
                pDevIntDetData, RequiredSize,
                NULL,
                &DevInfoData
            );

            r.push_back(wstring(pDevIntDetData->DevicePath));
            free(pDevIntDetData);
        }
    }

    return r;
}

请记住使用上述功能,您还可以请求类型为GUID_DEVINTERFACE_USB_HUBGUID_DEVINTERFACE_USB_DEVICE的设备,这样就无需直接与主机控制器或集线器进行交互。