• 开发WDM型的USB设备驱动程序


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

    2004-11-21 00:04作者:鲜征征 杨皓出处:计算机与信息技术责任编辑:方舟
      用Driver Studio工具包开发WDM型的USB设备驱动程序

      前文所提及的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和驱动程序的认识,取得事半功倍的效果。

    你问我生命中还有什么可追寻?

  • 相关阅读:
    信息量
    MVC4的实战:排球计分(一)(综述)
    排球计分规则3.17
    观后感-----怎样成为一个高手
    本学期最后一个博客
    第五组作业
    个人作业
    第五组作业
    个人作业
    一周的总结
  • 原文地址:https://www.cnblogs.com/avril/p/1503420.html
Copyright © 2020-2023  润新知