#pragma once
#ifndef USB_DEVICE_H
#define USB_DEVICE_H
class UsbDevice
{
int mvid;
int mpid;
void* dev_handler;
bool usb_ok = false;
public:
UsbDevice();
~UsbDevice();
int open(int pid, int vid);
int close();
int write(const unsigned char* buf, const int l);
int read(unsigned char* buf, const int l, const int timeout_ms);
int reconnect();
private:
static void* getDeviceHandle(unsigned short vendor, unsigned short product, unsigned int MI = 0x0000);
static bool IsMatchingDevice(wchar_t *pDeviceID, unsigned int uiVID, unsigned int uiPID, unsigned int uiMI);
};
#endif
///---------------------------------------------usbdevice.cpp--------------------------------------------------------
///------------------------------------------------------------------------------------------------------------------------
#include <cstdio>
#include <sstream>
#include <wchar.h>
#include <string.h>
#include <Windows.h>
#include <hidsdi.h>
#include <SetupAPI.h>
#include <cfgmgr32.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <Windows.h>
#include "UsbDevice.h"
#pragma comment(lib, "hid.lib")
#pragma comment(lib, "setupapi.lib")
HANDLE UsbDevice::getDeviceHandle(unsigned short uiVID, unsigned short uiPID, unsigned int uiMI) {
printf("Attempting to open: vid=%04x pid=%04x mid=%04x\n", uiVID, uiPID, uiMI);
const GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
//std::cout << hDevInfo << std::endl;
if (hDevInfo == INVALID_HANDLE_VALUE)
return 0;
HANDLE hReturn = 0;
SP_DEVINFO_DATA deviceData = { 0 };
deviceData.cbSize = sizeof(SP_DEVINFO_DATA);
for (unsigned int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &deviceData); ++i) {
wchar_t wszDeviceID[MAX_DEVICE_ID_LEN];
if (CM_Get_Device_IDW(deviceData.DevInst, wszDeviceID, MAX_DEVICE_ID_LEN, 0))
continue;
if (!IsMatchingDevice(wszDeviceID, uiVID, uiPID, uiMI))
continue;
SP_INTERFACE_DEVICE_DATA interfaceData = { 0 };
interfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
if (!SetupDiEnumDeviceInterfaces(hDevInfo, &deviceData, &GUID_DEVINTERFACE_HID, 0, &interfaceData))
break;
DWORD dwRequiredSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, 0, 0, &dwRequiredSize, 0);
SP_INTERFACE_DEVICE_DETAIL_DATA *pData = (SP_INTERFACE_DEVICE_DETAIL_DATA *)new unsigned char[dwRequiredSize];
pData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, pData, dwRequiredSize, 0, 0))
{
delete pData;
break;
}
// get device handle(with and without overlapping mode)
HANDLE hDevice = CreateFile(pData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, NULL, 0);
//HANDLE hDevice = CreateFile(pData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hDevice == INVALID_HANDLE_VALUE)
{
delete pData;
printf(" Failed open: vid=%04x pid=%04x mid=%04x\n", uiVID, uiPID, uiMI);
break;
}
hReturn = hDevice;
printf("!!! Opened: vid=%04x pid=%04x mid=%04x\n", uiVID, uiPID, uiMI);
break;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return hReturn;
}
//void UsbDevice::readDataFromDevice(HANDLE hFile, unsigned char* buf, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped = NULL) {
// ReadFile(hFile, buf, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
//}
bool UsbDevice::IsMatchingDevice(wchar_t *pDeviceID, unsigned int uiVID, unsigned int uiPID, unsigned int uiMI) {
unsigned int uiLocalVID = 0, uiLocalPID = 0, uiLocalMI = 0;
LPWSTR pszNextToken = 0;
LPWSTR pszToken = wcstok(pDeviceID, L"\\#&");
while (pszToken) {
std::wstring tokenStr(pszToken);
if (tokenStr.find(L"VID_", 0, 4) != std::wstring::npos) {
std::wistringstream iss(tokenStr.substr(4));
iss >> std::hex >> uiLocalVID;
}
else if (tokenStr.find(L"PID_", 0, 4) != std::wstring::npos) {
std::wistringstream iss(tokenStr.substr(4));
iss >> std::hex >> uiLocalPID;
}
else if (tokenStr.find(L"MI_", 0, 3) != std::wstring::npos) {
std::wistringstream iss(tokenStr.substr(3));
iss >> std::hex >> uiLocalMI;
}
pszToken = wcstok(0, L"\\#&");
}
if (uiVID != uiLocalVID || uiPID != uiLocalPID || uiMI != uiLocalMI)
return false;
return true;
}
UsbDevice::UsbDevice() {
usb_ok = false;
mvid = 0;
mpid = 0;
dev_handler = 0;
}
UsbDevice::~UsbDevice() {
close();
}
int UsbDevice::open(int vid, int pid) {
mvid = vid;
mpid = pid;
dev_handler = getDeviceHandle(vid, pid);
if (dev_handler == 0) {
usb_ok = false;
return -1;
}
usb_ok = true;
return 1;
}
int UsbDevice::reconnect() {
if (!usb_ok) {
if (open(mvid, mpid) < 0)
return -1;
else
return 1;
}
return 1;
}
int UsbDevice::close() {
if (dev_handler) {
int res = CloseHandle(dev_handler);
if (res) {
dev_handler = 0;
usb_ok = false;
}
return res;
}
return 0;
}
int UsbDevice::write(const unsigned char* buf, const int l) {
DWORD bytes_written=-1;
unsigned char innerbuf[65];
memset(innerbuf, 0, sizeof(innerbuf));
if (l <= sizeof(innerbuf)) {
memcpy(innerbuf, buf, l);
} else {
memcpy(innerbuf, buf, sizeof(innerbuf));
}
BOOL res = WriteFile(dev_handler, innerbuf, sizeof(innerbuf), &bytes_written,0);
if (res == 0) {
printf("WriteFile error=%d\n", (int)GetLastError());
}
FlushFileBuffers(WriteFile);
// if (!res) {
// if (GetLastError() != ERROR_IO_PENDING) {
// /* WriteFile() failed. Return error. */
// bytes_written = -1;
// goto end_of_function;
// }
// }
// /* Wait here until the write is done. This makes
// hid_write() synchronous. */
// res = GetOverlappedResult(dev_handler, &ol, &bytes_written, TRUE/*wait*/);
// if (!res) {
// /* The Write operation failed. */
// bytes_written = -1;
// goto end_of_function;
// }
//end_of_function:
return bytes_written;
}
int UsbDevice::read(unsigned char* buf, const int l, const int timeout_ms) {
DWORD read_byte = 0;
//readDataFromDevice(dev_handler, buf, l, &read_byte);
if (0 == ReadFile(dev_handler, buf, l, &read_byte, 0)) {
return -1;
}
return read_byte;
}