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