Hey Jan,
I could easily understand and play with your Visual C++ code snippets in 3rd edition. But I cannot compile your visual C++ code put up on the website. Also I cannot think of making any changes to the Visual C# code, so I decided to rewrite everything starting from basics, that way I can get a clear understanding and find where the problem actually lies instead of working in loops and hitting a dead end. I made some progress. Here is my simple code -
#include <iostream>
#include <windows.h>
#include <hidclass.h>
#include <hidsdi.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
#pragma comment(lib,"hid")
int main()
{
GUID HidGuid;
HidD_GetHidGuid(&HidGuid);
//HANDLE DeviceInfoSet;
HDEVINFO DeviceInfoSet;
DeviceInfoSet = SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
/**/
if(DeviceInfoSet== INVALID_HANDLE_VALUE)
return NULL;
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData;
MyDeviceInterfaceData.cbSize = sizeof(MyDeviceInterfaceData);
SP_DEVINFO_DATA dd;
dd.cbSize = sizeof(SP_DEVINFO_DATA);
HANDLE DeviceHandle=NULL;
for (DWORD MemberIndex = 0; SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, &HidGuid, MemberIndex, &MyDeviceInterfaceData); MemberIndex++)
{
SP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
DetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
DWORD Length = 0;
if (!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, NULL, 0, &Length, NULL))
{
int err = GetLastError();
if (err == ERROR_NO_MORE_ITEMS)
break;
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, Length);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, pInterfaceDetailData, Length, &Length, &dd))
break;
DeviceHandle = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);
HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(Attributes);
HidD_GetAttributes(DeviceHandle, &Attributes);
const unsigned int VendorID = 0x1F38;
const unsigned int ProductID = 0x0100;
if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
std::cout << "The Vendor ID and Product ID match.";
std::cout << "\nDeviceHandle: " << DeviceHandle;
std::cout << "\nVendor ID: " << Attributes.VendorID;
std::cout << "\nProduct ID: " << Attributes.ProductID;
std::cout << "\nVersionNumber: " << Attributes.VersionNumber;
std::cout << "\nSize: " << Attributes.Size;
PHIDP_PREPARSED_DATA PreparsedData;
HidD_GetPreparsedData(DeviceHandle, &PreparsedData);
HIDP_CAPS Capabilities;
HidP_GetCaps(PreparsedData, &Capabilities);
std::cout << "\nUsage: " << Capabilities.Usage;
std::cout << "\nUsagePage: " << Capabilities.UsagePage;
std::cout << "\nInputReportByteLength: " << Capabilities.InputReportByteLength;
std::cout << "\nOutputReportByteLength: " << Capabilities.OutputReportByteLength;
std::cout << "\nNumberLinkCollectionNodes: " << Capabilities.NumberLinkCollectionNodes;
std::cout << "\nNumberInputButtonCaps: " << Capabilities.NumberInputButtonCaps;
std::cout << "\nNumberInputValueCaps: " << Capabilities.NumberInputValueCaps;
std::cout << "\nNumberInputDataIndices: " << Capabilities.NumberInputDataIndices;
std::cout << "\nNumberOutputButtonCaps: " << Capabilities.NumberOutputButtonCaps;
std::cout << "\nNumberOutputValueCaps: " << Capabilities.NumberOutputValueCaps;
std::cout << "\nNumberOutputDataIndices: " << Capabilities.NumberOutputDataIndices;
CHAR InputReportBuffer[3];
DWORD BytesRead;
DWORD Result;
HANDLE hEventObject;
OVERLAPPED HIDOverlapped;
hEventObject = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, FALSE, TRUE, NULL);
HIDOverlapped.hEvent = hEventObject;
HIDOverlapped.Offset = 0;
HIDOverlapped.OffsetHigh = 0;
// Set the first byte in the buffer to the Report ID.
InputReportBuffer[0] = 0;
HANDLE ReadHandle = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); //NULL, NULL);
if (ReadHandle == INVALID_HANDLE_VALUE)
std::cout << "\ncould not open";
else
std::cout << "\nopened";
Result = ReadFile(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength, &BytesRead, (LPOVERLAPPED)&HIDOverlapped); //NULL);
Result = WaitForSingleObject(hEventObject, 3000);
switch (Result)
{
case WAIT_OBJECT_0:
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer: " << InputReportBuffer;
// Success;
// Use the report data;
break;
}
case WAIT_TIMEOUT:
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer: " << InputReportBuffer;
// Timeout error;
//Cancel the read operation.
CancelIo(ReadHandle);
break;
}
default:
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer: " << InputReportBuffer;
// Undefined error;
//Cancel the read operation.
CancelIo(ReadHandle);
break;
}
}
}
}
GlobalFree(pInterfaceDetailData);
}
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
I am able to obtain handle to my device but not able to read any data. Upto CreateFile() everything works fine. Also how can I get information about endpoint/s? Is there any HID function for that?
I tried using
1. Result = HidD_GetInputReport(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength);
if (Result)
std::cout << "\nsuccess";
else
std::cout << "\nfail";
2. Result = ReadFile(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength, &BytesRead, NULL); //(LPOVERLAPPED)&HIDOverlapped);
if (Result)
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer[1]" << InputReportBuffer[1];
std::cout << "\nInputReportBuffer[2]" << InputReportBuffer[2];
std::cout << "\nInputReportBuffer[3]" << InputReportBuffer[3];
}
else
std::cout << "\nfail1";
Both print out 'fail'. I also tried changing InputReportBuffer[0] to 0 and 1, just in case.