HID 异步访问和同步访问

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

https://blog.csdn.net/phenixyf/article/details/72478933

https://blog.csdn.net/phenixyf/article/details/9153195

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

HID 异步访问和同步访问_第1张图片

 

本文主要讲一下异步和同步方式读写 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.csdn.net/phenixyf/article/details/126854005

https://blog.csdn.net/phenixyf/article/details/126853088

(582条消息) Overlapped_Phenixyf的博客-CSDN博客

你可能感兴趣的:(Windows使用,USB,驱动开发,windows)