读取 USB HID 功能报告
Reading a USB HID feature report
我想从 USB 设备读取 HID 功能报告,我有 VendorID 和 DeviceID,并且可以保证只有一台设备符合该描述。
这个应该不难,但是看了MSDN文档感觉很迷茫。
我在几个小时内就在 linux 上运行了,感谢 libudev :)。但我需要一个原生 windows 实现(最好是 VC++,并且可能使用 Hidsdi.h 和/或 Setupapi.h)
谁能给我指出正确的方向。
它与本机 windows 库一起使用,它可能不是完成此任务的正确方法,但它有效。我建议不要直接使用这段代码,因为它很糟糕,但请随意阅读它以获取任何有用的信息。
找到设备 ID 为 0021 且供应商 ID 为 2833 的 HID
然后读取功能报告 0x0F;
#include <Windows.h>
#include <iostream>
#include <Setupapi.h>
#include <Hidsdi.h>
using namespace std;
// returns true if full_string contains the substring
BOOL findSubstring(WCHAR *full_string, const char *substring){
unsigned int c = 0, d = 0;
while (true) {
if (substring[d] == '[=10=]')
return true;
if (full_string[c] == '[=10=]')
return false;
d = (full_string[c] == substring[d]) ? d + 1 : 0;
if (c++ > MAX_PATH)
return false;
}
}
int main()
{
GUID guid;
HDEVINFO hDeviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail;
DWORD i = 0;
WCHAR *devicePath = NULL;
// Obtain a handle to the connected HID devices
HidD_GetHidGuid(&guid);
hDeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDeviceInfo == INVALID_HANDLE_VALUE) {
cerr << "Failed to get Device Handle" << endl;
return 1;
}
i = 0;
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
// Enumerate through all the HID devices
while (SetupDiEnumDeviceInterfaces(hDeviceInfo, NULL, &guid, i++, &deviceInterfaceData)) {
ULONG requiredSize;
// Get the details with null values to get the required size of the buffer
SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, NULL, 0, &requiredSize, 0);
deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredSize);
deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
// Fill the buffer with the device details
if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, deviceDetail, requiredSize, &requiredSize, NULL)) {
cerr << "Could not obtain the HID device for some reason" << endl;
SetupDiDestroyDeviceInfoList(hDeviceInfo);
free(deviceDetail);
return 1;
}
// Check that the device path contains two strings, which are our vendorID and pathID.
if (findSubstring(deviceDetail->DevicePath, "vid_2833") && findSubstring(deviceDetail->DevicePath, "pid_0021")) {
devicePath = deviceDetail->DevicePath;
}
}
if (devicePath != NULL) {
// Open the HID
HANDLE HIDfile = CreateFile(devicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD err = GetLastError();
if (err != 0) {
cerr << "unable to obtain read permissions for the HID device, error: " << err << endl;
} else {
// Allocate buffer for the feature report
BYTE buffer[30];
memset(buffer, 0, sizeof(buffer[0]));
buffer[0] = 0x0FU; // Feature report 0x0F
if (!HidD_GetFeature(HIDfile, buffer, sizeof(buffer))){
cout << "Feature report failed" << endl;
}
else {
cout << "Feature report successful" << endl;
for (int i = 0; i < 30; i++)
cout << hex << (int)buffer[i];
}
cout << endl;
}
}
// probably small memory leak
// free(deviceDetail);
SetupDiDestroyDeviceInfoList(hDeviceInfo);
return 0;
}
我想从 USB 设备读取 HID 功能报告,我有 VendorID 和 DeviceID,并且可以保证只有一台设备符合该描述。
这个应该不难,但是看了MSDN文档感觉很迷茫。
我在几个小时内就在 linux 上运行了,感谢 libudev :)。但我需要一个原生 windows 实现(最好是 VC++,并且可能使用 Hidsdi.h 和/或 Setupapi.h)
谁能给我指出正确的方向。
它与本机 windows 库一起使用,它可能不是完成此任务的正确方法,但它有效。我建议不要直接使用这段代码,因为它很糟糕,但请随意阅读它以获取任何有用的信息。
找到设备 ID 为 0021 且供应商 ID 为 2833 的 HID 然后读取功能报告 0x0F;
#include <Windows.h>
#include <iostream>
#include <Setupapi.h>
#include <Hidsdi.h>
using namespace std;
// returns true if full_string contains the substring
BOOL findSubstring(WCHAR *full_string, const char *substring){
unsigned int c = 0, d = 0;
while (true) {
if (substring[d] == '[=10=]')
return true;
if (full_string[c] == '[=10=]')
return false;
d = (full_string[c] == substring[d]) ? d + 1 : 0;
if (c++ > MAX_PATH)
return false;
}
}
int main()
{
GUID guid;
HDEVINFO hDeviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail;
DWORD i = 0;
WCHAR *devicePath = NULL;
// Obtain a handle to the connected HID devices
HidD_GetHidGuid(&guid);
hDeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDeviceInfo == INVALID_HANDLE_VALUE) {
cerr << "Failed to get Device Handle" << endl;
return 1;
}
i = 0;
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
// Enumerate through all the HID devices
while (SetupDiEnumDeviceInterfaces(hDeviceInfo, NULL, &guid, i++, &deviceInterfaceData)) {
ULONG requiredSize;
// Get the details with null values to get the required size of the buffer
SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, NULL, 0, &requiredSize, 0);
deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredSize);
deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
// Fill the buffer with the device details
if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, deviceDetail, requiredSize, &requiredSize, NULL)) {
cerr << "Could not obtain the HID device for some reason" << endl;
SetupDiDestroyDeviceInfoList(hDeviceInfo);
free(deviceDetail);
return 1;
}
// Check that the device path contains two strings, which are our vendorID and pathID.
if (findSubstring(deviceDetail->DevicePath, "vid_2833") && findSubstring(deviceDetail->DevicePath, "pid_0021")) {
devicePath = deviceDetail->DevicePath;
}
}
if (devicePath != NULL) {
// Open the HID
HANDLE HIDfile = CreateFile(devicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD err = GetLastError();
if (err != 0) {
cerr << "unable to obtain read permissions for the HID device, error: " << err << endl;
} else {
// Allocate buffer for the feature report
BYTE buffer[30];
memset(buffer, 0, sizeof(buffer[0]));
buffer[0] = 0x0FU; // Feature report 0x0F
if (!HidD_GetFeature(HIDfile, buffer, sizeof(buffer))){
cout << "Feature report failed" << endl;
}
else {
cout << "Feature report successful" << endl;
for (int i = 0; i < 30; i++)
cout << hex << (int)buffer[i];
}
cout << endl;
}
}
// probably small memory leak
// free(deviceDetail);
SetupDiDestroyDeviceInfoList(hDeviceInfo);
return 0;
}