0

我需要检测何时为我的游戏插入了游戏手柄(出于某种原因,我没有使用更高级别的输入 API),我该怎么做?我已经枚举了所有 HID 设备并在它们上打开了文件(键盘、鼠标除外),并且可以获得设备上的所有信息,但我想要什么信息?例如,什么值会立即告诉我这是一个 Xbox 控制器,这些值在哪里?

我用于枚举设备的代码(非常混乱的 atm :p):

    DWORD required_size = 0, determined_size;
    SP_DEVICE_INTERFACE_DATA device_interface_data;
    device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data;
    HANDLE current_device;
    PHIDP_PREPARSED_DATA preparsed_data;
    WCHAR product_string[128];

    for (int i = 0; ; ++i) /* Enumerate HID devices */
    {
        rv = SetupDiEnumDeviceInterfaces(device_enumeration, NULL, &interface_guid, i, &device_interface_data); /* Does the actual enumeration,
                                                                                                                each time we increase index i
                                                                                                                to get the next device */      
        error = GetLastError();
        if (error == ERROR_NO_MORE_ITEMS) /* If there are no more devices, break */
            break;
        else if (!rv && error != ERROR_NO_MORE_ITEMS) /* Otherwise, we have a legit error */
        {
            cr_print_error(GetLastError());
            return EXIT_FAILURE;
        }

        SetupDiGetDeviceInterfaceDetail(device_enumeration, &device_interface_data, NULL, 0, &required_size, NULL); /* Probing call only to get buffer size,
                                                                                                                    so error code (122) ignored */
        /* Allocate new device detail struct using buffer size we obtained */
        determined_size = required_size;
        device_interface_detail_data = cr_safe_malloc(required_size);
        device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        /* Get detailed info about device */
        rv = SetupDiGetDeviceInterfaceDetail(device_enumeration, &device_interface_data, device_interface_detail_data, determined_size, &required_size, NULL);

        if (!rv)
        {
            cr_print_error(GetLastError());
            return EXIT_FAILURE;
        }

        cr_printf("FOUNDD DEVICE: %s\n\n", device_interface_detail_data->DevicePath);
        
        current_device = cr_open_device(device_interface_detail_data->DevicePath);

        if (!current_device && GetLastError() == ERROR_ACCESS_DENIED)
            goto Done;

        cr_printf("OPENED DEVICE: %s\n\n", device_interface_detail_data->DevicePath);

        preparsed_data = HidD_GetPreparsedData(current_device, &preparsed_data);

        if (!preparsed_data)
        {
            cr_print_error(GetLastError());
            return EXIT_FAILURE;
        }

        HidD_GetProductString(current_device, product_string, sizeof(product_string));

        cr_printf("PRODUCT STRING: %S\n\n", product_string);

        HidD_FreePreparsedData(&preparsed_data);
        DeleteFile(device_interface_detail_data->DevicePath);
    Done:
        cr_safe_free(&device_interface_detail_data);
    }

    SetupDiDestroyDeviceInfoList(device_enumeration);

如您所见,我找到了产品字符串,它告诉我设备实际上是什么,但也许比较产品字符串不是进行 PnP 的最佳方式?

4

1 回答 1

0

检查设备 ID 是否包含“IG_”。如果是这样,那么它就是一个 XInput 设备。 更多信息。但是哪个设备对应哪个 XInput dwUserIndex 是更难的问题......

您也可以尝试检查 XUSB 接口:

// {EC87F1E3-C13B-4100-B5F7-8B84D54260CB}
DEFINE_GUID(XUSB_INTERFACE_CLASS_GUID, 0xEC87F1E3, 0xC13B, 0x4100, 0xB5, 0xF7, 0x8B, 0x84, 0xD5, 0x42, 0x60, 0xCB);
于 2021-05-03T11:00:14.273 回答