Linux下USB子系统软件结构为

USB

内核(USB驱动,USBD

)处于系统的中心,对于它进行研究是能够进行USB驱动开发(包括客户驱动和主机驱动)的第一步。它为客户端驱动和主机控制器驱动提供了主要数据结构和接

口函数,主要有四类功能:客户端驱动管理,USB设备的配置和管理,主机控制器的管理,协议控制命令集和数据传输的管理。具体代码主要集中在

linux/drivers/usb下的usb.c, usb.h中

主要数据结构分析

主要有四个数据结构,分别是USB设备usb_device,保存了一个USB设备的信息,包括设备地址,设备描述符,配置描述符,等等

USB总线系统usb_bus,保存了一个USB总线系统的信息,包括总线上设备地址信息,根集线器,带宽使用情况等。一个USB总线系统肯定有一个主机控制器和一个根集线器。Linux支持多USB总线系统

客户端驱动程序usb_driver,保存了客户驱动信息,包括驱动名称,以及驱动提供给USB内核使用的函数指针等

(USB Request Block)urb,是进行USB通信的数据结构。Linux的USB子系统只使用这么一种数据结构来进行USB通信,urb包含了建立任何 USB传输所需的所有信息,并贯穿于USB协议栈对数据处理的整个过程。

下面是对各部分进行详细分析。

struct usb_device{            //代表一个USB设备

int devnum;              //分配的设备地址,1-127

enum {

USB_SPEED_UNKNOWN = 0,               /* enumerating */

USB_SPEED_LOW, USB_SPEED_FULL,              /* usb 1.1 */

USB_SPEED_HIGH                       /* usb 2.0 */

} speed;                       //设备速度,低速/全速/高速

struct usb_device *tt;              /* usb1.1 device on usb2.0 bus */,事务处理解释器

int ttport;               /* device/hub port on that tt */设备所连接的具有事务处理解释器功能的集线器端口

atomic_t refcnt;            /* Reference count */引用计数

struct semaphore serialize; //用于同步

unsigned int toggle[2];              /* one bit for each endpoint ([0]

= IN, [1] = OUT) */用于同步切换的位图,每个端点占用1位,[0]表示输入,[1]输出

unsigned

int halted[2];        /* endpoint halts; one bit per endpoint # &

direction;  [0] = IN, [1] = OUT */表示端点是否处于停止状态的位图

int epmaxpacketin[16];          /* INput endpoint specific maximums */输入端点的最大包长

int epmaxpacketout[16];              /* OUTput endpoint specific maximums */输出端点的最大包长

struct usb_device *parent;   //表示设备所连的上游集线器指针

struct usb_bus *bus;        /* Bus we‘re part of */设备所属的USB总线系统

struct usb_device_descriptor descriptor;/* Descriptor */ 设备描述符

struct usb_config_descriptor *config; /* All of the configs */指向设备的配置描述符和其所包含的接口描述符,端点描述符的指针

struct usb_config_descriptor *actconfig;/* the active configuration */当前的配置描述符指针

char **rawdescriptors;            /* Raw descriptors for each config */

int have_langid;           /* whether string_langid is valid yet *// 是否有string_langid

int string_langid;         /* language ID for strings */和字符描述符相关的语言ID

void *hcpriv;                /* Host Controller private data */设备在HCD层占用的资源指针,对USB内核层是透明的

/* usbdevfs inode list */ 设备在usbdevfs中的inode列表

struct list_head inodes;

struct list_head filelist;

/*

* Child devices - these can be either new devices

* (if this is a hub device), or different instances

* of this same device.

*

* Each instance needs its own set of data structures.

*/只对当前设备是集线器的情况有效

int maxchild;                     /* Number of ports if hub */ hub的下游端口数

struct usb_device *children[USB_MAXCHILDREN]; hub所连设备指针

};

struct usb_bus { //USB总线系统

int busnum;                     /* Bus number (in order of reg) */当前总线系统的序列号,Linux支持多总线系统并为它们编号

#ifdef DEVNUM_ROUND_ROBIN

int devnum_next;     /* Next open device number in round-robin allocation */

#endif /* DEVNUM_ROUND_ROBIN */给连接到子系统上的设备分配设备号的数据结构

struct usb_devmap devmap;       /* Device map */给连接到子系统上的设备分配设备号的数据结构

struct usb_operations *op;      /* Operations (specific to the HC) */HCD为USB内核提供的一系统函数集指针

struct usb_device *root_hub;    /* Root hub */指向根Hub的指针

struct list_head bus_list;       双向链表指针,USB内核用一个双向链表来维护系统中所有USB总线系统

void *hcpriv; /* Host Controller private data */与主机控制器相关数据,对USB内核层是透明

int bandwidth_allocated;       /* on this Host Controller; applies to

Int. and Isoc. pipes; measured in microseconds/frame; range is 0..900,

where 900 = 90% of a 1-millisecond frame

*/当前子系统的带宽使用情况,单位是毫秒/帧,取值范围[0,900]

int bandwidth_int_reqs;        /* number of Interrupt requesters */子系统中当前的中断传输的数量

int bandwidth_isoc_reqs;       /* number of Isoc. requesters */子系统中当前的实时传输的数量

/* usbdevfs inode list */ 在usbdevfs中的inode列表       struct list_head inodes;

atomic_t refcnt;

};

struct usb_driver { //客户端驱动程序为USB内核提供的调用接口

const char *name;    //客户端驱动程序的字符串名称,用于避免重复安装和卸载

void *(*probe)(//给USB内核提供的函数,用于判断驱动程序是否能对设备的某个接口进行驱动,如能则分配资源

struct usb_device *dev,              /* the device */

unsigned intf,                /* what interface */

const struct usb_device_id *id   /* from id_table */

);

void (*disconnect)(struct usb_device *, void *);//给USB内核提供的函数,用于释放设备的某个接口所占用的资源

struct list_head driver_list;//对应的双向指针,USB内核通过一个双向指针链表维护USB子系统中所用的客户端驱动程序

struct file_operations *fops;

int minor; 驱动的次版本号

struct semaphore serialize;

/* ioctl -- userspace apps can talk to drivers through usbdevfs */

int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);

/* support for "new-style" USB hotplugging

* binding policy can be driven from user mode too

*/

const struct usb_device_id *id_table;

/* suspend before the bus suspends;

* disconnect or resume when the bus resumes */

// void (*suspend)(struct usb_device *dev);

// void (*resume)(struct usb_device *dev);

};

typedef structurb//USB Request Block,包含了建立任何 USB传输所需的所有信息,并贯穿于USB协议栈对数据处理的整个过程

{

spinlock_t lock;              // lock for the URB

void *hcpriv;                // private data for host controller与主机控制器相关数据,对USB内核层是透明

struct list_head urb_list;       // list pointer to all active urbs双向指针,用于将此URB连接到处于活动的URB双向链表中

struct urb *next;            // pointer to next URB 指向下一个URB的指针

struct usb_device *dev;       // pointer to associated USB device 接受此URB的USB设备指针

unsigned int pipe;// pipe information表示设备的某个端点和客户端驱动程序之间的管道

int status;                     // returned status 返回状态

unsigned int transfer_flags;       // USB_DISABLE_SPD | USB_ISO_ASAP | etc.

USB_DISABLE_SPD   //拒绝短数据包,即比最大传输包长度小的数据包

USB_ISO_ASAP     //用于实时传输,告诉主机控制器立即进行此请求的数据传输。如果没有置位,则需要给start_frame赋值,用来通知主机控制器该在哪个帧上开始此请求的数据传输

USB_ASYNC_UNLINK  //告诉USBD采用异步方式取消请求

USB_QUEUE_BULK    //表示批量请求可以排队,一般一个设备的批量请求端点只有一个URB

USB_NO_FSBR       //表示全速传输站用的带宽不要回收

USB_ZERO_PACKET //表示批量传输的数据长度等于端点的包最大长度时,主机控制器在发送完数据后,再发送一个零长度的包表示数据结束

USB_TIMEOUT_KILLED //本位只被HCD设置,表示发生了超时。客户驱动可以给URB的处理设置一个超时时间,如果处理超时,则要求USBD结束对此URB的处理,URB的返回信息中会反映该此状态。

void *transfer_buffer;            // associated data buffer传输数据缓存区指针,接收或发送设备的数据,它必须是物理连续的,不可换页的内存块,用kmalloc(,GFP_KERNEL)分配

int transfer_buffer_length;     // data buffer length缓存区长度

int actual_length;      // actual data buffer length 实际数据长度

int bandwidth;                   // bandwidth for this transfer request (INT or ISO) 此请求每次占用一帧的带宽,只适用实时/中断传输

unsigned char *setup_packet;       // setup packet (control only) 用于指向控制传输中控制命令的指针,只适用控制传输

int start_frame;    // start frame (iso/irq

only)此请求所开始传输的帧号,只适用实时/中断传输。中断传输时,表示返回启动此请求的第一次中断传输的帧号。实时传输时,指明处理第一个实时请求

数据报包的帧号,如果设置了USB_ISO_ASAP,此变量表示返回启动第一次实时传输的帧号。

int number_of_packets;  // number of packets in this request (iso)此请求所包含的数据包数,只适合实时传输

int interval; // polling interval (irq only) 中断传输的周期,1〈= interval〈=255

int error_count;   // number of errors in this transfer (iso only)发生传输错误次数的累加值,只适用实时传输

int timeout;       // timeout (in jiffies)

void *context;               // context for completion routine回调函数中的参数

usb_complete_t complete;       // pointer to completion routine 指向回调函数的指针。当数据传输完成后,主机控制器驱动会回调该函数。

iso_packet_descriptor_t iso_frame_desc[0]; 要进行实时传输的结构数组,每个结构表示一次数据传输

} urb_t, *purb_t;

usb linux 内核,Linux下USB内核之学习笔记相关推荐

  1. windows下32位汇编语言学习笔记

    windows下32位汇编语言学习笔记 第一章  第一章 背景知识 80x86处理器的存储器 4个数据寄存器 EAX,EBX,ECX,EDX EAX寄存器 所有API函数的返回值都保存在EAX里,注意 ...

  2. ctf线下AWD攻防赛学习笔记

    Hello,我是普通Gopher,00后男孩,极致的共享主义者,想要成为一个终身学习者.专注于做最通俗易懂的计算机基础知识类公众号.每天推送Golang技术干货,内容起于K8S而不止于K8S,涉及Do ...

  3. algorithm头文件下的常用函数-学习笔记

    algorithm头文件下的常用函数-学习笔记 max(x,y),min(x,y),abs(x) swap(x,y) reverse(it,it2) next_permutation() fill( ...

  4. Linux下进程通信知识点学习笔记(一)

    4种主要事件导致进程创建: 系统的初始化: 执行了正在运行的进程所调用的进程创建系统调用: 用户请求创建一个进程: 一个批处理作业的初始化: 进程的终止: 正常退出: 出错退: 严重错误: 被其他进程 ...

  5. openni linux arm,Ubuntu下安装配置OpenNI实战笔记

    1. 库OpenNI SensorKinect NITE的安装 (1)OpenNI step1 :下载 OpenNI库文件 选择"OpenNI Binaries"->&quo ...

  6. 黑马程序员新版Linux零基础快速入门到精通——学习笔记

    01初识Linux 1.1.操作系统概述 1.1.1.硬件和软件 我们所熟知的计算机是由硬件和软件组成的. 硬件: 计算机系统中由电子.机械和光电元件等组成的各种物理装置的总称. ​ (看的见.摸得着 ...

  7. linux基础的一些常见问题总结_学习笔记

    平时自己的总结(miscellaneous) oracle无法实现远程用户连接:   解决办法:        #sqlplus /nolog     SQL> connect / as sys ...

  8. 《Linux设备驱动开发详解》学习笔记一

    Linux设备驱动开发详解学习笔记<一> 书名:<Linux设备驱动开发详解>第二版 主机环境:Linux version 2.6.25-14.fc9.i686@Fedora ...

  9. linux数据库创建score表,MySQL数据库学习笔记

    MySQL数据库学习笔记phpma (实验环境:Redhat9.0,MySQL3.23.54) 纲要: 一,连接MySQL phpma 二,MySQL管理与授权 三,数据库简单操作 四, 数据库备份 ...

  10. linux编程 —— vscode 开发编译 CMakeList.txt 学习笔记

    文档声明: 以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正.并且该文档在后期会随着学习的深入不断补充完善.感谢各位的参考查看. 笔记资料仅供学习交流使用,转载请标明出处 ...

最新文章

  1. 这老哥把GPU当暖气用,省钱了!
  2. 英特尔高管晒照片不小心泄密,正在研发的雷电5就这样暴露了
  3. das服务器未响应是怎么回事,google-chrome - WSO2 Data Analytics Server-Analytics仪表板视图功能未响应任何浏览器 - 堆栈内存溢出...
  4. python里面temp是啥-请问Python里temp是什么意思?
  5. python之父叫什么-Python之父谈Python的未来形式
  6. bzoj 4832 抵制克苏恩
  7. 匿名函数、普通函数、箭头函数作用域
  8. excel2010冻结行列
  9. [渝粤教育] 广东-国家-开放大学 21秋期末考试管理会计10171k2
  10. OJ1073: 级数求和(C语言)
  11. git linux 部署网站,centos 搭建git自动部署web应用
  12. sql 2008 清空数据库日志
  13. JSK-15 单独的数字【位运算】
  14. 如何在 Mac 上使用“隔空投送”?
  15. 字典总结一|脚本类、用户名字典
  16. python下载自己网易云歌单的歌曲
  17. HP1020打印机加入域后,域用户无法使用HP1020域打印功能
  18. 使用js拖拽盒子移动()
  19. CSDN 发布文章时 添加的图片 怎么 去掉水印
  20. 开始自学SAP以及学习路线

热门文章

  1. 在Linux下进行Apache+tomcat整合
  2. 比特币现金(BCH)独立日一周年庆!里程碑一览!
  3. 理解haslayout
  4. Linux下使用ssh密钥实现无交互备份
  5. 2015年11月 广州深圳 MVP 线下活动
  6. C# DEBUG 调试信息打印及输出详解
  7. iOS开发-UITextField手机号和邮箱验证
  8. 定义派生类拷贝构造函数
  9. AndroidManifest.xml配置详解
  10. 关于redis的几件小事(一)redis的使用目的与问题