HID 异步访问和同步访问

本文详细介绍了如何使用Windows API进行HID设备的同步和异步读写操作。通过CreateFile函数的不同参数设置来选择同步或异步模式,并通过WriteFile和ReadFile函数配合OVERLAPPED结构实现异步读写。异步操作避免了主进程阻塞,提高了程序效率。同时,提供了异步读写的示例代码,展示了如何处理ERROR_IO_PENDING错误并使用WaitForSingleObject等待读写完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用 Windows 自带 API 枚举并完成读写的详细步骤,参考下面两篇文章:

https://blog.youkuaiyun.com/phenixyf/article/details/72478933

https://blog.youkuaiyun.com/phenixyf/article/details/9153195

根据上面文章自己完成的 HID GUI 模板位置如下:

 

本文主要讲一下异步和同步方式读写 HID 的区别。

使用同步还是异步方式访问 HID 在下面两个地方确定:

  • 枚举 HID 设备过程中,用 CreateFile 打开 HID 设备时。(主要区别就是 CreateFile 倒数第二个参数)

        用同步方式打开 HID 设备:

hidHandle = CreateFile(devDetail->DevicePath,
					NULL,		// 第一次必须用非读写模式打开
					FILE_SHARE_READ | FILE_SHARE_WRITE,
					NULL,
					OPEN_EXISTING,
					0,		// 用同步方式
					NULL);

        用异步方式打开 HID 设备:

hidHandle = CreateFile(devDetail->DevicePath,
					NULL,		// 第一次必须用非读写模式打开
					FILE_SHARE_READ | FILE_SHARE_WRITE,
					NULL,
					OPEN_EXISTING,
					FILE_FLAG_OVERLAPPED,	// 用异步方式 (overlap)
					NULL);
  • 用 WriteFile 和 ReadFile 函数读写 HID 时。(主要区别就是 WriteFile, ReadFile 的最后一个参数)

        用同步方式读写

//写操作
WriteFile(hidHandle, Write_HID_Buf, HIDREPORTNUM, &bytesWritten, NULL);

//读操作
ReadFile(hidHandle, Read_HID_Buf, HIDREPORTNUM, &bytesRead, NULL);

        用异步方式读写 

//写操作
OVERLAPPED hid_write_overlap;	//定义 overlap 对象
WriteFile(hidHandle, Write_HID_Buf, HIDREPORTNUM, &bytesWritten, &hid_write_overlap);

//读操作
OVERLAPPED hid_read_overlap;    //定义 overlap 对象
ReadFile(hidHandle, Read_HID_Buf, HIDREPORTNUM, &bytesRead, &hid_read_overlap);

同步方式和异步方式操作过程中的不同:

  • 使用同步方式,当用 WriteFile 和 ReadFile 进行读写操作时,主进程会被阻塞,主进程的其它操作都会被block,直到读写操作完成后,主进程才能进行其它操作。
  • 使用异步方式就不会出现同步的阻塞现象,当 HID 设备在执行读写操作时,主进程仍可以进行其它操作。

所以一般情况下都会使用异步方式访问 HID 设备。

异步操作的具体实现

异步方式有两种实现方式:

  • 启动读写线程
  • 使用 overlap

用线程的方式比较麻烦,如果是在 Windows 系统开发,可以使用 overlap,具体实现如下代码

void ChidTemplateDlg::WriteHIDOutputReport()
{
	DWORD	bytesWritten = 0;
	BOOL	result = false;
	DWORD	res_wait_object;

	Write_HID_Buf[0] = REPORTID_DATA;

	if (hidHandle != INVALID_HANDLE_VALUE)
	{
		result = WriteFile(hidHandle, Write_HID_Buf, HIDREPORTNUM, &bytesWritten, &hid_write_overlap);

		if (!result)	//因为是 overlap 异步操作,所以 WriteFile 后不会马上返回 true,这是正常的。
						//判断最终写操作是否成功,是在下面的 switch 中
		{
			if (GetLastError() == ERROR_IO_PENDING)
			{//当错误是ERROR_IO_PENDING,那意味着写文件的操作还在进行中
			 //等候,直到文件读完

				switch ( WaitForSingleObject(hidHandle, HIDREADTIMEOUT) )
				{
				case WAIT_OBJECT_0:
//					MessageBox(_T("HID write successfully"));
					break;
				case WAIT_TIMEOUT:
					MessageBox(_T("HID write fail: timeout"));

					CloseHandle(hidHandle);		// close hid handle
					OpenHIDDevice(1);			// re-open hid
					break;
				default:
					MessageBox(_T("HID write fail: in overlap process"));
					break;
				}	
			}
			else
			{
				MessageBox(_T("HID write fail: not in overlap process"));
			}
		}		
	}
	else
		MessageBox(_T("write hid fail: hid handle is invaliable"));
}


void ChidTemplateDlg::ReadHIDInputReport()
{

	DWORD	bytesRead = 0;
	BOOL	result = false;
	DWORD	res_wait_object;

	if (hidHandle != INVALID_HANDLE_VALUE)
	{
		result = ReadFile(hidHandle, Read_HID_Buf, HIDREPORTNUM, &bytesRead, &hid_read_overlap);

		if (!result)	//因为是 overlap 异步操作,所以 ReadFile 后不会马上返回 true,这是正常的。
						//判断最终读操作是否成功,是在下面的 switch 中
		{
			if (GetLastError() == ERROR_IO_PENDING)
			{//当错误是ERROR_IO_PENDING,那意味着读文件的操作还在进行中
			 //等候,直到文件读完

				switch (WaitForSingleObject(hidHandle, HIDREADTIMEOUT))
				{
				case WAIT_OBJECT_0:
					//					MessageBox(_T("HID write successfully"));
					break;
				case WAIT_TIMEOUT:
					MessageBox(_T("HID read fail: timeout"));

					CloseHandle(hidHandle);		// close hid handle
					OpenHIDDevice(1);			// re-open hid
					break;
				default:
					MessageBox(_T("HID read fail: in overlap process"));
					break;
				}
			}
			else
			{
				MessageBox(_T("HID read fail: not in overlap process"));
			}
		}
	}
	else
		MessageBox(_T("read hid fail: hid handle is invaliable"));
}

关于 overlap 及其使用的具体讲解可参考下面文章:

https://blog.youkuaiyun.com/phenixyf/article/details/126854005

https://blog.youkuaiyun.com/phenixyf/article/details/126853088

(582条消息) Overlapped_Phenixyf的博客-优快云博客

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值