Wince 流接口驱动

来源:互联网 发布:逍遥游软件下载 编辑:程序博客网 时间:2024/05/16 05:40

转载:  网上各种转载,出处已不详


流接口驱动简单说就是可以导出一组流接口函数的驱动, 也就是说,你只要按照规定实现一组标准接口, 这个驱动就完成了. 说来简单,具体实现起来还有一些小的细节要注意.

 

第一步,

建立一个源文件实现下面几个接口函数, 这个源文件可以是.cpp 也可以是.c

BOOL WINAPI DllEntry(HANDLE hinstDLL, DWORD dwReason,LPVOID lpvReserved);DWORD XXX_Init(LPCXXXR pContext, LPCVOID lpvBusContext);BOOL XXX_Deinit(DWORD hDeviceContext);DWORD XXX_Open(DWORD hDeviceContext, DWORD AcessCode,DWORD ShareMode);BOOL XXX_Close(DWORD hOpenContext);BOOL XXX_IOControl(DWORD hOpenContext, DWORD dwCode,                                        PBYTE pBufIn, DWORD dwLenIn,                                        PBYTE pBufOut, DWORD dwLenOut,                                        PDWORD pdwActualOut);void XXX_PowerDown(DWORD hDeviceContext);void XXX_PowerUp(DWORD hDeviceContext);DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count);DWORD XXX_Seek(DWORD hOpenContext, long Amount, DWORD Type);DWORD XXX_Write(DWORD hOpenContext, LPCVOID pSourceBytes,                                     DWORD NumberOfBytes);

 

对于上面几个函数,在几点要说明一下.

1   DllEntry是动态链接库的入口点. 它在动态链接库加载和卸载时被调用.dwReason参数比较重要, 一般用到它的两个值:DLL_PROCESS_ATTACH--表明dll被加载, DLL_PROCESS_DETACH--表明dll被释放. 用户可以在这两种情况下做一些必要的处理.

过实际测试发现这个接口可以不要, 它并不影响其它的接口的使用.

 

2  XXX_Init该函数在DllEntry后被调用. 但不是被应用程序调用,而是在一定的情况下被设备管理器调用. 那么"一定情况下"是指当用户开始用一个设备时,设备管理器调用该函数初始化设备. 当要实现多个流接口驱动的实例时(串口是个典型的例子, COMx就是COM的多个实例),XXX_Init应该被调用多次. 如果你熟悉MFC, 你一定想到了DllEntry与XXX_Init的关系就像InitApplication与InitInstance的关系. 而流接口驱动就对应窗体.第二个参数一般情况下是用不到的, 所以有时候会看到该函数会写成下面的形式DWORD XXX_Init(DWORD pContext).该函数要返回非零值其它的接口函数才能使用.

 

3   XXX_Deinit是设备被卸载时调用. XXX_Open与 XXX_Close分别在用户调用CreateFile和CloseHandle时被调用. XXX_Open的参数hDeviceContext是由XXX_Init返回的值.是一个指向设备context的句柄. 另外, 用CreateFile打开设备时要用”XXX1:”的形式. 后面的数字根据注册表active下的键值确定

 

4   XXX_IOControl 是当用户用DeviceIOControl定义要完成的操作时, 系统调用该函数. dwCode是操作码,特定于不同的设备.可通过头文件传给应用程序. 这两个参数是必须的, 其它几个可为NULL, pBufIn输入buffer, pBufOut是输出buffer. 输入输出是相对设备的, pdwActualOut是实际输出的字节数. 这个函数的功能比较强大,为什么这么说呢, 因为它的上层DeviceIOControl比较强大, 事实上,DeviceIOControl可以完成几乎所有的操作其中就包括读写操作

 

5   XXX_PowerDown与XXX_PowerUp这两个函数, 是在系统掉电与上电时执行的, 所以很显然,你不能调用它. 它是在内核模式下执行的. 为了避免死机, 这两个函数最好什么都不要做,尽快返回.

 

6   为了方便测试你写的驱动,上面每个接口函数里可以用 RETAILMSG输出一些调试信息.

 

第二步 

建立def文件声明要输出的接口(比如TestDRV.def, 这个名字可以随便命名)

文件的内容如下:

LIBRARY TestDRVEXPORTSXXX_CloseXXX_DeinitXXX_InitXXX_IOControlXXX_OpenXXX_PowerDownXXX_PowerUpXXX_ReadXXX_SeekXXX_Write


 LIBRARY 后面的名字也是可以随便命名的, 我在网上看到说这个名字要和最后生成的dll名相同,但我实际测试发现这个并没有影响.

 

第三步 

编译. 编译有两种方法, 一种是仿照wince下的driver架构, 建立source, makefile等文件在pb下编译. 最终是生成一个.dll的文件. 还有一种方法就是用evc建立一个基于动态库的工程, 把上述两个文件加进工程, 编译生成一个dll的文件就可以了. 我用第二种方法.

 

第四步 

这一步的工作是把前面生成的dll加进wince的image里, 并设置相关的注册表项,让系统可以识别该设备.

1 在platform.bib下加入下面的语句

TestDRV.dll                $(_FLATRELEASEDIR)/TestDRV.dll            NK    SH

注意中间的路径要根据你自己的实际情况来写.


2 在platform.reg里加入下面的语句

[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/TestDrv]         "Index"=dword:1         "Prefix"="XXX"         "Dll"="TestDRV.dll"                  "Order"=dword:0

这个应该不用解释了.

 

第五步 

编译内核. 编译内核不用全部build整个系统,这个要很长时间(我一般都一个小时左右), 直接把platform.reg和platform.bib 复制到release目录下, 然后make image就行了.

 

第六步 

测试驱动. 怎样测试驱动呢. 测试很简单,用evc建一个wince的应用程序, 里面调用一些上层的文件操作函数, 比如CreateFile, CloseHandle, ReadFile等,看一下系统输出的调试信息就可以了.

原创粉丝点击