编写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 设备如何与主机通信。
USB驱动程序开发全程

USB驱动程序开发全程编写USB驱动程序步骤:1所有usb驱动都必须创建主要结构体struct usb_driver struct usb_driver->struct module *owner(有他可正确对该驱动程序引用计数,应为THIS_MODULE)->const char *name(驱动名字,运行时可在查看 /sys/bus/usb/drivers/)->const struct usb_device_id *id_table(包含该驱动可支持的所有不同类型的驱动设备,没添探测回调函数不会被调用)->int (*probe)(struct usb_interface *intf,const struct usb_device_id *id)(usb驱动探测函数,确认后struct usb_interface 应恰当初始化,然后返0,如果出错则返负值)->void(*disconnect)(struct usb_interface *intf)(当struct usb_interface 被从系统中移除或驱动正从usb核心中卸载时,usb核心将调用此函数)代码实例:static struct usb_driver skel_driver={.owner = THIS_MODULE,.name = "skeleton",.id_table = skel_table,.probe = skel_probe,.disconnect = skel_disconnect,};↓2usb_register()注册将struct usb_driver 注册到usb核心,传统是在usb驱动程序模块初始化代码中完成该工作的static int __init usb_skel_init(void){...usb_register(&skel_driver);...}↓3struct usb_device_id usb核心用该表判断哪个设备该使用哪个驱动程序,热插拔脚本使用它来确定当一个特定的设备插入到系统时该自动装载哪个驱动程序。
Linux驱动之USB鼠标驱动编写

Linux驱动之USB⿏标驱动编写本篇博客分以下⼏部分讲解1、介绍USB四⼤描述符USB设备驱动程序⾥定义了许多与驱动程序密切相关的描述符。
这⾥介绍⼀下四种⽐较关键的描述符:设备描述符、配置描述符、接⼝描述符、端点描述符。
这⼏个描述符都位于include\linux\usb\ch9.h中,先看⼀下每个描述直接的关系,从图中可以看出每⼀个查到USB主机上的USB设备都有⼀个设备描述符,设备描述符下⾯可以接多个配置描述符,配置描述符下⾯⼜可以接多个当USB设备接到USB控制器上后,USB控制器第⼀次读取到的数据包,总共8字节/*当USB设备接到USB控制器上后,USB控制器第⼀次读取到的数据包,总共8字节*/struct usb_ctrlrequest {__u8 bRequestType;__u8 bRequest;__le16 wValue;__le16 wIndex;__le16 wLength;} __attribute__ ((packed));设备描述符是在设备连接时,主机第⼀个读取的描述符,包含了主机需要从设备读取的基本信息。
设备描述符有14个字段,如下所⽰。
依照功能来分,设备描述符的字段包含了描述符本⾝、设备、配置以及类别4⼤类。
/* USB_DT_DEVICE: Device descriptor */struct usb_device_descriptor {__u8 bLength; //描述符长度__u8 bDescriptorType; //描述符类型__le16 bcdUSB; //USB规范版本号码,BCD码表⽰__u8 bDeviceClass; //USB设备类别__u8 bDeviceSubClass; //USB设备⼦类别__u8 bDeviceProtocol; //USB设备协议码__u8 bMaxPacketSize0; //端点0的最⼤信息包⼤⼩(端点0⽤于控制传输,既能输出也能输⼊)__le16 idVendor; //⼚商ID__le16 idProduct; //产品ID__le16 bcdDevice; //设备版本编号,BCD码表⽰__u8 iManufacturer; //制造者的字符串描述符的索引值__u8 iProduct; //产品的字符串描述符的索引值__u8 iSerialNumber; //序号的字符串描述符的索引值__u8 bNumConfigurations;//可能配置的数⽬} __attribute__ ((packed));在读取设备描述符后,主机可以读取该设备的配置、接⼝以及端点描述符。
USB驱动程序编写

USB驱动程序编写linux下usb驱动编写(内核2.4)——2.6与此接口有区别2006-09-15 14:57我们知道了在Linux下如何去使用一些最常见的USB设备。
但对于做系统设计的程序员来说,这是远远不够的,我们还需要具有驱动程序的阅读、修改和开发能力。
在此下篇中,就是要通过简单的USB驱动的例子,随您一起进入USB驱动开发的世界。
USB骨架程序(usb-skel eton),是USB驱动程序的基础,通过对它源码的学习和理解,可以使我们迅速地了解USB驱动架构,迅速地开发我们自己的USB硬件的驱动。
USB驱动开发在掌握了USB设备的配置后,对于程序员,我们就可以尝试进行一些简单的USB驱动的修改和开发了。
这一段落,我们会讲解一个最基础U SB框架的基础上,做两个小的US B驱动的例子。
USB骨架在Linux kernel源码目录中driver/usb/u sb-skeleton.c为我们提供了一个最基础的USB驱动程序。
我们称为USB骨架。
通过它我们仅需要修改极少的部分,就可以完成一个USB设备的驱动。
我们的US B驱动开发也是从她开始的。
那些linux下不支持的USB设备几乎都是生产厂商特定的产品。
如果生产厂商在他们的产品中使用自己定义的协议,他们就需要为此设备创建特定的驱动程序。
当然我们知道,有些生产厂商公开他们的USB协议,并帮助Linux驱动程序的开发,然而有些生产厂商却根本不公开他们的USB协议。
因为每一个不同的协议都会产生一个新的驱动程序,所以就有了这个通用的USB驱动骨架程序,它是以pci 骨架为模板的。
如果你准备写一个lin ux驱动程序,首先要熟悉USB协议规范。
USB主页上有它的帮助。
一些比较典型的驱动可以在上面发现,同时还介绍了USB urbs的概念,而这个是usb驱动程序中最基本的。
USB驱动程序的编写采用WDM驱动程序

U S B驱动程序的编写采用W D M驱动程序Document serial number【UU89WT-UU98YT-UU8CB-UUUT-UUT108】USB驱动程序的编写采用WDM 驱动程序。
WDM 驱动程序是一些例程的集合,它们被动地存在,等待主机系统软件(PnP 管理器、I/O 管理器、电源管理器等)来调用或激活它们。
具体驱动程序不同,其所包含的例程也不同。
一个WDM 驱动程序的基本组成包括以下5个例程:(1)驱动程序入口例程:处理驱动程序的初始化。
(2)即插即用例程:处理PnP 设备的添加、删除和停止。
(3)分发例程:处理用户应用程序发出的各种 I/O 请求。
(4)电源管理例程:处理电源管理请求。
(5)卸载例程:处理驱动程序的卸载。
包含文件:, ,, , , makefile,sources)在文件中,包含了上述五个例程:中定义了各种数据结构还有各种IOCTL控制码,用于不同数据的读写。
中实现了各种驱动例程。
包含了上述五个所说例程外还包含了其他例程,课程从下面的驱动程序入口例程得出一些信息。
驱动程序入口例程:NTSTATUSDriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath){NTSTATUS ntStatus = STATUS_SUCCESS;PDEVICE_OBJECT deviceObject = NULL;DriverObject->MajorFunction[IRP_MJ_CREATE] = Ezusb_Create; DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ezusb_Close; ources. If you want to add a new source # file to thiscomponent. This file merely indirects to the real make file # that is shared by all thedriver components of the Windows NT DDK # !INCLUDE $(NTMAKEENV) 不要编辑这个文件。
USB设备的驱动程序实现

USB设备的驱动程序实现
USB驱动是用来控制使用USB接口的设备的软件程序,其实现是将实
际的硬件设备抽象为虚拟的设备,使其能够在计算机操作系统上应用。
一
般来讲,当你将USB设备插入你的计算机时,它将通过计算机的USB主控
芯片找到USB设备,然后测试它的功能,并决定它是否能够被用来通信,
最后安装相应的驱动程序。
实际的USB驱动程序的实现有若干方法,其中
有两种常用的技术:应用程序编程接口(API)和驱动程序模板。
1、应用程序编程接口(API)
API是一组用于访问操作系统提供的服务和功能的特殊指令序列。
应
用程序编程接口(API)可以用来创建USB驱动程序,其实现包括以下步骤:
(1)定义硬件设备的描述
在编写USB驱动程序时,首先需要定义硬件设备,即定义设备的功能,记录其编号、最大支持通信速率、硬件连接方式、发送和接收设备数据的
方式以及支持的驱动软件要求等信息。
(2)实现设备驱动的关键函数
关键函数是控制USB设备正常工作所必需的函数,包括初始化函数、
发送和接收数据的函数、获取设备状态的函数以及关闭设备的函数等。
USB驱动程序编写

分类∙首页标签∙about love(8)∙recollect(6)∙Study DAY(17)∙FPGA(16)∙USB(3)∙VOIP(1)∙Linux(17)∙ C Language(25)日历<<< 2006 - 5 >>>日一二三四五六123456 78910111213 14151617181920 21222324252627 28293031登陆用户名:密码:记住密码登录用户注册忘记密码最新文章∙鬼故事下载∙鬼故事下载∙OS 推荐∙ARM的开发步骤∙s3c44b0x + uclinux∙74系列芯片资料∙集成电路应用索引∙密码学里的随机数发生器∙研究密码学的网站集锦∙10分钟完成一个USB驱动程序回复∙::签写留言::∙WISHBONE System-on站点统计∙日志总数:96∙评论数量:7∙留言数量:1∙访问次数:6461∙加为好友发送短信友情链接sunny sky with wind and rainWork Place10分钟完成一个USB驱动程序2006-5-16 9:45:0010分钟完成一个USB驱动程序很多写Windows Device Driver的开发人员基本上都是使用Windows DDK进行开发的。
但是,现在也有不少人都开始借助一些辅助工具。
笔者去年开始接触到riverStudio,发现它真的是一个不错的开发工具,不仅写代码的时候思路清晰,而且和DDK的结合很好。
当然,也有很多人觉得用DriverStudio不够正宗,或者说不能很好的理解Windows Device Driver的架构。
我感觉这就有点像MFC和SDK的关系,关于这个问题在很多地方都有争论,比如在万千新闻组上,就讨论了将近2个月。
每个人都有自己的最爱,都有自己的习惯,只要你能把事情做好,我想用什么方法应该都是一样的。
如果你已经习惯了用DDK开发,那完全还可以继续用下去;如果你觉得DriverStudio不错,那尝试用一个可以给你按照OOP概念来编程的工具有什么不好呢?在驱动开发网上,经常看到有人询问一些关于DriverStudio的使用的问题。
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个外设端口。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编写USB驱动程序步骤:
1所有usb驱动都必须创建主要结构体struct usb_driver
struct usb_driver
->struct module *owner
(有他可正确对该驱动程序引用计数,应为THIS_MODULE)
->const char *name
(驱动名字,运行时可在查看 /sys/bus/usb/drivers/)
->const struct usb_device_id *id_table
(包含该驱动可支持的所有不同类型的驱动设备,没添探测回调函数不会被调用)
->int (*probe)(struct usb_interface *intf,const struct usb_device_id *id)
(usb驱动探测函数,确认后struct usb_interface 应恰当初始化,然后返0,如果出错则返负值) ->void(*disconnect)(struct usb_interface *intf)
(当struct usb_interface 被从系统中移除或驱动正从usb核心中卸载时,usb核心将调用此函数)代码实例:
static struct usb_driver skel_driver={
.owner = THIS_MODULE,
.name = "skeleton",
.id_table = skel_table,
.probe = skel_probe,
.disconnect = skel_disconnect,
};
↓
2usb_register()注册将struct usb_driver 注册到usb核心,传统是在usb驱动程序模块初始化代码中完成该工作的
static int __init usb_skel_init(void)
{
...
usb_register(&skel_driver);
...
}
↓
3struct usb_device_id usb核心用该表判断哪个设备该使用哪个驱动程序,热插拔脚本使用它来确定当一个特定的设备插入到系统时该自动装载哪个驱动程序。
->__u16 match_flags(确定设备和结构体中下列字段中哪一个相匹配)
->__u16 idVendor(设备的usb制造商id)
->__u16 idProduct(设备的usb产品id)
↓
4USB骨架程序的关键几点如下:
1. USB驱动的注册和注销
Usb驱动程序在注册时会发送一个命令给usb_register,通常在驱动程序的初始化函数里。
当要从系统卸载驱动程序时,需要注销usb子系统。
即需要usb_unregister 函数处理。
2 当usb设备插入时,为了使linux-hotplug(Linux中PCI、USB等设备热插拔支持)系统自动装载驱动程序,你需要创建一个MODULE_DEVICE_TABLE。
代码如下(这个模块仅支持某一特定设备): static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* Terminating entry */};
MODULE_DEVICE_TABLE (usb, skel_table);
USB_DEVICE宏利用厂商ID和产品ID为我们提供了一个设备的唯一标识。
当系统插入一个ID匹配的USB设备到USB总线时,驱动会在USB core中注册。
驱动程序中probe 函数也就会被调用。
usb_device 结构指针、接口号和接口ID都会被传递到函数中。
3 static void * skel_probe(struct usb_device *dev,unsigned int ifnum, const struct
usb_device_id *id)
驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个NULL值。
否则返回一个含有设备驱动程序状态的指针。
通过这个指针,就可以访问所有结构中的回调函数。
4 在骨架驱动程序里,最后一点是我们要注册devfs。
我们创建一个缓冲用来保存那些被发送给usb 设备的数据和那些从设备上接受的数据,同时USB urb 被初始化,并且我们在devfs子系统中注册设备,允许devfs用户访问我们的设备。
注册过程如下:
/* initialize the devfs node for this device and register it */sprintf(name, "skel%d", skel->;minor);
skel->devfs = devfs_register (usb_devfs_handle, name,DEVFS_FL_DEFAULT,
USB_MAJOR,USB_SKEL_MINOR_BASE + skel->minor,
S_IFCHR | S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP | S_IROTH, &skel_fops, NULL);
如果devfs_register函数失败,不用担心,devfs子系统会将此情况报告给用户。
当然最后,如果设备从usb总线拔掉,设备指针会调用disconnect 函数。
驱动程序就需要清除那些被分配了的所有私有数据、关闭urbs,并且从devfs上注销调自己。
/* remove our devfs node */devfs_unregister(skel->;devfs);
↓
5其他
1 struct usb_host_endpoint(描述usb端点)
→(包含) struct usb_endpoint_descriptor(含真正端点信息,数据格式,是真正驱动关心的字段)
端点描述符:
bEndpointAddress = 81(in)(第8位为1是输入设备)(usb的端点地址,包含端点方向)
bmAttibutes = 03(interrupt)(端点类型,为中断传输)
wMaxPacketSize = 0008(每次传8个字节)(端点每次可处理最大字节长度)
bInterval = 08(8ms)(如端点为中断,该值为轮询间隔)
2 usb端点捆绑为接口,usb接口只处理一种usb逻辑连接,如鼠标键盘等.
一个usb设备可有多接口,usb扬声器:一个usb键盘用于按键,一个usb音频流,则需两个不同的驱动程序。
usb驱动通常将struct usb_interface 转成 struct usb_device 用函数 interface_to_usbdev 转
3 struct usb_interface 描述usb接口
→struct usb_host_interface * altsetting(接口结构体数组,包含所有可能用于该接口的可选设置)
→struct usb_host_endpoint
→unsigned num_a ltsetting(可选设置的数量)
→struct usb_host_interface * cur_altsetting(接口当前活动设置)
→int minor(usb核心分配给接口的次设备号,成功调用usb_register_dev有效)
4 usb设备非常复杂,由许多不同逻辑单元组成,简单关系如下:
设备通常有一个以上的配置
配置经常有一个以上接口
接口通常有一个以上设置
接口通常有一个以上端点
设备描述-》配置描述-》接口描述-》端点描述
5 usb sysfs设备命名方案
根集线器-集线器端口号:配置。
接口
对于usb hub树中层次更高的字树命名方案
根集线器-集线器端口号-集线器端口号:配置。
接口
6 linux内核的代码通过一个成为urb(usb请求块)和所有usb设备通信. 用struct urb描述(include/linux/usb.h中定义)
->urb用异步同usb设备特定usb端点发送/接收数据,使用类似网络代码中的struct skbuff
-> urb 被动态创建,随时可被驱动程序或usb核心取消,内部有引用计数,可被多次调用,使他们可在最后一个使用者释放他们时自动地销毁
-> urb使得流处理或其他复杂的重叠的通信成为可能,获得高数据传输速度。
->usb_alloc_urb() 创建urb包 usb_free_urb() 释放urb包
->usb_fill_int_urb()正确初始化将发送到usb设备的中断端点urb
usb_fill_bulk_urb() .. .. .. ... 批量传输端点urb
usb_fill_control_urb() .. .. .. ... 控制端点urb
等时urb在提交给核心时必须手动初始化(很不幸,没函数)
->usb_submit_urb()urb被usb驱动正确创建和初始化后,就可提交到usb核心,发送到usb设备上了,如果调用成功,函数返0,urb控制权转给usb核心
->usb_kill_urb() or usb_unlink_urb()取消已经被提交给核心的urb。