开发usb驱动程序的方法(连载一)

合集下载

USB驱动程序(较详细)一

USB驱动程序(较详细)一

USB驱动程序(较详细)一内核使用2.6.29.4拓扑结构上, 一个 USB 子系统并不是以总线的方式来分布; 它是一棵由几个点对点连接构成的树。

这些连接是连接设备和集线器的4线电缆(地, 电源, 和 2 个差分信号线), 如同以太网的双绞线。

USB主控制器负责询问每个USB设备是否有数据需要发送。

由于这个拓扑结构,一个 USB 设备在没有主控制器要求的情况下不能发送数据. 也就是说:USB是单主方式的实现,主机轮询各外设。

但是设备也可以要求一个固定的数据传输带宽,以保证可靠的音视频I/O。

USB只作为数据传输通道,对他所收发的数据格式没有特殊的内容和结构上的要求,也就是类似于透传。

Linux内核支持两种主要类型的USB驱动程序:Host系统上的驱动程序(USB device driver)和device上的驱动程序(USB gadget driver)(设备端驱动)。

USB 驱动程序存在于不同的内核子系统和USB硬件控制器之中。

USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口,它隐藏了USB控制器的硬件细节。

从这里我们要知道:《LDD3》所谓的USB驱动是针对USB核心提供的接口而写的,并不是真正去操纵USB硬件控制器中的寄存器。

这样你必须保证你的板子上CPU的USB硬件控制器的驱动是可用的。

否则您就得先搞定CPU的USB硬件控制器的驱动才行。

以下是Linux内核中USB驱动的软件构架:如左下图所示,从主机侧的观念去看,在Linux驱动中,USB驱动处于最底层的是USB主机控制器硬件,在其之上运行的是USB主机控制器驱动,主机控制器之上为USB核心层,再上层为USB设备驱动层(插入主机上的U盘、鼠标、USB转串口等设备驱动)。

因此,在主机侧的层次结构中,要实现的USB驱动包括两类:USB主机控制器驱动和USB设备驱动,前者控制插入其中的USB设备,后者控制USB 设备如何与主机通信。

10分钟完成一个USB驱动程序

10分钟完成一个USB驱动程序

很多写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/161 IN/OUT Bulk 0x81/0x01 16/162 IN/OUT Bulk 0x82/0x02 64/64我们的驱动程序需要实现的功能就是控制设备上的LED灯的亮和灭,以及通过Endpoint 2对设备进行读写。

由于DriveStudio由几个部分组成,我们写这个驱动程序只要用到DriverWorks,因此下面我们就简称它为DW。

在这里,我们假定读者已经正确的安装了DW,并且已经编译好了各个库文件。

USB驱动程序编写

USB驱动程序编写

USB驱动程序编写linux‎下usb驱动编写(内核2.4)—‎—2.6与此接口有区别2006-‎09-15 14:57我们知道了‎在Linux下如何去使用一些最常‎见的USB设备。

但对于做系统设计‎的程序员来说,这是远远不够的,我‎们还需要具有驱动程序的阅读、修改‎和开发能力。

在此下篇中,就是要通‎过简单的USB驱动的例子,随您一‎起进入USB驱动开发的世界。

‎USB骨架程序(usb-ske‎l eton),是USB驱动程序的‎基础,通过对它源码的学习和理解,‎可以使我们迅速地了解USB驱动架‎构,迅速地开发我们自己的USB硬‎件的驱动。

USB驱动开发‎在掌握了USB设备的配置后,‎对于程序员,我们就可以尝试进行一‎些简单的USB驱动的修改和开发了‎。

这一段落,我们会讲解一个最基础‎U SB框架的基础上,做两个小的U‎S B驱动的例子。

USB骨架‎在Linux kernel‎源码目录中driver/usb/‎u sb-skeleton.c为我‎们提供了一个最基础的USB驱动程‎序。

我们称为USB骨架。

通过它我‎们仅需要修改极少的部分,就可以完‎成一个USB设备的驱动。

我们的U‎S B驱动开发也是从她开始的。

‎那些linux下不支持的USB‎设备几乎都是生产厂商特定的产品。

‎如果生产厂商在他们的产品中使用自‎己定义的协议,他们就需要为此设备‎创建特定的驱动程序。

当然我们知道‎,有些生产厂商公开他们的USB协‎议,并帮助Linux驱动程序的开‎发,然而有些生产厂商却根本不公开‎他们的USB协议。

因为每一个不同‎的协议都会产生一个新的驱动程序,‎所以就有了这个通用的USB驱动骨‎架程序,它是以pci 骨架为模‎板的。

如果你准备写一个li‎n ux驱动程序,首先要熟悉USB‎协议规范。

USB主页上有它的帮助‎。

一些比较典型的驱动可以在上面发‎现,同时还介绍了USB urbs‎的概念,而这个是usb驱动程序中‎最基本的。

USB 接口驱动程序开发

USB 接口驱动程序开发

USB 接口驱动程序开发1 引言随着微机技术水平的日益提高,传统的计算机接口已经不能满足当前计算机高速发展的需求,计算机业迫切需要一种新的通用型、高速总线接口,通用外设接口标准USB 就应运而生。

USB,全称是Universal Serial Bus(通用串行总线),是一种新型的、基于令牌的、高速的串行总线标准,由Compaq、Microsoft、Intel、IBM 等七家公司共同开发的, 旨在解决日益增加的PC 外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信标准[3],自1995年在Comdex 上亮相以来已广泛地为各PC 厂家支持。

现在市场上几乎所有的P C 机器都配备了US B 接口,USB 接口之所以能够得到广泛支持和快速普及,是因为它具备以下优点:正由于上述优点, 开发USB 接口的设备已成为一种发展趋势。

然而随着USB 技术的迅猛发展, 传统的USB1 . 1 接口已经不能适应用户的需求, 于是在1 9 9 9年在I nt e l 的开发者论坛大会上又提出了USB2 . 0 技术, 使得US B 不仅支持1 . 5Mb / s 的“低速”, 传输和12Mb/s 的“全速”传输,而且支持480Mb/s 的“高速”传输,比USB1.1 标准快40 倍左右,速度的提高对于用户的最大好处就是意味着用户可以使用到更高效的外部设备, 而且具有多种速度的周边设备都可以被连接到USB 2.0 的线路上,而且无需担心数据传输时发生瓶颈效应。

2 USB 驱动程序设计一个完整的USB 系统包括主机系统包括主机系统和USB 设备。

所有的传输事务都是由主机发起的。

一个主机系统又可以分为以下几个层次结构, 。

USB 总线接口包括USB 主控制器和根集线器,其中USB 主控制器负责处理主机与设备之间电气和协议层的互连,根集线器提供USB 设备连接点。

USB设备的驱动程序实现

USB设备的驱动程序实现

USB设备的驱动程序实现
USB驱动是用来控制使用USB接口的设备的软件程序,其实现是将实
际的硬件设备抽象为虚拟的设备,使其能够在计算机操作系统上应用。


般来讲,当你将USB设备插入你的计算机时,它将通过计算机的USB主控
芯片找到USB设备,然后测试它的功能,并决定它是否能够被用来通信,
最后安装相应的驱动程序。

实际的USB驱动程序的实现有若干方法,其中
有两种常用的技术:应用程序编程接口(API)和驱动程序模板。

1、应用程序编程接口(API)
API是一组用于访问操作系统提供的服务和功能的特殊指令序列。


用程序编程接口(API)可以用来创建USB驱动程序,其实现包括以下步骤:
(1)定义硬件设备的描述
在编写USB驱动程序时,首先需要定义硬件设备,即定义设备的功能,记录其编号、最大支持通信速率、硬件连接方式、发送和接收设备数据的
方式以及支持的驱动软件要求等信息。

(2)实现设备驱动的关键函数
关键函数是控制USB设备正常工作所必需的函数,包括初始化函数、
发送和接收数据的函数、获取设备状态的函数以及关闭设备的函数等。

LinuxUSB驱动开发实例(一)——USB摄像头驱动实现源码分析

LinuxUSB驱动开发实例(一)——USB摄像头驱动实现源码分析

LinuxUSB驱动开发实例(一)——USB摄像头驱动实现源码分析Spac5xx的实现是按照标准的USB VIDEO设备的驱动框架编写(其具体的驱动框架可参照/usr/src/linux/drivers/usb/usbvideo.c文件),整个源程序由四个主体部分组成:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)设备模块的初始化模块和卸载模块,上层软件接口模块,数据传输模块。

具体的模块分析如下:一、初始化设备模块该驱动采用了显式的模块初始化和消除函数,即调用module_init 来初始化一个模块,并在卸载时调用moduel-exit函数其具体实现如下:1、模块初始化:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)2、模块卸载:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)关键数据结构 USB驱动结构,即插即用功能的实现总结送免费学习资料(包含视频、技术学习路线图谱、文档等)用两个函数调用spca5xx_probe 和spca5xx_disconnect来支持USB设备的即插即用功能:a -- spca5xx_probe具体实现如下:static void * spca5xx_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_interface_descriptor *interface; //USB设备接口描述符struct usb_spca50x *spca50x; //物理设备数据结构 int err_probe; int i; if (dev->descriptor.bNumConfigurations != 1) //探测设备是不是可配置goto nodevice; if (ifnum > 0) goto nodevice; interface = &dev->actconfig->interface[ifnum].altsetting[0];MOD_INC_USE_COUNT; interface = &intf->altsetting[0].desc; if (interface->bInterfaceNumber > 0) goto nodevice; if ((spca50x = kmalloc (sizeof (struct usb_spca50x), GFP_KERNEL)) == NULL) //分配物理地址空间{ err ('couldn't kmalloc spca50x struct'); goto error; } memset (spca50x, 0, sizeof (struct usb_spca50x)); spca50x->dev = dev; spca50x->iface = interface->bInterfaceNumber; if ((err_probe = spcaDetectCamera (spca50x)) < 0) //具体物理设备查找,匹配厂商号,设备号(在子程序中){ err (' Devices not found !! '); goto error; } PDEBUG (0, 'Camera type %s ', Plist[spca50x->cameratype].name) for (i = 0; i < SPCA50X_NUMFRAMES; i++) init_waitqueue_head (&spca50x->frame[i].wq); //初始化帧等待队列init_waitqueue_head (&spca50x->wq); //初始化驱动等待队列if (!spca50x_configure (spca50x)) //物理设备配置(主要完成传感器侦测和图形参数配置),主要思想是给控制寄存器写值,读回其返回值,以此判断具体的传感器型号{ spca50x->user = 0; init_MUTEX (&spca50x->lock); //信号量初始化init_MUTEX (&spca50x->buf_lock); spca50x->v4l_lock = SPIN_LOCK_UNLOCKED; spca50x->buf_state = BUF_NOT_ALLOCATED; } else { err ('Failed to configure camera'); goto error; } /* Init video stuff */ spca50x->vdev = video_device_alloc (); //设备控制块内存分配if (!spca50x->vdev) goto error; memcpy (spca50x->vdev, &spca50x_template, sizeof (spca50x_template)); //系统调用的挂接,在此将驱动实现的系统调用,挂到内核中video_set_drvdata (spca50x->vdev, spca50x); if (video_register_device (spca50x->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { //video设备注册err ('video_register_device failed'); goto error; } spca50x->present = 1; if (spca50x->force_rgb) info ('data format set to RGB'); spca50x->task.sync = 0; spca50x->task.routine = auto_bh; spca50x->task.data = spca50x; spca50x->bh_requested = 0; MOD_DEC_USE_COUNT; //增加模块使用数 return spca50x; //返回数剧结构error://错误处理if (spca50x->vdev) { if (spca50x->vdev->minor == -1) video_device_release (spca50x->vdev); else video_unregister_device (spca50x->vdev); spca50x->vdev = NULL; } if (spca50x) { kfree (spca50x); spca50x = NULL; } MOD_DEC_USE_COUNT; return NULL; nodevice: return NULL; }b -- Spca5xx_disconnect 的具体实现如下:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)static void spca5xx_disconnect (struct usb_device *dev, void *ptr) {struct usb_spca50x *spca50x = (struct usb_spca50x *) ptr;int n; MOD_INC_USE_COUNT; //增加模块使用数if (!spca50x) return;down (&spca50x->lock); //减少信号量spca50x->present = 0; //驱动卸载置0for (n = 0; n < SPCA50X_NUMFRAMES; n++) //标示所有帧ABORTING状态{spca50x->frame[n].grabstate = FRAME_ABORTING;spca50x->curframe = -1; }for (n = 0; n < SPCA50X_NUMFRAMES; n++) //唤醒所有等待进程{if (waitqueue_active (&spca50x->frame[n].wq))wake_up_interruptible (&spca50x->frame[n].wq);if (waitqueue_active (&spca50x->wq))wake_up_interruptible (&spca50x->wq); } spca5xx_kill_isoc(spca50x); //子函数终止URB包的传输PDEBUG (3,'Disconnect Kill isoc done');up (&spca50x->lock); //增加信号量while(spca50x->user) /如果还有进程在使用,进程切换schedule(); down (&spca50x->lock);if (spca50x->vdev) {video_unregister_device (spca50x->vdev); //注销video 设备usb_driver_release_interface (&spca5xx_driver,&spca50x->dev->actconfig->interface[spca50x->iface]); //端口释放spca50x->dev = NULL; }up (&spca50x->lock); #ifdef CONFIG_PROC_FSdestroy_proc_spca50x_cam (spca50x); //注销PROC文件 #endif /* CONFIG_PROC_FS */ if (spca50x && !spca50x->user) //释放内存空间{spca5xx_dealloc (spca50x);kfree (spca50x); spca50x = NULL;} MOD_DEC_USE_COUNT; //减少模块记数PDEBUG (3, 'Disconnect complete'); }二、上层软件接口模块:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)该模块通过file_operations数据结构,依据V4L协议规范,实现设备的关键系统调用,实现设备文件化的UNIX系统设计特点。

开发WDM型USB设备驱动程序

开发WDM型USB设备驱动程序

开发WDM型USB设备驱动程序USB设备驱动程序开发⼯具开发USB设备驱动程序需要专门的开发⼯具,⽬前应⽤⼴泛的⼯具主要有两⼤类。

⼀类是Microsoft公司提供的Windows DDK(Device Driver Kit)。

它有Windows 98 DDK 和Windows 2000 DDK两个版本。

Windows 98 DDK能够开发Windows 95/98/Me/NT下的VxD、KMD和WDM驱动程序。

Windows 2000 DDK 能够开发Windows 98/Me/NT/2000下的KMD和WDM驱动程序。

由于DDK基于汇编语⾔的编程⽅式和内核模式的调⽤,对没有深厚的OS原理和编程⽔平的⼈员来说,任务相当艰巨。

另⼀类是NuMega公司提供的DriverStudio,它是⼀个⼤的开发⼯具包,包含VtoolsD、SoftICE和DriverWorks等开发⼯具。

VtoolsD开发包提供了对VxD编程的C/C++类库⽀持,利⽤VtoolsD中的QuickVxD⼯具可以快速⽣成VxD的C/C++代码框架,开发者可以在此基础上根据各⾃的需要添加⾃⼰的代码。

DriverWorks⽤于开发KMD和WDM驱动程序,并且对DDK函数进⾏了类的封装,从⽽为开发Windows NT、Windows 2000和Widnwos98 WDM设备驱动程序提供了⼀个⾃动化的⽅法。

DriverWorks,提供了VC++下的开发向导Driver Wizard,按照它的提⽰可以迅速地⽣成驱动程序的框架。

这个框架结构提供可以正确执⾏WDM动态环境中IRP的请求,⽽且,也包含⽤于简化系统提供的标准类驱动程序(如HID、流)和总线驱动程序(如PCI和USB)接⼝的类等。

总之,利⽤DriverWorks开发WDM驱动程序,可以⼤⼤简化开发⼈员的⼯作量、缩短开发周期以及降低开发驱动程序的难度。

[1]⽤DriverWorks开发WDM型USB设备驱动程序要想使⽤DriverWorks,必须先安装以下软件:DriverStudio2.5,VisualStudio6.0,以及Windows2000DDK。

05-USB驱动程序开发

05-USB驱动程序开发

2、USB设备类型 USB设备类型
八、USB设备列举 USB设备列举
在USB规范中有一个非常重要的“动作” USB规范中有一个非常重要的 动作” 规范中有一个非常重要的“ 过程” 这个动作将会让PC PC机知道何 或“过程”。这个动作将会让PC机知道何 USB设备刚接上以及其所含的各种信息 设备刚接上以及其所含的各种信息。 种USB设备刚接上以及其所含的各种信息。 这样,PC机就可以与这个USB设备开始进行 机就可以与这个USB 这样,PC机就可以与这个USB设备开始进行 数据传输的工作了。 数据传输的工作了。这个动作称之为设备 列举(enumeration) (enumeration)。 列举(enumeration)。
7 . USB2.0 的 High-speed 模式支持音频和视频设备 , 可 USB2 High-speed模式支持音频和视频设备 模式支持音频和视频设备, 以保证其固定带宽; 以保证其固定带宽; 8 . 为了适应各种不同类型外围设备的要求 USB 提供了 为了适应各种不同类型外围设备的要求USB 四种不同的数据传输类型:控制传输,Bulk数据传输 数据传输, 四种不同的数据传输类型:控制传输, Bulk数据传输, 中断数据传输,同步数据传输。 中断数据传输, 同步数据传输。 同步数据传输可为音 频和视频等实时设备的实时数据传输提供固定带宽。 频和视频等实时设备的实时数据传输提供固定带宽。 的端口具有很灵活的扩展性。 一个USB 9 . USB 的端口具有很灵活的扩展性 。 一个 USB 端口串 接上一个USB 就可以扩展为多个USB 端口。 USB端口 接上一个 USB Hub 就可以扩展为多个 USB 端口 。 规范 中说,USB可以扩展到127个外设端口 可以扩展到127个外设端口。 中说,USB可以扩展到127个外设端口。

最新开发usb驱动程序的方法连载一

最新开发usb驱动程序的方法连载一

最新开发USb驱动程序的方法连载一开发USb驱动程序的方法(连载二)NT还有更藝其他的对象,例如中断对紀Controller对盘、定时器对歓等等,但在我们开发的驱动程序中并没有用到•因此在这里不做介绍。

I/O缓冲策賂很明显的,驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。

这就就设讣到设备的"0缓冲策賂。

读写请求的I/O缓冲策賂前面说到通过设置Device对象的Flag可以选择控制处理读写请求的I/O缓冲策略。

下啲对这些缓冲策略分别做一介绍。

1、缓冲I/O(DO_BUFFERED_IO)在读写请求的一开始,I/O管理器检査用户缓冲区的可访问性,然后分配与调用者的缓冲区一样大的非分贞池,并把它的地址放在IRP的Associatedlrp.SystemBuiYer域中。

驱动程序就利用这个域來进行实际数据的传输°对于IRPJV1J_READ读请求.I/O管理器还把IRP的UserBuffer域设宜成调用者缓冲区的用户空间地址。

X请求完成时• I/O管理器利用这个地址将数据从驱动程序的系统空间拷贝回调用者的缓冲区。

对于IRP」V1J_WRITE写请求.UserBuffer被设辻为NULL,并把川户缓冲区的数据拷贝到系统缓冲区中。

2、直接VO(DO_DIRECTJO)I/O管理器首先检査用户缓冲区的可访问性,并在物理内存中锁定它。

然后它为该缓冲区创建一个内存描述表(MDL).并把MDL 的地址存放在IRP 的MdlAddress 域中。

Associaledlrp.SystemBuffer 和UserBuffer 都被设置为NULJ驱动程序可以调用函数MmGetSystemAddressForMdl得到用户缓冲区的系统空间地址. 从而进行数据操作。

这个函数将调用者的缓冲区映射到非份页的地址空间。

驱动程序完成I/O请求后.系统自动从系统空间解除缓冲区的映射。

usb驱动教程

usb驱动教程

usb驱动教程Windows驱动编程基础教程我经常在网上遇到心如火燎的提问者。

他们碰到很多工作中的技术问题,是关于驱动开发的。

其实绝大部分他们碰到的“巨大困难”是被老牛们看成初级得不能再初级的问题。

比如经常有人定义一个空的UNICODE_STRING,然后往里面拷贝字符串。

结果无论如何都是蓝屏。

也有人在堆栈中定义一个局部SPIN_LOCK,作为下面的同步用——这样用显然没有任何意义。

我无法一一回答这些问题:因为往往要耐心的看他们的代码,才能很不容易的发现这些错误。

而且我又不是总是空闲的,可以无休止的去帮网友阅读代码和查找初级错误。

但是归根结底,这些问题的出现,是因为现在写驱动的同行越来越多,但是做驱动开发又没有比较基础的,容易读懂的资料。

为此我决定从今天开始连载一篇超级入门级的教程,来解决那些最基本的开发问题。

老牛们就请无视这篇教程,一笑而过了。

Windows驱动编程基础教程(1.1-1.3)1.1 使用字符串结构常常使用传统C语言的程序员比较喜欢用如下的方法定义和使用字符串:char *str = { “my first string” }; // ansi字符串wchar_t *wstr = { L”my first string” }; // unicode字符串size_t len = strlen(str); // ansi字符串求长度size_t wlen = wcslen(wstr); // unicode字符串求长度printf(“%s %ws %d %d”,str,wstr,len,wlen); // 打印两种字符串但是实际上这种字符串相当的不安全。

很容易导致缓冲溢出漏洞。

这是因为没有任何地方确切的表明一个字符串的长度。

仅仅用一个’\0’字符来标明这个字符串的结束。

一旦碰到根本就没有空结束的字符串(可能是攻击者恶意的输入、或者是编程错误导致的意外),程序就可能陷入崩溃。

使用高级C++特性的编码者则容易忽略这个问题。

开发usb驱动程序的方法连载一

开发usb驱动程序的方法连载一

开发usb驱动程序的⽅法连载⼀开发usb驱动程序的⽅法(连载⼀)开始驱动程序设计下⾯的⽂字是从Microsoft的DDK帮助中节选出来的,它让我们明⽩在开始设计驱动程序应该注意些什么问题,这些都是具有普遍意义的开发准则。

应该⽀持哪些I/O请求在开始写任何代码之前,应该⾸先确定我们的驱动程序应该处理哪些IRP例程。

如果你在设计⼀个设备驱动程序,你应该⽀持和其他相同类型设备的NT驱动程序相同的IRP_MJ_XXX 和IOCTL请求代码。

如果你是在设计⼀个中间层NT驱动程序,应该⾸先确认你下层驱动程序所管理的设备,因为⼀个⾼层的驱动程序必须具有低层驱动程序绝⼤多数IRP_MJ_XXX例程⼊⼝。

⾼层驱动程序在接到I/O 请求时,在确定⾃⾝IRP当前堆栈单元参数有效的前提下,设置好IRP中下⼀个低层驱动程序的堆栈单元,然后再调⽤IoCallDriver 将请求传递给下层驱动程序处理。

⼀旦决定好了你的驱动程序应该处理哪些IRP_MJ_XXX,就可以开始确定驱动程序应该有多少个Dispatch例程。

当然也可以考虑把某些 RP_MJ_XXX处理的例程合并为同⼀例程处理。

例如在ChangerDisk 和 VDisk⾥,对IRP_MJ_CREATE和IRP_MJ_CLOSE处理的例程就是同⼀函数。

对IRP_MJ_READ和IRP_MJ_WRITE处理的例程也是同⼀个函数。

应该有多少个Device对象?⼀个驱动程序必须为它所管理的每个可能成为I/O请求的⽬标的物理和逻辑设备创建⼀个命名Device对象。

⼀些低层的驱动程序还可能要创建⼀些不确定数⽬的Device对象。

例如⼀个硬盘驱动程序必须为每⼀个物理硬盘创建⼀个Device对象,同时还必须为每个物理磁盘上的每个逻辑分区创建⼀个Device对象。

⼀个⾼层驱动驱动程序必须为它所代表的虚拟设备创建⼀个Device 对象,这样更⾼层的驱动程序才能连接它们的Device对象到这个驱动程序的Device对象。

USB从设备驱动实现流程

USB从设备驱动实现流程

USB从设备驱动实现流程1.硬件初始化:首先需要对USB从设备的硬件进行初始化。

这包括配置USB接口和相关寄存器,分配内存用于数据传输等。

2. 设备描述符定义:USB设备需要提供设备描述符,以描述其功能、厂商信息等。

设备描述符是一个结构体,包含各种属性,如设备的VID (Vendor Id)、PID(Product Id)、设备类别等。

3.端点描述符定义:端点描述符用于描述设备的输入输出端点。

从设备可以有多个端点,包括控制端点、批量端点、中断端点和等时端点。

每个端点都有一个端点地址、传输方向、传输类型、包大小等属性。

B设备注册和初始化:驱动程序需要注册USB设备,并进行初始化。

这包括获取USB总线的指针,通过指针与USB总线进行通信,并与USB总线驱动进行通信。

5.数据传输:驱动程序需要实现数据的传输功能,包括收发数据。

从设备收到主机的请求后,驱动程序需要根据请求进行相应的操作,如读取设备信息、发送数据等。

6.中断处理:从设备在一些情况下可能会触发中断,如数据接收完成、传输超时等。

驱动程序需要实现中断处理函数来处理这些中断事件,以确保设备的正常工作。

7.错误处理:在驱动程序的实现过程中,可能会遇到一些错误,如传输超时、报文解析错误等。

驱动程序需要通过错误处理函数来对这些错误进行处理,如重试传输、重新配置设备等。

8.资源释放:当USB设备不再使用时,驱动程序需要释放相应的资源,如内存、中断处理函数等。

9.调试和测试:在驱动程序的实现过程中,可以使用调试工具对代码进行调试和测试,以确保程序的正确性和可靠性。

总结来说,USB从设备驱动的实现流程包括硬件初始化、设备和端点描述符定义、设备注册和初始化、数据传输、中断处理、错误处理、资源释放以及调试和测试等步骤。

通过这些步骤,可以使USB从设备与主机进行正常的通信和数据传输。

usb 驱动开发原理

usb 驱动开发原理

usb 驱动开发原理USB驱动开发原理USB(Universal Serial Bus,通用串行总线)是一种用于连接计算机与外部设备的通信接口标准。

USB驱动开发是为了实现计算机与USB设备之间的数据传输而进行的软件编程。

本文将介绍USB驱动开发的原理和步骤。

一、USB驱动开发的基本原理USB驱动开发的基本原理是通过驱动程序与USB设备之间的通信来实现数据的传输。

USB驱动程序负责管理和控制USB设备,将计算机的请求传递给USB设备,并将USB设备的响应传递给计算机。

USB驱动开发的基本流程如下:1. 初始化USB驱动程序:驱动程序需要初始化USB控制器和USB设备。

这包括初始化数据结构、分配内存空间、设置中断处理程序等操作。

2. 建立通信连接:驱动程序需要与USB设备建立通信连接。

这包括检测和识别USB设备、分配端点和接口、设置传输模式等操作。

3. 数据传输:驱动程序通过读取和写入USB设备的寄存器来实现数据的传输。

这包括发送和接收数据包、处理中断和错误等操作。

4. 终止通信连接:在完成数据传输后,驱动程序需要关闭通信连接。

这包括释放端点和接口、清除中断和错误等操作。

二、USB驱动开发的步骤USB驱动开发的步骤如下:1. 确定USB设备的功能和特性:USB设备可以具有多种功能和特性,例如存储设备、打印机、摄像头等。

驱动程序需要了解USB设备的功能和特性,以便正确地管理和控制USB设备。

2. 编写驱动程序:驱动程序是实现USB驱动开发的核心部分。

驱动程序需要根据USB设备的功能和特性编写相应的代码,以实现数据的传输和设备的控制。

3. 进行调试和测试:在编写驱动程序后,需要进行调试和测试来验证驱动程序的正确性和稳定性。

这包括检查驱动程序的功能、性能和兼容性等方面。

4. 发布和维护驱动程序:在通过调试和测试后,可以将驱动程序发布给用户使用。

同时,还需要对驱动程序进行维护,以修复bug和提升性能。

三、USB驱动开发的挑战和解决方案USB驱动开发面临一些挑战,例如设备的兼容性、驱动程序的稳定性、传输性能的优化等。

开发usb驱动程序的方法连载一

开发usb驱动程序的方法连载一

开发usb驱动程序的方法(连载一)开始驱动程序设计下面的文字是从Microsoft的DDK帮助中节选出来的,它让我们明白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍意义的开发准则。

应该支持哪些I/O请求在开始写任何代码之前,应该首先确定我们的驱动程序应该处理哪些IRP例程。

如果你在设计一个设备驱动程序,你应该支持和其他相同类型设备的NT驱动程序相同的IRP_MJ_XXX 和IOCTL请求代码。

如果你是在设计一个中间层NT驱动程序,应该首先确认你下层驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层驱动程序绝大多数IRP_MJ_XXX例程入口。

高层驱动程序在接到I/O 请求时,在确定自身IRP当前堆栈单元参数有效的前提下,设置好IRP中下一个低层驱动程序的堆栈单元,然后再调用IoCallDriver 将请求传递给下层驱动程序处理。

一旦决定好了你的驱动程序应该处理哪些IRP_MJ_XXX,就可以开始确定驱动程序应该有多少个Dispatch例程。

当然也可以考虑把某些 RP_MJ_XXX处理的例程合并为同一例程处理。

例如在ChangerDisk 和 VDisk里,对IRP_MJ_CREATE和IRP_MJ_CLOSE处理的例程就是同一函数。

对IRP_MJ_READ和IRP_MJ_WRITE处理的例程也是同一个函数。

应该有多少个Device对象?一个驱动程序必须为它所管理的每个可能成为I/O请求的目标的物理和逻辑设备创建一个命名Device对象。

一些低层的驱动程序还可能要创建一些不确定数目的Device对象。

例如一个硬盘驱动程序必须为每一个物理硬盘创建一个Device对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个Device对象。

一个高层驱动驱动程序必须为它所代表的虚拟设备创建一个Device 对象,这样更高层的驱动程序才能连接它们的Device对象到这个驱动程序的Device对象。

一文入门usb设备的驱动编写方法

一文入门usb设备的驱动编写方法

一文入门usb设备的驱动编写方法USB设备驱动编写入门USB(通用串行总线)是一种广泛使用的协议,用于在计算机和外围设备之间建立通信渠道。

编写USB设备驱动程序需要对USB规范以及操作系统提供的底层机制有深入的理解。

1. 理解USB规范USB规范定义了设备之间的通信协议、设备类型和描述符格式等方面。

理解规范对于编写符合标准且能够与其他USB设备交互的驱动程序至关重要。

2. 选择操作系统平台不同操作系统对USB设备驱动程序的要求有所不同。

为Windows环境编写驱动程序与为Linux或macOS编写驱动程序具有不同的方法。

了解目标操作系统的特定要求至关重要。

3. 设置开发环境设置开发环境包括安装必要的工具和库。

这可能需要安装USB 开发工具包或编译器。

阅读操作系统的文档以设置正确的环境。

4. 创建USB描述符USB描述符是描述设备功能和配置的数据结构。

驱动程序需要创建这些描述符才能注册设备并向操作系统公开其功能。

5. 实现USB端点USB端点是设备与计算机之间的数据传输通道。

驱动程序需要实现端点处理程序来处理数据传输和控制请求。

6. 处理USB事件驱动程序需要处理各种USB事件,例如设备插入、拔出和配置更改。

实现事件处理程序来响应这些事件并更新设备状态。

7. 使用USB堆栈操作系统提供USB堆栈,为驱动程序提供与底层USB硬件接口的抽象层。

了解USB堆栈的API和功能对于与硬件交互至关重要。

8. 调试驱动程序调试USB设备驱动程序需要专门的工具和技术。

使用调试器、日志记录和分析工具来识别并解决问题。

9. 测试驱动程序在不同环境和条件下全面测试驱动程序至关重要。

执行功能测试、兼容性测试和压力测试以验证驱动程序的可靠性和稳定性。

10. 提交并分发驱动程序开发完成后,需要向操作系统供应商提交驱动程序以进行认证和分发。

遵守供应商的准则并提供必要的文档。

开发usb驱动程序的方法

开发usb驱动程序的方法

开发驱动程序的方法(连载一)开始驱动程序设计下面的文字是从的帮助中节选出来的,它让我们明白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍意义的开发准则。

应该支持哪些请求在开始写任何代码之前,应该首先确定我们的驱动程序应该处理哪些例程。

如果你在设计一个设备驱动程序,你应该支持和其他相同类型设备的驱动程序相同的和请求代码。

如果你是在设计一个中间层驱动程序,应该首先确认你下层驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层驱动程序绝大多数例程入口。

高层驱动程序在接到请求时,在确定自身当前堆栈单元参数有效的前提下,设置好中下一个低层驱动程序的堆栈单元,然后再调用将请求传递给下层驱动程序处理。

一旦决定好了你的驱动程序应该处理哪些,就可以开始确定驱动程序应该有多少个例程。

当然也可以考虑把某些处理的例程合并为同一例程处理。

例如在和里,对和处理的例程就是同一函数。

对和处理的例程也是同一个函数。

应该有多少个对象?一个驱动程序必须为它所管理的每个可能成为请求的目标的物理和逻辑设备创建一个命名对象。

一些低层的驱动程序还可能要创建一些不确定数目的对象。

例如一个硬盘驱动程序必须为每一个物理硬盘创建一个对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个对象。

一个高层驱动驱动程序必须为它所代表的虚拟设备创建一个对象,这样更高层的驱动程序才能连接它们的对象到这个驱动程序的对象。

另外,一个高层驱动程序通常为它低层驱动程序所创建的对象创建一系列的虚拟或逻辑对象。

尽管你可以分阶段来设计你的驱动程序,因此一个处在开发阶段的驱动程序不必一开始就创建出所有它将要处理的所有对象。

但从一开始就确定好你最终要创建的所有对象将有助于设计者所要解决的任何同步问题。

另外,确定所要创建的对象还有助于你定义对象的的内容和数据结构。

开始驱动程序开发驱动程序的开发是一个从粗到细逐步求精的过程。

的\ 目录下有一个庞大的样板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。

USB驱动开发(一)

USB驱动开发(一)

一USB的框架提到USB的框架,先看一张很经典的架构图总结一句话就是:设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有一个或多个设置,接口有零或多个端点。

设备描述符是用来记录设备的通用信息,比如供应商ID、产品ID和修订ID,支持的设备类、子类和适用的协议以及默认端点的最大包大小等struct usb_device_descriptor{_ _u8 bLength; //描述符长度_ _u8 bDescriptorType; //描述符类型编号_ _le16 bcdUSB; //USB版本号_ _u8 bDeviceClass; //USB分配的设备类code_ _u8 bDeviceSubClass; // USB分配的子类code_ _u8 bDeviceProtocol; //USB分配的协议code_ _u8 bMaxPacketSize0; //endpoint0最大包大小_ _le16 idVendor; //厂商编号_ _le16 idProduct; //产品编号_ _le16 bcdDevice; //设备出厂编号_ _u8 iManufacturer; //描述厂商字符串的索引_ _u8 iProduct; //描述产品字符串的索引_ _u8 iSerialNumber; //描述设备序列号字符串的索引_ _u8 bNumConfigurations; //可能的配置数量} _ _attribute_ _ ((packed));配置描述符可以包含一个或多个配置,比如USB设备的低功耗模式和高功耗模式可分别对应一个配置。

但是存在多个配置时,在使用USB设备前,必须为其选择一个合适的配置。

USB设备的每一个配置都必须有一个配置描述符。

struct usb_config_descriptor{_ _u8 bLength; //描述符长度_ _u8 bDescriptorType; //描述符类型编号_ _le16 wTotalLength; //配置所返回的所有数据的大小_ _u8 bNumInterfaces; // 配置所支持的接口数_ _u8 bConfigurationValue; //Set_Configuration命令需要的参数值_ _u8 iConfiguration; //描述该配置的字符串的索引值_ _u8 bmAttributes; //供电模式的选择_ _u8 bMaxPower; //设备从总线提取的最大电流} _ _attribute_ _ ((packed));接口描述符是用来实现某一个功能的,一个配置下面可以有多个接口,比如说:既可以播放音频又可以播放视频,这样就需要两个接口来实现了,接口是端点的集合。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

开发usb驱动程序的方法(连载一)开始驱动程序设计下面的文字是从Microsoft的DDK帮助中节选出来的,它让我们明白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍意义的开发准则。

应该支持哪些I/O请求在开始写任何代码之前,应该首先确定我们的驱动程序应该处理哪些IRP例程。

如果你在设计一个设备驱动程序,你应该支持和其他相同类型设备的NT驱动程序相同的IRP_MJ_XXX 和IOCTL请求代码。

如果你是在设计一个中间层NT驱动程序,应该首先确认你下层驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层驱动程序绝大多数IRP_MJ_XXX例程入口。

高层驱动程序在接到I/O 请求时,在确定自身IRP当前堆栈单元参数有效的前提下,设置好IRP中下一个低层驱动程序的堆栈单元,然后再调用IoCallDriver 将请求传递给下层驱动程序处理。

一旦决定好了你的驱动程序应该处理哪些IRP_MJ_XXX,就可以开始确定驱动程序应该有多少个Dispatch例程。

当然也可以考虑把某些 RP_MJ_XXX处理的例程合并为同一例程处理。

例如在ChangerDisk 和 VDisk里,对IRP_MJ_CREATE和IRP_MJ_CLOSE处理的例程就是同一函数。

对IRP_MJ_READ和IRP_MJ_WRITE处理的例程也是同一个函数。

应该有多少个Device对象?一个驱动程序必须为它所管理的每个可能成为I/O请求的目标的物理和逻辑设备创建一个命名Device对象。

一些低层的驱动程序还可能要创建一些不确定数目的Device对象。

例如一个硬盘驱动程序必须为每一个物理硬盘创建一个Device对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个Device对象。

一个高层驱动驱动程序必须为它所代表的虚拟设备创建一个Device 对象,这样更高层的驱动程序才能连接它们的Device对象到这个驱动程序的Device对象。

另外,一个高层驱动程序通常为它低层驱动程序所创建的Device对象创建一系列的虚拟或逻辑Device对象。

尽管你可以分阶段来设计你的驱动程序,因此一个处在开发阶段的驱动程序不必一开始就创建出所有它将要处理的所有Device对象。

但从一开始就确定好你最终要创建的所有Device对象将有助于设计者所要解决的任何同步问题。

另外,确定所要创建的Device对象还有助于你定义Device对象的Device Extension 的内容和数据结构。

开始驱动程序开发驱动程序的开发是一个从粗到细逐步求精的过程。

NT DDK的src\ 目录下有一个庞大的样板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。

在开始开发你的驱动程序之前,你应该在这个样板库下面寻找是否有和你所要开发的类似类型的例程。

例如我们所开发的驱动程序,虽然DDK 对USB描述得不是很详细,我们还是可以在src\storage\class目录发现很多和USB设备有关的驱动程序。

下面我们来看开发驱动程序的基本步骤。

最简的驱动程序框架1、写一个DriverEntry例程,在里面调用IoCreateDevice创建一个Device对象。

2、写一个处理IRP_MJ_CREA TE请求的Dispatch例程的基本框架 (参见DDK Kernel-Mode Drivers 4.4.3描述的一个DispatchCreate 例程所要完成的最基本工作。

当然写了DispatchCreate例程后,要在DriverEntry 例程为IRP_MJ_CREA TE初始化例程入口)。

如果驱动程序创建了多于一个Device对象,则必须为IRP_MJ_CLOSE 请求写一个例程,该例程通常情况下可以和DispatchCreate共用一个例程,参见参见DDK Kernel-Mode Drivers 4.4.3。

3、编译连接你的驱动程序。

用下面的方法来测试你的驱动程序。

首先按上面介绍的方法安装好驱动程序。

其次我们还得为NT逻辑设备名称和目标Device对象名称之间建立起符号连接,我们在前面已经知道Device对象名称对WIN32用户模式是不可见的,是不能直接通过API来访问的,WIN 32 API只能访问NT 逻辑设备名称。

我们可以通过修改注册表来建立这两种名称之间的符号连接。

运行REGEDT32.EXE在\HKEY_LOCAL_MACHINE\ System\ CurrentControlSet\Control\ Session Manager\ DOS Devices下建立起符号连接(这种符号连接也可以在驱动程序里调用函数 IoCreateSymbolicLink来创建)。

重新启动系统。

编写一个简单的测试程序调用WIN32API CreateFile函数以刚才你命名的NT逻辑设备名打开这个设备。

如果打开成功,那么你也就成功地写出了一个最简单的驱动程序了。

支持更多的设备I/O请求例如你的驱动程序可能需要对IRP_MJ_READ请求做出响应(完成后可用WIN32 API ReadFile函数进行测试)。

如果你的驱动程序需要能够手工卸载,那么还必须对IRP_MJ_CLOSE做出响应。

为你所需要处理IRP_MJ_XXX写好处理例程,并在DriverEntry里面初始化好这些例程入口。

一个低层的驱动程序可能需要最起码一个StartIo,ISR和DpcForIsr 例程,可能需要一个SynchCritSection 例程,如果设备使用了DMA,那么可能还需要一个AdapterControl例程。

关于这些例程,请参考 DDK相应文档。

对于高层驱动程序可能需要一个或多个IoCompletion例程,最起码完成检查I/O状态块然后调用IoCompleteRequest的工作。

如果需要,还要对Device Extension数据结构和内容做些修改开发usb驱动程序的方法(连载二)NT还有更多其他的对象,例如中断对象、Controller对象、定时器对象等等,但在我们开发的驱动程序中并没有用到,因此在这里不做介绍。

I/O缓冲策略很明显的,驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。

这就就设计到设备的I/O缓冲策略。

读写请求的I/O缓冲策略前面说到通过设置Device对象的Flag可以选择控制处理读写请求的I/O缓冲策略。

下面对这些缓冲策略分别做一介绍。

1、缓冲I/O(DO_BUFFERED_IO)在读写请求的一开始,I/O管理器检查用户缓冲区的可访问性,然后分配与调用者的缓冲区一样大的非分页池,并把它的地址放在IRP的AssociatedIrp.SystemBuffer域中。

驱动程序就利用这个域来进行实际数据的传输。

对于IRP_MJ_READ读请求,I/O管理器还把IRP的UserBuffer域设置成调用者缓冲区的用户空间地址。

当请求完成时,I/O管理器利用这个地址将数据从驱动程序的系统空间拷贝回调用者的缓冲区。

对于IRP_MJ_WRITE写请求,UserBuffer被设置为NULL,并把用户缓冲区的数据拷贝到系统缓冲区中。

2、直接I/O(DO_DIRECT_IO)I/O管理器首先检查用户缓冲区的可访问性,并在物理内存中锁定它。

然后它为该缓冲区创建一个内存描述表(MDL),并把MDL的地址存放在IRP的MdlAddress域中。

AssociatedIrp.SystemBuffer和 UserBuffer 都被设置为NULL。

驱动程序可以调用函数 MmGetSystemAddressForMdl得到用户缓冲区的系统空间地址,从而进行数据操作。

这个函数将调用者的缓冲区映射到非份页的地址空间。

驱动程序完成I/O请求后,系统自动从系统空间解除缓冲区的映射。

3、这两种方法都不是这种情况比较少用,因为这需要驱动程序自己来处理缓冲问题。

I/O管理器仅把调用者缓冲区的用户空间地址放到IRP的UserBuffer 域中。

我们并不推荐这种方式。

IOCTL缓冲区的缓冲策略IOCTL请求涉及来自调用者的输入缓冲区和返回到调用者的输出缓冲区。

为了理解IOCTL请求,我们先来看看WIN32 API DeviceIoControl函数的原型。

BOOL DeviceIoControl (HANDLE hDevice, // 设备句柄DWORD dwIoControlCode, // IOCTL请求操作代码LPVOID lpInBuffer, // 输入缓冲区地址DWORD nInBufferSize, // 输入缓冲区大小LPVOID lpOutBuffer, // 输出缓冲区地址DWORD nOutBufferSize, // 输出缓冲区大小LPDWORD lpBytesReturned, // 存放返回字节数的指针LPOVERLAPPED lpOverlapped // 用于同步操作的Overlapped结构体指针);IOCTL请求有四种缓冲策略,下面一一介绍。

1、输入输出缓冲I/O(METHOD_BUFFERED)I/O管理器首先分配一个非分页池,它足够大地存放调用者的输入或输出缓冲区(不管哪个更大)。

非分页缓冲区的地址放在IRP的AssociatedIrp.SystemBuffer域中,然后把IOCTL的输入数据拷贝到这个非份页缓冲区中,并把IRP的UserBuffer域设置成调用者输出缓冲区的用户空间地址。

当驱动程序完成IOCTL请求时,I/O管理器将这个非份页缓冲区中的数据拷贝到调用者的输出缓冲区。

注意这里同一个非份页池同时用于输入和输出缓冲区,因此驱动程序在向缓冲区写东西之前应该把输入的所有数据读出来。

2、直接输入缓冲输出I/O(METHOD_IN_DIRECT)I/O管理器首先检查调用者输入缓冲区的可访问性,并在物理内存中将其锁定。

然后为该输入缓冲区创建一个MDL,并把指定该MDL的指针存放到IRP的MdlAddress域中。

同时,I/O管理器还在非份页池中分配一输出缓冲区,并把这个缓冲区的地址存放在IRP的AssociatedIrp.SystemBuffer域中,并把IRP的UserBuffer 域设置成调用者输出缓冲区的用户空间地址。

当驱动程序完成IOCTL请求时,I/O管理器将非份页缓冲区中的数据拷贝到调用者的输出缓冲区。

3、缓冲输入直接输出I/O(METHOD_OUT_DIRECT)I/O管理器首先检查调用者输出缓冲区的可访问性,并在物理内存中将其锁定。

然后为该输出缓冲区创建一个MDL,并把指定该MDL的指针存放到IRP的MdlAddress域中。

相关文档
最新文档