当前位置: 首页 > news >正文

usb驱动描述符数据结构

USB描述符数据结构

  • 简介
  • 设备描述符
    • usb设备数据结构 usb_device
    • usb_device_descriptor
  • USB配置描述符
    • usb_host_config
    • usb_config_descriptor
  • 接口描述符
    • usb_interface
    • usb_host_interface
    • usb_interface_descriptor
  • 端点描述符
    • usb_host_endpoint
    • usb_endpoint_descriptor

简介

本文主要记录Linux下关于USB描述符数据结构的定义,以便后续查看和使用。
在USB描述符中,从上到下拓扑关系主要分为4个层次:

  • USB设备描述符(struct usb_device_descriptor)
  • USB配置描述符(struct usb_config_descriptor)
  • USB接口描述符(struct usb_interface_descriptor)
  • USB端点描述符(struct usb_endpoint_descriptor)
    一个设备只有一个设备描述符
    一个设备描述符可以有多个配置描述符,但通常情况下也是只有一个配置描述符
    一个配置描述符可以有多个接口描述符,这个很常见:如声卡设备就有两个接口:录音接口和播放接口,UVC设备至少两个接口:视频控制接口和视频流接口
    一个接口描述符可以有多个端点描述符

设备描述符

usb设备数据结构 usb_device

该结构体是描述一个usb device的最顶层数据结构,它包含了一个usb设备所有的描述符信息及类特定描述符信息。

struct usb_device {int devnum;         //devnum只是usb设备在一条usb总线上的编号.一条usb_bus_type类型的总线上最多可以连上128个设备char devpath [16];   /* Use in messages: /port/port/...*/  //对于root hub.会将dev->devpath[0]=’0’enum usb_device_state   state;  //设备的状态Attached,Powered,Default,Address,Configured,Suspended;//Attached表示设备已经连接到usb接口上了,是hub检测到设备时的初始状态。那么这里所谓的USB_STATE_NOTATTACHED就是表示设备并没有Attached。//Address状态表示主机分配了一个唯一的地址给设备,此时设备可以使用缺省管道响应主机的请求//Configured状态表示设备已经被主机配置过了,也就是协议里说的处理了一个带有非0值的SetConfiguration()请求,此时主机可以使用设备提供的所有功能//Suspended挂起状态,为了省电,设备在指定的时间内,3ms吧,如果没有发生总线传输,就要进入挂起状态。此时,usb设备要自己维护包括地址、配置在内的信息             enum usb_device_speed   speed;  /* high/full/low (or error) */struct usb_tt   *tt;            //如果一个高速设备里有这么一个TT,那么就可以连接低速/全速设备,如不然,那低速/全速设备没法用,只能连接到OHCI/UHCI那边出来的hub口里。int             ttport;         //如果一个高速设备里有这么一个TT,那么就可以连接低速/全速设备,如不然,那低速/全速设备没法用,只能连接到OHCI/UHCI那边出来的hub口里。unsigned int toggle[2];         /* one bit for each endpoint     //他实际上就是一个位图.IN方向的是toggle[0].OUT方向的是toggle[1].其实,这个数组中的每一位表示ep的toggle值* ([0] = IN, [1] = OUT) */它里面的每一位表示的就是每个端点当前发送或接收的数据包是DATA0还是DATA1struct usb_device *parent;      /* our hub, unless we're the root *///USB设备是从Root Hub开始,一个一个往外面连的,比如Root Hub有4个口,每个口连一个USB设备,比如其中有一个是Hub,那么这个Hub有可以继续有多个口,于是一级一级的往下连,//最终连成了一棵树。struct usb_bus *bus;            /* Bus we're part of */设备所在的总线struct usb_host_endpoint ep0;   //端点0的特殊地位决定了她必将受到特殊的待遇,在struct usb_device对象产生的时候它就要初始化struct device dev;              /* Generic device interface */嵌入到struct usb_device结构里的struct device结构struct usb_device_descriptor descriptor;/* Descriptor */设备描述符,此结构体的bMaxPacketSize0 filed保存了端点0的maximum packet sizestruct usb_host_config *config; //设备拥有的所有配置struct usb_host_config *actconfig;//设备正在使用的配置struct usb_host_endpoint *ep_in[16];//ep_in[16],359行,ep_out[16],除了端点0,一个设备即使在高速模式下也最多只能再有15个IN端点和15个OUT端点,端点0太特殊了,struct usb_host_endpoint *ep_out[16];//对应的管道是Message管道,又能进又能出特能屈能伸的那种,所以这里的ep_in和ep_out数组都有16个值char **rawdescriptors;          /* Raw descriptors for each config */unsigned short bus_mA;          /* Current available from the bus */这个值是在host controller的驱动程序中设置的,通常来讲,计算机的usb端口可以提供500mA的电流u8 portnum;                     //不管是root hub还是一般的hub,你的USB设备总归要插在一个hub的端口上才能用,portnum就是那个端口号。u8 level;                       //层次,也可以说是级别,表征usb设备树的级连关系。Root Hub的level当然就是0,其下面一层就是level 1,再下面一层就是level 2,依此类推unsigned discon_suspended:1;    /* Disconnected while suspended */unsigned have_langid:1;         /* whether string_langid is valid */int string_langid;              /* language ID for strings *//* static strings from the device */char *product;                  /* iProduct string, if present */char *manufacturer;             /* iManufacturer string, if present */char *serial;                   /* iSerialNumber string, if present *///分别用来保存产品、厂商和序列号对应的字符串描述符信息struct list_head filelist;
#ifdef CONFIG_USB_DEVICE_CLASSstruct device *usb_classdev;
#endif#ifdef CONFIG_USB_DEVICEFSstruct dentry *usbfs_dentry;    /* usbfs dentry entry for the device */
#endif/** 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 */struct usb_device *children[USB_MAXCHILDREN];int pm_usage_cnt;               /* usage counter for autosuspend */u32 quirks;                     //quirk就是用来判断这些有毛病的产品啥毛病的#ifdef CONFIG_PMstruct delayed_work autosuspend; /* for delayed autosuspends */struct mutex pm_mutex;          /* protects PM operations */unsigned long last_busy;        /* time of last use */int autosuspend_delay;          /* in jiffies */unsigned auto_pm:1;             /* autosuspend/resume in progress */unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */unsigned autosuspend_disabled:1; /* autosuspend and autoresume */unsigned autoresume_disabled:1;  /*  disabled by the user */
#endif
};

usb_device_descriptor

struct usb_device_descriptor {__u8  bLength;                          //本描述符的size__u8  bDescriptorType;              //描述符的类型,这里是设备描述符DEVICE__u16 bcdUSB;                           //指明usb的版本,比如usb2.0__u8  bDeviceClass;                 //类__u8  bDeviceSubClass;             //子类__u8  bDeviceProtocol;              //指定协议__u8  bMaxPacketSize0;            //端点0对应的最大包大小__u16 idVendor;                         //厂家ID__u16 idProduct;                        //产品ID__u16 bcdDevice;                       //设备的发布号__u8  iManufacturer;                 //字符串描述符中厂家ID的索引__u8  iProduct;                         //字符串描述符中产品ID的索引__u8  iSerialNumber;                 //字符串描述符中设备序列号的索引__u8  bNumConfigurations;              //配置描述符的个数,表示有多少个配置描述符
} __attribute__ ((packed));

USB配置描述符

usb_host_config

struct usb_host_config {struct usb_config_descriptor    desc;char *string;        /* iConfiguration string, if present *//* List of any Interface Association Descriptors in this* configuration. */struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS]; //此配置中所有相关联的接口描述符的列表/* the interfaces associated with this configuration,* stored in no particular order */struct usb_interface *interface[USB_MAXINTERFACES]; //配置所包含的接口,这个数组的顺序未必是按照配置里接口号的顺序/* Interface information available even when this is not the* active configuration */struct usb_interface_cache *intf_cache[USB_MAXINTERFACES]; //usb接口的缓存unsigned char *extra;   /* Extra descriptors */int extralen;
};

usb_config_descriptor

struct usb_config_descriptor {   __u8  bLength;                          //描述符的长度__u8  bDescriptorType;              //描述符类型的编号__le16 wTotalLength;               //配置 所返回的所有数据的大小,包括除设备描述符以外的所有描述符大小__u8  bNumInterfaces;              //配置 所支持的接口个数, 表示有多少个接口描述符__u8  bConfigurationValue;        //Set_Configuration命令需要的参数值__u8  iConfiguration;                        //描述该配置的字符串的索引值__u8  bmAttributes;                         //供电模式的选择__u8  bMaxPower;                    //设备从总线提取的最大电流} __attribute__ ((packed));

接口描述符

usb_interface

usb_interface字面意思既是接口,什么的接口:设备的接口,USB接口。

为什么会出现这样的类型出来,根据实际情况,例如:
一个设备有两种功能 一个键盘 一个音频,两种接口,那这样肯定得要两个驱动程序,一个是键盘驱动程序,一个是音频流驱动程序。两种功能整合在一起称为一个设备。但是不同的接口需要不同的驱动,音频驱动 和键盘驱动。用interface来区分,就有了接口类型。

struct usb_interface {/* array of alternate settings for this interface,* stored in no particular order */struct usb_host_interface *altsetting;  // 当前接口的可选设置/* the currently active alternate setting */struct usb_host_interface *cur_altsetting;  // 当前接口使用的设置/* number of alternate settings */ unsigned num_altsetting;  // 当前接口具有的可选设置总数/* If there is an interface association descriptor then it will list* the associated interfaces */struct usb_interface_assoc_descriptor *intf_assoc;/* minor number this interface is * bound to */ /*** 当前接口的在主设备号为USB_MAJOR时的子设备号,minor只在USB_MAJOR起作用时起作用。 usb设备没有与其它任何子系统关联,* 就需要在对应驱动的probe函数里使用usb_register_dev函数来注册并获得主设备号USB_MAJOR。如果usb设备关联了其它子系统,* 则需要在对应驱动的probe函数里使用相应的注册函数,USB_MAJOR也就该干吗干吗去,用不着它了。比如,usb键盘关联了input子系统,* 驱动对应drivers/hid/usbhid目录下的usbkbd.c文件,在它的probe函数里可以看到使用了input_register_device来注册一个输入设备。 * */int minor;   enum usb_interface_condition condition; /* state of binding */ // 当前接口 所处的连接绑定阶段unsigned sysfs_files_created:1; /* the sysfs attributes exist */unsigned ep_devs_created:1; /* endpoint "devices" exist */unsigned unregistering:1; /* unregistration is in progress */unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */unsigned needs_binding:1; /* needs delayed unbind/rebind */unsigned resetting_device:1; /* true: bandwidth alloc after reset */struct device dev; /* interface specific device info */ // linux设备模型里的device嵌在这儿的对象struct device *usb_dev;  // 当接口使用USB_MAJOR作为主设备号时,usb_dev才会用到, usb_register_dev和usb_deregister_dev使用这个结构体,usb_dev指向的就是usb_register_dev函数里创建的usb class device。atomic_t pm_usage_cnt; /* usage counter for autosuspend */struct work_struct reset_ws; /* for resets in atomic context */
}

struct usb_interface中的struct usb_host_interface *cur_altsetting成员,表示当前正在使用的设置

usb_host_interface

struct usb_host_interface 
{struct usb_interface_descriptor desc;//usb描述符,主要有四种usb描述符,设备描述符,配置描述符,接口描述符和端点描述符,协议里规定一个usb设备是必须支持这四大描述符的。//usb描述符放在usb设备的eeprom里边/* array of desc.bNumEndpoint endpoints associated with this* interface setting. these will be in no particular order.*/struct usb_host_endpoint *endpoint;//这个设置所使用的端点char *string;           /* iInterface string, if present */ //接口描述字符串/***关于额外描述符, 通常是类特定描述符,比如uvc中的类特定控制接口描述符,类特定视频流接口描述符*/unsigned char *extra;   /* Extra descriptors */int extralen;
};

具体到接口描述符,它当然就是描述接口本身的信息的。一个接口可以有多个设置,使用不同的设置,描述接口的信息会有些不同,所以接口描述符并没有放在struct usb_interface结构里,而是放在表示接口设置的struct usb_host_interface结构里。

usb_interface_descriptor

struct usb_interface_descriptor {  __u8  bLength;                          //描述符的长度__u8  bDescriptorType;              //描述符类型的编号__u8  bInterfaceNumber;           //接口的编号__u8  bAlternateSetting;            //备用的接口描述符编号,提供不同质量的服务参数.__u8  bNumEndpoints;              //要使用的端点个数(不包括端点0), 表示有多少个端点描述符,比如鼠标就只有一个端点__u8  bInterfaceClass;              //接口类型,与驱动的id_table __u8  bInterfaceSubClass;                 //接口子类型__u8  bInterfaceProtocol;                 //接口所遵循的协议__u8  iInterface;                        //描述该接口的字符串索引值} __attribute__ ((packed)

端点描述符

usb_host_endpoint

struct usb_host_endpoint 
{struct usb_endpoint_descriptor desc; //端点描述符struct list_head                urb_list;//端点要处理的urb队列.urb是usb通信的主角,设备中的每个端点都可以处理一个urb队列.要想和你的usb通信,就得创建一个urb,并且为它赋好值,//交给咱们的usb core,它会找到合适的host controller,从而进行具体的数据传输void                            *hcpriv;//这是提供给HCD(host controller driver)用的struct ep_device                *ep_dev;        /* For sysfs info */unsigned char *extra;   /* Extra descriptors */int extralen;int enabled;  //使能的话,urb才能被提交到此端口int streams;
};

usb_endpoint_descriptor

struct usb_endpoint_descriptor {
__u8  bLength;                          //描述符的长度
__u8  bDescriptorType;              //描述符类型的编号__u8  bEndpointAddress;              //端点编号,比如端点1,就是1
__u8  bmAttributes;                  //端点的属性, 比如中断传输类型,输入类型
__le16 wMaxPacketSize;               //一个端点的最大包大小,
__u8  bInterval;                     //间隔时间,用在中断传输上,比如间隔时间查询鼠标的数据/* NOTE:  these two are _only_ in audio endpoints. */
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8  bRefresh;
__u8  bSynchAddress;} __attribute__ ((packed));

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • <数据集>工程机械识别数据集<目标检测>
  • extern关键字在C语言中的作用
  • 【python】三种方式实现将2个3×5数组拼接形成6×5数组
  • 了解消息中间件TongLINK/Q
  • 实验5-1 使用函数计算两点间的距离
  • 以西门子winCC为代表的组态界面,还是有很大提升空间的。
  • 【C++】文件IO流
  • 涨点发论文神器:即插即用多尺度融合模块!
  • web以及nginx
  • 【网络世界】HTTPS协议
  • 《程序猿入职必会(5) · CURD 页面细节规范 》
  • logstash 全接触
  • 深入了解-什么是CUDA编程模型
  • CUDA的(详细版)占用率优化策略
  • 使用docker在CentOS 7上安装php+mysql+nginx环境教程并运行WordPress
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • C语言笔记(第一章:C语言编程)
  • golang 发送GET和POST示例
  • Gradle 5.0 正式版发布
  • JavaScript 基本功--面试宝典
  • Java比较器对数组,集合排序
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • LintCode 31. partitionArray 数组划分
  • mongo索引构建
  • php的插入排序,通过双层for循环
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 构建二叉树进行数值数组的去重及优化
  • 汉诺塔算法
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 理清楚Vue的结构
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 运行时添加log4j2的appender
  • postgresql行列转换函数
  • 仓管云——企业云erp功能有哪些?
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ![CDATA[ ]] 是什么东东
  • #if #elif #endif
  • #QT 笔记一
  • (16)Reactor的测试——响应式Spring的道法术器
  • (Java入门)抽象类,接口,内部类
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (纯JS)图片裁剪
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (十一)c52学习之旅-动态数码管
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一一四)第九章编程练习