上位機——自定義HID設備與主機通訊

一、開發環境
平臺:vs2015
頭文件:

#include <Windows.h>
#include <SetupAPI.h>
#include <hidsdi.h>
#include <initguid.h>

庫文件:
setupapi.lib
hid.lib

二、開發流程
1、獲取HID設備的GUID

void __stdcall HidD_GetHidGuid (_Out_  LPGUID   HidGuid);
typedef struct _GUID {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[ 8 ];
} GUID;

2、獲取設備信息集合

HDEVINFO SetupDiGetClassDevs(
    _In_opt_ CONST GUID *ClassGuid, //指定設備的GUID
    _In_opt_ PCWSTR Enumerator,    //指定設備實例字符串,NULL爲不指定
    _In_opt_ HWND hwndParent,      //窗口句柄
    _In_ DWORD Flags
    );

3、獲取設備接口信息

BOOL SetupDiEnumDeviceInterfaces(
    _In_ HDEVINFO DeviceInfoSet,  //設備信息集合
    _In_opt_ PSP_DEVINFO_DATA DeviceInfoData,  //指定某個設備信息
    _In_ CONST GUID *InterfaceClassGuid,  //GUID
    _In_ DWORD MemberIndex,  //設備index
    _Out_ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
    );

4、獲取設備接口詳細信息

BOOL SetupDiGetDeviceInterfaceDetail(
    _In_ HDEVINFO DeviceInfoSet,
    _In_ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
    _Out_writes_bytes_to_opt_(DeviceInterfaceDetailDataSize, *RequiredSize) PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
    _In_ DWORD DeviceInterfaceDetailDataSize,
    _Out_opt_ _Out_range_(>=, sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)) PDWORD RequiredSize,
    _Out_opt_ PSP_DEVINFO_DATA DeviceInfoData
    );

5、創建設備文件

HANDLE CreateFile(
    _In_ LPCWSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );

6、獲取HID 信息

BOOLEAN __stdcall
HidD_GetAttributes (
    _In_  HANDLE              HidDeviceObject,
    _Out_ PHIDD_ATTRIBUTES    Attributes
    );
typedef struct _HIDD_ATTRIBUTES {
    ULONG   Size; // = sizeof (struct _HIDD_ATTRIBUTES)
    USHORT  VendorID;
    USHORT  ProductID;
    USHORT  VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;

7、讀數據

BOOL ReadFile(
    _In_ HANDLE hFile,
    LPVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToRead,
    _Out_opt_ LPDWORD lpNumberOfBytesRead,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );

8、寫數據

BOOL WriteFile(
    _In_ HANDLE hFile,
    LPCVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToWrite,
    _Out_opt_ LPDWORD lpNumberOfBytesWritten,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );

 三、完整示例代碼
 

#include <Windows.h>
#include <SetupAPI.h>
#include <hidsdi.h>
#include <initguid.h>
#include <iostream>

using namespace std;

HANDLE userHidFileHandle;
BOOL find_device(uint32_t PID, uint32_t VID);

int main(int argc, char *argv[])
{
	BOOL isReadFile = false;
	uint8_t readbuf[3];
	DWORD numberOfBytesRead;
	cout << "***********User Hid Device SoftWare************ " << endl;
	if (find_device(22352, 1155))
	{
		while (true)
		{
			Sleep(1);
			isReadFile = ReadFile(userHidFileHandle, readbuf,3,&numberOfBytesRead,NULL);
			if(isReadFile)
			{
				for (int i = 0; i < numberOfBytesRead; i++)
				{
					cout << "0x" << hex << (uint32_t)readbuf[i] << endl;
				}
			}
		}
	}
	return 0;
}

void show_guid(LPGUID HidGuid)
{
	cout << hex << HidGuid->Data1 << "-";
	cout << hex << HidGuid->Data2 << "-";
	cout << hex << HidGuid->Data3 << "-";
	for (int i = 0; i < 8; i++)
	{
		cout << hex << (uint32_t)(HidGuid->Data4[i]);
	}
	cout << endl;
}

BOOL find_device(uint32_t PID, uint32_t VID)
{
	BOOL isFind = false;
	GUID hid_guid;
	HDEVINFO device_info;
	BOOL isGetDeviceInterfaces = false;
	BOOL isGetDeviceInterfaceDetail = false;
	BOOL isGetAttributes = false;
	uint32_t deviceIndex = 0;
	SP_DEVICE_INTERFACE_DATA device_interface_data;
	PSP_DEVICE_INTERFACE_DETAIL_DATA p_device_interface_detail_data;
	DWORD requiredSize = 0;
	HANDLE fileHandle;
	HIDD_ATTRIBUTES hid_attribute;

	HidD_GetHidGuid(&hid_guid);
	show_guid(&hid_guid);
	
	device_info = SetupDiGetClassDevs(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
	do
	{
		device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
		isGetDeviceInterfaces = SetupDiEnumDeviceInterfaces(device_info, NULL, &hid_guid, deviceIndex,
			&device_interface_data);
		deviceIndex++;
		if (isGetDeviceInterfaces)
		{
			cout << "GetDeviceInterFace success" << endl;
		}

		/*獲取requiredSize*/
		SetupDiGetDeviceInterfaceDetail(device_info, &device_interface_data,
			NULL, 0, &requiredSize, NULL);
		cout << "requiredSize:" << requiredSize << endl;

		p_device_interface_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
		p_device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		isGetDeviceInterfaceDetail = SetupDiGetDeviceInterfaceDetail(
			device_info,
			&device_interface_data, 
			p_device_interface_detail_data,
			requiredSize,
			NULL,
			NULL);
		if (isGetDeviceInterfaceDetail)
		{
			cout << "GetDeviceInterFaceDetail success" << endl;
			/*創建設備文件*/
			fileHandle = CreateFile(
				p_device_interface_detail_data->DevicePath, 
				GENERIC_READ|GENERIC_WRITE,
				FILE_SHARE_READ| FILE_SHARE_WRITE,
				NULL, 
				OPEN_EXISTING, 
				FILE_ATTRIBUTE_NORMAL,
				NULL);
			if (fileHandle == INVALID_HANDLE_VALUE)
			{
				cout << "CreateFile Error!" << endl;
			}
			else
			{
				cout << "CreateFile success!" << endl;
				/*獲取HID信息*/
				isGetAttributes = HidD_GetAttributes(fileHandle,&hid_attribute);
				if (isGetAttributes)
				{
					cout << "PID:0x"<< hid_attribute.ProductID << endl;
					cout << "VID:0x"<< hid_attribute.VendorID  << endl;
					if (hid_attribute.ProductID == PID && hid_attribute.VendorID == VID)
					{
						userHidFileHandle = fileHandle;
						return true;
					}
				}
			}
		}		
	} while (isGetDeviceInterfaces);
	return isFind;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章