前面分析了usb的四大描述符之端点描述符,接口描述符(每一个接口对应一个功能,与之配备相应驱动),下面是看配置描述符还是看设备描述符呢??我们知道,设备大于配置,配置大于接口,接口可以有多种设置。

我们还是按照从小到大的顺序,继续看配置结构体吧!

struct usb_host_config {

struct usb_config_descriptor desc;

char *string; /* iConfiguration string, if present */

/* 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];

unsigned char *extra; /* Extra descriptors */

int extralen;

};

和前面分析一下,我们先略过usb_config_descriptor结构体的分析,大餐总是喜欢最后吃。

string,这个字符串保存了配置描述符iConfiguration字段对应的字符串描述符信息。

interface[USB_MAXINTERFACES],配置所包含的接口。注释里说的很明确,这个数组的顺序未必是按照配置里接口号的顺序,所以你要想得到某个接口号对应的struct usb_interface结构对象,就必须使用drivers/usb/usb.c里定义的usb_ifnum_to_if函数。

struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,

unsigned ifnum)

{

struct usb_host_config *config = dev->actconfig;

int i;

if (!config)

return NULL;

for (i = 0; i < config->desc.bNumInterfaces; i++)

if (config->interface[i]->altsetting[0]

.desc.bInterfaceNumber == ifnum)

return config->interface[i];

return NULL;

}

这个函数实现,就是用指定的接口号和当前配置的每一个接口可选设置0里的接口描述符的bInterfaceNumber字段做比较,相等了,那个接口就是你要寻找的。

如果你看了协议,可能会在9.6.5里看到,An interface descriptor is always returned as part of a configuration descriptor. Interface descriptors cannot be directly accessed with a GetDescriptor() or SetDescriptor() request…….请求配置描述符时,配置里的所有接口描述符是按照顺序一个一个返回的。那为什么这里又明确说明,让咱们不要期待它就会是接口号的顺序那?其实很久很久以前这里并不是这么说地,它就说这个数组是按照0..desc.bNumInterfaces的顺序,但同时又说需要通过usb_ifnum_to_if函数来获得指定接口号的接口对象,为什么改?因为协议归协议,厂商归厂商,有些厂商就是有不遵守协议的癖好,它非要先返回接口1再返回接口0,你也没辙,所以就不得不增加usb_ifnum_to_if函数。

intf_cache[USB_MAXINTERFACES],这是个struct usb_interface_cache对象的结构数组,usb_interface_cache就是usb接口的缓存。缓存些什么?看看include/linux/usb/usb.h里的定义。

struct usb_interface_cache {

unsigned num_altsetting; /* number of alternate settings */

struct kref ref; /* reference counter */

/* variable-length array of alternate settings for this interface,

* stored in no particular order */

struct usb_host_interface altsetting[0];

};

重点看一下成员altsetting[0],它是一个可变长数组,按需分配的那种,当对设备GET_DESCRIPTOR的时候,内核就根据返回的每个接口可选设置的数目(值num_altsetting)分配给intf_cache数组相应的空间。为什么要缓存这些东东?设备的配置会发生变化,为了在配置被取代之后仍然能够获取它的一些信息,就需要把一些信息放在intf_cache数组的struct usb_interface_cache对象里。那么谁会需要用到呢?你通过sysfs这个窗口只能看到设备当前配置的一些信息,即使是这个配置下面的接口,也只能看到接口正在使用的那个可选设置的信息,可是你希望能够看到更多的,怎么办?usbfs就是这个门,里面显示有你的系统中所有usb设备的可选配置和端点信息,它就是利用intf_cache这个数组里缓存的东东实现的。

回到配置结构体usb_host_config 的剩下两个成员extra和extralen,有关额外扩展的描述符的,和struct usb_host_interface里的差不多,只是这里的是针对配置的,如果你使用GET_DESCRIPTOR请求从设备里获得配置描述符信息,它们会紧跟在标准的配置描述符后面返回给你。

还是老规矩,最后看一下usb_config_descriptor;

struct usb_config_descriptor {

__u8 bLength;

__u8 bDescriptorType;

__le16 wTotalLength;

__u8 bNumInterfaces;

__u8 bConfigurationValue;

__u8 iConfiguration;

__u8 bmAttributes;

__u8 bMaxPower;

} __attribute__ ((packed));

bLength,描述符的长度,值为#define USB_DT_CONFIG_SIZE 9

bDescriptorType,描述符的类型。还记得端点描述符和接口描述符类型是什么吗??所以多想想就能记住了,记不住也没关系,知道有这么个东东。这里为什么又要提一下?因为这里有一个转折,配置描述符的值可以为USB_DT_CONFIG,0x02,也可以为#define USB_DT_OTHER_SPEED_CONFIG 0x07。这么说对不对?0x07描述符描述的是高速设备操作在低速或全速模式时的配置信息,和配置描述符的结构完全相同,区别只是描述符的类型不同,是只有名字不同的孪生兄弟。

wTotalLength,使用GET_DESCRIPTOR请求从设备里获得配置描述符信息时,返回的数据长度,也就是说对包括配置描述符、接口描述符、端点描述符,class-或vendor-specific描述符在内的所有描述符算了个总帐。

bNumInterfaces,这个配置包含的接口数目。

bConfigurationValue,对于拥有多个配置的幸运设备来说,可以拿这个值为参数,使用SET_CONFIGURATION请求来改变正在被使用的 USB配置,bConfigurationValue就指明了将要激活哪个配置。咱们的设备虽然可以有多个配置,但同一时间却也只能有一个配置被激活。SET_CONFIGURATION请求也是标准的设备请求之一,专门用来设置设备的配置。

iConfiguration,描述配置信息的字符串描述符的索引值。

bmAttributes,这个字段表征了配置的一些特点,比如bit 6为1表示self-powered,bit 5为1表示这个配置支持远程唤醒。另外,它的bit 7必须为1,为什么?协议里就这么说的,我也不知道,这个世界上并不是什么事情都找得到原因的。ch9.h里有几个相关的定义

/* from config descriptor bmAttributes */

#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */

#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */

#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */

#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */

bMaxPower,设备正常运转时,从总线那里分得的最大电流值,以2mA为单位。设备可以使用这个字段向hub表明自己需要的的电流,但如果设备需求过于旺盛,请求的超出了hub所能给予的,hub就会直接拒绝,不会心软。你去请求她给你多一点点爱,可她心系天下人,没有多的分到你身上,于是怎么办?拒绝你呗,不要说爱情是多么残酷,这个世界就是很无奈。还记得struct usb_device结构里的bus_mA吗?它就表示从总线上获取到的当前值,也就是hub所能够赋予给设备的值。

usb驱动开发8之配置描述符的更多相关文章

  1. usb驱动开发7之接口描述符

    前面struct usb_interface里表示接口设置的struct usb_host_interface被有意的飘过了,咱们在这节主要讲讲这个结构体,同样在include/linux/usb.h ...

  2. usb驱动开发6之端点描述符

    学到这里不容易,先说一段故事吧. 二兄弟住一大楼的第80层,某深夜回家忘看通知(内容今夜停电). 兄弟俩背着沉重的大背包,在楼底下商量一下,决定一鼓作气,爬楼梯回家.两人抖擞精神,开始爬楼.爬到20楼 ...

  3. usb驱动开发9之设备描述符

    前面分析了usb的四大描述符之端点描述符,接口描述符(每一个接口对应一个功能,与之配备相应驱动),配置描述符,最后分析设备如何包括这些描述符.首先记住,在usb的世界里,设备大于配置,配置大于接口,接 ...

  4. STM32 USB设备描述符、配置描述符、端点描述符含义

    查了一整天的资料,自己把不懂的全部试了一遍 一下是程序以及注释 /* USB设备描述符*/ const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ ...

  5. HarmonyOS USB DDK助你轻松实现USB驱动开发

    HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...

  6. USB驱动开发大全【转】

    本文转载自:http://www.360doc.com/content/12/0504/19/8363527_208666082.shtml 编写USB驱动程序步骤:1所有usb驱动都必须创建主要结构 ...

  7. usb驱动开发22之驱动生命线

    我们总是很喜欢高潮,不是吗?那就好好对待她哦.我们来看一下linux中的高潮部分设备是怎么从Address进入Configured的. usb_set_configuration函数的代码就不贴了,可 ...

  8. usb驱动开发21之驱动生命线

    现在开始就沿着usb_generic_driver的生命线继续往下走.设备的生命线你可以为是从你的usb设备连接到hub的某个端口时开始,而驱动的生命线就必须得回溯到usb子系统的初始化函数usb_i ...

  9. usb驱动开发18之设备生命线

    现在已经使用GET_DESCRIPTOR请求取到了包含一个配置里所有相关描述符内容的一堆数据,这些数据是raw的,即原始的,所有数据不管是配置描述符.接口描述符还是端点描述符都挤在一起,所以得想办法将 ...

随机推荐

  1. 在SharePoint中无代码开发InfoPath应用: 一个测试Web Service的工具

    这是这个系列的第一篇,介绍一个小工具,主要是用在Web Service测试的. 因为为了用一点高级的东西,就免不了和web service打交道. 你可以使用按照KB819267来修改web.conf ...

  2. Sharepoint学习笔记—习题系列--70-573习题解析 -(Q100-Q103)

    Question 100You create a Web Part.You need to display the number of visits to a SharePoint site coll ...

  3. 安卓开发_浅谈OptionsMenus(选项菜单)

    Android平台下所提供的菜单大体上可分为三类:选项菜单.上下文菜单和子菜单. 当Activity在前台运行时,如果用户按下手机上的Menu键,此时就会在屏幕低端弹出相应的选项菜单.但这个功能需要开 ...

  4. iOS启动图和开屏广告图,类似网易

    iOS启动图和开屏广告图,类似网易 启动图是在iOS开发过程中必不可少的一个部分,很多app在启动图之后会有一张自定义的开屏广告图,点击该广告图可以跳转到广告图对应的页面.今天呢,和大家分享一下如何添 ...

  5. Linux0.11内核剖析--内核体系结构

    一个完整可用的操作系统主要由 4 部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如下图所示: 用户应用程序是指那些字处理程序. Internet 浏览器程序或用户自行编制的各种应用程序: ...

  6. android 学习运用海马模拟器教程与android环境的搭建

    第三方海马玩模拟器 第一天的学习android采用的模拟器是海马,因此就分享给大家海马模拟器的相关步骤: 海马玩模拟器官网: http://droid4x.haimawan.com 下载相关平台的模拟 ...

  7. 一个基于Myeclipse开发的Java打地鼠小游戏(Appletcation)

    package javaes.zixue.wangshang.daima; 2 3 import java.awt.Cursor; import java.awt.Image; import java ...

  8. 第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众 ...

  9. 轮式移动机器人QBot的使用

    夏季学期选了智能移动机器人导论课程,开始接触移动机器人.作为一门面向大二.大三学生的一门导论式的课程,课程作业其实并不太难,然而我们为了完成课程作业,前前后后还是弄了好几个星期,以至放了暑假都还要和Q ...

  10. poj 3237 Tree [LCA] (树链剖分)

    poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...