如何为RawInput HID设备获取人类可读的名称?

时间:2012-09-29 20:29:31

标签: windows device hid

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

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

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

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

3 个答案:

答案 0 :(得分:3)

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

似乎您必须使用CreateFile作为GetRawInputDeviceInfo参数的参数调用RIDI_DEVICENAME来调用uiCommand并使用RawInput提供的名称。这将为您提供设备的句柄,您可以使用该句柄调用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鼠标没有成功。我还没有发现为什么会这样,但也许我的进步会帮助你。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

您可以从设备界面符号链接中获取其设备信息,如下所示:

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

  • 有了设备实例ID后,可以将CM_Get_DevNode_PropertySetupDiGetDevicePropertyDEVPKEY_NAME一起使用,以获取设备的本地化友好名称(在设备管理器中显示)。 / p>

以下是来自my test repoCM_* 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;
}