Source file: /~heha/hsn/bl/hid-flash.zip/src/hid-win.cpp

/*
 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