10

我正在将应用程序从 DirectInput 切换到 RawInput 以进行游戏手柄处理,并且我想为每个游戏手柄提供人类可读的描述。理想的情况是出现在设备管理器中的设备文本,但 USB 产品描述也可以。任何方法都应该在没有管理员许可的情况下工作。

到目前为止,我发现了一组线索:注册表中似乎有一个文本字段,其下HKLM\SYSTEM\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM与 DirectInput 提供的名称相同。这并不完美 - 我有一个在设备管理器中以英文显示的游戏手柄,但在注册表中列为氀。

有没有办法从提供的 HANDLEWM_INPUT到设备管理器描述?HidD_GetProductString看起来很有希望,但我不知道如何从 RawInput 句柄中获取 Hid 顶级集合句柄。

编辑:我有一个设备实例路径(例如\\?\HID#VID_1267&PID_A001#8&1d630df6&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030},这可能足以从 SetupAPI 中提取我需要的信息。有没有人知道如何在给定实例路径的情况下到达此路径?

4

3 回答 3

4

我一直有类似的问题,并相信我找到了一个潜在的解决方案。

看来您必须CreateFile使用 RawInput 提供的名称GetRawInputDeviceInfo作为RIDI_DEVICENAME参数uiCommand的参数进行调用。这将为您提供可以调用的设备的句柄HidD_GetProductString

wchar_t DeviceName[126];
HANDLE HIDHandle = CreateFile(RawInputDeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if(HIDHandle)
{
    BOOLEAN Result = HidD_GetProductString(HIDHandle, DeviceName, sizeof(wchar_t) * 126);
    CloseHandle(HIDHandle);
}

但是,似乎HidD_GetProductString在我系统上连接的大多数设备上都失败了,并且似乎只在我的 USB 键盘和网络摄像头上成功了。我的 USB 鼠标没有成功。我还没有发现为什么会这样,但也许我的进步会对你有所帮助。

于 2012-11-18T22:18:04.957 回答
0

您可以获得顶级集合的句柄,如下所述:https ://msdn.microsoft.com/en-us/library/windows/hardware/ff538731%28v=vs.85%29.aspx

于 2015-06-01T17:17:46.203 回答
0

对于 HID 设备,您可以使用HidD_GetProductString,但键盘和鼠标不能通过 Windows 上的 HID API 使用,并作为单独的设备类型公开:GUID_DEVINTERFACE_KEYBOARD / GUID_DEVINTERFACE_MOUSE(出于安全原因,用户模式应用程序无法直接读取它们)。

您可以从设备接口符号链接获取他们的设备信息,如下所示:

  • 使用CM_Get_Device_Interface_PropertySetupDiGetDeviceInterfacePropertywithDEVPKEY_Device_InstanceId获取设备实例 ID(一个设备可以有多个接口)。

  • 获得设备实例 ID 后,您可以使用CM_Get_DevNode_PropertySetupDiGetDevicePropertywithDEVPKEY_NAME来获取设备的本地化友好名称(显示在设备管理器中)。

这是我的测试仓库CM_*中通过API的示例代码:

bool FillDeviceInfo(const std::wstring& deviceInterfaceName)
{
    // you need to provide deviceInterfaceName
    // example from my system: `\\?\HID#VID_203A&PID_FFFC&MI_01#7&2de99099&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}`

    DEVPROPTYPE propertyType;
    ULONG propertySize = 0;
    CONFIGRET cr = ::CM_Get_Device_Interface_PropertyW(deviceInterfaceName.c_str(), &DEVPKEY_Device_InstanceId, &propertyType, nullptr, &propertySize, 0);

    if (cr != CR_BUFFER_SMALL)
        return false;

    std::wstring deviceId;
    deviceId.resize(propertySize);
    cr = ::CM_Get_Device_Interface_PropertyW(deviceInterfaceName.c_str(), &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE)deviceId.data(), &propertySize, 0);

    if (cr != CR_SUCCESS)
        return false;

    // here is deviceId will contain device instance id
    // example from my system: `HID\VID_203A&PID_FFFC&MI_01\7&2de99099&0&0000`

    DEVINST devInst;
    cr = ::CM_Locate_DevNodeW(&devInst, (DEVINSTID_W)deviceId.c_str(), CM_LOCATE_DEVNODE_NORMAL);

    if (cr != CR_SUCCESS)
        return false;

    propertySize = 0;
    cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, nullptr, &propertySize, 0);

    if (cr != CR_BUFFER_SMALL)
        return false;

    std::wstring friendlyString;
    friendlyString.resize(propertySize);
    cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, (PBYTE)friendlyString.data(), &propertySize, 0);

    // here is friendlyString will contain localized device friendly name

    propertySize = 0;
    cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_Device_Manufacturer, &propertyType, nullptr, &propertySize, 0);

    if (cr != CR_BUFFER_SMALL)
        return false;

    std::wstring manufacturer;
    manufacturer.resize(propertySize);
    cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_Device_Manufacturer, &propertyType, (PBYTE)manufacturer.data(), &propertySize, 0);

    // here is manufacturer will contain localized device "manufacturer-identifier"

    return true;
}

更新:原来HidD_GetProductString和家人正在为 HID 键盘和鼠标工作。您只需以只读方式打开其设备接口(路径)。例如,请参阅https://github.com/DJm00n/RawInputDemo/blob/master/RawInputLib/RawInputDevice.cpp#L77-L86

于 2020-10-12T15:48:55.633 回答