现在的位置: 首页 > 综合 > 正文

【转】Linux那些事儿 之 戏说USB(31)设备的生命线(十)

2013年09月23日 ⁄ 综合 ⁄ 共 4429字 ⁄ 字号 评论关闭
经过了许多事

你是不是觉得累

这样的心情

我曾有过几回

现在的你我想一定

很疲惫

内核代码就象酒

有的苦有的烈

这样的滋味

你我早晚要体会

把那内核当作一场宿醉

明日的代码莫再要装着昨天的伤悲

请与我举起杯

跟内核干杯

跟着设备的生命线走到现在,我算是明白了,什么东西的发展都是越往后越高级越复杂,就好像人一样,从Attached走到Powered只是弹指一挥间,从Powered再到Default虽说要复位一下,也算是三下五除二了,再从Default走到Address简直练吃奶劲儿都使出来了,应该把阿Q拉过来念叨两句“Address?有趣!来了一群鬼佬,叫到,AddressAddress,于是就Address了。”再给张小表,看看现在和上次那张表出现的时候有什么变化。

state

USB_STATE_ADDRESS

speed

taken

ep0

ep0.urb_list,描述符长度/类型,wMaxPacketSize

接下来设备的目标当然就是Configured了,My god!又要经过多少事,遇到多少人?如果实在觉得辛苦,可以去穿件绿衣服,因为忍者神龟先生说了:要想生活过得去,背上就得带点绿!

要进入Configured状态,你得去配置设备,当然不能是盲目的去配置,要知道设备是可能有多个配置的,所以你要有选择有目的有步骤有计划的去配置,要做这样一个四有新人,就要先去获得设备的设备描述符,message.c中的usb_get_device_descriptor()就是core里专门干这个的。

842 /*

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 ()

847  *

848  * Updates the copy of the device descriptor stored in the device structure,

849  * which dedicates space for this purpose.

850  *

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.

854  *

855  * This call is synchronous, and may not be used in an interrupt context.

856  *

857  * Returns the number of bytes received on success, or else the status code

858  * returned by the underlying usb_control_msg() call.

859  */

860 int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)

861 {

862         struct usb_device_descriptor *desc;

863         int ret;

865         if (size > sizeof(*desc))

866                 return -EINVAL;

867         desc = kmalloc(sizeof(*desc), GFP_NOIO);

868         if (!desc)

869                 return -ENOMEM;

871         ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);

872         if (ret >= 0)

873                 memcpy(&dev->descriptor, desc, size);

874         kfree(desc);

875         return ret;

876 }

这个函数比较的精悍,先是准备了一个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()是专属内核用的接口。

596 /**

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 ()

604  *

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.

612  *

613  * This call is synchronous, and may not be used in an interrupt context.

614  *

615  * Returns the number of bytes received on success, or else the status code

616  * returned by the underlying usb_control_msg() call.

617  */

618 int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)

619 {

620         int i;

621         int result;

622        

623         memset(buf,0,size);     // Make sure we parse really received data

625         for (i = 0; i < 3; ++i) {

626                 /* retry on length 0 or stall; some devices are flakey */

627                 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),

628                                 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,

629                                 (type << 8) + index, 0, buf, size,

630                                 USB_CTRL_GET_TIMEOUT);

631                 if (result == 0 || result == -EPIPE)

632                         continue;

633                 if (result > 1 && ((u8 *)buf)[1] != type) {

634                         result = -EPROTO;

635                         continue;

636                 }

637                 break;

638         }

639         return result;

640 }

参数type就是用来区分不同的描述符的,协议里说了,GET_DESCRIPTOR请求主要就是适用于三种描述符,设备描述符,配置描述符和字符串描述符。参数index是要获得的描述符的序号,如果希望得到的这种描述符设备里可以有多个,你需要指定获得其中的哪个,比如配置描述符就可以有多个,不过对于设备描述符来说,是只有一个的,所以这里的index应该为0。参数bufsize就是描述你用来放置获得的描述符的缓冲区的。

这个函数的内容挺单调的,主要就是调用了一个usb_control_msg(),你如果到现在还觉得usb_control_msg()只是个熟悉的陌生人,那俺也就太失败了。这里要说的第一个问题是它的一堆参数,这就需要认真了解一下spec 9.4.3里的这张表


GET_DESCRIPTOR请求的数据传输方向很明显是device-to-host的,而且还是协议里规定所有设备都要支持的标准请求,也不是针对端点或者接口什么的,而是针对设备的,所以bRequestType只能为0x80,就是上面表里的10000000B,也等于628行的USB_DIR_INwValue的高位字节表示描述符的类型,低位字节表示描述符的序号,所以就有629行的(type << 8) + indexwIndex对于字符串描述符应该设置为使用语言的ID,对于其它的描述符应该设置为0,所以也有了629行中间的

抱歉!评论已关闭.