C++ HID WriteFile失败,错误为\u参数无效

C++ HID WriteFile失败,错误为\u参数无效,c++,c++11,winapi,hid,C++,C++11,Winapi,Hid,我正在尝试与通用HID设备(而不是鼠标或键盘)通信。根据微软的文档和我找到的一些示例代码,我已经到了我相信我可以开始与设备通信的地步。不幸的是,给它写信是行不通的 下面的代码达到了失败的程度。某些清理代码缺失或不完整,但代码应具有正确的VID和PID功能。请注意,调用setupDienumDeviceInterface中的硬编码1是我的设备在计算机上的索引 #include <Windows.h> #include <hidsdi.h> #include <Setu

我正在尝试与通用HID设备(而不是鼠标或键盘)通信。根据微软的文档和我找到的一些示例代码,我已经到了我相信我可以开始与设备通信的地步。不幸的是,给它写信是行不通的

下面的代码达到了失败的程度。某些清理代码缺失或不完整,但代码应具有正确的VID和PID功能。请注意,调用
setupDienumDeviceInterface
中的硬编码
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;
}
#包括
#包括
#包括
#包括
#包括
std::uint16_t constexpr vid=/*我的vid*/;
std::uint16_t constexpr pid=/*我的pid*/;
int main(int argc,char*argv[])
{
GUID-hidGuid;
HidD_GetHidGuid(&hidGuid);
HDEVINFO=SetupDiGetClassDevsA(&hidGuid、nullptr、nullptr、,
DIGCF_当前| DIGCF_设备接口);
if(info==无效的\u句柄\u值)
返回1;
SP_设备_接口_数据;
data.cbSize=sizeof(数据);
if(!SetupDienumDeviceInterface(信息、nullptr和hidGuid、1和数据))
返回1;
德沃德要求的尺寸;
如果(SetupDiGetDeviceInterfaceDetailA,信息和数据,空PTR,0,
&requiredSize,nullptr)| | GetLastError()!=错误_缓冲区不足)
返回1;
SP_设备_接口_详情_数据_A*详情数据=
静态浇铸(
标准:malloc(所需尺寸);
detailData->cbSize=sizeof(SP\u设备\u接口\u细节\u数据\u A);
如果(!SetupDiGetDeviceInterfaceDetailA(信息、数据、详细数据、,
所需大小、空PTR、空PTR)
返回1;
SetupDiDestroyDeviceInfo列表(信息);
HANDLE capsHandle=CreateFileA(detailData->DevicePath,0,
文件共享读取文件共享写入空PTR,
打开(现有,0,空PTR);
if(capsHandle==无效的句柄值)
返回1;
HIDD_属性属性属性;
属性大小=sizeof(属性);
if(!HidD_GetAttributes(capsHandle和attr))
返回1;
if(attr.VendorID!=vid | | attr.ProductID!=pid)
返回1;
PHIDP_PREPARSED_数据PREPARSED数据;
if(!HidD_GetPreparsedData(capsHandle和preparsedData))
返回1;
拉手;
HIDP_帽;
if(HidP_GetCaps(准备数据和caps)!=HidP_状态_成功)
返回1;
HidD_FreePreparsedData(preparsedData);
std::uint8\u t*输入缓冲区=
静态广播(标准::malloc(caps.InputReportByTeleLength));
std::uint8_t*输出缓冲区=
静态广播(标准::malloc(caps.OutputReportByTeleLength));
HANDLE hidHandle=CreateFileA(detailData->DevicePath,
通用读取、通用写入、文件共享读取、文件共享写入、,
nullptr,OPEN_EXISTING,0,nullptr);
if(hidHandle==无效的句柄值)
返回1;
零内存(outputBuffer,caps.OutputReportByTeleLength);
outputBuffer[0]=11;
outputBuffer[1]=12;
德沃德·拜特斯莱特;
如果(!WriteFile(hidHandle、outputBuffer、caps.OutputReportByTeleLength、,
&BytesWrited,nullptr))
{
auto x=GetLastError();
返回1;
}
返回0;
}

在调用
WriteFile
之前,这将按预期运行。此时,如果失败,x被分配值87(
ERROR\u INVALID\u PARAMETER
)。为什么这会失败?在我看来,所有参数都是正确的。

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

您删除了大量代码。所有的错误都在检查一个开始。MCVE会很好。你检查了所有参数的所有值了吗?或者你是在假设吗?所有函数的结果都会得到验证,都是通过在代码中测试它们,以及使用逐步调试程序验证数字。也许你弄错了。为什么我们不能有MCVE?你不需要帮助吗?我在工作中发布了问题,在家中发布了评论。我会尽快用MCVE更新。