📄 usb.c
字号:
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; 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 at 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 descriptor which is at or below */ /* us in the descriptor heirarchy then return */ 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 = NULL; ifp->extralen = 0; } else { 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(dev, 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_device *dev, struct usb_config_descriptor *config, char *buffer){ int i; int retval; int size; struct usb_descriptor_header *header; memcpy(config, buffer, USB_DT_INTERFACE_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; for (i = 0; i < config->bNumInterfaces; i++) { header = (struct usb_descriptor_header *)buffer; if ((header->bLength > size) || (header->bLength <= 2)) { err("ran out of descriptors parsing"); return -1; } if (header->bDescriptorType != USB_DT_INTERFACE) { warn("unexpected descriptor 0x%X", header->bDescriptorType); buffer += header->bLength; size -= header->bLength; continue; } retval = usb_parse_interface(dev, config->interface + i, buffer, size); if (retval < 0) return retval; buffer += retval; size -= retval; } return size;}void usb_destroy_configuration(struct usb_device *dev){ int c, i, j, k; if (!dev->config) return; 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);} void usb_init_root_hub(struct usb_device *dev){ dev->devnum = -1; dev->slow = 0; dev->actconfig = NULL;}/* * __usb_get_extra_descriptor() finds a descriptor of specific type in the * extra field of the interface and endpoint descriptor structs. */int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr){ struct usb_descriptor_header *header; 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 (header->bDescriptorType == type) { *ptr = header; return 0; } buffer += header->bLength; size -= header->bLength; } return -1;}/* * Something got disconnected. Get rid of it, and all of its children. */void usb_disconnect(struct usb_device **pdev){ struct usb_device * dev = *pdev; int i; if (!dev) return; *pdev = NULL; info("USB disconnect on device %d", dev->devnum); if (dev->actconfig) { for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { struct usb_interface *interface = &dev->actconfig->interface[i]; struct usb_driver *driver = interface->driver; if (driver) { driver->disconnect(dev, interface->private_data); usb_driver_release_interface(driver, interface); } } } /* Free up all the children.. */ for (i = 0; i < USB_MAXCHILDREN; i++) { struct usb_device **child = dev->children + i; if (*child) usb_disconnect(child); } /* remove /proc/bus/usb entry */ usbdevfs_remove_device(dev); /* Free up the device itself, including its device number */ if (dev->devnum > 0) clear_bit(dev->devnum, &dev->bus->devmap.devicemap); usb_free_dev(dev); }/* * Connect a new USB device. This basically just initializes * the USB device information and sets up the topology - it's * up to the low-level driver to reset the port and actually * do the setup (the upper levels don't know how to do that). */void usb_connect(struct usb_device *dev){ int devnum; // FIXME needs locking for SMP!! /* why? this is called only from the hub thread, * which hopefully doesn't run on multiple CPU's simulatenously 8-) */ dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); if (devnum < 128) { set_bit(devnum, dev->bus->devmap.devicemap); dev->devnum = devnum; }}/* * These are the actual routines to send * and receive control messages. */#define GET_TIMEOUT 3#define SET_TIMEOUT 3int usb_set_address(struct usb_device *dev){ return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, 0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT);}int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size){ int i = 5; int result; memset(buf,0,size); // Make sure we parse really received data while (i--) { if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) >= 0 || result == -EPIPE) break; } return result;}int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size){ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, (type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);}int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size){ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (USB_DT_STRING << 8) + index, langid, buf, size, HZ * GET_TIMEOUT);}int usb_get_device_descriptor(struct usb_device *dev){ int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); if (ret >= 0) { le16_to_cpus(&dev->descriptor.bcdUSB); le16_to_cpus(&dev->descriptor.idVendor); le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&dev->descriptor.bcdDevice); } return ret;}int usb_get_status(struct usb_device *dev, int type, int target, void *data){ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ * GET_TIMEOUT);}int usb_get_protocol(struct usb_device *dev, int ifnum){ unsigned char type; int ret; if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0) return ret; return type;}int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol){ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT);}int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id){ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (duration << 8) | report_id, ifnum, NULL, 0, HZ * SET_TIMEOUT);}static void usb_set_maxpacket(struct usb_device *dev){ int i, j, b; struct usb_interface *ifp; for (i=0; i<dev->actconfig->bNumInterfaces; i++) { ifp = dev->actconfig->interface + i; for (j = 0; j < ifp->num_altsetting; j++) { struct usb_interface_descriptor *as = ifp->altsetting + j; struct usb_endpoint_descriptor *ep = as->endpoint; int e; for (e=0; e<as->bNumEndpoints; e++) { b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; } else if (usb_endpoint_out(ep[e].bEndpointAddress)) { if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; } else { if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -