⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hiddevice.cpp

📁 HID 设备VC读写例程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -