PCIe设备漫游记----设备打开/关闭篇

        上篇中,我们从驱动层面上探讨了系统是如何为我们PCIe设备分配资源以及如何启动它的。现在的问题是,我们的上层软件如何才能对我们的设备进行访问呢。这其中首先涉及的就是设备的开打与关闭。


1:设备打开

针对本次PCI设备,上层程序打开设备函数的具体代码如下。

/********************************************************************/
/*           Open device ident=0, b--FALSE or TRUE		    */
/********************************************************************/
DLLEXP HANDLE CCONV ClLib_Open( unsigned char ident, BOOLEAN b )
{
	HANDLE                                  hHandle = INVALID_HANDLE_VALUE;
	GUID				        *pGuid=(LPGUID)&DEMOPCI_GUID;
	HDEVINFO				hDevInfo;
	SP_INTERFACE_DEVICE_DATA		IfDevData;
	SP_INTERFACE_DEVICE_DETAIL_DATA	*IfDevDetail = NULL;
	DWORD					ReqLen;

	// HDEVINFO as all source device is generated
	hDevInfo = SetupDiGetClassDevs(pGuid,
					0, // Enumerator
				        0, // 
				        DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );

        if (hDevInfo == INVALID_HANDLE_VALUE)
	{
		// Error processing
		return (INVALID_HANDLE_VALUE);
	}

	// All device is enumerated
	IfDevData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

	if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, ident, &IfDevData))
	{
		// A necessary amount of the memory in the buffer is obtained
		SetupDiGetDeviceInterfaceDetail(hDevInfo ,&IfDevData, NULL, 0, &ReqLen, NULL);
		// Memory allocation to acquire detailed information
		IfDevDetail = (SP_INTERFACE_DEVICE_DETAIL_DATA *)(new char[ReqLen]);
		if(!IfDevDetail)
		{
			return (INVALID_HANDLE_VALUE);
		}
		IfDevDetail->cbSize=sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

		// Detailed information (pass) is actually acquired
		if(SetupDiGetDeviceInterfaceDetail(hDevInfo,&IfDevData, IfDevDetail, ReqLen, NULL, NULL))
		{
			// Open the driver
			if(b == TRUE)
			{
				sg_bOverlapFlag = 1;
				hHandle=CreateFile(IfDevDetail->DevicePath, GENERIC_READ | GENERIC_WRITE,
								FILE_SHARE_READ | FILE_SHARE_WRITE,
								NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 
								NULL);
			}
			else
			{
				sg_bOverlapFlag = 0;
				hHandle=CreateFile(IfDevDetail->DevicePath, GENERIC_READ | GENERIC_WRITE,
								FILE_SHARE_READ | FILE_SHARE_WRITE,
								NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 
								NULL);
			}
		}
		// Opening of allocated memory
		delete IfDevDetail;
	}
	//  Cleanup
	SetupDiDestroyDeviceInfoList(hDevInfo);

	return (hHandle);
}

来看几个关键函数:

HDEVINFO SetupDiGetClassDevs(
  __in_opt  const GUID *ClassGuid,
  __in_opt  PCTSTR Enumerator,
  __in_opt  HWND hwndParent,
  __in      DWORD Flags
);
该函数用于获取指定类别的设备信息结构的句柄。值得注意的是参数*ClassGuid应指定成我们驱动安装时的.inf文件中Guid号(DEMOPCI_GUID),这样才能保证正确得到对应的设备句柄。


BOOL SetupDiEnumDeviceInterfaces(
  __in      HDEVINFO DeviceInfoSet,
  __in_opt  PSP_DEVINFO_DATA DeviceInfoData,
  __in      const GUID *InterfaceClassGuid,
  __in      DWORD MemberIndex,
  __out     PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
);
该函数枚举所有指定类别的设备接口。


BOOL SetupDiGetDeviceInterfaceDetail(
  __in       HDEVINFO DeviceInfoSet,
  __in       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  __out_opt  PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,
  __in       DWORD DeviceInterfaceDetailDataSize,
  __out_opt  PDWORD RequiredSize,
  __out_opt  PSP_DEVINFO_DATA DeviceInfoData
);
该函数返回设备接口的设置信息。


HANDLE WINAPI CreateFile(
  __in      LPCTSTR lpFileName,
  __in      DWORD dwDesiredAccess,
  __in      DWORD dwShareMode,
  __in_opt  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  __in      DWORD dwCreationDisposition,
  __in      DWORD dwFlagsAndAttributes,
  __in_opt  HANDLE hTemplateFile
);
该函数应用很广泛,可以用来创建或者打开文件或者设备。本例中我们可以通过设置参数dwFlagsAndAttributes(FILE_FLAG_OVERLAPPED)来决定设备是异步还是同步方式打开。


2:设备关闭

相比起前面的设备打开程序,设备关闭显得要简单许多,直接调用CloseHandle函数注销设备句柄即可。

/********************************************************************/
/*                         Close device          				    */
/********************************************************************/
DLLEXP int CCONV ClLib_Close( HANDLE hHandle )
{
	BOOL bRet;

	bRet = CloseHandle(hHandle);

	if(bRet)
		return RTN_OK;
	else
		return RTN_ERR;
}

小结:通过上述打开设备函数,我们已经得到相应设备的句柄,后续操作中直接使用该句柄就能实现对设备的访问了(如寄存器读写等)。

你可能感兴趣的:(PCIe设备漫游记)