Linux那些事儿之我是USB
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
 29.设备的生命线(十)

29.设备的生命线(十)

跟着设备的生命线走到现在,我算是明白了,事物的发展都是越往后就越高级越复杂,再看一看表1.29.1,比较和上次那张表出现时有什么变化。

表 1.29.1

接下来设备的目标当然就是Configured了。

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

860 int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
861 {
862     struct usb_device_descriptor *desc;
863     int ret;
864
865     if (size > sizeof(*desc))
866         return -EINVAL;
867     desc = kmalloc(sizeof(*desc), GFP_NOIO);
868     if (!desc)
869         return -ENOMEM;
870
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()是专属内核用的接口。

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     me mset(buf,0,size);  // Make sure we parse really received data
624
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。参数buf和size就是描述你用来放置获得的描述符的缓冲区的。

这个函数的内容挺单调的,主要就是调用了一个usb_control_ msg()。这里要说的第一个问题是它的一堆参数,这就需要认真了解如图1.29.1所示的这张表。

图1.29.1 GET_DESCRIPTOR请求

GET_DESCRIPTOR请求的数据传输方向是device-to-host,而且还是协议中规定所有设备都要支持的标准请求,也不是针对端点或者接口,而是针对设备的。所以bRequestType只能为0x80,就是上面表里的10000000B,也等于628行的USB_DIR_IN。wValue的高位字节表示描述符的类型,低位字节表示描述符的序号,所以就有629行的(type << 8) + index。wIndex对于字符串描述符应该设置为使用语言的ID,对于其他的描述符应该设置为0,所以也有了629行中间的那个0。至于wLength,就是描述符的长度,对于设备描述符,一般来说你都会指定为USB_DT_DEVICE_SIZE。

USB_CTRL_GET_TIMEOUT是定义在include/linux/usb.h里的一个宏,值为5000,表示有5s的超时时间。

1330 #define USB_CTRL_GET_TIMEOUT  5000
1331 #define USB_CTRL_SET_TIMEOUT  5000

第二个问题就是为什么会有3次循环。这个又要归咎于一些不守规矩的生产设备厂商了,比如一些USB读卡器,一次请求还不一定能成功,但是设备描述符拿不到接下来就没法子走了,所以这里多试几次。至于631行到636行之间的代码都是判断是不是成功得到请求的描述符,这个版本的内核在这里的判断还比较混乱,就不多说了,你只要知道((u8 *)buf)[1] != type是用来判断获得描述符是不是请求的类型就可以了。

现在设备描述符已经有了,但是只有设备描述符是远远不够的,你从设备描述符里只能知道它一共支持几个配置,但是要配置一个设备时要知道具体每个配置有什么用,所以接下来就要获得各个配置的配置描述符,并且拿结果去充实struct usb_device的config、rawdescriptors等相关元素。

core内部并不直接调用上面的usb_get_descriptor()去完成这个任务,而是调用config.c里的usb_get_configuration()。

476 int usb_get_configuration(struct usb_device *dev)
477 {
478     struct device *ddev = &dev->dev;
479     int ncfg = dev->descriptor.bNumConfigurations;
480     int result = -ENOMEM;
481     unsigned int cfgno, length;
482     unsigned char *buffer;
483     unsigned char *bigbuffer;
484     struct usb_config_descriptor *desc;
485
486     if (ncfg > USB_MAXCONFIG) {
487         dev_warn(ddev, "too many configurations: %d, "
488                  "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
489         dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
490     }
491
492     if (ncfg < 1) {
493         dev_err(ddev, "no configurations\n");
494         return -EINVAL;
495     }
496
497     length = ncfg * sizeof(struct usb_host_config);
498     dev->config = kzalloc(length, GFP_KERNEL);
499     if (!dev->config)
500         goto err2;
501
502     length = ncfg * sizeof(char *);
503     dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
504     if (!dev->rawdescriptors)
505         goto err2;
506
507     buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
508     if (!buffer)
509         goto err2;
510     desc = (struct usb_config_descriptor *)buffer;
511
512     for (cfgno = 0; cfgno < ncfg; cfgno++) {
513        /* We grab just the first descriptor so we know how long
514         * the whole configuration is */
515        result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
516                buffer, USB_DT_CONFIG_SIZE);
517        if (result < 0) {
518            dev_err(ddev, "unable to read config index %d "
519                      "descriptor/%s\n", cfgno, "start");
520            dev_err(ddev, "chopping to %d config(s)\n", cfgno);
521            dev->descriptor.bNumConfigurations = cfgno;
522            break;
523         } else if (result < 4) {
524            dev_err(ddev, "config index %d descriptor too short "
525                      "(expected %i, got %i)\n", cfgno,
526                      USB_DT_CONFIG_SIZE, result);
527            result = -EINVAL;
528            goto err;
529         }
530         length = max((int) le16_to_cpu(desc->wTotalLength),
531                USB_DT_CONFIG_SIZE);
532
533   /* Now that we know the length, get the whole thing */
534       bigbuffer = kmalloc(length, GFP_KERNEL);
535       if (!bigbuffer) {
536           result = -ENOMEM;
537           goto err;
538       }
539       result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
540               bigbuffer, length);
541       if (result < 0) {
542           dev_err(ddev, "unable to read config index %d "
543                  "descriptor/%s\n", cfgno, "all");
544           kfree(bigbuffer);
545           goto err;
546   }
547   if (result < length) {
548       dev_warn(ddev, "config index %d descriptor too short "
549           "(expected %i, got %i)\n", cfgno, length, result);
550       length = result;
551    }
552
553    dev->rawdescriptors[cfgno] = bigbuffer;
554
555    result = usb_parse_configuration(&dev->dev, cfgno,
556             &dev->config[cfgno], bigbuffer, length);
557   if (result < 0) {
558       ++cfgno;
559       goto err;
560    }
561  }
562  result = 0;
563
564 err:
565   kfree(buffer);
566   dev->descriptor.bNumConfigurations = cfgno;
567 err2:
568   if (result == -ENOMEM)
569       dev_err(ddev, "out of memory\n");
570   return result;
571 }

要想得到配置描述符,最终都不可避免要向设备发送GET_DESCRIPTOR请求,这就需要以USB_DT_CONFIG为参数调用usb_get_descriptor函数,也就需要知道该为获得的描述符准备多大的一个缓冲区。本来这个长度应该很明确地为USB_DT_CONFIG_SIZE,它表示的就是配置描述符的大小,但是实际上不是这么回事儿,USB_DT_CONFIG_SIZE只表示配置描述符本身的大小,并不表示GET_DESCRIPTOR请求返回结果的大小。因为向设备发送GET_DESCRIPTOR请求时,设备并不只是返回一个配置描述符,而是将这个配置下面的所有接口描述符、端点描述还有class-或vendor-specific描述符都返回了。

那么这个总长度如何得到呢?在神秘的配置描述符里有一个神秘的字段wTotalLength,它里面记录的就是这个总长度。那么问题就简单了,可以首先发送USB_DT_CONFIG_SIZE个字节的请求过去,获得这个配置描述符的内容,从而获得那个总长度,然后以这个长度再请求一次,这样就可以获得一个配置下面所有的描述符内容了。上面的usb_get_configuration()采用的就是这个处理方法。

479行,获得设备理配置描述符的数目。

486行,USB_MAXCONFIG是config.c中定义的。

14 #define USB_MAXCONFIG       8   /* Arbitrary limit */

限制了一个设备最多只能支持8种配置拥有8个配置描述符,如果超出了这个限制,489行就强制它为这个最大值。不过如果设备中没有任何一个配置描述符,什么配置都没有,那是不可能的,492行这关就过不去。

498行,struct usb_device里的config表示设备拥有的所有配置,你设备有多少个配置就为它准备多大的空间。

503行,rawdescriptors,这是一个字符指针数组里的每一项都指向一个使用GET_DESCRIPTOR请求去获取配置描述符时所得到的结果。

507行,准备一个大小为USB_DT_CONFIG_SIZE的缓冲区,第一次发送GET_DESCRIPTOR请求要用到。

512行,剩下的主要就是这个for循环了,获取每一个配置的那些描述符。

515行,如上面所说的,首先发送USB_DT_CONFIG_SIZE个字节请求,获得配置描述符的内容。然后对返回的结果进行检验,知道为什么523行会判断结果是不是小于4吗?答案就在配置描述符中,里面的第3字节和第4字节就是wTotalLength,只要得到前4个字节,就已经完成任务能够获得总长度了。

534行,既然总长度已经有了,那么这里就为接下来的GET_DESCRIPTOR请求准备一个大点的缓冲区。

539行,现在可以获得这个配置相关的所有描述符了。然后是对返回结果的检验,将得到的那一堆数据的地址赋给rawdescriptors数组里的指针。

555行,从这个颇有韵味的数字555开始,你将会遇到另一个函数,它将对前面GET_ DESCRIPTOR请求获得的那堆数据进行处理。