经过了许多事
你是不是觉得累
这样的心情
我曾有过几回
现在的你我想一定
很疲惫
内核代码就象酒
有的苦有的烈
这样的滋味
你我早晚要体会
把那内核当作一场宿醉
明日的代码莫再要装着昨天的伤悲
请与我举起杯
跟内核干杯
跟着设备的生命线走到现在,我算是明白了,什么东西的发展都是越往后越高级越复杂,就好像人一样,从Attached走到Powered只是弹指一挥间,从Powered再到Default虽说要复位一下,也算是三下五除二了,再从Default走到Address简直练吃奶劲儿都使出来了,应该把阿Q拉过来念叨两句“Address?有趣!来了一群鬼佬,叫到,Address,Address,于是就Address了。”再给张小表,看看现在和上次那张表出现的时候有什么变化。
state
|
USB_STATE_ADDRESS
|
speed
|
taken
|
ep0
|
ep0.urb_list,描述符长度/类型,wMaxPacketSize
|
接下来设备的目标当然就是Configured了,My god!又要经过多少事,遇到多少人?如果实在觉得辛苦,可以去穿件绿衣服,因为忍者神龟先生说了:要想生活过得去,背上就得带点绿!
要进入Configured状态,你得去配置设备,当然不能是盲目的去配置,要知道设备是可能有多个配置的,所以你要有选择有目的有步骤有计划的去配置,要做这样一个四有新人,就要先去获得设备的设备描述符,message.c中的usb_get_device_descriptor()就是core里专门干这个的。
843 * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
844 * @dev: the device whose device descriptor is being updated
845 * @size: how much of the descriptor to read
846 * Context: !in_interrupt ()
848 * Updates the copy of the device descriptor stored in the device structure,
849 * which dedicates space for this purpose.
851 * Not exported, only for use by the core. If drivers really want to read
852 * the device descriptor directly, they can call usb_get_descriptor() with
853 * type = USB_DT_DEVICE and index = 0.
855 * This call is synchronous, and may not be used in an interrupt context.
857 * Returns the number of bytes received on success, or else the status code
858 * returned by the underlying usb_control_msg() call.
这个函数比较的精悍,先是准备了一个struct usb_device_descriptor结构体,然后就用它去调用message.c里的usb_get_descriptor()获得设备描述符,获得之后再把得到的描述符复制到设备struct usb_device结构体的descriptor成员里。因此,这个函数成功与否的关键就在usb_get_descriptor()。其实对于写驱动的来说,眼里是只有usb_get_descriptor()没有usb_get_device_descriptor()的,不管你想获得哪种描述符都是要通过usb_get_descriptor(),而usb_get_device_descriptor()是专属内核用的接口。
597 * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
598 * @dev: the device whose descriptor is being retrieved
599 * @type: the descriptor type (USB_DT_*)
600 * @index: the number of the descriptor
601 * @buf: where to put the descriptor
602 * @size: how big is "buf"?
603 * Context: !in_interrupt ()
605 * Gets a USB descriptor. Convenience functions exist to simplify
606 * getting some types of descriptors. Use
607 * usb_get_string() or usb_string() for USB_DT_STRING.
608 * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG)
609 * are part of the device structure.
610 * In addition to a number of USB-standard descriptors, some
611 * devices also use class-specific or vendor-specific descriptors.
613 * This call is synchronous, and may not be used in an interrupt context.
615 * Returns the number of bytes received on success, or else the status code
616 * returned by the underlying usb_control_msg() call.
626 /* retry on length 0 or stall; some devices are flakey */
参数type就是用来区分不同的描述符的,协议里说了,GET_DESCRIPTOR请求主要就是适用于三种描述符,设备描述符,配置描述符和字符串描述符。参数index是要获得的描述符的序号,如果希望得到的这种描述符设备里可以有多个,你需要指定获得其中的哪个,比如配置描述符就可以有多个,不过对于设备描述符来说,是只有一个的,所以这里的index应该为0。参数buf和size就是描述你用来放置获得的描述符的缓冲区的。
这个函数的内容挺单调的,主要就是调用了一个usb_control_msg(),你如果到现在还觉得usb_control_msg()只是个熟悉的陌生人,那俺也就太失败了。这里要说的第一个问题是它的一堆参数,这就需要认真了解一下spec 9.4.3里的这张表
GET_DESCRIPTOR请求的数据传输方向很明显是device-to-host的,而且还是协议里规定所有设备都要支持的标准请求,也不是针对端点或者接口什么的,而是针对设备的,所以bRequestType只能为0x80,就是上面表里的10000000B,也等于628行的USB_DIR_IN。wValue的高位字节表示描述符的类型,低位字节表示描述符的序号,所以就有629行的(type << 8) + index。wIndex对于字符串描述符应该设置为使用语言的ID,对于其它的描述符应该设置为0,所以也有了629行中间的