很多写Windows Device Driver的开发人员基本上都是使用Windows DDK进行开发的。但是,现在也有不少人都开始借助一些辅助工具。笔者去年开始接触到DriverStudio,发现它真的是一个不错的开发工具,不仅写代码的时候思路清晰,而且和DDK的结合很好。

当然,也有很多人觉得用DriverStudio不够正宗,或者说不能很好的理解Windows Device Driver的架构。我感觉这就有点像MFC和SDK的关系,关于这个问题在很多地方都有争论,比如在万千新闻组上,就讨论了将近2个月。每个人都有自己的最爱,都有自己的习惯,只要你能把事情做好,我想用什么方法应该都是一样的。如果你已经习惯了用DDK开发,那完全还可以继续用下去;如果你觉得DriverStudio不错,那尝试用一个可以给你按照OOP概念来编程的工具有什么不好呢?

在驱动开发网上,经常看到有人询问一些关于DriverStudio的使用的问题。我正好很有幸用它作了几个驱动程序,包括VXD, KMD和WDM,稍微有点心得,因此想写下来给大家作一个小小的参考。如果其中有错误,欢迎大家给我指出,谢谢。

下面我就介绍一下用DriverStudio开发一个USB驱动程序的过程。这个USB设备有3个双向端点,每个端点的配置如下:

EP        类型        地址 buffer(Bytes)
0 IN/OUT Control 0x80/0x00 16/16
1 IN/OUT Bulk 0x81/0x01 16/16
2 IN/OUT Bulk 0x82/0x02 64/64

我们的驱动程序需要实现的功能就是控制设备上的LED灯的亮和灭,以及通过Endpoint 2对设备进行读写。

由于DriveStudio由几个部分组成,我们写这个驱动程序只要用到DriverWorks,因此下面我们就简称它为DW。在这里,我们假定读者已经正确的安装了DW,并且已经编译好了各个库文件。

1. 首先,我们通过快捷方式“Setup DDK and Start MSVC“来启动VC IDE。这个快捷方式所指向的程序,会进行一些必要的设置,然后再启动VC IDE,这样我们的程序就可以使用DDK和DW的头文件和库了。

2. 从VC IDE的菜单"DriverStudio"中选择"DriverWizard", 在如图1所示的对话框中, 写上项目名称. 在这里, 我们将这个项目称为: TEST, 所在的目录为D:\TEST. 然后点按钮"Next >".
 
图1

3. 在接下来的这个对话框中(如图2), 我们需要选择驱动程序的类型. 由于USB设备驱动程序是WDM类型的, 所以我们选择第二项并且点按钮"Next >".
 
图2

4. 在第3个对话框中(如图3), 选择我们的驱动程序所操作的总线类型. 这里, 我们选择USB. 在USB Vendor ID和USB Product ID中填入USB设备的VID和PID. 假定我们的USB设备的VID和PID分别是16进制的0471和1801. 然后点按钮"Next >". 关于VID和PID的规定请参考USB-IF的规范.
 
图3

5. 在接下来的对话框中(如图4), 我们需要加入Endpoint 1和Endpoint 2的定义. 由于在USB中规定Endpoint 0是必须存在的, 所以我们不需要对Endpoint 0进行定义. 点"Add..."按钮, 弹出一个如图5所示的对话框. 我们将它修改成如图6所示. 其中, 按照USB的规定, 对于端点, 它的地址是1; 按照前面说明的设备的特点, Endpoint 1的最大的包大小为16字节, 因此在"Max Transer Size"中填入16; Endpoint Name可以通过"Suggest Name"得到. 按照这些原则, 继续设置其他的配置, 以使对话框4变成如图7所示. 接下来, 继续按"Next >"按钮.
 
图4
 
图5
 
图6
 
图7

6. 在如图8所示的对话框中, 可以填入我们需要的Driver Class的名字和文件名. 一般我们不需要更改. 继续按"Next >"按钮.
 
图8

7. 在如图9所示的对话框中, 因为不需要给其他的驱动程序提供接口, 也不需要提供Flush功能, 所以不需要任何修改, 直接按"Next >"按钮.
 
图9

8. 在如图10所示的对话框中, 我们选择给端点2产生BULK Read的代码, 并且按"Next >"按钮. DW会给我们产生一套对端点2进行读的代码, 不用修改, 就可以直接使用.
 
图10

9. 在如图11所示的对话框中, 我们选择给端点2产生BULK Write的代码, 并且按"Next "按钮. 这样, DW也会给我们产生一套对端点2进行写的代码, 不用修改, 就可以直接使用.
 
图11

10. 对于如图12的对话框, 我们直接按"Next >"按钮. 这里是设置是否要将I/O请求排队, 在这里, 我们不需要排队.
 
图12

11. 在如图13所示的对话框中, 我们不需要创建任何注册表项, 所以直接按"Next >"按钮.
 
图13

12. 如图14所示的对话框, 是让我们设置一些驱动程序的属性, 比如接口, 缓冲区之类的. 一般的都可以使用缺省设置. 继续按"Next >"按钮.
 
图14

13. 在如图15所示的对话框中, 是让我们给驱动程序增加一些IOCTL接口. 我们只增加一个如图16所示的IOCTL来控制USB设备的LED灯. 然后按"Next >"按钮.
 
图15
 
图16

14. 在最后一个如图17所示的对话框中, 可以设置一些驱动程序的属性, 产生一个console测试程序. 按下"Finish"按钮, 就结束了Wizard.
 
图17

这样, 我们就创建好了一个基本的驱动程序, 下面来看看还要做哪些工作才可以和我们的设备以及上层的应用程序通讯.

把函数NTSTATUS TESTDevice::TEST_IOCTL_LED_Handler(KIrp I)改成如下面的样子:

NTSTATUS TESTDevice::TEST_IOCTL_LED_Handler(KIrp I)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;

t << "Entering TESTDevice::TEST_IOCTL_LED_Handler, " << I << EOL;

__try

{

// TODO: Verify that the input parameters are correct

// If not, return STATUS_INVALID_PARAMETER

if(I.IoctlOutputBufferSize() || !I.IoctlBuffer() ||

(I.IoctlInputBufferSize() != sizeof(UCHAR)))

__leave;

// TODO: Handle the the ZBUARD_IOCTL_LED_ON request, or

// defer the processing of the IRP (i.e. by queuing) and set

// status to STATUS_PENDING.

PURB pUrb = m_Lower.BuildVendorRequest(

NULL, // transfer buffer

0, // transfer buffer size

0, // request reserved bits

(UCHAR)(*(PUCHAR)I.IoctlBuffer()), // request. 1 = LED_ON, 0 = LED_OFF

0 // Value

);

// transmit

status = m_Lower.SubmitUrb(pUrb, NULL, NULL, 5000L);

}

__finally

{

// TODO: Assuming that the request was handled here. Set I.Information

// to indicate how much data to copy back to the user.

I.Information() = 0;

I.Status() = status;

}

return status;

}

这个函数是控制LED灯的,它是通过USB Vendor Request来向设备传送的。其中,request=1的时候表示让LED亮,request=0的时候让LED灭。它是通过DeviceIoControl由上层应用程序传下来。

再看看读写部分,经过检查NTSTATUS TESTDevice::Read(KIrp I)和NTSTATUS TESTDevice::Write(KIrp I)可以发现,DW已经给我们写好了读写的代码,我们可以直接使用了。这些代码就是在上面的第8和第9步中产生的代码。

最后,修改编译一下DriverStudio产生的测试程序Test_TEST程序,我们就可以通过命令行来测试我们的驱动程序了。对于LED的控制,我们可以直观的在设备上看到,但对于读写的操作就需要和firmware程序配合,这已经超出了本文的范围,不在这里讨论了。

通过上面的讲解,我们可以看到有了DriverStudio,就可以快速的产生一个驱动程序,然后在里面作一些小的改动就可以使用了。即使是写一个比较复杂的USB驱动程序,我们也可以不用管一些系统的IRP处理,只要专注于我们自己的特定应用就可以了。而且它把一个驱动程序概括成几个类的概念,并且DW还附带有一些很有用的STL类,在VC IDE里面有了一个很清晰直观的表示。这样,对一些从上层应用转向驱动程序的开发人员,或者一些对C++/OOP很熟悉但不太了解系统内核的开发人员,都比较容易上手。即使对于推崇直接用DDK编程的人来说,通过阅读DriverStudio附带的源代码,也可以对驱动程序的开发有一个更加深入的了解

用DriverStudio开发USB驱动程序的更多相关文章

  1. USB2.0学习笔记连载(三):通用USB驱动程序解析

    对于USB驱动的开发,读者可以使用Windows DDK.DriverStudio等多种开发工具来实现USB的驱动,但是驱动程序的开发过程都比较复杂,而且很容易致使USB主机内存泄露而死机.那么对于笔 ...

  2. 驱动07.USB驱动程序

    1 了解USB识别的过程 eg:在Windows系统下的一个现象:把手机的USB设备接到PC 1. 右下角弹出"发现android phone" 2. 跳出一个对话框,提示你安装驱 ...

  3. 获取 Google USB 驱动程序

    获取 Google USB 驱动程序       另请参阅 安装 USB 驱动程序 使用硬件设备 使用任何 Google Nexus 设备进行 ADB 调试时,只有 Windows 需要 Google ...

  4. USB驱动程序之USB设备驱动程序1简单编写

    1.驱动编写分析 (1)usb总线驱动程序在我们接入USB设备的时候会帮我们构造一个新的usb_device.注册到总线里面来.左边这一块已经帮我们做好了,我们要做的是右边这一块.我们要构造一个usb ...

  5. USB驱动程序之USB总线驱动程序学习笔记

    USB总线驱动程序的作用 1. 识别USB设备 1.1 分配地址 1.2 并告诉USB设备(set address) 1.3 发出命令获取描述符 描述符的信息可以在include\linux\usb\ ...

  6. usb驱动程序小结(六)

    title: usb驱动程序小结 tags: linux date: 2018/12/20/ 17:59:51 toc: true --- usb驱动程序小结 linux中为usb驱动也提供了一套总线 ...

  7. USB驱动程序之概念介绍学习笔记

    现象:把USB设备接到PC 1. 右下角弹出"发现android phone" 2. 跳出一个对话框,提示你安装驱动程序 问1. 既然还没有"驱动程序",为何能 ...

  8. USB驱动程序涉及的概念及框架

    引入:当我们把一个USB设备接入PC机时,会出现什么样的现象? 现象:把USB设备接到PC1.右下角弹出“发现android phone”2.跳出一个对话框,提示你安装驱动程序 首先来看一下,USB驱 ...

  9. LDD3 第13章 USB驱动程序

    通用串行总线(USB)是主机和外围设备之间的一种连接.最新USB规范修订增加了理论上高达480Mbps的高速连接. 从拓扑上看,USB子系统并不是以总线的方式来布置的,它是一颗由几个点对点的连接构建而 ...

随机推荐

  1. 关于HTTP GET & POST的区别(转)

    Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE. URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTT ...

  2. RAID知识总结[转]

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://815632410.blog.51cto.com/1544685/1394306 ...

  3. 《Thinking in Java》学习笔记(七)

    1.关于反射还有一些需要补充的 package reflect; public class HiddenClass { public A HiddenA(){ return new A(); } } ...

  4. HDU 6181 Two Paths

    这是一道次短路的题 但是本题有两个坑 注意边权的范围,一定要在所有与距离有关的地方开 long long 本题所求的并不是次短路,而是与最短路不同的最短的路径,如果最短路不止一条,那么就输出最短路的长 ...

  5. BZOJ 4108: [Wf2015]Catering [上下界费用流]

    4108: [Wf2015]Catering 题意:有一家装备出租公司收到了按照时间顺序排列的n个请求. 这家公司有k个搬运工.每个搬运工可以搬着一套装备按时间顺序去满足一些请求.一个搬运工从第i个请 ...

  6. nginx隐藏版本号

    在实际运用nginx中我们最好将我们的版本号直接隐藏,因为有些版本号的nginx被爆出了漏洞,所以我们为了安全起见,最好将我们的版本号隐藏. 1.对于未安装的nginx我们使用源码编译安装才可以将版本 ...

  7. Halcon一日一练:图像分辨率与像素

    1.图像像素: 像素是指由图像的小方格即所谓的像素(pixel)组成的,这些小方块都有一个明确的位置和被分配的色彩数值,而这些一小方格的颜色和位置就决定该图像所呈现出来的样子.像素是构成图像的基本单元 ...

  8. 解决PhpStorm卡顿的问题

    以前的开发一直使用phpstorm.可谓是情有独钟,但是发现随着开发phpStorm逐渐变得卡顿,也试过其他的编译器,但是都感觉没有PhpSrom好用,网上百度了一下,看到不一样的回答.只要修改两个J ...

  9. 分布式集群下的Session存储方式窥探

    传统的应用服务器,自身实现的session管理是大多是基于单机的,对于大型分布式网站来说,支撑其业务的远远不止一台服务器,而是一个分布式集群,请求在不同的服务器之间跳转.那么,如何保持服务器之前的se ...

  10. window 下生成NodeJs(v8.9.3) 的 VS2015 解决方案node.sln

    window 下生成NodeJs(v8.9.3) 的 VS2015 解决方案node.sln 使用步骤 也可以参照 github: https://github.com/nodejs/node/blo ...