HID WriteFile失败,出现ERROR_INVALID_PARAMETER

时间:2017-01-11 22:34:23

标签: c++ c++11 winapi hid

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

以下代码可以解决问题。某些清理代码缺失或不完整,但代码应该使用正确的VID和PID。请注意,1调用中的硬编码SetupDiEnumDeviceInterfaces是我的设备在我的计算机上的索引。

#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)。为什么会失败?所有参数对我来说都是正确的。

1 个答案:

答案 0 :(得分:0)

与生产我们设备的人沟通后,我发现问题是输出缓冲区填写错误。非零的两个字节应该是索引1和2处的字节,而不是索引0和1处的字节。