usb设备驱动程序开发
引言
usb总线是1995年微软、ibm等公司推出的一种新型通信标准总线,特点是速度快、价格低、独立供电、支持热插拔等,其版本从早期的1.0、1.1已经发展到目前的2.0版本,2.0版本的最高数据传输速度达到480mbit/s,能满足包括视频在内的多种高速外部设备的数据传输要求,由于其众多的优点,usb总线越来越多的被应用到计算机与外设的接口中,芯片厂家也提供了多种usb接口芯片供设计者使用,为了开发出功能强大的usb设备,设计者往往需要自己开发usb设备驱动程序,驱动程序开发一直是windows开发中较难的一个方面,但是通过使用专门的驱动程序开发包能减小开发的难度,提高工作效率,本文使用compuware numega公司的driverstudio3.2开发包,开发了基于nxp公司usb2.0控制芯片isp1581的usb设备驱动程序。
usb设备驱动程序的模型
usb设备驱动程序是一种典型的wdm(windows driver model)驱动程序,其程序模型如图1所示。用户应用程序工作在windows操作系统的用户模式层,它不能直接访问usb设备,当需要访问时,通过调用操作系统的api(application programming interface)函数生成i/o请求信息包(irp),irp被传输到工作于内核模式层的设备驱动程序,并通过驱动程序完成与ubs外设通信。设备驱动程序包括两层:函数驱动程序层和总线驱动程序层,函数驱动程序一方面通过irp及api函数与应用程序通信,另一方面调用相应的总线驱动程序,总线驱动程序完成和外设硬件通信。usb总线驱动程序已经由操作系统提供,驱动程序开发的重点是函数驱动程序。
usb设备驱动程序的设计
使用driverstudio3.2开发usb设备驱动程序
该驱动程序的主要功能包括:从控制端点0读取规定个数的数据、向端点0发出控制命令、从端点2批量读数据、向端点2批量写数据,驱动程序的开发采用driverstudio3.2驱动程序开发包及vc++6.0,使用开发包中的向导程序driverwizard就可以方便的生成驱动程序框架、模块及部分程序源代码,开发者只需要在功能模块中加入自己的实现程序就能完成复杂的usb设备驱动程序设计,下面介绍使用driverwizard生成isp1581驱动程序的过程:
(1)启动driverwizard,选择driverworks project创造一个名为usbdio的vc++项目;
(2)在驱动程序类型中选择wdm driver,wdm function driver,在硬件设备所支持的总线类型中选择usb(wdm only),在usb vendor id(厂商识别码)中填写0741,在usb product id(产品识别码)中填写0821;
(3)增加usb设备端点,设置端点2为批量输入/输出传输方式;
(4)在驱动程序支持的功能项中选择read、write、device control、cleanup;
(5)选择自动产生批量读及批量写程序代码;
(6)在i/o请求irp处理方式中选择none,即irp不排队;
(7)在接口的打开方式中选择symbolic link:usbdiodevice,即应用程序以符号链接名打开设备;
(8)定义应用程序调用deviceio control 函数对wdm驱动程序通信的控制命令,结果如图2所示。
(9)最后选择完成并确认生成新的项目信息,向导程序就会在usbdio目录中生成一个名为usbdio的项目文件,其中包括了isp1581驱动程序框架、模块及部分源代码。
usb设备驱动程序的编程
在使用driverwizard生成驱动程序框架、模块及部分程序源代码后,开发者只需完成图2中三个控制代码所对应的三个功能模块的编程:模块usbdio_ioctl_ id_code_handler的功能是从控制端点0读取数据,模块usbdio_ioctl_ test_command_handler的功能是向控制端点0发送一个控制命令,模块usbdio_ioctl_dma_command _handler的功能是向控制端点0发送一个要求usb设备进行dma传输的控制命令,下面是第一个模块的编程实例。
ntstatus usbdiodevice::usbdio
_ioctl_id_code_handler(kirp i)
{
ntstatus status =status_
success;
t << entering usbdiodevice
::usbdio _ioctl_id_ code_
handler, << i << eol;
purb purb;
ulong numdata;
numdata=*(puchar)i.ioctlbuffer();
//设置读取的数据个数
purb=m_lower.buildvendorrequest(
(puchar)i.ioctlbuffer(),//驱动程
序存放读取的数据的内存区
numdata,//wlength,读取的数据个数
0,
0x0c,//brequest 0,//wvalue
true,//input
true,
null,
0x0472,//windex,传输到固件程序
的读数命令码
urb_function_vendor_endpoint,
null
);
if(purb==null)
{
i.information() =0;
status=status_insufficient_
resources;
}
else
{
i.information() =numdata;
tatus=m_lower.submiturb(purb,null,
null,0);
delete purb;
}
return status;
}
对象i包含了应用程序下传的irp内容,包括命令或数据等参数,函数buildvendorrequest用来分配并初始化一个用于厂商请求的urb(usb request block),该urb将作为下传irp的一个参数,通过函数submiturb发送给总线驱动程序,以便完成与硬件的通信。
在初始化urb时需要了解usb的传输方式及传输协议,该功能使用了usb的控制传输方式,该方式包括三个阶段:设置阶段、数据阶段和状态阶段,其中数据阶段可选,开发者主要关注设置阶段中的8个关键字节的定义,8字节分成了5个字段,定义了传输请求及相关信息,这8个字节的格式如图3所示。
bmrequesttype:1字节,用来指定数据流动的方向,请求的类型,以及接收者。
brequest:1字节,用来指定请求。
wvalue:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。
windex:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。
wlength:2字节,包含数据阶段中接下来要传输的数据字节数目。
以上字段的应用已经在程序注释中标出,在此不再赘述。
usb设备驱动程序的安装及调用
usb设备驱动程序的安装
驱动程序编译完成后会生成一个名为usbdio.sys的文件,即usb设备驱动程序,另外在使用向导程序wizarddriver生成驱动程序时会产生一个名为usbdio.inf的驱动程序安装程序,对此程序只需稍做修改就能正常使用,具体是将类改为usb,即class=usb,由于本驱动程序使用符号链接名打开设备,所以删除classguid选项,注意设备标识符必需为:%devicedesc%=usbdio_ddi, usb\vid_0471&pid_0821,其中0471是usb控制芯片的厂商识别码,0821是usb设备标识码。
驱动程序安装过程是:将usb设备加电,连入计算机的usb接口,这时候会看到windows操作系统提示发现新硬件,提问是否安装驱动程序,选择是,然后选择驱动程序所在文件夹,选择文件usbdio.inf即可完成安装。
usb设备驱动程序的调用
为了完成对驱动程序的调用,笔者使用vc++6.0编写了usb应用程序包,程序包共由五个功能模块组成,用户通过调用这些模块即可方便的完成对usb外设的控制及读写,这些模块如下。
● int ctrlreaddata(unsigned char usbselect,unsigned char *rbuffer,unsigned char numdata),主要功能是读取isp1581控制端点0发来的数据,数据存放在缓冲区rbuffer中。
● int ctrlsendtestcommand (unsigned char usbselect,unsigned short int testcommand),主要功能是发送测试命令,变量testcommand定义了测试命令。
● int ctrlsenddmacommand (unsigned char usbselect,unsigned char dmadirection,unsigned char ramselect,unsigned long dmalength),主要功能是发送dma传输命令,变量dmadirection定义数据传输方向,ramselect定义将要操作的usb外设的存储器,dmalength定义了数据传输总数。
● int dmaread(unsigned char usbselect,unsigned char *rbuffer,int len,int waittime),主要功能是计算机批量读取isp1581中的数据,而isp1581以dma方式从外部ram读取数据。
● int dmawrite(unsigned char usbselect,unsigned char *rbuffer,int len, int waittime),主要功能是计算机批量写数据到isp1581,而isp1581将以dma方式写数据到外部ram。
LED电源产业:在摸索中走向成熟
工地扬尘噪声监测系统特点及功能
如如何让四旋翼飞行器在一个执行器损坏后继续飞行呢
科学家研发可测量颈部运动的传感器
中国广电将利用700MHz的广覆盖的特性在5大领域全面开展科研和服务
USB设备驱动程序开发
影响电动汽车发展的蓄电池性能比较
如何在HLS中描述数字时钟?
农业无人机大有作为,千亿市场待掘金
天合即将发布新一代液冷储能系统Elementa 2和工商储解决方案Potentia
马化腾两会八份建言:VR/AR/AI技术应用是首先推广的技术
微软智能云 Azure具备强大的延展性和扩展
ATM光交换,ATM光交换是什么意思
1024程序员节暨「源聚一堂」开源技术沙龙(北京站)火热报名中
AI技术让人死后在虚拟网络世界中复活
可穿戴式设备实用性不足,谁会为它买单?
将手机植入大脑 这才是移动技术的未来?
vivoX7曜石黑版高清图赏
物联网中的工业无线标准
ESD保护的智能小型化