本文转载自: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. 【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-2 工程及程序构架介绍

    视频简介: 该视频介绍iCore3应用开发平台出厂源代码中ARM部分程序构架. 源视频包下载地址: http://pan.baidu.com/s/1jHGnc7k   银杏科技优酷视频发布区: htt ...

  2. 2016 年 50 个最佳的轻量级 JavaScript 框架和库

    作者:IT程序狮链接:https://zhuanlan.zhihu.com/p/24598210来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 回顾今年已发布的 JS ...

  3. Struts2 OGNL 自动转换Date类型的一些注意事项

    Strut2 有比较完善的使用OGNL的jsp标签自动转化为对应的后台对象的功能. 这里java.util.Date的自动转化有一些需要注意的地方(局部转换): 1.必须要在struts的xml文件中 ...

  4. div span

    无牵无挂,不带任何样式,因此经常使用div完成整体样式的构建,span完成细微样式的构建. div为块级元素,span为行内元素. 使用div完成显示区域的居中.左右浮动等,完成整体的样式布局,然后在 ...

  5. JQuery中的DOM操作

    JQuery中有很多DOM操作,但是因为之前没有总结过,所以用来用去都是那几个,一写html中的表单交互,尤其是那些复杂的表单交互,就是一大坨的js,我自己看着都费劲. 所以我感觉有必要总结一下 &l ...

  6. visual studio2015使用git管理源代码

    1.注册https://git.oschina.net/ 2.注册好后,创建一个测试项目,如下图: 点击创建,如下: 上面的红框中的地址下面会用到. 3.git初始化设置 在本地电脑要安装git,打开 ...

  7. [SharePoint 2013] Create event receiver for external list

    Main list for creating event receiver for external list Subscribe   storage, it could be data table ...

  8. logstash插件

    codec 插件   goeip插件 input { file { path => ["/data/nginx/logs/access.log"] type =>&qu ...

  9. Prototype based langue LUA

    Prototype-based programming https://en.wikipedia.org/wiki/Prototype-based_programming Prototype-base ...

  10. lua拾遗之lua中冒号(:)与点号(.)的区别和来由

    参考资料 1.https://my.oschina.net/lonewolf/blog/173065 其结论为: 1.定义的时候:Class:test()与 Class.test(self)是等价的, ...