Windows下USB HID设备通信

1. HID API

前面有写过一文来介绍 STM32F072 HID 自定义设备,这里记录windows下如何与之进行通信,也就是上位机的编写。windows作为主机端与HID设备通信流程大致如下:

  1. 通过VID/PID等信息查找到对应的设备路径
  2. 通过CreateFile获取设备的操作句柄
  3. 使用WriteFile/ReadFile、HidD_SetFeature/HidD_GetFeature 发送接收数据
  4. 关闭对应句柄,释放资源

windows 相关API

  • HANDLE CreateFile(
      LPCWSTR lpFileName,        // 指向路径的指针
      DWORD dwDesiredAccess,      // 访问模式(读/写)
      DWORD dwShareMode,         // 共享模式
      LPSECURITY_ATTRIBUTES lpSecurityAttributes,   // 指向安全属性的指针
      DWORD dwCreationDisposition,    // 如何创建
      DWORD dwFlagsAndAttributes,     // 文件属性(同步或异步)
      HANDLE hTemplateFile        // 用于复制文件句柄
    );

  • WriteFile(
      HANDLE hFile,            // 设备句柄,可通过CreateFile得到
      LPCVOID lpBuffer,            // 要发送的buffer(指针)
      DWORD nNumberOfBytesToWrite,    // 要发送数据的长度
      LPDWORD lpNumberOfBytesWritten,   // 实际发送数据的长度
      LPOVERLAPPED lpOverlapped    // OVERLAPPED结构体指针,如果设备是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL
    );

  • ReadFile(
      HANDLE hFile,
      LPVOID lpBuffer,
      DWORD nNumberOfBytesToRead,
      LPDWORD lpNumberOfBytesRead,
      LPOVERLAPPED lpOverlapped
    );

  • HidD_SetFeature (
      HANDLE HidDeviceObject,        // 设备句柄,通过CreateFile得到
      PVOID ReportBuffer,             // 待发送的数据
      ULONG ReportBufferLength       // 待发送数据的长度
    );

  • HidD_GetFeature (
      HANDLE HidDeviceObject,
      PVOID ReportBuffer,
      ReportBufferLength
    );

  • HidD_SetOutputReport (
      HANDLE HidDeviceObject,
      PVOID ReportBuffer,
      ULONG ReportBufferLength
    );

  • HidD_GetInputReport (
      HANDLE HidDeviceObject,
      PVOID ReportBuffer,
      ULONG ReportBufferLength
    );

  • CloseHandle(
      HANDLE hObject
    );

所需开发库及头文件

  • 添加库文件(附加依赖项)
    setupapi.lib
    hid.lib

  • 包含头文件
    extern “C” {
    #include “hidsdi.h”
    #include “setupapi.h”
    }

2. 查找设备

直接上代码

/*
HANDLE hWriteHandle = INVALID_HANDLE_VALUE;
HANDLE hReadHandle = INVALID_HANDLE_VALUE;

CString DevicePathName = "";
BOOL DeviceFound = FALSE;
UINT FoundDevice_Num;

HIDP_CAPS Capabilities;
PHIDP_PREPARSED_DATA HidParsedData;
*/
BOOL CUSB_HID_APPDlg::FindHidDevice(DWORD vid, DWORD pid)
{
   
	GUID HidGuid;				//定义一个GUID的结构体HidGuid来保存HID设备的接口类GUID
	HDEVINFO hDevInfoSet;		//定义一个DEVINFO的句柄hDevInfoSet来保存获取到的设备信息集合句柄	
	SP_DEVICE_INTERFACE_DATA DevInterfaceData;			//DevInterfaceData,用来保存设备的驱动接口信息

	PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetailData;	//定义一个指向设备详细信息的结构体指针
	
	HIDD_ATTRIBUTES DevAttributes;		//定义一个HIDD_ATTRIBUTES的结构体变量,保存设备的属性

	DWORD RequiredSize;					//定义一个RequiredSize的变量,用来接收需要保存详细信息的缓冲长度
	
	HANDLE hDevHandle;

	BOOL Result;
	DWORD MemberIndex = 0;				//定义MemberIndex,表示当前搜索到第几个设备,0表示第一个设备

	FoundDevice_Num = 0;
	DeviceFound = FALSE;
	
	hWriteHandle = INVALID_HANDLE_VALUE;
	hReadHandle = INVALID_HANDLE_VALUE;
	hDevHandle = INVALID_HANDLE_VALUE;

	DevInterfaceData.cbSize = sizeof(DevInterfaceData);
	DevAttributes.Size = sizeof(DevAttributes);

	HidD_GetHidGuid(&HidGuid);

	hDevInfoSet = SetupDiGetClassDevs(&HidGuid,
		NULL,
		NULL,
		DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

	while (1)
	{
   
		// 1
		Result = SetupDiEnumDeviceInterfaces(hDevInfoSet,//设备信息集合句柄
			NULL,
			&HidGuid,
			MemberIndex,
			&DevInterfaceData);

		if (Result == FALSE) break;

		MemberIndex++;						// search next
											
		Result = SetupDiGetDeviceInterfaceDetail(hDevInfoSet,
			&DevInterfaceData,
			NULL,
			NULL,
			&RequiredSize,
			NULL);

		pDevDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
		if (pDevDetailData == NULL)
		{
   
			SetupDiDestroyDeviceInfoList(hDevInfoSet);
			return FALSE;
		}

		pDevDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		// 2
		Result = SetupDiGetDeviceInterfaceDetail(hDevInfoSet,
			&DevInterfaceData,
			pDevDetailData,
			RequiredSize,
			NULL,
			NULL);

		DevicePathName = pDevDetailData->DevicePath;
		free(pDevDetailData);

		if (Result == FALSE) 
  • 7
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值