/*
HIDAPI - Multi-Platform library for communication with HID devices.
8/22/2009 Alan Ott, Signal 11 Software
*/
#ifdef _WIN32
#include "hidapi.h"
#include <setupapi.h>
HidDev::HidDev():handle(0),readbuf(0) {}
bool HidDev::connect(unsigned n) {
GUID guid;// = {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
HidD_GetHidGuid(&guid);
int device_index = 0;
/* Get information for all the devices belonging to the HID class. */
HDEVINFO di=SetupDiGetClassDevs(&guid,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
/* Iterate over each device in the HID class, looking for the right one. */
SP_DEVICE_INTERFACE_DATA did;
did.cbSize = sizeof did;
++n;
for (int i=0;SetupDiEnumDeviceInterfaces(di,0,&guid,i,&did);i++) {
SP_DEVINFO_DATA info;
info.cbSize = sizeof info;
struct{
SP_DEVICE_INTERFACE_DETAIL_DATA dd;
TCHAR space[MAX_PATH];
}dd;
dd.dd.cbSize = sizeof dd.dd;
if (!SetupDiGetDeviceInterfaceDetail(di,&did,&dd.dd,sizeof dd,0,0)) continue;
/* Open a handle to the device */
HANDLE h=CreateFile(dd.dd.DevicePath,GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
if (h==INVALID_HANDLE_VALUE) continue;
attr.Size = sizeof attr;
HidD_GetAttributes(h, &attr); // give match() some info
handle=h; // as a possible parameter for match() to get descriptors
if (match() && !--n) { // call-back the virtual match() member function
PHIDP_PREPARSED_DATA data;
if (HidD_GetPreparsedData(h,&data)) {
HidP_GetCaps(data, &caps);
readbuf = new char[caps.InputReportByteLength];
HidD_FreePreparsedData(data);
}
break; // keep handle open
}
CloseHandle(h);
handle=0;
}
SetupDiDestroyDeviceInfoList(di);
return operator bool();
}
HidDev::~HidDev() {
if (readbuf) delete[] readbuf;
if (handle) CloseHandle(handle);
}
bool HidDev::setOutputReport(const BYTE*data, unsigned attempts, unsigned ms) {
do{
DWORD bw=0;
OVERLAPPED ol;
memset(&ol,0,sizeof ol);
if (!WriteFile(handle, data, caps.OutputReportByteLength, &bw, &ol)
&& GetLastError()==ERROR_IO_PENDING
&& (WaitForSingleObject(handle,ms)
|| !GetOverlappedResult(handle,&ol,&bw,false))) CancelIo(handle);
if (bw==caps.OutputReportByteLength) return true;
retry_msg();
}while(--attempts);
return false;
}
bool HidDev::getInputReport(BYTE*data, unsigned attempts, unsigned ms) {
do{
DWORD br = 0;
OVERLAPPED ol;
memset(&ol,0,sizeof ol);
if (!ReadFile(handle,data,caps.InputReportByteLength,&br, &ol)
&& GetLastError()==ERROR_IO_PENDING
&& (WaitForSingleObject(handle,ms)
|| !GetOverlappedResult(handle,&ol,&br,false))) CancelIo(handle);
if (br==caps.InputReportByteLength) return true;
retry_msg();
// Im Gegensatz zu USB befindet sich am Anfang stets die Report-ID auch dann,
// wenn sie nicht benutzt wird, also Null ist.
}while(--attempts);
return false;
}
bool HidDev::setFeatureReport(const BYTE*data, unsigned attempts) {
do{ //Seltsam: Mehrere Versuche erforderlich! Problem bei Windows oder Firmware?
if (HidD_SetFeature(handle, (PVOID)data, caps.FeatureReportByteLength)) return true;
retry_msg();
}while(--attempts);
return false;
}
bool HidDev::getFeatureReport(BYTE*data, unsigned attempts) {
do{
if (HidD_GetFeature(handle, data, caps.FeatureReportByteLength)) return true;
retry_msg();
}while(--attempts);
return false;
}
HidDev::RetStr HidDev::getIndexedStr(byte index) const{
if (!HidD_GetIndexedString(handle,index,__$ReturnUdt->s,256)) __$ReturnUdt->s[0]=0;
return *__$ReturnUdt;
}
HidDev::RetStr HidDev::getManufacturerStr() const{
if (!HidD_GetManufacturerString(handle,__$ReturnUdt->s,256)) __$ReturnUdt->s[0]=0;
return *__$ReturnUdt;
}
HidDev::RetStr HidDev::getProductStr() const{
if (!HidD_GetProductString(handle,__$ReturnUdt->s,256)) __$ReturnUdt->s[0]=0;
return *__$ReturnUdt;
}
HidDev::RetStr HidDev::getSerialStr() const{
if (!HidD_GetSerialNumberString(handle,__$ReturnUdt->s,256)) __$ReturnUdt->s[0]=0;
return *__$ReturnUdt;
}
DWORD HidDev::vidpid() const{
return *reinterpret_cast<const DWORD*>(&attr.VendorID);
}
#endif
Detected encoding: ASCII (7 bit) | 2
|