PCIe驱动开发-设备打开/关闭

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


1:设备打开

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

  1. /********************************************************************/  
  2. /*           Open device ident=0, b--FALSE or TRUE          */  
  3. /********************************************************************/  
  4. DLLEXP HANDLE CCONV ClLib_Open( unsigned char ident, BOOLEAN b )  
  5. {  
  6.     HANDLE                                  hHandle = INVALID_HANDLE_VALUE;  
  7.     GUID                        *pGuid=(LPGUID)&DEMOPCI_GUID;  
  8.     HDEVINFO                hDevInfo;  
  9.     SP_INTERFACE_DEVICE_DATA        IfDevData;  
  10.     SP_INTERFACE_DEVICE_DETAIL_DATA *IfDevDetail = NULL;  
  11.     DWORD                   ReqLen;  
  12.   
  13.     // HDEVINFO as all source device is generated   
  14.     hDevInfo = SetupDiGetClassDevs(pGuid,  
  15.                     0, // Enumerator   
  16.                         0, //    
  17.                         DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );  
  18.   
  19.         if (hDevInfo == INVALID_HANDLE_VALUE)  
  20.     {  
  21.         // Error processing   
  22.         return (INVALID_HANDLE_VALUE);  
  23.     }  
  24.   
  25.     // All device is enumerated   
  26.     IfDevData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);  
  27.   
  28.     if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, ident, &IfDevData))  
  29.     {  
  30.         // A necessary amount of the memory in the buffer is obtained   
  31.         SetupDiGetDeviceInterfaceDetail(hDevInfo ,&IfDevData, NULL, 0, &ReqLen, NULL);  
  32.         // Memory allocation to acquire detailed information   
  33.         IfDevDetail = (SP_INTERFACE_DEVICE_DETAIL_DATA *)(new char[ReqLen]);  
  34.         if(!IfDevDetail)  
  35.         {  
  36.             return (INVALID_HANDLE_VALUE);  
  37.         }  
  38.         IfDevDetail->cbSize=sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);  
  39.   
  40.         // Detailed information (pass) is actually acquired   
  41.         if(SetupDiGetDeviceInterfaceDetail(hDevInfo,&IfDevData, IfDevDetail, ReqLen, NULL, NULL))  
  42.         {  
  43.             // Open the driver   
  44.             if(b == TRUE)  
  45.             {  
  46.                 sg_bOverlapFlag = 1;  
  47.                 hHandle=CreateFile(IfDevDetail->DevicePath, GENERIC_READ | GENERIC_WRITE,  
  48.                                 FILE_SHARE_READ | FILE_SHARE_WRITE,  
  49.                                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,   
  50.                                 NULL);  
  51.             }  
  52.             else  
  53.             {  
  54.                 sg_bOverlapFlag = 0;  
  55.                 hHandle=CreateFile(IfDevDetail->DevicePath, GENERIC_READ | GENERIC_WRITE,  
  56.                                 FILE_SHARE_READ | FILE_SHARE_WRITE,  
  57.                                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,   
  58.                                 NULL);  
  59.             }  
  60.         }  
  61.         // Opening of allocated memory   
  62.         delete IfDevDetail;  
  63.     }  
  64.     //  Cleanup   
  65.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  66.   
  67.     return (hHandle);  
  68. }  
/********************************************************************/
/*           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函数注销设备句柄即可。

  1. /********************************************************************/  
  2. /*                         Close device                             */  
  3. /********************************************************************/  
  4. DLLEXP int CCONV ClLib_Close( HANDLE hHandle )  
  5. {  
  6.     BOOL bRet;  
  7.   
  8.     bRet = CloseHandle(hHandle);  
  9.   
  10.     if(bRet)  
  11.         return RTN_OK;  
  12.     else  
  13.         return RTN_ERR;  
  14. }  
/********************************************************************/
/*                         Close device          				    */
/********************************************************************/
DLLEXP int CCONV ClLib_Close( HANDLE hHandle )
{
	BOOL bRet;

	bRet = CloseHandle(hHandle);

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

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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值