在Linux 内核中,使用usb_driver 结构体描述一个USB 设备驱动,usb_driver 结构体的定义如代码清单20.11 所示。
代码清单20.11 usb_driver 结构体

struct usb_driver {
const char *name; /* 驱动名称 */
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id); /*探测函数*/
void (*disconnect) (struct usb_interface *intf); /*断开函数*/
int (*ioctl) (struct usb_interface *intf, unsigned int code,
void *buf); /* I/O 控制函数 */
int (*suspend) (struct usb_interface *intf, pm_message_t message);/*挂起函数*/
int (*resume) (struct usb_interface *intf); /* 恢复函数 */
int (*reset_resume)(struct usb_interface *intf);
void (*pre_reset) (struct usb_interface *intf);
void (*post_reset) (struct usb_interface *intf);
const struct usb_device_id *id_table;/* usb_device_id 表指针 */
struct usb_dynids dynids;
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
unsigned int soft_unbind:1;
};

  

在编写新的USB 设备驱动时,主要应该完成的工作是probe()和disconnect()函数,即探测和断开函数,它们分别在设备被插入和拔出的时候被调用,用于初始化和释放软硬件资源。对usb_driver 的注册和注销通过这两个函数完成:
int usb_register(struct usb_driver *new_driver)
void usb_deregister(struct usb_driver *driver);
usb_driver 结构体中的id_table 成员描述了这个USB 驱动所支持的USB 设备列表,它指向一个usb_device_id 数组,usb_device_id 结构体用于包含USB 设备的制造商ID、产品ID、产品版本、设备类、接口类等信息及其要匹配标志成员match_flags(标明要与哪些成员匹配,包含DEV_LO、DEV_HI、DEV_CLASS、DEV_SUBCLASS、DEV_PROTOCOL、INT_CLASS、INT_SUBCLASS、INT_PROTOCOL)。可以借助下面一组宏来生成usb_device_id 结构体的实例:
USB_DEVICE(vendor, product)
该宏根据制造商ID 和产品ID 生成一个usb_device_id 结构体的实例,在数组中增加该元素将意味着该驱动可支持匹配制造商ID、产品ID 的设备。
USB_DEVICE_VER(vendor, product, lo, hi)
该宏根据制造商ID、产品ID、产品版本的最小值和最大值生成一个usb_device_id 结构体的实例,在数组中增加该元素将意味着该驱动可支持匹配制造商ID、产品ID 和lo~hi 范围内版本的设备。
USB_DEVICE_INFO(class, subclass, protocol)
该宏用于创建一个匹配设备指定类型的usb_device_id 结构体实例。
USB_INTERFACE_INFO(class, subclass, protocol)
该宏用于创建一个匹配接口指定类型的usb_device_id 结构体实例。

当USB 核心检测到某个设备的属性和某个驱动程序的usb_device_id 结构体所携带的信息一致时,这个驱动程序的probe()函数就被执行。拔掉设备或者卸掉驱动模块后,USB 核心就执行disconnect()函数来响应这个动作。

上述usb_driver 结构体中的函数是USB 设备驱动中USB 相关的部分,而USB 只是一个总线,真正的USB 设备驱动的主体工作仍然是USB 设备本身所属类型的驱动,如字符设备、tty 设备、块设备、输入设备等。因此USB 设备驱动包含其作为总线上挂在设备的驱动和本身所属设备类型的驱动两部分。

与platform_driver 类似,usb_driver 起到了“牵线”的作用,即在probe()里注册相应的字符、tty 等设备,在disconnect()注销相应的字符、tty 等设备,而原先对设备的注册和注销一般直接发生在模块加载和卸载函数中。
尽管USB 本身所属设备驱动的结构与其不挂在USB 总线上时完全相同,但是在访问方式上却发生了很大的变化,例如,对于USB 接口的字符设备而言,尽管仍然是write()、read()、ioctl()这些函数,但是在这些函数中,贯穿始终的是称为URB 的USB 请求块。
如图20.4 所示,在这棵树里,我们把树根比作主机控制器,树叶比作具体的USB 设备,树干和树枝就是USB 总线。树叶本身与树枝通过usb_driver 连接,而树叶本身的驱动(读写、控制)则需要通过其树叶设备本身所属类设备驱动来完成。树根和树叶之间的“通信”依靠在树干和树枝里“流淌”的URB 来完成。

由此可见,usb_driver 本身只是起到了找到USB 设备、管理USB 设备连接和断开的作用,也就是说,它是公司入口处的“打卡机”,可以获得员工(USB 设备)的上/下班情况。树叶和员工一样,可以是研发工程师也可以是销售工程师,而作为USB 设备的树叶可以是字符树叶、网络树叶或块树叶,因此必须实现相应设备类的驱动。

USB设备驱动的更多相关文章

  1. usb设备驱动描述,王明学learn

    usb设备驱动 本章主要内容包含以下:USB总线介绍,USB协议分析,USB系统架构 一.USB总线介绍 1.1USB发展史 USB(Universal Serial Bus)通用串行总线,是一种外部 ...

  2. USB设备驱动概述

    USB设备驱动 ·  )USB Hub:每个USBHost控制器都会自带一个USB Hub,被称为根(Root)Hub.这个根Hub可以接子(Sub)Hub,每个Hub上挂载USB设备.一般PC有8个 ...

  3. Linux下 USB设备驱动分析(原创)

    之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...

  4. Linux下usb设备驱动详解

    USB驱动分为两块,一块是USB的bus驱动,这个东西,Linux内核已经做好了,我们可以不管,我们只需要了解它的功能.形象的说,USB的bus驱动相当于铺出一条路来,让所有的信息都可以通过这条USB ...

  5. Linux USB驱动学习总结(二)---- USB设备驱动

    USB 设备驱动: 一.USB 描述符:(存在于USB 的E2PROM里面) 1.  设备描述符:struct usb_device_descriptor 2.  配置描述符:struct usb_c ...

  6. 嵌入式Linux驱动学习之路(二十)USB设备驱动

    USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...

  7. Linux usb子系统(二):USB设备驱动usb-skeleton.c

    usb驱动分为通过usbfs操作设备的用户空间驱动,内核空间的内核驱动.两者不能同时进行,否则容易引发对共享资源访问的问题,死锁!使用了内核驱动,就不能在usbfs里驱动该设备. 下面转载的一篇分析u ...

  8. USB2.0学习笔记连载(九):USB设备驱动的安装

    在第一次插入USB设备时(笔者用的是自己做的USB最小系统来测试),插入电脑后,在设备管理器中会显示 未知设备,如下图所示: 点击右键,选择属性,在详细信息中可以看到硬件ID以及PID等,如下图所示. ...

  9. USB设备驱动_WDS

    1. usb_alloc_dev中的 bus_type 中指定了匹配函数,和uevent中的环境参数. ====>不同的bus_type的匹配函数可能是不同的,uevent的环境变量参数也可能是 ...

随机推荐

  1. python3 AttributeError: 'NoneType' object has no attribute 'split'

    from wsgiref.simple_server import make_server def RunServer(environ, start_response): start_response ...

  2. 在页面中使用Eval的两种方案

    ①直接取<%#Eval("name")%> ②进行运算<%#Convert.ToInt32(Eval("count"))-(Eval(&quo ...

  3. php操作mysql的基础链接实例

  4. "开发路上踩过的坑要一个个填起来————持续更新······(7月30日)"

    欢迎转载,请注明出处! https://gii16.github.io/learnmore/2016/07/29/problem.html 踩过的坑及解决方案记录在此篇博文中! 个人理解,如有偏颇,欢 ...

  5. 剖析Disruptor:为什么会这么快?(二)神奇的缓存行填充

    原文链接:http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-why-its-so-fast_22.html 需FQ 计算机入门   ...

  6. nginx 配置.json文件直接访问

    不要弹出下载 配置nginx.conf http { include mime.types; default_type application/json;

  7. def

    a = 97,A = 65,z = 122,Z = 90 小写字母比大写字母整形数值高,upper->lower相差32 把小写字母转化成大写字母,将小写字母 - 32 1. typedef 数 ...

  8. Linux下的多进程编程

    1.进程 1.1进程的定义 <计算机操作系统>这门课对进程有这样的描述:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统 ...

  9. C#中string类型前加@标志的作用

    转自:http://stackoverflow.com/questions/4879152/c-sharp-before-a-string   (stackoverflow) string字符串前加@ ...

  10. 对js闭包的粗浅理解

    只能是粗浅的,毕竟js用法太灵活. 首先抛概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制.这样写鬼能看懂. 所以要大致搞清三个东西:函数对象(funct ...