当前位置:文档之家› usb驱动开发篇简易介绍-经典

usb驱动开发篇简易介绍-经典

usb驱动开发篇简易介绍-经典
usb驱动开发篇简易介绍-经典

我这里重点的介绍如何写驱动程序,对于一些应用程序我就不做介绍了,因为我对于那些高层的东西写得很少。倘若再讲,有班门弄斧之嫌,呵呵!

作为WIN98和WIN2K推荐的一项新技术来说,USB的驱动程序和以往的直接跟硬件打交道的WIN95的VXD的方式的驱动程序不同,它应该是WDM类型的。

USB的WDM接口框图如下(这个图可以说是USB软件总体框图)

对于HID的设备,就可以采用上图左上边的结构,其它类的话采用右上的结构,其实右边的结构可以又细分成两层,一层是Class Driver,一层是Miniport Driver。而倒数第三行的UHCD和OpenHCI分别是由INTEL和COMPAQ两位老大定的一个和硬件有关的底层驱动程序标准,各位可以根据所需要的选择。

对于USB的驱动程序,大家还得去了解WDM驱动程序的写法,或者早些时候的NT驱动程序,其实WDM驱动程序可以看做是NT驱动程序的一个update,只是增加了一些新的特性。

“写驱动程序是一个很漫长和繁琐的工作,在此之前,你最好要熟悉硬件,熟悉C/C++,还要用过DDK,会用一些调试程序,如SOFTICE和WINDBG之类。如果一切就绪,你就可以开始写驱动程序,工作的进程有时侯会取决于你的运气”。(这是一位留美的朋友对我说的,我写出来和大家共享)

下面是我从一个朋友那里得到的一篇文章的摘要:

NT驱动程序的分层结构

驱动程序是指管理某个外围设备的一段程序代码。NT采用更灵活的分层驱动方法,允许杂应用程序和硬件之间 存在几个驱动程序层次。分层机制允许NT更加广泛地定义驱动程序,包括文件系统、逻辑卷管理器和各种网络组件,各种物理设备驱动程序等等。

1、 设备驱动程序

这些是管理实际数据传输和控制特定类型的物理设备的操作的驱动程序,包括开始和完成I /O操作,处理中断和执行特定的设备要求的任何差错处理。

2、 中间驱动程序

NT允许在物理设备驱动程序上分层任意数目的中间驱动程序。这些中间层次提供扩展I/O 系统的功能一种方法,而不必修改底层的驱动程序。这也是微软鼓吹的他们的系统灵活的一面!实际上我觉得这样反而牺牲了一些效率上的东西。

3、 文件系统驱动程序(FSD)

FSD是一类比较特殊的驱动程序,通常负责维护各种文件系统 所需要的磁盘结构。注意我们并不能使用DDK来开发FSD,而必须使用Microsoft的文件系统开发人员工具包。

一般比较少写中间过滤驱动程序,过滤驱动程序它截获和修改高层发送给类驱动程序的请求。这样就允许利用现有类驱动程序的功能,而不必从头开始写所有程序。NT内核模式对象在我们的实际开发过程中的对象是设备,由于端口驱动程序已经隐藏了硬件控制操作,因此我在这里不讲述跟硬件相关的部份。如果今后的开发对象不同,需要对硬件进行操作的时候,可能会对中断、DMA等有比较详细的了解,这些内容可以参考DDK帮助。

NT使用对象技术管理所有的数据,下面分别对一般驱动程序所涉及的一些对象做一介绍。不过在介绍这些对象之前,有必要先对驱动程序的结构做一介绍。

驱动程序结构

NT驱动程序和一般的DOS/Windows C语言程序不一样,它没有main()或者WinMain()函数

入口。和DLL类似地,它向操作系统显露一个名称为DriverEntry()的函数,在启动驱动程序的时候,操作系统将调用这个入口。DriverEntry除了做一些必 要的设备初始化工作外,还初始化一些Dispatch例程入口。我们知道,NT应用和设备驱动程序打交道主要是通过C reateFile、 ReadFile、WriteFile 和DeviceIoControl等Win32 API来进行 的。这些AP I其实都对应着驱动程序的一些Dispatch例程。而驱动程序除了DriverEntry以外,主要就是由这些Dispatch例 程组成的。例如调用Win32 API CreateFile的时候,操作系统最终转化为对驱动程序IRP_MJ_CREATE功能代码所对应的 Dispatch例程的调用,如果驱动程序没有提供该例程, CreateFile调用就会失败。

NT中一些常用的功能代码和Win32 API的对象关系如下所示。

功能代码 说明 IRP_MJ_CREATE 打开设备CreateFi le

IRP_MJ_CLEANUP 在关闭设备时,取消挂起的I/O请求CloseHandle

IRP_MJ_CLOSE 关闭设备CloseHa ndle

IRP_MJ_READ 从设备获得数据R eadFile

IRP_MJ_WRITE 向设备发送数据WriteFile

IRP_MJ_DEVICE_CONTROL 对用户模式或内核模式客户程序可用的控制操作DeviceIoControl

IRP_MJ_INTERNAL_DEVICE_CONTROL 只对内核模式客户程序可用的控制操作 IRP_MJ_QUERY_INFORMATION 得到文件的长度GetFileLength

IRP_MJ_SET_INFORMATION 设置文件的长度SetFileLe ngth

IRP_MJ_FLUSH_BUFFERS 写输出缓冲区或丢弃输入缓冲区

FlushFileBuffers

FlushConsoleInputBuffer

PurgeComm

IRP_MJ_SHUTDOWN 系统关闭InitialSyste mShutdown

和上面的驱动程序支持的功能代码相对应,一般的驱动程序看起来就象下面的样子。 DriverEntry(…) // 驱动程序入口

{

DeviceObject->MajorFunction[IRP_MJ_CREATE] = XXDriverCreateClose; //XX对应的是你自己给你的驱动程序的命名

DeviceObject->MajorFunction[IRP_MJ_CLOSE] = XXDriverCreateClose; DeviceObject->MajorFunction[IRP_MJ_READ] = XXDriverReadWrite;

DeviceObject->MajorFunction[IRP_MJ_WRITE] = XXDriverReadWrite;

}

XXDriverCreateClose(…) // 对应IRP_MJ_CREATE和IRP_MJ_CLOSE的例程

{

//……….

}

XXDriverDeviceControl(…)// 对应IRP_MJ_DEVICE_CONTROL的例程

{

//……….

}

XXDriverReadWrite(…) // 对应IRP_MJ_READ和IRP_MJ_WRITE的例程

{

//……….

}

一个驱动程序并不需要支持所有的功能代码,比如如果一个驱动程序根本就不必要与用户模

式客户程序交互,那么就不用支持IRP_MJ_CREATE和IRP_MJ_CLOSE。又如设备不支持设备读写,就不用支持IRP_MJ_READ和IRP_MJ_WRITE。 驱动程序对象是在操作系统启动驱动程序、在调用驱动程序 入口DriverEntry之前就已经创建好了的,并且作为DriverEntry 函数的参数传递给驱动程序。如果驱动程序启动失败,操作 系统将删除该对象。该对象的数据结构如下。注意下表并不是完整地列出了ntddk.h中的DEVICE_OBJECT结构体的所有数 据项,这里仅列出了一般驱动程序可能使用到的数据项。

Driver对象数据项 说明

PDEVICE_OBJECT DeviceObject 由本驱动程序创建的Device对象的链表ULONG Flags PDRIVER_INITIALIZE

DriverInit

驱动程序初始化例程(一般较少用)

PDRIVER_STARTIO DriverStartIo StartIo例程入口,一般该例程对低层设备驱动程序用得较多, 高层驱动程序较少使用本例程。

PDRIVER_UNLOAD DriverUnload

卸载驱动程序例程,如果想在控制面版的设备

里停止该设备,应该提供本例程。PDRIVER_DISPATCH

MajorFunction[IRP_MJ_MAXIMUM_FUNCTION +

1]

驱动程序的Dispatch例程表

在上面提到过驱动程序是管理同类型的所有设备,所以上面的 结构中DeviceObject指向的就不是单个的设备对象,而是一个对象链表,这个链表的维护在下面介绍Device对象时可以看到。 Device对象与Device Extension 驱动程序在调用IoCreateDevice函数成功后就创建了一个Device 对象。下面对Device对象几个比较重要的数据做一介绍。

Device对象数据

说明

PVOID

DeviceExtension

指向Device Extension结构的指针

PDRIVER_OBJECT DriverObject 指向这个设备的Driver对象的指针,IoCreateDevice会 自动填写本数据。

ULONG Flags 指定这个设备的缓冲策略

PDEVICE_OBJECT NextDevice 指向属于这个驱动程序的下一个设备对象,依靠本数据来维护设备对象链表

CCHAR StackSize

发送到这个设备的IRP需要的I/O堆栈单元的最小数目,一般对分

层驱动程序来说,本数据应该比其下层设备的大1

ULONG AlignmentRequirement 缓冲区要求的内存对齐,一般对分层驱动程序来说,本值应该 和其下层设备的对齐一致

Device记录着设备的特徵和状态信息,对系统上的每个虚拟的、逻辑的和物理的设备都有一个Device对象。例如对一个硬盘驱动程序,对一个物理硬盘有一个名称为Partition0的Device对象,对应整个物理磁盘,同时对硬盘的每个分区,也都有一个Device对象,它们的名称分别为PartitionX(X从1开始,每个分区对应一个数字)。

Device Extension是连接到Device对象的一个很重要的数据结构,它的数据结构是由驱动程序设计者自己来确定的,在 调用IoCreateDevice的时候应该指定它的大小,Device Ex tension其实是由操作系统在非份页内存池中为每个Device 对象分配的一块内存。由于驱动程序必须是完全可重入的, 因此使用任何全局变量和静态变量都不是好的办法,一般来 说和设备有关的任何需要保持的信息都应该放到Device Extension里去。

设备的缓冲策略也必须提一下,这里的Flag的缓冲策略主要 决定设备读写(功能代码IRP_ MJ_READ和IRP_MJ_WRITE)时候的 缓冲策略,另外功能代码IRP_MJ_DEVICE_CONTROL时候的缓冲 策略是由IOCTL控制代码本身来决定的。两者不能混为一谈。 在下面我将专门用一节来讨论I/O的缓冲策略。

I/O请求包(IRP)

在上面的结构里面已经出现了IRP了,在这里对它做一说明。 在NT中,几乎所有的I/O 都是包驱动的,可以说驱动程序和操作系统其他部份都是通过I/O请求包来进行交互的。我们 来看看一个I/O请求的执行过程。

(1) 操作系统的I/O管理器从非分页内存分配一个IRP,响应一个I/O请求。基于由客户指定的I/O函数,I/O管理器将该 IRP传递给合适的驱动程序的Dispatch例程。

(2) Dispatch例程检查请求的参数是否有效,如果有效,驱动程序根据请求的内容进行一系列的操作。否则设置错 误状态信息直接返回。

(3) 操作完成时,将数据(如果有)和状态信息存放到IRP中 并返回给I/O管理器。

(4) I/O管理器对返回的IRP进行适当的处理后将最后状态和 数据(如果有)返回给用户。

一个IRP的主要数据项如下表所示。

IRP包括一个IRP头和一个IRP stack 的区域。由于WDM的模式下都是包驱动的,所里IRP 可以说是一个非常重要的东东。还有那个该死的URB(God damn URB!)[人一辈子真的很过瘾,有些人或有些事你明明不喜欢或做不来,可是有时侯你又不得不硬着头皮去做,就像一大堆球迷围着一堆狗屎般的中国足球,那班傻儿真是要钱不要脸,丢咱中国人的脸]

IRP主要数据项说明

IO_STATUS_BLOCK IoStatus存放I/O请求的状态

PVOID

AssociatedIrp.SystemBuffer 如果设备执行缓冲I/O,则为指向系统空间缓冲区的指针。 否则为NULL

PMDL MdlAddress

如果设备执行直接I/O,指向用户空间缓冲区的内存描述表

的指针

PVOID UserBuffer I/O缓冲区的用户空间地址

BOOLEAN Cancel 指示IRP已被取消

关于AssociatedIrp.SystemBuffer、MdlAddress和UserBuffer将在 下面的I/O缓冲区策略里面更详细地讨论。

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域中。AssociatedIr p.SystemBuffer和 UserBuffer都被设置为NULL。驱动程序可以调用函数 MmGetSystemAdd ressForMdl得到用户缓冲区的系统空间地址,从而 进行数据操作。这个函数将调用者的缓冲区映射到非份页的地址空 间。驱动程序完成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的Associate dIrp.SystemBuffer域中,并把IRP的UserBuffer域设置成调用者输出缓冲区的用户空间地址。当驱动程序完成IOCTL请求时,I/O管理器将非份页缓冲区中的数据拷贝到调用者的输出缓冲区。

3、 缓冲输入直接输出I/O(METHOD_OUT_DIRECT)

I/O管理器首先检查调用者输出缓冲区的可访问性,并在物理内存中将其锁定。然后为该输出缓冲区创建一个MDL,并把指定该MDL的指针存放到IRP的MdlAddress域中。同时,I/O 管理器还在非份页池中分配一输入缓冲区,并把这个缓冲区的地址存放在IRP的Associate dIrp.SystemBuffer域中, 同时把调用者用户输入缓冲区中的数据拷贝到系统缓冲区中,并把IRP的 UserBuffer域设置为NULL。

4、 上面三种方法都不是(METHOD_NEITHER)

I/O管理器把调用者的输入缓冲区的地址放到IRP当前I/O堆栈单元的Parameters.Devi c eIoControl.TypeInputBuffer域中,把输出缓冲 区的地址存放到IRP的UserBuffer域中。这两个地址都是用户空间地 址。

从上面的说明可以看出,在执行缓冲I/O时,I/O管理器将在非份页池 中分配内存,如果调用者的缓冲区比较大时,分配的非份页池也将 比较大。非份页池是系统比较宝贵的资源,因此,如果调用者的缓 冲区比较大时,我们一般采用直接I/O的方式(例如磁盘读写请求等), 这样不仅节省系统资源,另一方面由于省去了I/O管理器在系统缓冲 区和调用者缓冲区之间的数据拷贝,也提高了效率,这对存在大量 数据传送的驱动程序尤其明显。

可以注意到DDK中的Samples下,几乎所有的例程的读写请求都是直 接I/O的,而对于IO CTL请求则是缓冲区I/O的居多。

开始驱动程序设计

下面的文字是从Microsoft的DDK帮助中节选出来的,它让我们明 白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍 意义的开发准则。应该支持哪些I/O请求在开始写任何代码之前, 应该首先确定我们的驱动程序应该处理哪些IRP例程。

如果你在设计一个设备驱动程序,你应该支持和其他相同类型 设备的NT驱动程序相同的I RP_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对象。 但从一开始就确定好你最终要创建的所有Dev ice对象将有助于设计者所要解决的任何同步问题。另外,确定所要创建的Device对象还有助于你定义Device对象的Device Extension的内容和数据结构。

开始驱动程序开发

驱动程序的开发是一个从粗到细逐步求精的过程。NT DDK的src\ 目录下有一个庞大的样板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。在开始开发你的驱动程序之前,你应该在这个样板库下面寻找是否有和你所要开发的类似类型的例程。例如我们所开发的驱动程序,虽然DDK对USB描述得不是很详细,我们还是可以在src\sto rage\class目录发现很多和USB设备有关的驱动程序。下面我们来看开发驱动程序的基本步骤。

最简的驱动程序框架

1、 写一个DriverEntry例程,在里面调用IoCreateDevice创建 一个Device对象。

2、 写一个处理IRP_MJ_CREATE请求的Dispatch例程的基本框架 (参见DDK Kernel-Mode Drivers 4.4.3描述的一个DispatchCreate 例程所要完成的最基本工作。当然写了Dispat chCreate例程后, 要在DriverEntry例程为IRP_MJ_CREATE初始化例程入口)。如果驱动程序创建了多于一个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\Co ntrol\ 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数据结构和内容做些修改。

驱动程序的书写过程的确是很烦人的,从你开始理解结构开始,你就像掉在一个泥潭里一样,无论你如何出拳,发觉总是稀泥一堆。即使你是计算机高手,可以写三千行源代码没犯一个错,一次写完,一次就编译通过(我的一个“同事”在面试的时候对我们老板说的,我想他说的对,他没犯一个错,而是犯了三十万零一个半错,不过,由不的你不信,俺朋友老板就信世间有这类高手,并供为上宾),你还得了解一些基础的硬件知识,你还要了解你的驱动程序的设备的种类,设备的硬件结构,一些特殊的寄存器,或许一些更基础的汇编程序你也的去跑一遍。还的去看什么微微有点软出的什么鸟DDK(这玩意是最重要的),我看像敌敌畏(啊啊,给我一杯敌敌畏,让我不用写程序........哈哈,我的水平直逼牛得滑了,好耍!好耍!)。然后你开始写了一大堆你自认为不比“葵花宝典”差的驱动程序,嘿嘿,你发觉整个程序就是编译不过去,就好像你花十块零五毛RMB买了本“葵花宝典”,终于下定决心按照书的首页要求的引刀什么的,可是你发觉费了九马二骡之力引完了刀,神功依旧未成,点解!你又得去学什么程序调试,去Debug,俺们称其为捉虫,NN的,TMD,虫没有捉到,脑袋可肿的大大的。什么SOFTICE,WINDBG之类,尽是一些系统杀手的角色,一不小心改错了一个内存地址,哼,我CRASH你的机器,你只好又装机,又调试,又死翘翘,你不见密西

西比河不死心,又重来一遍,如此三番,惹得你无名火起,起身饮茶,又见隔壁部门的老板正和小蜜在讨论周末去哪里加班工作,不由的气不打一处出,大吼一声“呔,来将何人!洒家张翼德在此!”..........哎,人在老板下,哪能不干活,只有硬头再上.............无数次的失败,无数次的徒劳之后,终于让你的机器跑的欢极了,你不由的小哼一句“对面的小蜜看过来,这里的男孩很能干!”

驱动程序真的得看个人造化,若你有张无忌般奇遇,有韦小宝般艳福,有段舆般韧劲,(对了,还要有东方不败般的勇气)还有什么做不了的。哈哈!

usb驱动程序教程

编写Windows https://www.doczj.com/doc/811509695.html,的usb驱动程序教程 Windows https://www.doczj.com/doc/811509695.html, 是微软推出的功能强大的嵌入式操作系统,国内采用此操作系统的厂商已经很多了,本文就以windows https://www.doczj.com/doc/811509695.html,为例,简单介绍一下如何开发windows https://www.doczj.com/doc/811509695.html, 下的USB驱动程序。 Windows https://www.doczj.com/doc/811509695.html, 的USB系统软件分为两层: USB Client设备驱动程序和底层的Windows CE实现的函数层。USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。USB设备驱动主要利用 USBD接口函数和他们的外围设备打交道。 USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。 主要的传输函数有: abourttransfer issuecontroltransfer closetransfer issuein te rruptransfer getisochresult issueisochtransfer gettransferstatus istransfercomplete issuebulktransfer issuevendortransfer 主要的用于打开和关闭usbd和usb设备之间的通信通道的函数有: abortpipetransfers closepipe isdefaultpipehalted ispipehalted openpipe resetdefaultpipe resetpipe 相应的打包函数接口有: getframelength getframenumber releaseframelengthcontrol setframelength takeframelengthcontrol 取得设置设备配置函数: clearfeature setdescriptor getdescriptor setfeature

Linux设备驱动程序举例

Linux设备驱动程序设计实例2007-03-03 23:09 Linux系统中,设备驱动程序是操作系统内核的重要组成部分,在与硬件设备之间 建立了标准的抽象接口。通过这个接口,用户可以像处理普通文件一样,对硬件设 备进行打开(open)、关闭(close)、读写(read/write)等操作。通过分析和设计设 备驱动程序,可以深入理解Linux系统和进行系统开发。本文通过一个简单的例子 来说明设备驱动程序的设计。 1、程序清单 //MyDev.c 2000年2月7日编写 #ifndef __KERNEL__ #define __KERNEL__//按内核模块编译 #endif #ifndef MODULE #define MODULE//设备驱动程序模块编译 #endif #define DEVICE_NAME "MyDev" #define OPENSPK 1 #define CLOSESPK 2 //必要的头文件 #include //同kernel.h,最基本的内核模块头文件 #include //同module.h,最基本的内核模块头文件 #include //这里包含了进行正确性检查的宏 #include //文件系统所必需的头文件 #include //这里包含了内核空间与用户空间进行数据交换时的函数宏 #include //I/O访问 int my_major=0; //主设备号 static int Device_Open=0; static char Message[]="This is from device driver"; char *Message_Ptr; int my_open(struct inode *inode, struct file *file) {//每当应用程序用open打开设备时,此函数被调用 printk ("\ndevice_open(%p,%p)\n", inode, file); if (Device_Open) return -EBUSY;//同时只能由一个应用程序打开 Device_Open++; MOD_INC_USE_COUNT;//设备打开期间禁止卸载 return 0; } static void my_release(struct inode *inode, struct file *file)

未能成功安装设备驱动程序MTPUSB设备安装失败的解决办法

未能成功安装设备驱动程序M T P U S B设备安装失败的解决办法 文件编码(GHTU-UITID-GGBKT-POIU-WUUI-8968)

M T P U S B设备安装失败未能成功安装设备驱动程序 终极解决方法 环境介绍:电脑系统win7(32位)已安装摩托罗拉手机驱动版本(其他版本应该也行,不行的话去摩托罗拉官网下载最新驱动) 手机型号:摩托罗拉defy mb525(系统) 备注:其他电脑操作系统和不同型号手机可参考此方法,找到相应设置项即可。 问题简介: 1.当我们把手机连接至电脑,把模式调制成“摩托罗拉手机门户”时,出现下列情况 2.过一会之后便会弹出提示说:未能成功安装设备驱动程序

3.单击查看详情便弹出窗口如下图所示: 4.此时桌面右下角图标出现黄色三角号,如图所示: 5.于是我们就开始不淡定了,怎么看怎么别扭、抓狂、按耐不住。下面介绍问题解决方案 解决方法: 1.我的电脑——右键单击——管理——设别管理器,之后会看到如图所示:在便携设备下有黄色三角号提示,即是我们纠结的MTP USB设备安装不成功的展示。

MIUI手机操作系统为例,其他手机操作系统需将USB绑定服务开启即可)。选择设置——系统——共享手机网络——USB绑定,将该选项设置为“开”,这是你会发现如图所示变化,在设备管理器面板中没有了便携设备选项及黄色三角号提醒,如图所示:(但桌面右下角的黄色三角警示还在)

3.在完成以上步骤后,用手机打开WIFI并登录无线WLAN,手机打开网页检验连接是否正常,若正常则如下图所示,黄色三角号警示消失,问题解决;若以上步骤没有解决问题,请先连接WIFI并登录WLAN之后,再按步骤操作。 4.完成以上步骤并解决问题后,选择电脑桌面网络——右键单击——属性,如下图所示:此时不仅手机能上网,而且电脑也能正常连接网络,正常上网。(我的体验是连接数据不稳定,时不时的要手机重新登陆WIFI,才有数据传输,可能是高校WLAN的问题,在家网速快的可以尝试一下) 5.通过这个问题的解决,我才知道原来MTP USB设备安装失败,未能成 功安装设备驱动程序的原因是我们手机里面没有启用该设备服务。今天 才知道MTP USB设备是与手机里的共享手机网络中“USB绑定”服务相关 联的,是电脑用来使用手机WIFI网络连接进行上网的工具。

字符设备驱动开发实验

字符设备驱动实验 实验步骤: 1、将设备驱动程序使用马克file文件编译 生成模块firstdev.ko 2、将模块加载到系统中insmod firstdev.ko 3、手动创建设备节点 mknod /dev/first c 122 0 4、使用gcc语句编译firsttest.c生成可执行 文件 5、运行可执行文件firsttest,返回驱动程序 中的打印输出语句。 查看设备号:cat /proc/devices 卸载驱动:rmmod firstdev 删除设备节点:rm /dev/first 显示printk语句,(打开一个新的终端)while true do sudo dmesg -c sleep 1 done

源码分析 设备驱动程序firstdev.c #include #include #include #include #include #include //#include static int first_dev_open(struct inode *inode, struct file *file) { //int i; printk("this is a test!\n"); return 0; }

static struct file_operations first_dev_fops ={ .owner = THIS_MODULE, .open = first_dev_open, }; static int __init first_dev_init(void) { int ret; ret = register_chrdev(122,"/dev/first",&first_dev_fo ps); printk("Hello Modules\n"); if(ret<0) { printk("can't register major number\n"); return ret; }

USB设备驱动程序设计

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 设备驱动程序的设计

《Linux设备驱动开发详解:基于最新的Linux 4.0内核》19. Linux电源管理系统架构和驱动

以下电子书来源于宋宝华《Linux设备驱动开发详解:基于最新的Linux 4.0内核》第19章《Linux电源管理系统架构和驱动》 本章导读 Linux在消费电子领域的应用已经铺天盖地,而对于消费电子产品而言,省电是一个重要的议题。 本章将介绍Linux设备树(Device Tree)的起源、结构和因为设备树而引起的驱动和BSP 变更。 19.1节阐述了Linux电源管理的总体架构。 19.2~19.8节分别论述了CPUFreq、CPUIdle、CPU热插拔以及底层的基础设施Regulator、OPP以及电源管理的调试工具PowerTop。 19.9节讲解了系统Suspend to RAM的过程以及设备驱动如何提供对Suspend to RAM的支持。 19.10节讲解了设备驱动的Runtime suspend。 本章是相对《Linux设备驱动开发详解(第2版)》全新的一章内容,也是Linux设备驱动工程师必备的知识体系。

第十九章Linux电源管理系统架构和驱动 1.Linux电源管理全局架构 Linux电源管理非常复杂,牵扯到系统级的待机、频率电压变换、系统空闲时的处理以及每个设备驱动对于系统待机的支持和每个设备的运行时电源管理,可以说和系统中的每个设备驱动都息息相关。 对于消费电子产品来说,电源管理相当重要。因此,这部分工作往往在开发周期中占据相当大的比重,图19.1呈现了Linux内核电源管理的整体架构。大体可以归纳为如下几类: 1.CPU在运行时根据系统负载进行动态电压和频率变换的CPUFreq 2.CPU在系统空闲时根据空闲的情况进行低功耗模式的CPUIdle 3.多核系统下CPU的热插拔支持 4.系统和设备对于延迟的特别需求而提出申请的PM QoS,它会作用于CPUIdle的具体 策略 5.设备驱动针对系统Suspend to RAM/Disk的一系列入口函数 6.SoC进入suspend状态、SDRAM自刷新的入口 7.设备的runtime(运行时)动态电源管理,根据使用情况动态开关设备 8.底层的时钟、稳压器、频率/电压表(OPP模块完成)支撑,各驱动子系统都可能用 到 图19.1 Linux电源管理系统架构 2.CPUFreq驱动 CPUFreq子系统位于drivers/cpufreq目录,负责进行运行过程中CPU频率和电压的动态

USB WDM 设备驱动程序

USB WDM 设备驱动程序DriverStudio 引言 随着微机技术水平的日益提高,传统的计算接口已经不能满足当前计算机高速发展的需求,计算机业界迫切需要新的通用型、高速总线接口。通用外设接口标准USB应运而生。USB,全称为通用串行总线(Universal Serial Bus),它是Compaq、IBM等PC大厂商联合开发的一种新型的、基于令牌的、高速的串行总线标准。开发者要设计USB设备接口,就必须首先了解USB协议,在此基础上有针对性的开发USB设备驱动程序。 USB简介 在众多的PC机总线中,USB以其突出的优点独树一帜:①使用方便。支持热拔插,不涉及中断请求(IRQ)冲突等问题,能真正做到“即插即用”。②传输速率高。目前的USB 2.0协议速度高达480Mbps 。③易于扩展。通过使用Hub扩展可连接多达127个外设。④使用灵活。USB共有4种传输模式:控制(control)、同步(Synchronization)、中断(interrupt)、批量(bulk),以适应不同设备的需要。⑤独立供电。正由于上述优点,开发USB接口的设备已成为一种发展趋势。 一个完整的USB系统包括主机系统和USB设备。所有的传输事务都是由主机发起的。一个主机系统又可以分为以下几个层次结构,如图1所示:

图1 USB 互连通信模型 USB总线接口包括USB主控制器和根集线器,其中USB主控制器负责处理主机与设备之间电气和协议层的互连,根集线器提供USB设备连接点。USB系统使用USB主控制器来管理主机和USB设备之间的数据传输,另外它也负责管理USB资源,如带宽等。应用软件不能直接访问USB设备硬件,而通过USB系统和USB总线接口与USB设备进行交互。 USB设备包含一些向主机软件提供一系列USB设备的特征和能力的信息的设备描述符,用来配置设备和定位USB设备驱动程序。这些信息确保了主机以正确的方式访问设备。通常,一个设备有一个或多个配置(Configuration)来控制其行为。配置是接口(Interface)的集合,接口指出软件应该如何访问硬件。接口又是端点(endpoint)的集合,每一个与USB交换数据的硬件就为端点,它是作为通信管道的一个终点。图1显示了一个多层次结构的通信模型,它表明了端点和管道所扮演的角色。 WDM驱动程序和USB驱动程序的分层结构 设备驱动程序实际上是指一系列控制硬件设备的函数,是操作系统中控制和连接硬件的关键模块。它提供连接到计算机的硬件设备的软件接口。

一个简单字符设备驱动实例

如何编写Linux设备驱动程序 Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。本文是在编写一块多媒体卡编制的驱动程序后的总结,获得了一些经验,愿与Linux fans共享,有不当之处,请予指正。 以下的一些文字主要来源于khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关device driver的一些资料. 这些资料有的已经过时,有的还有一些错误,我依据自己的试验结果进行了修正. 一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1)对设备初始化和释放; 2)把数据从内核传送到硬件和从硬件读取数据; 3)读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4)检测和处理设备出现的错误。 在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待. 已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序. 最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 二、实例剖析 我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理.把下面的C代码输入机器,你就会获得一个真正的设备

从零开始搭建Linux驱动开发环境

参考: 韦东山视频第10课第一节内核启动流程分析之编译体验 第11课第三节构建根文件系统之busybox 第11课第四节构建根文件系统之构建根文件系统韦东山书籍《嵌入式linux应用开发完全手册》 其他《linux设备驱动程序》第三版 平台: JZ2440、mini2440或TQ2440 交叉网线和miniUSB PC机(windows系统和Vmware下的ubuntu12.04) 一、交叉编译环境的选型 具体的安装交叉编译工具,网上很多资料都有,我的那篇《arm-linux- gcc交叉环境相关知识》也有介绍,这里我只是想提示大家:构建跟文件系统中所用到的lib库一定要是本系统Ubuntu中的交叉编译环境arm-linux- gcc中的。即如果电脑ubuntu中的交叉编译环境为arm-linux-

二、主机、开发板和虚拟机要三者互通 w IP v2.0》一文中有详细的操作步骤,不再赘述。 linux 2.6.22.6_jz2440.patch组合而来,具体操作: 1. 解压缩内核和其补丁包 tar xjvf linux-2.6.22.6.tar.bz2 # 解压内核 tar xjvf linux-2.6.22.6_jz2440.tar.bz2 # 解压补丁

cd linux_2.6.22.6 patch –p1 < ../linux-2.6.22.6_jz2440.patch 3. 配置 在内核目录下执行make 2410_defconfig生成配置菜单,至于怎么配置,《嵌入式linux应用开发完全手册》有详细介绍。 4. 生成uImage make uImage 四、移植busybox 在我们的根文件系统中的/bin和/sbin目录下有各种命令的应用程序,而这些程序在嵌入式系统中都是通过busybox来构建的,每一个命令实际上都是一个指向bu sybox的链接,busybox通过传入的参数来决定进行何种命令操作。 1)配置busybox 解压busybox-1.7.0,然后进入该目录,使用make menuconfig进行配置。这里我们这配置两项 一是在编译选项选择动态库编译,当然你也可以选择静态,不过那样构建的根文件系统会比动态编译的的大。 ->Busybox Settings ->Build Options

安装USB驱动过程中可能遇到的问题及解决方案

安装USB 驱动过程中可能遇到的问题及解决方案 概述: 本文列举了在安装USB 驱动程序过程中可能遇到的常见问题,并提供了常用的解 决方案。对于其他特殊的情况,如:驱动安装之后出现打印乱码等现象,将在相 关的技术文档中予以进一步的说明。 本文包括: 1. 故障现象: 在打印时遇到:打印到DOT4_00x 端口错误。 故障分析: 1 ).USB 端口没有被正确地识别。USB 电缆不符合规范,长度太长,或者加装 延长线,转接线,共享器等附加设备; 2 ).端口选择不正确; 3 ). 打印机驱动程序未正确安装;如果安装了不匹配的驱动也会出现端口错误。 比如:lj1010 打印机安装了同系列1015 的PCL5e 驱动; 4)). 系统和USB Host Controller 的影响; 5 ).端口供电不足。 解决方案: 1 ).正确连接USB 线,保证USB 电缆长度应小于 2 米,通讯质量较好;取 消延长线和共享器等附加设备; 2 ).检查打印机驱动属性中的端口选项,如果存在多个DOT4 端口, 则首选数 目较高的端口;查看是否有USB 端口,选择USB 端口打印测试; 3 ).取消双向支持;

4 ).完全卸载当前驱动,然后重新启动或热拔插USB 电缆,若系统自动找到新硬件,取消,在device manager 里发现usb printing support 后,再利用“添加打印机向导”添加打印机,安装与打印机语言相匹配的驱动程序,此时,应该选择USB-00X 端口;若系统无法检测到新硬件,要检查系统是否正确识别USB 芯片组,步骤如下: 在Windows 2000/XP 中(Windows 9x/Me 的操作步骤基本类似) ,依次点击“开始→设置→控制面板→系统→硬件→设备管理器”,找到并双击“通用串行总线控制器”。其中应当至少列出两类条目,一类是USB 控制器,另一个是USB Root Hub。如果PC 主板支持USB 2.0 ,并正常安装了驱动程序,一般会在此处显示USB 2.0 Root Hub 。 如果Windows 无法识别出USB 控制器,或在“其他设备”中出现“ USB 控制器”,那么说明主板芯片组的驱动程序或USB 2.0 的驱动程序没有安装成功。建议到芯片组官方网站下载最新的驱动程序,并确认Windows 能正确识别; 5 ).建议将打印机安装到其他计算机上测试; 6 ).保证USB 接口获得足够的电力。USB 设备包含从计算机通过USB 电缆驱动USB 通讯的电源。计算机在100mA 的低电力级别下可以检测到设备,但是需要500mA 才能维持大功率USB 设备的高速通讯(movable disk) 。当打印机得不到充分的电流供应时,也可能造成DOT4 无法正确的设定。建议将打印机直接插在屋内的电源插孔上,而非插在延长线上与其他的电器共用电流,同时尽量使用HP 所附的电源线而非其他可能不合格的电源线,或者为计算机添加有源的USB 集线器。 2. 故障现象: 1 ) . 激光打印机在运行光盘安装驱动程序,插入USB 电缆后或者在出现的新硬件向导下安装打印机时会发生这个错误“ 无法安装这个硬件,在安装LaserJet 1020 时出现了一个问题。安装该设备是发生了一个错误:这个设备的驱动程序丢失了一个必需的项,这可能是由于inf 是为Windows 95 或更新版本而写的。联系您的硬件供应商。”; 2 ).设备控制器的USB 主控制器中出现黄色叹号。 故障分析: 当用打印机驱动光盘的Windows 98 第二版的USB 打印支持驱动程序,而不是使用系统自带的USB 打印支持驱动程序时会发生这种错误。Windows 98 USB 打印驱动程序与更高版本的Windows 操作系统不兼容。

USB编程电缆驱动程序安装说明

USB编程电缆驱动程序安装说明 概述 USB编程电缆是通过将电脑的USB接口模拟成传统的串行口(通常为COM3),从而使用现有的编程软件或通信软件,通过编程电缆与PLC等设备的传统接口进行通信。 功能 ●支持的操作系统Windows2000/Windows XP ●完全兼容USB V1.1和USB CDC V1.1规范 ●USB总线供电(非隔离电缆)、或USB总线供电与PLC的编程口同时供 电(隔离型电缆) ●波特率:300bps~1Mbps自动适应 ●每台PC只支持一根USB编程电缆 系统要求 请在使用USB编程电缆之前确认你的电脑是IBM PC兼容型并具备以下最低系统要求: ●Intel兼容586DX4-100MHz中央处理器或更高 ●一个标准的USB接口(4-pin A型插座) ●运行操作系统为Windows2000或Windows XP 驱动程序的安装 驱动程序的安装非常简单,只需按提示进行即可,以Windows XP为例,按以下步骤进行: 1、打开将要连接USB编程电缆的电脑电源,并确认电脑的USB口已经启 动并正常工作。 2、将USB编程电缆插入电脑的USB接口,Windows将检测到设备并运行 添加新硬件向导帮助你设置新设备,插入驱动程序光盘并单击下一步继 续。 如果Windows没有提示找到新硬件,那么在设备管理器的硬件列表中, 展开“通用串行总线控制器”,选择带问号的USB设备,单击鼠标右键 并运行更新驱动程序。

3、Windows将检测到安装信息,显示“FOURSTAR USB Composite Device ” 设备,并出现如下没有通过Windows徽标测试的信息框,单击“仍然继续”。

USB HID 设备驱动程序设计

USB HID 设备驱动程序设计 引自:https://www.doczj.com/doc/811509695.html,/hudaweikevin/archive/2009/11/02/4756394.aspx 摘要:USB(Universal Serial Bus)即“通用串行总线”是一种应用在计算机领域的新型接口技术。它的出现大大简化了PC机和外围设备的连接过程,使PC机接口的扩展变得更加容易。USB作为近年来计算机和嵌入式领域中的热点,推动了计算机外设的飞速发展。本文介绍了适用于PC的嵌入式操作系统的USB HID设备驱动的设计,并给出了具体的实现方法。关键词:USB HID设备PC 嵌入式驱动程序 从USB 1.1到USB2.0再到目前的USB OTG(On-The-Go),USB在不断自我完善,并走向成熟。USB具有高速度、低成本、低功耗、即插即用和使用维护方便等优点,不仅成为了PC主板上的标准接口,而且成为了所有PC外部设备如键盘、鼠标、显示器、打印机、数码相机等与PC相连的标准协议之一,迅速占领了计算机中、低速外部设备的市场。 USB(Universal Serial Bus)即“通用串行总线”是一种应用在计算机领域的新型接口技术。USB的拓扑结构中居于核心地位的是Host(也称为主机)。任何一次USB的数据传输都必须由主机来发起和控制,所有的USB外设都只能和主机建立连接,任何两个外设之间或是两个主机之间无法直接通信。而目前,大量的扮演主机角色的是个人电脑PC。 随着USB应用领域的逐渐扩大,对于USB的期望也越来越高。我们希望USB能应用在各种计算机领域中,希望能通过PDA等移动设备直接和USB外设通信,使得USB能应用在没有PC的领域中。 而我们目前所使用的USB移动设备,大多数都是USB的外设,比如USB的移动硬盘、USB 接口的数码相机等。所有这些设备都只能在PC上使用,只能通过PC来进行相互的文件和数据交换。 本驱动程序是为完善我们自行设计的嵌入式操作系统,使得它具备能识别USB HID设备的功能而开发的。所使用的编程语言为C语言,并下载到目标机上,通过测试验证可以识别USB HID设备,如USB键盘,USB鼠标等。本文探讨的即是PC上实现USB HID设备驱动的方法。 ⒈HID 设备驱动简介 为简化USB设备的开发过程,USB提出了设备类的概念。HID设备类,即人机接口设备。典型的HID设备如键盘、鼠标。 所有设备类都必须支持标准USB描述符和标准USB设备请求。如果有必要,设备类还可以自行定义其专用的描述符和设备请求,这分别被称为设备类定义描述符和设备类定义请求。另外,一个完整的设备类还将指明其接口和端点的使用方法,如如接口所包含端点的个数、端点的最大数据包长度等。 HID设备既可以是低速设备也可以是全速设备,其典型的数据传输类型为中断IN传输,即它适用于主机接收USB设备发来的小量到中等量的数据。HID具有以下的功能特点:1)适用于传输少量或中量的数据;2)传输的数据具有突发性;3)传输的最大速率有限制;4)无固定

【IT专家】Linux设备驱动开发详解

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 Linux设备驱动开发详解 2010/05/09 0 typedef void (*lpFunction) ();//定义一个无参数,无返回类型的函数指针类型 ?//定义一个函数指针,指向cpu启动后所执行的第一条指令的位置 ?lpFunction lpReset = (lpFunction)0xF000FFF0; ?lpReset();//调用函数 ?MMU停供虚拟地址和物理地址的映射、内存访问权限保护和Cache缓存控制等硬件支持。操作系统内核借助MMU,可以让用户感觉到好像程序可以使用非常大的内存空间,从而使得编程人员在写程序时不用考虑计算机的物理内存的实际容量?如图,当ARM要访问存储器时,MMU先查找TLB中的虚拟地址表。如果ARM 的结构支持分开的数据TLB(DTLB)和指令TLB(ITLB),则除去指令使用的ITLB外,其他的都是用DTLB ? ?若TLB中没有虚拟地址的入口,则转换表遍历硬件从存放于主存储器中的转换表中获取地址转换信息和访问权限(即执行TTW),同时将这些信息放入TLB,它或者被放在一个没有使用的入口或者替换一个已经存在的入口。之后,在TLB条目中控制信息的控制下,当访问权限允许时,对真实物理地址的访问将在Cache或者在内存中发生 ?用户空间0-3GB,内核空间3-4GB,用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。用户进程只能通过系统调用等方式才能访问到内核空间 ?每个进程的用户空间都是完全独立、互不相干的,用户进程各自有不同的页表。而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的叶表,内核的虚拟空间独立于其他程序 ?Linux中的1GB内核地址空间又被划分为内存映射区,虚拟内存分配区、高端页面映射区、专用页面映射区和系统保留映射区

如何实现Linux设备驱动模型

文库资料?2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd. 如何实现Linux 设备驱动模型 设备驱动模型,对系统的所有设备和驱动进行了抽象,形成了复杂的设备树型结构,采用面向对象的方法,抽象出了device 设备、driver 驱动、bus 总线和class 类等概念,所有已经注册的设备和驱动都挂在总线上,总线来完成设备和驱动之间的匹配。总线、设备、驱动以及类之间的关系错综复杂,在Linux 内核中通过kobject 、kset 和subsys 来进行管理,驱动编写可以忽略这些管理机制的具体实现。 设备驱动模型的内部结构还在不停的发生改变,如device 、driver 、bus 等数据结构在不同版本都有差异,但是基于设备驱动模型编程的结构基本还是统一的。 Linux 设备驱动模型是Linux 驱动编程的高级内容,这一节只对device 、driver 等这些基本概念作介绍,便于阅读和理解内核中的代码。实际上,具体驱动也不会孤立的使用这些概念,这些概念都融合在更高层的驱动子系统中。对于大多数读者可以忽略这一节内容。 1.1.1 设备 在Linux 设备驱动模型中,底层用device 结构来描述所管理的设备。device 结构在文件中定义,如程序清单错误!文档中没有指定样式的文字。.1所示。 程序清单错误!文档中没有指定样式的文字。.1 device 数据结构定义 struct device { struct device *parent; /* 父设备 */ struct device_private *p; /* 设备的私有数据 */ struct kobject kobj; /* 设备的kobject 对象 */ const char *init_name; /*设备的初始名字 */ struct device_type *type; /* 设备类型 */ struct mutex mutex; /*同步驱动的互斥信号量 */ struct bus_type *bus; /*设备所在的总线类型 */ struct device_driver *driver; /*管理该设备的驱动程序 */ void *platform_data; /*平台相关的数据 */ struct dev_pm_info power; /* 电源管理 */ #ifdef CONFIG_NUMA int numa_node; /*设备接近的非一致性存储结构 */ #endif u64 *dma_mask; /* DMA 掩码 */ u64 coherent_dma_mask; /*设备一致性的DMA 掩码 */ struct device_dma_parameters *dma_parms; /* DMA 参数 */ struct list_head dma_pools; /* DMA 缓冲池 */ struct dma_coherent_mem *dma_mem; /* DMA 一致性内存 */ /*体系结构相关的附加项*/ struct dev_archdata archdata; /* 体系结构相关的数据 */ #ifdef CONFIG_OF

未能成功安装设备驱动程序MTPUSB设备安装失败的解决办法

M T P U S B设备安装失败未能成功安装设备驱动程序 终极解决方法 环境介绍:电脑系统win7(32位)已安装摩托罗拉手机驱动版本(其他版本应该也行,不行的话去摩托罗拉官网下载最新驱动) 手机型号 备注:其他电脑操作系统和不同型号手机可参考此方法,找到相应设置项即可。 问题简介: 1.当我们把手机连接至电脑,把模式调制成“摩托罗拉手机门户”时,出现下列情况 2.过一会之后便会弹出提示说:未能成功安装设备驱动程序 3.单击查看详情便弹出窗口如下图所示: 4.此时桌面右下角图标出现黄色三角号,如图所示: 5.于是我们就开始不淡定了,怎么看怎么别扭、抓狂、按耐不住。下面介绍问题解决方案 解决方法: 1.我的电脑——右键单击——管理——设别管理器,之后会看到如图所示:在便携设备下有黄色三角号提示,即是我们纠结的MTP USB设备安装不成功的展示。 2.对手机进行设置(这是关键步骤),(备注:以MIUI手机操作系统为例,其他手机操作系统需将USB 绑定服务开启即可)。选择设置——系统——共享手机网络——USB绑定,将该选项设置为“开”,这是你会发现如图所示变化,在设备管理器面板中没有了便携设备选项及黄色三角号提醒,如图所示:(但桌面右下角的黄色三角警示还在) 3.在完成以上步骤后,用手机打开WIFI并登录无线WLAN,手机打开网页检验连接是否正常,若正常则如下图所示,黄色三角号警示消失,问题解决;若以上步骤没有解决问题,请先连接WIFI并登录WLAN之后,再按步骤操作。 4.完成以上步骤并解决问题后,选择电脑桌面网络——右键单击——属性,如下图所示:此时不仅手机能上网,而且电脑也能正常连接网络,正常上网。(我的体验是连接数据不稳定,时不时的要手机重新登陆WIFI,才有数据传输,可能是高校WLAN的问题,在家网速快的可以尝试一下) 5.通过这个问题的解决,我才知道原来MTP USB设备安装失败,未能成功安装设备驱动程序的原因是我 们手机里面没有启用该设备服务。今天才知道MTP USB设备是与手机里的共享手机网络中“USB绑定”服 务相关联的,是电脑用来使用手机WIFI网络连接进行上网的工具。

11-4~6 字符设备驱动开发

一、字符驱动初步认识 (2) (一)字符设备驱动框架 (2) (二)主设备号 (2) (三)创建设备节点: (4) 1.手动创建 (4) 2.自动创建(通过udev/mdev机制) (4) (四)应用程序与驱动的交互 (5) 1.驱动中实现文件io操作接口: (5) 2.调用IO接口 (7) 3.应用程序需要传递数据给驱动 (8) 4.控制外设 (9) 二、字符设备驱动开发 (10) (一)应用程序和驱动扮演的是什么角色 (10) (二)步骤: (10) 1.实现模块加载和卸载入口函数 (10) 2.在模块加载入口函数中 (10) (三)规范: (11) 1.面向对象编程思想 (11) (四)做出错处理 (12) (五)操作寄存器地址到方式: (12) 三、 Day4作业 (13) 四、 Day5作业 (14) 五、 Day6作业 (14)

一、字符驱动基本操作 (一)字符设备驱动框架 用户空间对驱动的操作其实就是文件IO 字符设备:所产生的数据是字符流 大部分设备都是字符设备,如:LCD,keyboard,I2c等。 因为字符设备的数据是从寄存器中产生,所以数据量不大,速度快 字符设备的读取方式:文件IO 块设备:存储设备,数据以块为单位。如:硬盘、u盘、flash、sd卡等 读取的数据量大,速度慢 内核对这样的操作进行优化机制,如缓冲,文件系统层等 网络设备:因为是走协议的,linux把网络设备全部做成socket设备 当用户空间输入open打开一个字符设备的时候,会调用在字符设备驱动中会对应的XX_open,这个XX_open是一一对应的。而用户空间的open和内核中的open 对应关系是由,设备节点管理的。而设备节点就是一个文件,在这个文件中通过设备号来做到意义对应。 作为字符设备驱动要素: 1,必须有一个设备号,用在众多到设备驱动中进行区分 2,用户必须知道设备驱动对应到设备节点(设备文件) linux把所有到设备都看成文件 crw-r----- 1 root root 13, 64 Mar 28 20:14 event0 crw-r----- 1 root root 13, 65 Mar 28 20:14 event1 crw-r----- 1 root root 13, 66 Mar 28 20:14 event2 3,对设备操作其实就是对文件操作,应用空间操作open,read,write的时候实际在驱动代码有对应到open, read,write (二)主设备号 作为驱动必须有一个主设备号--向系统申请 功能:申请主设备号 原型:int register_chrdev(unsigned int major, const char * name, const struct file_operations * fops) 参数:1:major:主设备号 设备号(32bit--dev_t)==主设备号(高12bit) + 次设备号(20bit) 主设备号:表示一类设备--camera 次设备号:表示一类设备中某一个:前置,后置 给定到方式有两种:

怎样写linux下的USB设备驱动程序

怎样写linux下的USB设备驱动程序 发布时间:2007年11月19日 引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题;本文的目地是使大家了解怎样编制USB设备驱动,为更好地配置和使用USB设备提供方便;对于希望开发Linux系统下USB设备驱动的人员,也可作为进一步学习USB驱动的大体架构进而编写出特殊USB设备的驱动程序。 USB基础知识 USB是英文Universal Serial Bus的缩写,意为通用串行总线。USB最初是为了替代许多不同的低速总线(包括并行、串行和键盘连接)而设计的,它以单一类型的总线连接各种不同的类型的设备。USB的发展已经超越了这些低速的连接方式,它现在可以支持几乎所有可以连接到PC上的设备。最新的USB规范修订了理论上高达480Mbps的高速连接。Linux内核支持两种主要类型的USB驱动程序:宿主系统上的驱动程序和设备上的驱动程序,从宿主的观点来看(一个普通的宿主也就是一个PC机),宿主系统的USB设备驱动程序控制插入其中的USB设备,而USB设备的驱动程序控制该设备如何作为一个USB设备和主机通信。本文将详细介绍运行于PC机上的USB系统是如何运作的。并同时用USB驱动程序的框架程序当例子作详细的说明,我们在此文中不讨论USB器件的驱动程序。 USB驱动程序基础 在动手写USB驱动程序这前,让我们先看看写的USB驱动程序在内核中的结构,如下图: USB驱动程序存在于不同的内核子系统和USB硬件控制器之间,USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口,而不必考虑系统当前存在的各种不同类型的USB硬件控制器。USB是一个非常复杂的设备,linux内核为我们提供了一个称为USB的核心的子系统来处理大部分的复杂性,USB

USB设备驱动程序的开发与USB协议

第1章绪论 1.1USB简介 USB是由世界著名计算机和通信公司等共同推出的新一代接口标准,全称为Universal Serial Bus(通用串行总线)[1],是一种快速、灵活的总线接口。它是为了解决日益增加的PC外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信标准。USB应用十分广泛,并具有下述优点: 1、适用于多种外设,使它不需要为不同的外设准备不同的接口和协议; 2、Windows能自动检测到USB设备的热插拔,并自动配置; 3、PC机上的接口线非常紧缺,而USB设备并不需要用户设置端口故无论从用户使用方便性,或从对资源的占用方面看,USB都很优秀; 4、当接入一个USB设备时,全速USB接口可达12Mbit/s。考虑到状态、控制和出错信息,最大理论速度仍可达到9.6Mbit/s,这是其他串行接口协议所不能比拟的,且USB也支持1.5Mbit/s的低速传输。

5、USB接口芯片价格低廉,这也大大促进USB设备的开发与应用。 在USB出现之前,计算机典型接口有并行口、串行口、鼠标口、键盘口、显示器口,及各种卡式接口等,与这些接口对应的有各种不同的电缆,在传输速度方面,这些接口都存在速度偏低的问题。在技术方面,这种设计容易产生I/O冲突,中断不够用,以及对于每一种新的外设都必须设计新的接口卡等缺点。当今的计算机外部设备,都在追求高速度和高通用性。USB接口适应了这种要求,并以其速度快、使用方便、成本低等优点,迅速得到了众多PC厂商和半导体厂商的大力支持,外设向USB过度成为必然趋势。 1.2USB驱动程序的意义 如果PC主机不知道如何与USB外设通信,那么这个USB外设一点用处都没有,人机接口设备(HID)[2]类是Windows完全支持的USB设备类型中的一种,应用程序可以使用操作系统内设置的驱动与HID通信,但与HID 通信不像打开一个端口,设定几个参数,然后就可以读写数据那么简单,在应用程序能与HID交换数据之前,它先要找到设备,获取有关它的报告信息。为做到这些,应用程序必须通过访问通信API函数,使位于上层的应用程序与位于下层的设备驱动程序进行数据交换。应用程序可以使用任何能访问API函数的程序语言,VC++是一种能访问API函数的功能强大的语言,因此,我们应用Visual C++6.0环境下编写与USB设备通信的Windows程序。 1.3VC++软件的介绍 应用基于MFC AppWizard的应用程序。MFC (Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++提供了相应的工具来完成这个工作:

相关主题
文本预览
相关文档 最新文档