我正在尝试与通用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
)。为什么会失败?所有参数对我来说都是正确的。
答案 0 :(得分:0)
与生产我们设备的人沟通后,我发现问题是输出缓冲区填写错误。非零的两个字节应该是索引1和2处的字节,而不是索引0和1处的字节。