真正的实例-如何编写应用程序
虽然利用DriverStudio的工程向导为我们生成了测试程序示例,但它大量使用了DriverStudio自己的封装库,现在来介绍在不使用DriverStudio封装库的情况下如何编写测试程序。
1、打开设备的两种方式
我们知道打开设备用CreateFile函数,其第一个参数应指向欲打开的USB设备,它可以是Device Interface,也可以是Device Symbolic Link(设备连接符或叫设备名)。要么用Interface打开USB设备,要么用Symbolic Link打开(不知正确与否),在利用DriverStudio工程向导生成时USB驱动程序的过程中可选择应用程序打开此USB设备的方式(见下图),在这时就确定了将来该用何种方式来打开设备。
1)用Interface方式打开设备
首先取得设备的GUID(什么是GUID?请看这篇文章:USB编程之二(常见设备类型的GUID)),然后利用设备GUID来得到设备Interface,最后就可以用CreateFile函数来打开设备了。
GUID由驱动程序定义,如上一节的驱动程序实例中对GUID的定义如下:
还可以利用第三方工具取得设备GUID,如USBView,还有DriverStudio自带的Symbolic Viewer),下面是用Symbolic Viewer查得的上一节驱动实例的GUID
我们这里利用DEFINE_GUID宏来定义设备GUID,内容如下:
DEFINE_GUID宏在initguid.h中定义的,所以需要在加入对此文件的引用:
另外,我们将要用到的一些函数需要setupapi.h和setupapi.lib,它们是VC6自带的,所以需要添加对这两个文件的引用:
①#include "Setupapi.h"
②选择菜单“Project”->“Settings”,切换到“Link”页,在“Object/library modules”中填入:setupapi.lib
好了,现在贴出以Interface方式打开设备的代码:
2)用Symbolic Link方式打开设备
Driver Studio通过KUnitizedName函数生成设备的Symbolic Link,我们再利用CreateFile来打开设备,其一般形式为:
其中前缀“\\\\.\\”表示Createfile试图打开一个设备,然后紧跟设备名,其设备名可以利用DDK提供的“Device Tree”工具来查询,也可以查看DriverStudio向导生成的代码中KUnitizedName实例代码(位于AddDevice功能函数内),如果第一个参数为:L”TestDevice”,则设备名一般应为TestDevice0
在上一节实例中生成的驱动程序是以Interface方式打开的,现在我们重新配置此项目,在配置向导第“Step 12 of 14”中,打开设备(Open Device)选择“Symbolic Link”选项,并填写Symbolic Link的值为:Easy_USB_51_Programer_SymbolicDevice:
下载编译后的驱动 |
下载驱动源码 (需要放到C:\Easy_USB_51_Programer_Symbolic目录) |
安装驱动程序,然后就可以用Symbolic Link的方式打开设备了,而Symbolic Link的值就应该为Easy_USB_51_Programer_SymbolicDevice0,这个值在配置向导第“Step 12 of 14”中已经填好(但其后要加“0”),通过查看驱动源程序也可以得到(位于AddDevice功能函数的KUnitizedName实例代码的第一个参数),也可用第三方工具如Symbolic Link Viewer查询,下图是利用DriverStudio提供的Symbolic Link Viewer工具查询到的Symbolic Link值:
好了,现在贴出以Symbolic Link方式打开设备的代码:
2、读写设备
读写设备除了可以通过WriteFile和ReadFile函数以外,还可以利用DeviceIoControl函数。WriteFile最终会调用驱动程序的IRP_MJ_READ实例代码(DriverStudio里是Write实例函数),ReadFile最终会调用驱动程序的IRP_MJ_ WRITE实例代码(DriverStudio里是Read实例函数),而DeviceIoControl最终会调用驱动程序的IRP_MJ_DEVICE_CONTROL实例代码(DriverStudio里是DeviceControl)。
DeviceIoControl的第二个参数为操作代码,在驱动程序里的定义形如IOCTL_XXXX格式,对于自定义的设备操作代码,一般用CTL_CODE宏定义,我们需要拷贝上一节驱动程序中对IOCTL_LED和IOCTL_GET_KEY两个操作代码的定义(在使用前需要包含头文件:#include "Winioctl.h")
下面放上利用MFC编写的一个基于对话的程序,它主要实现与上一节中测试程序相似的功能(通过端点2读写数据,通过控制端点控制扩展板EXT-BOARD-A上的LED状态,通过控制端点读取扩展板EXT-BOARD-A上的按键的状态),另外还测试了两种打开设备的方式(设备安装驱动程序后就决定了设备只能以某一种方式打开,用不正确的方式打开会报错)。
应用程序界面
(呵呵,我已经投PCB了,所以没有用手工制作的那个原始东东来展示)
编译好的应用程序 |
应用程序源码 |
注意:这节的实例还需要再改一下设备程序,把之前main函数里的控制LED的代码删除,即
这句需要删除,而通过控制端点控制LED和读取按键状态的代码在《厂商自定义USB设备固件程序及特性》一节里已经介绍了。
设备固件源码 |
USB产品
EASY USB D12 是原EASY USB 51 PROGRAMER的升级版,是百合电子工作室历时一年精心设计的一款USB学习板/开发板,与老款相比,其实例更丰富,技术文档更详尽,更重要的是此款USB学习板还提供技术支持。......
|