Linux那些事儿 之 戏说USB(20)配置

原创 2007年09月30日 12:01:00

越来越觉得USB的世界是一个理想化的世界,在那里,一个设备可以有多种配置,做不同的事,过不一样的生活,而我们的配置永远只有一个,从生到死,没得选择。所谓的爱情的选择,职业的选择,在你选择过后再看,似乎冥冥中都有一种神秘的力量在支配着,而我们在其中只不过是上紧的发条,每个人自出生始就被配置了不同的路,你的彷徨,你的叛逆,你的伤心,你的快乐,都只不过是许多看似的偶然所组成的必然。

我不是宿命论者,我也经常在夜深人静不能入寐的时候回忆过去的悲欢与离合,惆怅现在的无助与无奈,思索将来要走的路。不过在爱成往事,烟花散尽后,过往的情形似乎都是不可逆转的必然。这就是所谓的人类一思考上帝就发笑吧,因为他知道你的努力都是徒劳,但是你还不得不去努力,这就是所谓的无奈的人生。

上帝又发笑了,还是接着看usb设备的配置吧,在include/linux/usb.h里定义

206 /**

207  * struct usb_host_config - representation of a device's configuration

208  * @desc: the device's configuration descriptor.

209  * @string: pointer to the cached version of the iConfiguration string, if

210  *      present for this configuration.

211  * @interface: array of pointers to usb_interface structures, one for each

212  *      interface in the configuration.  The number of interfaces is stored

213  *      in desc.bNumInterfaces.  These pointers are valid only while the

214  *      the configuration is active.

215  * @intf_cache: array of pointers to usb_interface_cache structures, one

216  *      for each interface in the configuration.  These structures exist

217  *      for the entire life of the device.

218  * @extra: pointer to buffer containing all extra descriptors associated

219  *      with this configuration (those preceding the first interface

220  *      descriptor).

221  * @extralen: length of the extra descriptors buffer.

222  *

223  * USB devices may have multiple configurations, but only one can be active

224  * at any time.  Each encapsulates a different operational environment;

225  * for example, a dual-speed device would have separate configurations for

226  * full-speed and high-speed operation.  The number of configurations

227  * available is stored in the device descriptor as bNumConfigurations.

228  *

229  * A configuration can contain multiple interfaces.  Each corresponds to

230  * a different function of the USB device, and all are available whenever

231  * the configuration is active.  The USB standard says that interfaces

232  * are supposed to be numbered from 0 to desc.bNumInterfaces-1, but a lot

233  * of devices get this wrong.  In addition, the interface array is not

234  * guaranteed to be sorted in numerical order.  Use usb_ifnum_to_if() to

235  * look up an interface entry based on its number.

236  *

237  * Device drivers should not attempt to activate configurations.  The choice

238  * of which configuration to install is a policy decision based on such

239  * considerations as available power, functionality provided, and the user's

240  * desires (expressed through userspace tools).  However, drivers can call

241  * usb_reset_configuration() to reinitialize the current configuration and

242  * all its interfaces.

243  */

245         struct usb_config_descriptor    desc;

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

248         /* the interfaces associated with this configuration,

249          * stored in no particular order */

250         struct usb_interface *interface[USB_MAXINTERFACES];

252         /* Interface information available even when this is not the

253          * active configuration */

254         struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];

256         unsigned char *extra;   /* Extra descriptors */

257         int extralen;

258 };

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

250 /* USB_DT_CONFIG: Configuration descriptor information.

251  *

252  * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the

253  * descriptor type is different.  Highspeed-capable devices can look

254  * different depending on what speed they're currently running.  Only

255  * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG

256  * descriptors.

257  */

259         __u8  bLength;

260         __u8  bDescriptorType;

262         __le16 wTotalLength;

263         __u8  bNumInterfaces;

264         __u8  bConfigurationValue;

265         __u8  iConfiguration;

266         __u8  bmAttributes;

267         __u8  bMaxPower;

268 } __attribute__ ((packed));

270 #define USB_DT_CONFIG_SIZE              9

259行,bLength,描述符的长度,值为USB_DT_CONFIG_SIZE

260行,bDescriptorType,描述符的类型,值为USB_DT_CONFIG0x02。这么说对不对?按照前面接口描述符、端点描述符和设备描述符的习惯来说,应该是没问题。但是,生活总是会在我们已经习惯它的时候来个转折,这里的值却并不仅仅可以为USB_DT_CONFIG,还可以为USB_DT_OTHER_SPEED_CONFIG0x07。这里说的OTHER_SPEED_CONFIG描述符描述的是高速设备操作在低速或全速模式时的配置信息,和配置描述符的结构完全相同,区别只是描述符的类型不同,是只有名字不同的孪生兄弟。

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

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

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

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

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

272 /* from config descriptor bmAttributes */

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

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

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

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

267行,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结构的247行,string,这个字符串保存了配置描述符iConfiguration字段对应的字符串描述符信息。

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

65 /**

66  * usb_ifnum_to_if - get the interface object with a given interface number

67  * @dev: the device whose current configuration is considered

68  * @ifnum: the desired interface

69  *

70  * This walks the device descriptor for the currently active configuration

71  * and returns a pointer to the interface with that particular interface

72  * number, or null.

73  *

74  * Note that configuration descriptors are not required to assign interface

75  * numbers sequentially, so that it would be incorrect to assume that

76  * the first interface in that descriptor corresponds to interface zero.

77  * This routine helps device drivers avoid such mistakes.

78  * However, you should make sure that you do the right thing with any

79  * alternate settings available for this interfaces.

80  *

81  * Don't call this function unless you are bound to one of the interfaces

82  * on this device or you have locked the device!

83  */

85                                       unsigned ifnum)

86 {

87         struct usb_host_config *config = dev->actconfig;

88         int i;

90         if (!config)

91                 return NULL;

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

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

94                                 .desc.bInterfaceNumber == ifnum)

95                         return config->interface[i];

97         return NULL;

98 }

这个函数的道理很简单,就是拿你指定的接口号,和当前配置的每一个接口可选设置0里的接口描述符的bInterfaceNumber字段做比较,相等了,那个接口就是你要寻找的,都不相等,那对不起,不能满足你的要求,虽然它已经尽力了。

如果你看了协议,可能会在9.6.5里看到,请求配置描述符时,配置里的所有接口描述符是按照顺序一个一个返回的。那为什么这里又明确说明,让咱们不要期待它就会是接口号的顺序那?其实很久很久以前这里并不是这么说地,它就说这个数组是按照0..desc.bNumInterfaces的顺序,但同时又说需要通过usb_ifnum_to_if函数来获得指定接口号的接口对象,Alan Stern大侠质疑了这种有些矛盾的说法,于是David Brownell大侠就把它改成现在这个样子了,为什么改?因为协议归协议,厂商归厂商,有些厂商就是有不遵守协议的癖好,它非要先返回接口1再返回接口0,你也没辙,所以就不得不增加usb_ifnum_to_if函数。

USB_MAXINTERFACESdrivers/usb/usb.h里定义的一个宏,值为32,不要说不够用,谁见过有很多接口的设备?

/* this maximum is arbitrary */

#define USB_MAXINTERFACES 32

254行,intf_cache[USB_MAXINTERFACES]cache是什么?缓存。答对了,不然大学四年岂不是光去吃老赵烤肉了。这是个struct usb_interface_cache对象的结构数组,usb_interfaceusb接口,cache,缓存,所以usb_interface_cache就是usb接口的缓存。缓存些什么?看看include/linux/usb/usb.h里的定义

179 /**

180  * struct usb_interface_cache - long-term representation of a device interface

181  * @num_altsetting: number of altsettings defined.

182  * @ref: reference counter.

183  * @altsetting: variable-length array of interface structures, one for

184  *      each alternate setting that may be selected.  Each one includes a

185  *      set of endpoint configurations.  They will be in no particular order.

186  *

187  * These structures persist for the lifetime of a usb_device, unlike

188  * struct usb_interface (which persists only as long as its configuration

189  * is installed).  The altsetting arrays can be accessed through these

190  * structures at any time, permitting comparison of configurations and

191  * providing support for the /proc/bus/usb/devices pseudo-file.

192  */

194         unsigned num_altsetting;        /* number of alternate settings */

195         struct kref ref;                /* reference counter */

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

198          * stored in no particular order */

199         struct usb_host_interface altsetting[0];

200 };

199行的altsetting[0]是一个可变长数组,按需分配的那种,你对设备说GET_DESCRIPTOR的时候,内核就根据返回的每个接口可选设置的数目分配给intf_cache数组相应的空间,有多少需要多少分配多少,在咱们还在为拥有一套房而奋斗终生的时候,这里已经提前步入了共产主义。

为什么要缓存这些东东?房价在变,物价在变,设备的配置也在变,此时这个配置可能还在欢快的被宠幸着,彼时它可能就躲在冷宫里写《后宫回忆录》,漫长的等待之后,哪个导演慧眼识剧本发现了它,她就又迎来了自己的第二春。这就叫此一时彼一时。为了在配置被取代之后仍然能够获取它的一些信息,就把日后可能会需要的一些东东放在了intf_cache数组的struct usb_interface_cache对象里。谁会需要?这么说吧,你通过sysfs这个窗口只能看到设备当前配置的一些信息,即使是这个配置下面的接口,也只能看到接口正在使用的那个可选设置的信息,可是你希望能够看到更多的,怎么办,窗户太小了,可以趴门口看,usbfs就是这个门,里面显示有你的系统中所有usb设备的可选配置和端点信息,它就是利用intf_cache这个数组里缓存的东东实现的。

256行,extra257行,extralen,有关额外扩展的描述符的,和struct usb_host_interface里的差不多,只是这里的是针对配置的,如果你使用GET_DESCRIPTOR请求从设备里获得配置描述符信息,它们会紧跟在标准的配置描述符后面返回给你。

 
版权声明:本文为博主原创文章,未经博主允许不得转载。

《Linux那些事儿之我是USB》前言

1992年,那是一个春天。不过其实1991年又何尝不是一个春天呢,因为正是在那一年,Linux诞生了。又因为开放源代码的缘故,十几年来Linux是越来越火,熊熊火焰也烧到了华夏大地。诸多高校开始开设L...
  • fudan_abc
  • fudan_abc
  • 2010年07月29日 12:34
  • 17620

《Linux那些事儿之我是USB》我是U盘(14)冰冻三尺非一日之寒

罗马不是一天建成的。在让U盘工作之前,其实我们的驱动做了很多准备工作。 我们继续跟着感觉走,storage_probe(),972行至975行,一系列的以init_*命名的函数在此刻被调用,这里涉及...
  • fudan_abc
  • fudan_abc
  • 2011年09月21日 22:58
  • 6881

《Linux那些事儿之我是USB》我是U盘(18)冬天来了,春天还会远吗?(四)

结束了get_device_info,我们继续沿着storage_probe一步一步地走下去。继续,这就是我们前面提到过的三个函数,get_transport、get_protocol和get_pip...
  • fudan_abc
  • fudan_abc
  • 2011年10月10日 21:49
  • 5762

Linux那些事儿之我是U盘 提供pdf下载

http://www.newsmth.net/att.php?p.299.44271.374.pdf还会继续修改,主要是加入一些图片.比如传输协议的,数据格式的,函数调用关系的图片.预计会在9月初提供...
  • fudan_abc
  • fudan_abc
  • 2007年08月07日 17:21
  • 12214

我是。。。。。

我是逗比张,哈哈哈哈哈哈嚯嚯嚯嚯嚯
  • Aaron_Zhang939
  • Aaron_Zhang939
  • 2018年01月31日 22:06
  • 6

linux 那些事儿系列

fudan_adc的博客主要博文包括: linux那些事儿系列 : http://blog.csdn.net/fudan_abc/article/category/335670 linux内核修...
  • mapeng892020
  • mapeng892020
  • 2017年01月05日 16:58
  • 1504

Linux那些事儿之我是Hub(10)While You Were Sleeping(三)

get_hub_descriptor()结束了,然后就返回hub_configure()中来.635到642行,判断刚才的返回值,小于零当然是出错了,大于零也还要多判断一次, USB_MAXCHILD...
  • fudan_abc
  • fudan_abc
  • 2007年08月23日 22:31
  • 5940

Linux那些事儿 之 戏说USB(16)配置

接着看usb设备的配置吧,在include/linux/usb.h里定义 struct usb_host_config { struct usb_config_descriptor desc; ...
  • zhqh100
  • zhqh100
  • 2015年03月25日 11:04
  • 967

Linux那些事儿之我是Sysfs(4)举例一lddbus

对了,你得把ldd3的examples代码下下来。不然没法继续了。接下来我们从例子着手,localhost:/home/XX/examples/lddbus#insmod lddbus.ko此时再看/...
  • fudan_abc
  • fudan_abc
  • 2007年09月01日 16:12
  • 17971

【转】Linux那些事儿 之 戏说USB(20)配置

越来越觉得USB的 世界是一个理想化的世界,在那里,一个设备可以有多种配置,做不同的事,过不一样的生活,而我们的配置永远只有一个,从生到死,没得选择。所谓的爱情的选 择,职业的选择,在你选择过后再看,...
  • aaronychen
  • aaronychen
  • 2008年01月24日 11:54
  • 715
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux那些事儿 之 戏说USB(20)配置
举报原因:
原因补充:

(最多只允许输入30个字)