USB Core 九

来源:互联网 发布:webkey 源码 编辑:程序博客网 时间:2024/06/05 04:34
static int usb_parse_configuration(struct device *ddev, int cfgidx,struct usb_host_config *config, unsigned char *buffer, int size){ unsigned char *buffer0 = buffer; int cfgno; int nintf, nintf_orig; int i, j, n; struct usb_interface_cache *intfc; unsigned char *buffer2; int size2; struct usb_descriptor_header *header; int len, retval; u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES]; memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); if (config->desc.bDescriptorType != USB_DT_CONFIG ||config->desc.bLength < USB_DT_CONFIG_SIZE) { dev_err(ddev, "invalid descriptor for config index %d: " "type = 0x%X, length = %d\n", cfgidx, config->desc.bDescriptorType, config->desc.bLength); return -EINVAL; } cfgno = config->desc.bConfigurationValue; buffer += config->desc.bLength; size -= config->desc.bLength; nintf = nintf_orig = config->desc.bNumInterfaces;//获得这个配置所拥有的接口数目 if (nintf > USB_MAXINTERFACES) { dev_warn(ddev, "config %d has too many interfaces: %d, " "using maximum allowed: %d\n", cfgno, nintf, USB_MAXINTERFACES); nintf = USB_MAXINTERFACES; } /* Go through the descriptors, checking their length and counting the * number of altsettings for each interface */ n = 0;//统计记录一下这个配置里每个接口所拥有的设置数目 for ((buffer2 = buffer, size2 = size);//这个循环里使用的是buffer2 和size2, buffer 和size 的两个替身 size2 > 0; (buffer2 += header->bLength, size2 -= header->bLength)) {/* struct usb_descriptor_header { __u8 bLength; __u8 bDescriptorType; } __attribute__ ((packed));*/ if (size2 < sizeof(struct usb_descriptor_header)) { dev_warn(ddev, "config %d descriptor has %d excess " "byte%s, ignoring\n", cfgno, size2, plural(size2)); break; } header = (struct usb_descriptor_header *) buffer2; if ((header->bLength > size2) || (header->bLength < 2)) { dev_warn(ddev, "config %d has an invalid descriptor " "of length %d, skipping remainder of theconfig\n", cfgno, header->bLength); break; } if (header->bDescriptorType == USB_DT_INTERFACE) { struct usb_interface_descriptor *d; int inum; d = (struct usb_interface_descriptor *) header; if (d->bLength < USB_DT_INTERFACE_SIZE) { dev_warn(ddev, "config %d has an invalid " "interface descriptor of length %d, " "skipping\n", cfgno, d->bLength); continue; } inum = d->bInterfaceNumber; if (inum >= nintf_orig) dev_warn(ddev, "config %d has an invalid " "interface number: %d but max is %d\n", cfgno, inum, nintf_orig - 1); /*   n 记录的是接口的数目,数组inums 里的每一项都表示一个接口号,数组nalts 里的每一项记录的是每个接口拥有的设置数目,inums 和nalts 两个数组里的元素是一一对应的,inums[0]就对应nalts[0],inums[1]就对应nalts[1]。发送GET_DESCRIPTOR 请求时,设备并不一定会按照接口1,接口2 这样的顺序循规蹈矩的返回数据. */ for (i = 0; i < n; ++i) { if (inums[i] == inum) break; } if (i < n) { if (nalts[i] < 255) ++nalts[i]; } else if (n < USB_MAXINTERFACES) { inums[n] = inum; nalts[n] = 1; ++n; } } else if (header->bDescriptorType == USB_DT_DEVICE || header->bDescriptorType == USB_DT_CONFIG) dev_warn(ddev, "config %d contains an unexpected " "descriptor of type 0x%X, skipping\n", cfgno, header->bDescriptorType); } /* for ((buffer2 = buffer, size2 = size); ...) */ size = buffer2 - buffer;//buffer 的最后边儿可能会有些垃圾数据,为了去除这些洋垃圾,这里需要将size和配置描述符里的那个wTotalLength 修正一下 config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0); if (n != nintf) dev_warn(ddev, "config %d has %d interface%s, different from " "the descriptor's value: %d\n", cfgno, n, plural(n), nintf_orig); else if (n == 0) dev_warn(ddev, "config %d has no interfaces?\n", cfgno); config->desc.bNumInterfaces = nintf = n; /* Check for missing interface numbers */ for (i = 0; i < nintf; ++i) { for (j = 0; j < nintf; ++j) { if (inums[j] == i) break; } if (j >= nintf) dev_warn(ddev, "config %d has no interface number " "%d\n", cfgno, i); } /* Allocate the usb_interface_caches and altsetting arrays */ for (i = 0; i < nintf; ++i) { j = nalts[i]; if (j > USB_MAXALTSETTING) { dev_warn(ddev, "too many alternate settings for " "config %d interface %d: %d, " "using maximum allowed: %d\n", cfgno, inums[i], j, USB_MAXALTSETTING); nalts[i] = j = USB_MAXALTSETTING; } len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j; config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL); if (!intfc) return -ENOMEM; kref_init(&intfc->ref); } /* Skip over any Class Specific or Vendor Specific descriptors; * find the first interface descriptor */ config->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_INTERFACE, USB_DT_INTERFACE, &n);//调用find_next_descriptor()在buffer 里寻找配置描述符后面跟着的第一个接口描述符。 config->extralen = i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "configuration"); buffer += i;//根据find_next_descriptor 的结果修正buffer 和size。 size -= i; /* Parse all the interface/altsetting descriptors *//*  如果size 大于0,就说明配置描述符后面找到了一个接口描述符,根据这个接口描述符的长度,已经可以解析出一个  完整的接口描述符了,但是仍然没到乐观的时候,这个接口描述符后面还会跟着一群端点描述符,再然后还会有其它的接口描述符*/ while (size > 0){ retval = usb_parse_interface(ddev, cfgno, config, buffer, size, inums, nalts);//暂时只需要知道它返回的时候,buffer 的位置已经在下一个接口描述符那里了 if (retval < 0) return retval; buffer += retval; size -= retval; } /* Check for missing altsettings */ for (i = 0; i < nintf; ++i) { intfc = config->intf_cache[i]; for (j = 0; j < intfc->num_altsetting; ++j) { for (n = 0; n < intfc->num_altsetting; ++n) { if (intfc->altsetting[n].desc.bAlternateSetting == j) break; }if (n >= intfc->num_altsetting)dev_warn(ddev, "config %d interface %d has no ""altsetting %d\n", cfgno, inums[i], j); } } return 0; }


 

原创粉丝点击