加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > 技术文章

用Driver Studio开发WDM型的USB设备驱动程序

时间:2012-11-24  来源:123485.com  作者:9stone

  前文所提及的WDM驱动程序开发方法,笔者都曾尝试过。个人认为用DriverStudio开发工具包来开发USB驱动程序行之有效。其中的Driver Wizard是创建WDM驱动程序框架的一个很好的工具,后文将介绍用它来创建USB设备驱动程序的基本框架。

  1、搭建开发平台

  由于利用 DriverStudio 开发WDM驱动程序在搭建开发平台的过程中对软件的安装顺序要求颇高,在开发过程中我也曾因为安装顺序的颠倒而失败。在实践中总结了以下的安装步骤,有必要在此作以介绍。

  ①在已装了Windows 2000 操作系统的机子上安装 Microsoft Visual C++6.0。 ②安装 Win2000 DDK 。③安装 NuMega DriverStudio 2.0 ( or 2.6 ) 驱动程序开发工具包。它包含DriverWorks(用于开发内核模式WDM驱动程序 )、SoftICE( 用于调试WDM驱动程序 )等开发工具。④由于DriverWorks 所用的类库是对 DDK 函数的封装,必须在 VC中编译,创建自己的库文件。⑤设置 DDK 路径。

  2、利用DriverStudio 的DriverWorks生成USB设备驱动程序框架

  驱动程序开发平台搭建成功后,我们可利用驱动程序生成向导Driver Wizard,根据硬件设置较为容易的生成USB设备驱动程序的大体框架。本人的设置如下:①选择WDM的驱动程序类型和Windows 2000运行平台。②选择USB总线类型,系统选择的USB芯片是Philip公司的ISP1581,填写它的VID(供应商ID)和PID(设备 ID),这些信息由芯片的供应商提供。③增加端点1和端点2,它们分别具有IN和OUT属性。④根据需要选择对设备的操作有:Read、Write、 Device Control和CleanUp。⑤选择给端点2产生BULK Read和Write的代码, 向导会自动产生一套对端点2进行读、写的代码。⑥设置驱动程序的属性,采用WDM接口;在选取读写方式时应遵循一条原则:需要快速传送大量数据时,用 Direct I/O ,反之用 Buffer I/O ,这里选择BufferI/O;由于无特殊的电源需求,故选用系统默认的Manage Power For This Device。⑧增加IOCTL接口,在其生成的代码框架中加入自己的操作,以实现一个完整的USB设备驱动程序。最后就生成了一个WDM型的USB设备驱动程序框架和一个测试该驱动程序的测试程序大体框架。然后在其中添加需要的功能代码。

  3、USB设备驱动程序中的关键例程代码实现

  下面以我们的驱动程序为例,介绍USB驱动程序开发中的几个关键例程的实现。本驱动程序的主要功能是控制USB设备上LED灯通断并且对设备进行读写。

  1) 初始化例程 DriverEntry()

  设备驱动程序与应用程序不同,它没有main()或WinMain()函数,而是有一个名为DriverEntry()的入口函数,它通常完成一些初始化工作。当设备驱动程序被加载时,操作系统调用这个入口。在使用DriverWizard 创建的驱动程序基本框架中,DriverEntry()函数已经写好了,无需添写代码。在该例程中,驱动程序要向操作系统登记并注册一些消息处理器,通过 RegistryPath来找到位于注册表中的驱动程序参数,当驱动程序正确安装后,在注册表KEY_LOCAL_MACHINE / SYSTEM / CurrentControlSet / Service 下可以找到MyUSB 项。而用DDK编写该入口函数还需初始化Dispatch(分派)例程入口。

  2) 创建设备例程 AddDevice()

  大多数的PDO 都是在 PnP 管理器调用该程序入口点时被创建的。插入新设备后,系统启动时,总线枚举器会发现总线上的所有设备,会自动寻找并安装设备的驱动程序,并由驱动程序中的处理 PnP 功能模块自动处理 AddDevice() 例程及其他PnP消息。此例程使用IoCreateDevice() 函数创建设备对象,再使用 IoRegisterDeviceInterface() 函数将设备组成为一个特定的设备接口,然后使用IoAttachDeviceToDeviceStack() 函数关联设备栈。

NTSTATUS MyUSBDevice::AddDevice( PDEVICE_OBJECT Pdo )
{
 // 产生一个DDK中KDevice类新的设备对象
 MyUSBDevice *pDevice = new ( static cast<PCWSTR>( KUnitizedName(L“MyUSBDevice”,m_Unit) ),// 设备名
  FILE_DEVICE_UNKNOWN, // 设备类型
  NULL, // 指针链接名
  0, // 设备特征标志位
  DO_BUFFERED_IO| DO_POWER_PAGABLE); // I/O传输方式
 MyUSBDevice(Pdo, m_Unit);
 if ( pDevice == NULL )
 {
  return STATUS_INSUFFICIENT_RESOURCES;
 }
 NTSTATUS status = devices -> ConstructorStatus();
 if ( !NT_SUCCESS(status) ) // 不成功,返回错误状态并删除指针
 {
  delete pDevice;
 }
 else // 如果成功,向系统报考设备的电源状态变化为PowerDeviceD0
 {
  m_Unit++;
  pDevice -> ReportNewDevicePowerState( PowerDeviceD0 );
 }
 return status;
}

  3) LED控制处理例程 MyUSB_IOCTL_LED_Handler()

  该例程是实现本驱动程序功能的关键例程,它是用来控制设备上的LED灯通断,主要利用USB Vendor Request来向设备传送。其中,request=1的时候表示让LED亮,request=0的时候让LED灭。它是通过DeviceControl 由上层应用程序传下来。实现代码如下:

 

 

NTSTATUS MyUSBDevice::MyUSB_IOCTL_LED_Handler(KIrp I)
{
 NTSTATUS status = STATUS_INVALID_PARAMETER;
 //检查输入参数是否正确,如果不正确,返回STATUS_INVALID_PARAMETER
 if(I.IoctlOutputBufferSize() || !I.IoctlBuffer() ||(I.IoctlInputBufferSize() != sizeof(UCHAR)))
  return status;
 //处理MyUSB_IOCTL_LED_ON请求
 PURB pUrb = m_Lower.BuildVendorRequest(NULL, // 传输缓冲区
  0, // 传输缓冲区大小
  0, // 请求保留位
  (UCHAR)(*(PUCHAR)I.IoctlBuffer()), // 请求1=LED_ON ,0=LED_OFF
  0 ); // 值
 //向下传送URB
 status = m_Lower.SubmitUrb(pUrb, NULL, NULL, 5000L);
 //若请求在此处理,设置I.Information指示多少数据拷贝回用户
 I.Information()=0;
 I.Status()=status;
 return status;
}

  4) 访问硬件例程 DeviceControl()

  上层应用软件程序就是通过此例程来将IRP传到下层。

 

 

NTSTATUS MyUSBDevice::DeviceControl(KIrp I)
{
 NTSTATUS status;
 switch (I.IoctlCode())
 {
  case MyUSB_IOCTL_LED:
   status = MyUSB_IOCTL_LED_Handler(I);
   break;
  default: // 未被声明的I/O 控制请求
   status = STATUS_INVALID_PARAMETER;
   break;
 }
}

  限于篇幅,这里仅介绍本驱动程序中的部分例程实现代码。编写完驱动程序后,首先在Visual C++ 中编译通过,然后连接硬件,用DriverStudio 工具包中的SoftICE调试器调试该驱动程序,并且修改编译DriverStudio产生的该驱动程序的测试程序,就通过命令行来测试我们的驱动程序。最后对于LED的控制,我们可以直观的在设备上看到。

  结束语

  USB技术的不断发展和完善,已经使其逐渐成为先进总线接口技术的标志和方向,如今USB OTG标准已经发布,那么USB的应用领域也将越发的广泛。开发一些特定功能的USB接口并设计其设备驱动程序也将成为应用USB技术的关键。通过对 USB的学习和Windows 2000下的WDM驱动程序的研究,本文已经给出了编写WDM型USB设备驱动程序的一般方法,读者可以在实际应用中逐步提高对USB和驱动程序的认识,取得事半功倍的效果。


分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->技术文章
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门