📄 hiddevice.cpp
字号:
// HIDDevice.cpp: implementation of the CHIDDevice class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HIDDevice.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHIDDevice::CHIDDevice()
{
// Initialize the timeouts to wait forever
m_GetReportTimeout = INFINITE;
m_SetReportTimeout = INFINITE;
// Call a reset on the device data to initialize
ResetDeviceData();
}
void CHIDDevice::ResetDeviceData()
{
// Reset the device handle
m_Handle = INVALID_HANDLE_VALUE;
// Set device opened to false
m_DeviceOpened = FALSE;
// Set all buffer lengths to 0
m_InputReportBufferLength = 0;
m_OutputReportBufferLength = 0;
m_FeatureReportBufferLength = 0;
// Obtain the OS version
OSVERSIONINFO osVer;
osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osVer);
// Only set the max report requests if we are using 2K or later
if ((osVer.dwPlatformId == 2) && (osVer.dwMajorVersion == 5))
{
if (osVer.dwMinorVersion >= 1)
{
// XP or later supports 512 input reports
m_MaxReportRequest = MAX_REPORT_REQUEST_XP;
}
else if (osVer.dwMinorVersion == 0)
{
// 2K supports 200 input reports
m_MaxReportRequest = MAX_REPORT_REQUEST_2K;
}
}
else
{
// Otherwise set the max reports to 0, and this will
// only allow te default
m_MaxReportRequest = 0;
}
}
CHIDDevice::~CHIDDevice()
{
// Call close on destruction
Close();
}
BYTE CHIDDevice::Close()
{
// This function will close the HID Device and then calls ResetDeviceData
// to reinitialize all of the members after the close completes
BYTE status = HID_DEVICE_SUCCESS;
// Check to see if the device is opened, otherwise return an error code
if (m_DeviceOpened)
{
// Check that we have valid handle values, otherwise return an error code
if ((m_Handle != INVALID_HANDLE_VALUE) && (m_Handle != NULL))
{
CloseHandle(m_Handle);
}
else
{
status = HID_DEVICE_HANDLE_ERROR;
}
// Reset the device data
ResetDeviceData();
}
else
{
status = HID_DEVICE_NOT_OPENED;
}
return status;
}
BOOL CHIDDevice::GetHidDevicePath(DWORD index, char* devicePath)
{
// This function will obtain the device path of an HID device by it's index
// TRUE is returned if the index is found, and contains a valid device path
// FALSE is returned if the index is not found
BOOL status = FALSE;
GUID hidGuid;
HDEVINFO hHidDeviceInfo = NULL;
// Obtain the HID GUID
HidD_GetHidGuid(&hidGuid);
// Use the HID GUID to get a handle to a list of all HID devices connected
hHidDeviceInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
// If the device info was NULL, return an error code
if (hHidDeviceInfo != NULL)
{
SP_DEVICE_INTERFACE_DATA hidDeviceInterfaceData;
hidDeviceInterfaceData.cbSize = sizeof(hidDeviceInterfaceData);
// Check that the index is less than the max number of USB devices connectable
if (index < MAX_USB_DEVICES)
{
// Query the device using the index to get the interface data
BOOL hidResult = hidResult = SetupDiEnumDeviceInterfaces(hHidDeviceInfo, 0, &hidGuid, index, &hidDeviceInterfaceData);
// If a successful query was made, use it to get the detailed data of the device
if (hidResult)
{
BOOL detailResult;
DWORD length, required;
PSP_DEVICE_INTERFACE_DETAIL_DATA hidDeviceInterfaceDetailData;
// Obtain the length of the detailed data structure, then allocate space and retrieve it
SetupDiGetDeviceInterfaceDetail(hHidDeviceInfo, &hidDeviceInterfaceData, NULL, 0, &length, NULL);
hidDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(length);
if (hidDeviceInterfaceDetailData)
{
hidDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
detailResult = SetupDiGetDeviceInterfaceDetail(hHidDeviceInfo, &hidDeviceInterfaceData, hidDeviceInterfaceDetailData, length, &required, NULL);
// If getting the device detail provides a valid result, then copy it's device
// path into the device path argument pointer and set status to TRUE
if (detailResult)
{
strcpy(devicePath, hidDeviceInterfaceDetailData->DevicePath);
status = TRUE;
}
// Deallocate space for the detailed data structure
free(hidDeviceInterfaceDetailData);
}
}
}
}
return status;
}
HANDLE CHIDDevice::OpenDeviceByVidPid(char* devicePath, WORD vid, WORD pid)
{
// This function attempts to open a device using a specific VID and PID. If it succeeds
// then a handle is returned. If it fails, then INVALID_HANDLE_VALUE is returned
// Open the device
HANDLE hHidDeviceHandle = CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
// Check that the device opened successfully
if (hHidDeviceHandle != INVALID_HANDLE_VALUE)
{
HIDD_ATTRIBUTES hidDeviceAttributes;
// Get the attributes of the HID device
if (HidD_GetAttributes(hHidDeviceHandle, &hidDeviceAttributes))
{
// Close the handle if either the VID or the PID don't match
if ((hidDeviceAttributes.VendorID != vid) || (hidDeviceAttributes.ProductID != pid))
{
CloseHandle(hHidDeviceHandle);
hHidDeviceHandle = INVALID_HANDLE_VALUE;
}
}
else
{
CloseHandle(hHidDeviceHandle);
hHidDeviceHandle = INVALID_HANDLE_VALUE;
}
}
return hHidDeviceHandle;
}
DWORD CHIDDevice::GetConnectedDeviceNum(WORD vid, WORD pid)
{
// This function will return the number of devices connected with a specified VID and
// PID, if no devices are connected, it will return a 0
DWORD deviceNum = 0;
char devicePath[MAX_PATH];
DWORD i = 0;
// Loop through to check all of the HID Device paths available
while (GetHidDevicePath(i, devicePath))
{
// Attempt to open the device by VID and PID
HANDLE hHidDeviceHandle = OpenDeviceByVidPid(devicePath, vid, pid);
// Check that the device is opened and the handle is valid
if (hHidDeviceHandle != INVALID_HANDLE_VALUE)
{
// Increment the number of devices found then close the handle
deviceNum++;
CloseHandle(hHidDeviceHandle);
}
// Increment i for next device
i++;
}
return deviceNum;
}
BYTE CHIDDevice::GetSerialString(DWORD deviceIndex, WORD vid, WORD pid, LPSTR serialString, DWORD serialStringLength)
{
// This function will obtain the serial string of a device by it's index within it's VID
// and PID. So if only 1 device is connected with VID 10C4, 9999, it's index is 0. If three
// devices are connected with VID 10C4, 9999 are connected, they would be referenced as
// device 0, 1, and 2
BYTE status = HID_DEVICE_NOT_FOUND;
char devicePath[MAX_PATH];
DWORD i = 0;
DWORD deviceNum = 0;
// Loop through to check all of the HID Device paths available
while (GetHidDevicePath(i, devicePath))
{
// Attempt to open the device by VID and PID
HANDLE hHidDeviceHandle = OpenDeviceByVidPid(devicePath, vid, pid);
// Check that the device is opened and the handle is valid
if (hHidDeviceHandle != INVALID_HANDLE_VALUE)
{
// If the device index matches our current device number, then get
// the serial string
if (deviceNum == deviceIndex)
{
BYTE serialBuf[512];
// Obtain the serial number
if (HidD_GetSerialNumberString(hHidDeviceHandle, serialBuf, 512))
{
// Reset the supplied string
memset(serialString, 0, serialStringLength);
// Convert the string from unicode to ansi
for (DWORD i = 0; i < serialStringLength; i++)
{
serialString[i] = serialBuf[i*2];
}
// Return success
status = HID_DEVICE_SUCCESS;
}
}
// Increment the number of devices found then close the handle
deviceNum++;
CloseHandle(hHidDeviceHandle);
}
// Increment the number of devices found
i++;
}
return status;
}
BYTE CHIDDevice::Open(DWORD deviceIndex, WORD vid, WORD pid, WORD numInputBuffers)
{
// This function will open a device by it's index and VID and PID. In addition, the number
// of inp
BYTE status = HID_DEVICE_SUCCESS;
char devicePath[MAX_PATH];
DWORD i = 0;
DWORD deviceNum = 0;
BOOL found = FALSE;
// Ensure that the we don't already have an open device
if (m_DeviceOpened)
{
status = HID_DEVICE_ALREADY_OPENED;
}
// Begin to look for the device if it is not opened
if (status == HID_DEVICE_SUCCESS)
{
while (GetHidDevicePath(i, devicePath))
{
// Attempt to open the device by VID and PID
HANDLE hHidDeviceHandle = OpenDeviceByVidPid(devicePath, vid, pid);
// Check that the device is opened and the handle is valid
if (hHidDeviceHandle != INVALID_HANDLE_VALUE)
{
// Set found to true to stop the loop if the device num is correct
if (deviceNum == deviceIndex)
{
found = TRUE;
// Set the member variables to an opened device and handle
m_DeviceOpened = TRUE;
m_Handle = hHidDeviceHandle;
PHIDP_PREPARSED_DATA preparsedData;
if (HidD_GetPreparsedData(hHidDeviceHandle, &preparsedData))
{
HIDP_CAPS capabilities;
// Used the preparsed data structure to get the device capabilities
if (HidP_GetCaps(preparsedData, &capabilities))
{
// Allocate memory for the input, output and feature reports
if (capabilities.InputReportByteLength)
{
m_InputReportBufferLength = capabilities.InputReportByteLength;
}
if (capabilities.OutputReportByteLength)
{
m_OutputReportBufferLength = capabilities.OutputReportByteLength;
}
if (capabilities.FeatureReportByteLength)
{
m_FeatureReportBufferLength = capabilities.FeatureReportByteLength;
}
// See if the input buffers should be adjusted, if max report request is 0
// then an OS not supported by ToolStick is being used, so dont modify it
if ((m_MaxReportRequest > 0) && (numInputBuffers != DEFAULT_REPORT_INPUT_BUFFERS))
{
// Ensure that we are setting the input buffers to a valid setting
if (numInputBuffers > m_MaxReportRequest) m_MaxReportRequest = numInputBuffers;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -