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

来源:互联网 发布:软件图标显示不正常 编辑:程序博客网 时间:2024/06/06 06:47

        上篇中,我们从驱动层面上探讨了系统是如何为我们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;HDEVINFOhDevInfo;SP_INTERFACE_DEVICE_DATAIfDevData;SP_INTERFACE_DEVICE_DETAIL_DATA*IfDevDetail = NULL;DWORDReqLen;// HDEVINFO as all source device is generatedhDevInfo = SetupDiGetClassDevs(pGuid,0, // Enumerator        0, //         DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );        if (hDevInfo == INVALID_HANDLE_VALUE){// Error processingreturn (INVALID_HANDLE_VALUE);}// All device is enumeratedIfDevData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, ident, &IfDevData)){// A necessary amount of the memory in the buffer is obtainedSetupDiGetDeviceInterfaceDetail(hDevInfo ,&IfDevData, NULL, 0, &ReqLen, NULL);// Memory allocation to acquire detailed informationIfDevDetail = (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 acquiredif(SetupDiGetDeviceInterfaceDetail(hDevInfo,&IfDevData, IfDevDetail, ReqLen, NULL, NULL)){// Open the driverif(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 memorydelete IfDevDetail;}//  CleanupSetupDiDestroyDeviceInfoList(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;elsereturn RTN_ERR;}

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

原创粉丝点击