USB设备驱动
在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设备驱动的更多相关文章
- usb设备驱动描述,王明学learn
usb设备驱动 本章主要内容包含以下:USB总线介绍,USB协议分析,USB系统架构 一.USB总线介绍 1.1USB发展史 USB(Universal Serial Bus)通用串行总线,是一种外部 ...
- USB设备驱动概述
USB设备驱动 · )USB Hub:每个USBHost控制器都会自带一个USB Hub,被称为根(Root)Hub.这个根Hub可以接子(Sub)Hub,每个Hub上挂载USB设备.一般PC有8个 ...
- Linux下 USB设备驱动分析(原创)
之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...
- Linux下usb设备驱动详解
USB驱动分为两块,一块是USB的bus驱动,这个东西,Linux内核已经做好了,我们可以不管,我们只需要了解它的功能.形象的说,USB的bus驱动相当于铺出一条路来,让所有的信息都可以通过这条USB ...
- Linux USB驱动学习总结(二)---- USB设备驱动
USB 设备驱动: 一.USB 描述符:(存在于USB 的E2PROM里面) 1. 设备描述符:struct usb_device_descriptor 2. 配置描述符:struct usb_c ...
- 嵌入式Linux驱动学习之路(二十)USB设备驱动
USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...
- Linux usb子系统(二):USB设备驱动usb-skeleton.c
usb驱动分为通过usbfs操作设备的用户空间驱动,内核空间的内核驱动.两者不能同时进行,否则容易引发对共享资源访问的问题,死锁!使用了内核驱动,就不能在usbfs里驱动该设备. 下面转载的一篇分析u ...
- USB2.0学习笔记连载(九):USB设备驱动的安装
在第一次插入USB设备时(笔者用的是自己做的USB最小系统来测试),插入电脑后,在设备管理器中会显示 未知设备,如下图所示: 点击右键,选择属性,在详细信息中可以看到硬件ID以及PID等,如下图所示. ...
- USB设备驱动_WDS
1. usb_alloc_dev中的 bus_type 中指定了匹配函数,和uevent中的环境参数. ====>不同的bus_type的匹配函数可能是不同的,uevent的环境变量参数也可能是 ...
随机推荐
- GroupId和ArtifactId
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency> ...
- nearly,about,almost的区别
nearly 几乎,将近almost 几乎,差一点儿就,差不多(与动词,副词,形容词以及名词连用时,可与nearly通用;与no,none,nothing,never等否定式连用时,不可与nearly ...
- Oracle 自定义函数Function
示例代码: CREATE OR REPLACE FUNCTION "MY_DATABASE"."F_GET_USER_COUNT_BY_DEPART" ( D ...
- 动态链接库(dll) __declspec(dllimport) __declspec(dllexport)
一. __declspec(dllexport) Microsoft 在 Visual C++ 的 16 位编译器版本中引入了 __export,使编译器得以自动生成导出名并将它们放到一个 .lib ...
- 【drp 11】使用Junit简单测试接口方法
一.Junit简介 JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个. JUn ...
- docker学习(二)
1 镜像 docker使用联合加载技术,一次同时加载多个文件系统,在外面只能看到一个文件系统 docker使用写时复制,每个只读镜像层都是只读的,也永远不会发生变化,建立一个新容器,会构建一个镜像栈, ...
- gulp.spritesmith修改px为rem单位
移动端开发中,使用gulp.spritesmith进行小图sprite并生成样式,但由于spritesmith默认是以px为单位,所以就把插件的内容修改了下让生成rem单位并且能把background ...
- ORA-00031: session marked for kill 处理Oracle中杀不掉的锁
一些ORACLE中的进程被杀掉后,状态被置为"killed",但是锁定的资源很长时间不释放,有时实在没办法,只好重启数据库.现在提供一种方法解决这种问题,那就是在ORACLE中杀不 ...
- 新手浅谈C#关于abstract和interface
abstract:抽象类,是对某一类对象的抽象,继承抽象类的类和抽象类是属于关系 interface:接口,可以说是一种规范,继承接口的类表达则是,我继承了这个接口,我能做什么 举个常用的例子:抽象一 ...
- Splash Screen开场屏在Android中的实现
很多网友可能发现近期Tencent推出的手机QQ Android版包含了一个开场屏Splash Screen载入效果,通常游戏或大型软件打开时可能需要一个释放解析资源的过程,需要一个前台的动画播放和后 ...