HID WriteFile 失败并显示 ERROR_INVALID_PARAMETER

HID WriteFile fails with ERROR_INVALID_PARAMETER

我正在尝试与通用 HID 设备(不是鼠标或键盘)通信。按照 Microsoft 的文档和我找到的一些示例代码,我已经到了我相信我可以开始与设备通信的地步。不幸的是,写入它不起作用。

以下代码到了失败的地步。一些清理代码丢失或不完整,但代码应该可以使用正确的 VID 和 PID。请注意,SetupDiEnumDeviceInterfaces 调用中的硬编码 1 是我的设备在计算机上的索引。

#include <Windows.h>
#include <hidsdi.h>
#include <SetupAPI.h>
#include <cstdlib>
#include <cstdint>
std::uint16_t constexpr vid = /* My VID */;
std::uint16_t constexpr pid = /* My PID */;

int main(int argc, char* argv[])
{
    GUID hidGuid;
    HidD_GetHidGuid(&hidGuid);
    HDEVINFO info = SetupDiGetClassDevsA(&hidGuid, nullptr, nullptr,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (info == INVALID_HANDLE_VALUE)
        return 1;
    SP_DEVICE_INTERFACE_DATA data;
    data.cbSize = sizeof(data);
    if (!SetupDiEnumDeviceInterfaces(info, nullptr, &hidGuid, 1, &data))
        return 1;
    DWORD requiredSize;
    if (SetupDiGetDeviceInterfaceDetailA(info, &data, nullptr, 0,
        &requiredSize, nullptr) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        return 1;
    SP_DEVICE_INTERFACE_DETAIL_DATA_A* detailData =
        static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>(
            std::malloc(requiredSize));
    detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
    if (!SetupDiGetDeviceInterfaceDetailA(info, &data, detailData,
        requiredSize, nullptr, nullptr))
        return 1;
    SetupDiDestroyDeviceInfoList(info);
    HANDLE capsHandle = CreateFileA(detailData->DevicePath, 0,
        FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
        OPEN_EXISTING, 0, nullptr);
    if (capsHandle == INVALID_HANDLE_VALUE)
        return 1;
    HIDD_ATTRIBUTES attr;
    attr.Size = sizeof(attr);
    if (!HidD_GetAttributes(capsHandle, &attr))
        return 1;
    if (attr.VendorID != vid || attr.ProductID != pid)
        return 1;
    PHIDP_PREPARSED_DATA preparsedData;
    if (!HidD_GetPreparsedData(capsHandle, &preparsedData))
        return 1;
    CloseHandle(capsHandle);
    HIDP_CAPS caps;
    if (HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS)
        return 1;
    HidD_FreePreparsedData(preparsedData);
    std::uint8_t* inputBuffer =
        static_cast<std::uint8_t*>(std::malloc(caps.InputReportByteLength));
    std::uint8_t* outputBuffer =
        static_cast<std::uint8_t*>(std::malloc(caps.OutputReportByteLength));
    HANDLE hidHandle = CreateFileA(detailData->DevicePath,
        GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
        nullptr, OPEN_EXISTING, 0, nullptr);
    if (hidHandle == INVALID_HANDLE_VALUE)
        return 1;
    ZeroMemory(outputBuffer, caps.OutputReportByteLength);
    outputBuffer[0] = 11;
    outputBuffer[1] = 12;
    DWORD bytesWritten;
    if (!WriteFile(hidHandle, outputBuffer, caps.OutputReportByteLength,
        &bytesWritten, nullptr))
    {
        auto x = GetLastError();
        return 1;
    }
    return 0;
}

这会按预期运行,直到调用 WriteFile。此时如果失败并且 x 被分配值 87 (ERROR_INVALID_PARAMETER)。为什么会失败?所有参数对我来说似乎都是正确的。

经过与生产我们设备的人沟通,我发现问题是输出缓冲区填错了。 non-zero 的两个字节应该是索引 1 和 2 处的字节,而不是索引 0 和 1 处的字节。