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

来源:互联网 发布:unity3d安卓真机调试 编辑:程序博客网 时间:2024/06/05 03:57
上篇中,我们从驱动层面上探讨了系统是如何为我们PCIe设备分配资源以及如何启动它的。现在的问题是,我们的上层软件如何才能对我们的设备进行访问呢。这其中首先涉及的就是设备的开打与关闭。


1:设备打开

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

[cpp] view plaincopyprint?
  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. }  
[cpp] view plain copy
print?
  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. }  

来看几个关键函数:

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函数注销设备句柄即可。

[cpp] view plaincopyprint?

  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. }  
[cpp] view plain copy

print?
  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. }  

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

原创粉丝点击