接着看usb设备的配置吧,在include/linux/usb.h里定义

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];unsigned char *extra;   /* Extra descriptors */int extralen;
};

desc,四大描述符里最后的一个终于出现了,同样是在它们的老巢include/uapi/linux/usb/ch9.h里定义

struct usb_config_descriptor {__u8  bLength;__u8  bDescriptorType;__le16 wTotalLength;__u8  bNumInterfaces;__u8  bConfigurationValue;__u8  iConfiguration;__u8  bmAttributes;__u8  bMaxPower;
} __attribute__ ((packed));#define USB_DT_CONFIG_SIZE       9

bLength,描述符的长度,值为USB_DT_CONFIG_SIZE。
bDescriptorType,描述符的类型,值为USB_DT_CONFIG,0x02。这么说对不对?按照前面接口描述符、端点描述符和设备描述符的习惯来说,应该是没问题。但是,生活总是会在我们已经习惯它的时候来个转折,这里的值却并不仅仅可以为USB_DT_CONFIG,还可以为USB_DT_OTHER_SPEED_CONFIG,0x07。这里说的OTHER_SPEED_CONFIG描述符描述的是高速设备操作在低速或全速模式时的配置信息,和配置描述符的结构完全相同,区别只是描述符的类型不同,是只有名字不同的孪生兄弟。
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所能够给予的。Alan Stern大侠告诉我们
(c->desc.bMaxPower * 2) is what the device requests and udev->bus_mA is what the hub makes available.
到此为止,四大标准描述符已经全部登场亮相了,还是回到struct usb_host_config结构的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;
}
EXPORT_SYMBOL_GPL(usb_ifnum_to_if);

这个函数的道理很简单,就是拿你指定的接口号,和当前配置的每一个接口可选设置0里的接口描述符的bInterfaceNumber字段做比较,相等了,那个接口就是你要寻找的,都不相等,那对不起,不能满足你的要求,虽然它已经尽力了。
如果你看了协议,可能会在9.6.5里看到,请求配置描述符时,配置里的所有接口描述符是按照顺序一个一个返回的。那为什么这里又明确说明,让咱们不要期待它就会是接口号的顺序那?其实很久很久以前这里并不是这么说地,它就说这个数组是按照0..desc.bNumInterfaces的顺序,但同时又说需要通过usb_ifnum_to_if 函数来获得指定接口号的接口对象,Alan Stern大侠质疑了这种有些矛盾的说法,于是David Brownell大侠就把它改成现在这个样子了,为什么改?因为协议归协议,厂商归厂商,有些厂商就是有不遵守协议的癖好,它非要先返回接口1再返回接口0,你也没辙,所以就不得不增加usb_ifnum_to_if函数。
USB_MAXINTERFACES是include/linux/usb.h里定义的一个宏,值为32,不要说不够用,谁见过有很多接口的设备?

/* this maximum is arbitrary */
#define USB_MAXINTERFACES   32

intf_cache[USB_MAXINTERFACES],cache是什么?缓存。答对了。这是个struct usb_interface_cache对象的结构数组,usb_interface,usb接口,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的时候,内核就根据返回的每个接口可选设置的数目分配给intf_cache数组相应的空间,有多少需要多少分配多少,在咱们还在为拥有一套房而奋斗终生的时候,这里已经提前步入了共产主义。
为什么要缓存这些东东?设备的配置会变,此时这个配置可能还在使用,彼时它可能就在等待。这就叫此一时彼一时。为了在配置被取代之后仍然能够获取它的一些信息,就把日后可能会需要的一些东东放在了intf_cache数组的struct usb_interface_cache对象里。谁会需要?这么说吧,你通过sysfs这个窗口只能看到设备当前配置的一些信息,即使是这个配置下面的接口,也只能看到接口正在使用的那个可选设置的信息,可是你希望能够看到更多的,怎么办,窗户太小了,可以趴门口看,usbfs就是这个门,里面显示有你的系统中所有usb设备的可选配置和端点信息,它就是利用intf_cache这个数组里缓存的东东实现的。
extra,extralen,有关额外扩展的描述符的,和struct usb_host_interface里的差不多,只是这里的是针对配置的,如果你使用GET_DESCRIPTOR请求从设备里获得配置描述符信息,它们会紧跟在标准的配置描述符后面返回给你。

Linux那些事儿 之 戏说USB(16)配置相关推荐

  1. Linux那些事儿 之 戏说USB(19)设备

    转载地址:http://blog.csdn.net/fudan_abc/article/details/1807800 第一眼看到struct usb_device这个结构,我仿佛置身于衡山路的酒吧里 ...

  2. 【转】Linux那些事儿 之 戏说USB(19)设备

    第一眼看到struct usb_device这个结构,我仿佛置身于衡山路的酒吧里,盯着舞池里扭动的符号,眼神迷离. 交大里苟了几年,毕业了又是住在学校附近的徐虹北路上,沿着虹桥路走过去,到徐家汇不过1 ...

  3. Linux那些事儿 之 戏说USB(27)设备的生命线(十)

    跟着设备的生命线走到现在,我算是明白了,什么东西的发展都是越往后越高级越复杂.再给张小表,看看现在和上次那张表出现的时候有什么变化. state        USB_STATE_ADDRESS sp ...

  4. Linux那些事儿 之 戏说USB(28)设备的生命线(十一)

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

  5. Linux那些事儿 之 戏说USB(25)设备的生命线(八)

    回到struct usb_hcd,继续努力的往下看. 7行,又见kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看drivers/usb/core/hcd ...

  6. Linux那些事儿 之 戏说USB(15)设备

    struct usb_device结构冗长而又杂乱 include/linux/usb.h struct usb_device {int devnum;char devpath[16];u32 rou ...

  7. Linux那些事儿 之 戏说USB(33)字符串描述符

    关于字符串描述符,前面的前面已经简单描述过了,地位仅次于设备/配置/接口/端点四大描述符,那四大设备必须得支持,而字符串描述符对设备来说则是可选的. 这并不是就说字符串描述符不重要,对咱们来说,字符串 ...

  8. Linux那些事儿 之 戏说USB(29)驱动的生命线(一)

    现在开始就沿着usb_generic_driver的成名之路走一走,设备的生命线你可以想当然的认为是从你的usb设备连接到hub的某个端口时开始,驱动的生命线就必须得回溯到usb子系统的初始化函数us ...

  9. Linux那些事儿 之 戏说USB(22)设备的生命线(五)

    下面接着看那三个基本点. 第一个基本点,usb_alloc_urb函数,创建urb的专用函数,为一个urb申请内存并做初始化,在drviers/usb/core/urb.c里定义. struct ur ...

最新文章

  1. 阿里腾讯裁员冲上热搜,消息称最高涉及30%,官方未回应
  2. kubernetes创建资源的两种方式
  3. Linux服务器硬件及RAID配置(操作实验详细图解)
  4. layui table 时间戳
  5. 分布式系统原理_终于有架构大牛把分布式系统概念讲明白了,竟然用了足足800页...
  6. LaTeX 页眉和页脚
  7. 安装VMware提示“此产品安装程序不支持降级“
  8. 安装 dpdk-ans 时的编译问题:librte_ans.a(ans_init.o): unrecognized relocation (0x2a) in section `.text'
  9. 树莓派 pcf8591 AD转换模块使用
  10. 快速删除大文件利器 node 包 rimraf
  11. 7-15 福到了 c语言,7-54 福到了 (15 分)
  12. (补)单片机原理及应用学习笔记(三)
  13. 抽象函数的对称性验证
  14. luogu p4995 跳跳
  15. MaxwellWorkbenchoptiSLang联合优化总结
  16. Javascript算法实现PDF批量加盖不同宽度骑缝章,vue加持。
  17. WM8960 audio codec
  18. java byte转成int数组_Java任意长度byte数组转换为int数组的方法
  19. 如何使用风向偏移简化风速风向传感器安装
  20. BES-DBQ蓝牙协议认证测试

热门文章

  1. TypeError: sequence item 1: expected str instance, int found
  2. Android 打包 aar文件的流程以及aar的引用
  3. baseUrl must end in /: http://v.juhe.cn/toutiao/index
  4. time 和 datetime 模块
  5. JAVA的instanceOf什么时候用
  6. C#中 int.TryParse 的用法
  7. 第18章:MYSQL分区
  8. ecos 编译时无法找到 tclConfig.sh 和 tkConfig.sh
  9. 爱不释手(Typingfaster)1.78beta,重大升级,欢迎试用,期待反馈。
  10. 计划任务执行php文件,linux系统下添加计划任务执行php文件方法