📄 usb.c
字号:
unsigned char *begin; int parsed = 0, len, numskipped; header = (struct usb_descriptor_header *)buffer; /* Everything should be fine being passed into here, but we sanity */ /* check JIC */ if (header->bLength > size) { err("ran out of descriptors parsing"); return -1; } if (header->bDescriptorType != USB_DT_ENDPOINT) { warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X", endpoint->bDescriptorType, USB_DT_ENDPOINT); return parsed; } if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); else memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE); le16_to_cpus(&endpoint->wMaxPacketSize); buffer += header->bLength; size -= header->bLength; parsed += header->bLength; /* Skip over the rest of the Class Specific or Vendor Specific */ /* descriptors */ begin = buffer; numskipped = 0; while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; if (header->bLength < 2) { err("invalid descriptor length of %d", header->bLength); return -1; } /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE)) break; dbg("skipping descriptor 0x%X", header->bDescriptorType); numskipped++; buffer += header->bLength; size -= header->bLength; parsed += header->bLength; } if (numskipped) dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); /* Copy any unknown descriptors into a storage area for drivers */ /* to later parse */ len = (int)(buffer - begin); if (!len) { endpoint->extra = NULL; endpoint->extralen = 0; return parsed; } endpoint->extra = kmalloc(len, GFP_KERNEL); if (!endpoint->extra) { err("couldn't allocate memory for endpoint extra descriptors"); endpoint->extralen = 0; return parsed; } memcpy(endpoint->extra, begin, len); endpoint->extralen = len; return parsed;}static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size){ int i, len, numskipped, retval, parsed = 0; struct usb_descriptor_header *header; struct usb_interface_descriptor *ifp; unsigned char *begin; interface->act_altsetting = 0; interface->num_altsetting = 0; interface->max_altsetting = USB_ALTSETTINGALLOC; interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); if (!interface->altsetting) { err("couldn't kmalloc interface->altsetting"); return -1; } while (size > 0) { if (interface->num_altsetting >= interface->max_altsetting) { void *ptr; int oldmas; oldmas = interface->max_altsetting; interface->max_altsetting += USB_ALTSETTINGALLOC; if (interface->max_altsetting > USB_MAXALTSETTING) { warn("too many alternate settings (max %d)", USB_MAXALTSETTING); return -1; } ptr = interface->altsetting; interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); if (!interface->altsetting) { err("couldn't kmalloc interface->altsetting"); interface->altsetting = ptr; return -1; } memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas); kfree(ptr); } ifp = interface->altsetting + interface->num_altsetting; ifp->endpoint = NULL; ifp->extra = NULL; ifp->extralen = 0; interface->num_altsetting++; memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); /* Skip over the interface */ buffer += ifp->bLength; parsed += ifp->bLength; size -= ifp->bLength; begin = buffer; numskipped = 0; /* Skip over any interface, class or vendor descriptors */ while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; if (header->bLength < 2) { err("invalid descriptor length of %d", header->bLength); return -1; } /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE)) break; numskipped++; buffer += header->bLength; parsed += header->bLength; size -= header->bLength; } if (numskipped) dbg("skipped %d class/vendor specific interface descriptors", numskipped); /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); if (len) { ifp->extra = kmalloc(len, GFP_KERNEL); if (!ifp->extra) { err("couldn't allocate memory for interface extra descriptors"); ifp->extralen = 0; return -1; } memcpy(ifp->extra, begin, len); ifp->extralen = len; } /* Did we hit an unexpected descriptor? */ header = (struct usb_descriptor_header *)buffer; if ((size >= sizeof(struct usb_descriptor_header)) && ((header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE))) return parsed; if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { warn("too many endpoints"); return -1; } ifp->endpoint = (struct usb_endpoint_descriptor *) kmalloc(ifp->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL); if (!ifp->endpoint) { err("out of memory"); return -1; } memset(ifp->endpoint, 0, ifp->bNumEndpoints * sizeof(struct usb_endpoint_descriptor)); for (i = 0; i < ifp->bNumEndpoints; i++) { header = (struct usb_descriptor_header *)buffer; if (header->bLength > size) { err("ran out of descriptors parsing"); return -1; } retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); if (retval < 0) return retval; buffer += retval; parsed += retval; size -= retval; } /* We check to see if it's an alternate to this one */ ifp = (struct usb_interface_descriptor *)buffer; if (size < USB_DT_INTERFACE_SIZE || ifp->bDescriptorType != USB_DT_INTERFACE || !ifp->bAlternateSetting) return parsed; } return parsed;}int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer){ int i, retval, size; struct usb_descriptor_header *header; memcpy(config, buffer, USB_DT_CONFIG_SIZE); le16_to_cpus(&config->wTotalLength); size = config->wTotalLength; if (config->bNumInterfaces > USB_MAXINTERFACES) { warn("too many interfaces"); return -1; } config->interface = (struct usb_interface *) kmalloc(config->bNumInterfaces * sizeof(struct usb_interface), GFP_KERNEL); dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces); if (!config->interface) { err("out of memory"); return -1; } memset(config->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface)); buffer += config->bLength; size -= config->bLength; config->extra = NULL; config->extralen = 0; for (i = 0; i < config->bNumInterfaces; i++) { int numskipped, len; char *begin; /* Skip over the rest of the Class Specific or Vendor */ /* Specific descriptors */ begin = buffer; numskipped = 0; while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; if ((header->bLength > size) || (header->bLength < 2)) { err("invalid descriptor length of %d", header->bLength); return -1; } /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE)) break; dbg("skipping descriptor 0x%X", header->bDescriptorType); numskipped++; buffer += header->bLength; size -= header->bLength; } if (numskipped) dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); if (len) { if (config->extralen) { warn("extra config descriptor"); } else { config->extra = kmalloc(len, GFP_KERNEL); if (!config->extra) { err("couldn't allocate memory for config extra descriptors"); config->extralen = 0; return -1; } memcpy(config->extra, begin, len); config->extralen = len; } } retval = usb_parse_interface(config->interface + i, buffer, size); if (retval < 0) return retval; buffer += retval; size -= retval; } return size;}// hub-only!! ... and only exported for reset/reinit path.// otherwise used internally on disconnect/destroy pathvoid usb_destroy_configuration(struct usb_device *dev){ int c, i, j, k; if (!dev->config) return; if (dev->rawdescriptors) { for (i = 0; i < dev->descriptor.bNumConfigurations; i++) kfree(dev->rawdescriptors[i]); kfree(dev->rawdescriptors); } for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { struct usb_config_descriptor *cf = &dev->config[c]; if (!cf->interface) break; for (i = 0; i < cf->bNumInterfaces; i++) { struct usb_interface *ifp = &cf->interface[i]; if (!ifp->altsetting) break; for (j = 0; j < ifp->num_altsetting; j++) { struct usb_interface_descriptor *as = &ifp->altsetting[j]; if(as->extra) { kfree(as->extra); } if (!as->endpoint) break; for(k = 0; k < as->bNumEndpoints; k++) { if(as->endpoint[k].extra) { kfree(as->endpoint[k].extra); } } kfree(as->endpoint); } kfree(ifp->altsetting); } kfree(cf->interface); } kfree(dev->config);}/* for returning string descriptors in UTF-16LE */static int ascii2utf (char *ascii, __u8 *utf, int utfmax){ int retval; for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) { *utf++ = *ascii++ & 0x7f; *utf++ = 0; } return retval;}/* * root_hub_string is used by each host controller's root hub code, * so that they're identified consistently throughout the system. */int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len){ char buf [30]; // assert (len > (2 * (sizeof (buf) + 1))); // assert (strlen (type) <= 8); // language ids if (id == 0) { *data++ = 4; *data++ = 3; /* 4 bytes data */ *data++ = 0; *data++ = 0; /* some language id */ return 4; // serial number } else if (id == 1) { sprintf (buf, "%x", serial); // product description } else if (id == 2) { sprintf (buf, "USB %s Root Hub", type); // id 3 == vendor description // unsupported IDs --> "stall" } else return 0; data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -