本文转载自:http://www.360doc.com/content/12/0504/19/8363527_208666082.shtml

编写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_altsetting(可选设置的数量)
   →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

USB驱动开发大全【转】的更多相关文章

  1. HarmonyOS USB DDK助你轻松实现USB驱动开发

    HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...

  2. usb驱动开发1之学习准备

    此系列是http://blog.csdn.net/fudan_abc/博文的整理,同时加入了自己的理解.很敬佩fudan_abc的文章,仔细学习和分析受益很多.注:fundan_abc所分析linux ...

  3. 庖丁解牛:USB 驱动开发技术彻底解密

    我们知道如果开发工程师不懂RS232 肯定会让人笑话可以想象面向未来USB 接口无处不在因此掌握USB 的原理固件编程及其驱动开发技术势必成为当务之急USB 即插即用的优点和灵活性运用于各种电子产品现 ...

  4. 转: 嵌入式linux下usb驱动开发方法--看完少走弯路【转】

    转自:http://blog.csdn.net/jimmy_1986/article/details/5838297 嵌入式linux下的usb属于所有驱动中相当复杂的一个子系统,要想将她彻底征服,至 ...

  5. usb驱动开发24之接口驱动

    从第一节我们已经知道,usb_generic_driver在自己的生命线里,以一己之力将设备的各个接口送给了linux的设备模型,让usb总线的match函数,也就是usb_device_match, ...

  6. usb驱动开发15之设备生命线

    总算是进入了HCD的片儿区,既然来到一个片区,怎么都要去拜会一下山头几个大哥吧.,先回忆一些我们怎么到这里的?给你列举一个调用函数过程usb_control_msg->usb_internal_ ...

  7. usb驱动开发14之设备生命线

    直接看代码吧. /*-------------------------------------------------------------------*/ /** * usb_submit_urb ...

  8. usb驱动开发12之设备生命线

    函数usb_control_msg完成一些初始化后调用了usb_internal_control_msg之后就free urb.剩下的活,全部留给usb_internal_control_msg去做了 ...

  9. usb驱动开发10之usb_device_match

    在第五节我们说过会专门分析函数usb_device_match,以体现模型的重要性.同时,我们还是要守信用的. 再贴一遍代码,看代码就要不厌其烦. static int usb_device_matc ...

随机推荐

  1. viewport

    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale= ...

  2. 关于string.format() 转

    string.format()函数用来生成具有特定格式的字符串,这个函数有两个参数,第一个参数为格式化串:由指示符和控制格式的字符组成.第二个参数是对应格式中每个代号的各种数据. 格式字符串可能包含以 ...

  3. PHP 模拟 HTTP 基本认证(Basic Authentication)

    当某个页面需要认证才能进行访问时,接到请求后服务器端会在响应头中发送一个 WWW-Authenticate 首部(用来标识认证安全域),语法为 WWW-Authenticate:Basic relam ...

  4. 几何服务,cut功能测试

    关于几何服务 几何服务用于辅助应用程序执行各种几何计算,如缓冲区.简化.面积和长度计算以及投影.在 ArcGIS Server 管理器中启动几何服务之后,您才能够在应用程序开发过程中使用该服务. 问题 ...

  5. linux 路由

  6. vert.x学习(三),Web开发之Thymeleaf模板的使用

    在vert.x中使用Thymeleaf模板,需要引入vertx-web-templ-thymeleaf依赖.pom.xml文件如下 <?xml version="1.0" e ...

  7. C++ 从一组数据中按概率选择一个

    #include <stdio.h> #include <stdint.h> #include <ctime> #include <vector> #i ...

  8. JQ first-child与:first的区别以及nth-child(index)与eq(index)的区别

    1.first-child和:first区别 first-child  是指选取每个父元素的第一个子元素 如$("div:first-child")指每个父级里的第一个div孩子 ...

  9. android获取textview的行数

    最近项目需求,需要获取Textview的行数,通过行数与TextView的maxLines进行比较来确定是否显示TextView下方的展开按钮是否显示,废话少说直接上代码,mTextView.getL ...

  10. scp使用

    从82服务器复制文件 scp -P 50028 -r root@***.**.**.82:/data/upload.tar / -P:指定非ftp22端口