static int usb_hub_probe(struct usb_device *usbdev, const struct usb_device_id *id) { usbdev->dev.detect = usb_hub_detect; return usb_hub_configure(usbdev); }
int usb_hub_probe(struct usb_device *dev, int ifnum) { struct usb_interface *iface; struct usb_endpoint_descriptor *ep; int ret; iface = &dev->config.if_desc[ifnum]; /* Is it a hub? */ if (iface->desc.bInterfaceClass != USB_CLASS_HUB) return 0; /* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((iface->desc.bInterfaceSubClass != 0) && (iface->desc.bInterfaceSubClass != 1)) return 0; /* Multiple endpoints? What kind of mutant ninja-hub is this? */ if (iface->desc.bNumEndpoints != 1) return 0; ep = &iface->ep_desc[0]; /* Output endpoint? Curiousier and curiousier.. */ if (!(ep->bEndpointAddress & USB_DIR_IN)) return 0; /* If it's not an interrupt endpoint, we'd better punt! */ if ((ep->bmAttributes & 3) != 3) return 0; /* We found a hub */ debug("USB hub found\n"); ret = usb_hub_configure(dev); return ret; }
int usb_hub_probe(struct usb_device *dev, int ifnum) { int ret; ret = usb_hub_check(dev, ifnum); if (ret) return 0; ret = usb_hub_configure(dev); return ret; }
int usb_hub_probe(struct usb_device *dev, int ifnum) { int ret; ret = usb_hub_check(dev, ifnum); if (ret) { debug("usb_hub_probe return with value = %d.\r\n", ret); return 0; } ret = usb_hub_configure(dev); return ret; }
static void *hub_probe(struct usb_device *dev, unsigned int i, const struct usb_device_id *id) { struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_hub *hub; unsigned long flags; DBG_HOST_HUB("### >>> Enter hub.c file --> hub_probe function \n"); interface = &dev->actconfig->interface[i].altsetting[0]; /* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((interface->bInterfaceSubClass != 0) && (interface->bInterfaceSubClass != 1)) { err("invalid subclass (%d) for USB hub device #%d", interface->bInterfaceSubClass, dev->devnum); return NULL; } /* Multiple endpoints? What kind of mutant ninja-hub is this? */ if (interface->bNumEndpoints != 1) { err("invalid bNumEndpoints (%d) for USB hub device #%d", interface->bNumEndpoints, dev->devnum); return NULL; } endpoint = &interface->endpoint[0]; /* Output endpoint? Curiousier and curiousier.. */ if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { err("Device #%d is hub class, but has output endpoint?", dev->devnum); return NULL; } /* If it's not an interrupt endpoint, we'd better punt! */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { err("Device #%d is hub class, but has endpoint other than interrupt?", dev->devnum); return NULL; } /* We found a hub */ info("USB hub found"); hub = kmalloc(sizeof(*hub), GFP_KERNEL); if (!hub) { err("couldn't kmalloc hub struct"); return NULL; } memset(hub, 0, sizeof(*hub)); INIT_LIST_HEAD(&hub->event_list); hub->dev = dev; init_MUTEX(&hub->khubd_sem); /* Record the new hub's existence */ spin_lock_irqsave(&hub_event_lock, flags); INIT_LIST_HEAD(&hub->hub_list); list_add(&hub->hub_list, &hub_list); spin_unlock_irqrestore(&hub_event_lock, flags); if (usb_hub_configure(hub, endpoint) >= 0) return hub; err("hub configuration failed for device #%d", dev->devnum); /* free hub, but first clean up its list. */ spin_lock_irqsave(&hub_event_lock, flags); /* Delete it and then reset it */ list_del(&hub->event_list); INIT_LIST_HEAD(&hub->event_list); list_del(&hub->hub_list); INIT_LIST_HEAD(&hub->hub_list); spin_unlock_irqrestore(&hub_event_lock, flags); kfree(hub); return NULL; }
int usb_hub_scan(struct udevice *hub) { struct usb_device *udev = dev_get_parentdata(hub); return usb_hub_configure(udev); }
static int hub_probe(USB_DEV_T *dev, USB_IF_DESC_T *ifd, const USB_DEV_ID_T *id) { EP_INFO_T *ep_info; USB_HUB_T *hub; int ifnum; int i; USB_debug("hub_probe - dev=0x%x\n", (int)dev); ifnum = ifd->bInterfaceNumber; if(dev->descriptor.bDeviceClass != 0x09) return USB_ERR_NODEV; ep_info = NULL; for(i = 0; i < dev->ep_list_cnt; i++) { if((dev->ep_list[i].ifnum == ifnum) && ((dev->ep_list[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { ep_info = &dev->ep_list[i]; break; } } if(ep_info == NULL) { USB_error("hub int ep not found!\n"); return USB_ERR_NODEV; } /* Output endpoint? Curiousier and curiousier.. */ if(!(ep_info->bEndpointAddress & USB_DIR_IN)) { USB_error("Error - Device #%d is hub class, but has output endpoint?\n", dev->devnum); return USB_ERR_NODEV; } /* If it's not an interrupt endpoint, we'd better punt! */ if((ep_info->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { USB_error("Error - Device #%d is hub class, but has endpoint other than interrupt?\n", dev->devnum); return USB_ERR_NODEV; } /* We found a hub */ USB_debug("USB hub found\n"); hub = usbh_alloc_hubdev(); if(!hub) return USB_ERR_NOMEM; INIT_LIST_HEAD(&hub->event_list); hub->dev = dev; if(usb_hub_configure(hub, ep_info) == 0) return 0; USB_error("Error - hub configuration failed for device #%d\n", dev->devnum); /* Delete it and then reset it */ list_del(&hub->event_list); INIT_LIST_HEAD(&hub->event_list); usbh_free_hubdev(hub); return USB_ERR_NODEV; }
static int usb_hub_configure(struct usb_device *dev) { int i; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ); unsigned char *bitmap; short hubCharacteristics; struct usb_hub_descriptor *descriptor; struct usb_hub_device *hub; #ifdef USB_HUB_DEBUG struct usb_hub_status *hubsts; #endif /* "allocate" Hub device */ hub = usb_hub_allocate(); if (hub == NULL) return -1; hub->pusb_dev = dev; /* Get the the hub descriptor */ if (usb_get_hub_descriptor(dev, buffer, 4) < 0) { USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \ "descriptor, giving up %lX\n", dev->status); return -1; } descriptor = (struct usb_hub_descriptor *)buffer; /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */ i = descriptor->bLength; if (i > USB_BUFSIZ) { USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \ "descriptor - too long: %d\n", descriptor->bLength); return -1; } if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) { USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \ "descriptor 2nd giving up %lX\n", dev->status); return -1; } memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength); /* adjust 16bit values */ put_unaligned(le16_to_cpu(get_unaligned( &descriptor->wHubCharacteristics)), &hub->desc.wHubCharacteristics); /* set the bitmap */ bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; /* devices not removable by default */ memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0]; memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i]; for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) hub->desc.PortPowerCtrlMask[i] = descriptor->PortPowerCtrlMask[i]; dev->maxchild = descriptor->bNbrPorts; USB_HUB_PRINTF("%d ports detected\n", dev->maxchild); hubCharacteristics = get_unaligned(&hub->desc.wHubCharacteristics); switch (hubCharacteristics & HUB_CHAR_LPSM) { case 0x00: USB_HUB_PRINTF("ganged power switching\n"); break; case 0x01: USB_HUB_PRINTF("individual port power switching\n"); break; case 0x02: case 0x03: USB_HUB_PRINTF("unknown reserved power switching mode\n"); break; } if (hubCharacteristics & HUB_CHAR_COMPOUND) USB_HUB_PRINTF("part of a compound device\n"); else USB_HUB_PRINTF("standalone hub\n"); switch (hubCharacteristics & HUB_CHAR_OCPM) { case 0x00: USB_HUB_PRINTF("global over-current protection\n"); break; case 0x08: USB_HUB_PRINTF("individual port over-current protection\n"); break; case 0x10: case 0x18: USB_HUB_PRINTF("no over-current protection\n"); break; } USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2); USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent); for (i = 0; i < dev->maxchild; i++) USB_HUB_PRINTF("port %d is%s removable\n", i + 1, hub->desc.DeviceRemovable[(i + 1) / 8] & \ (1 << ((i + 1) % 8)) ? " not" : ""); if (sizeof(struct usb_hub_status) > USB_BUFSIZ) { USB_HUB_PRINTF("usb_hub_configure: failed to get Status - " \ "too long: %d\n", descriptor->bLength); return -1; } if (usb_get_hub_status(dev, buffer) < 0) { USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n", dev->status); return -1; } #ifdef USB_HUB_DEBUG hubsts = (struct usb_hub_status *)buffer; #endif USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n", le16_to_cpu(hubsts->wHubStatus), le16_to_cpu(hubsts->wHubChange)); USB_HUB_PRINTF("local power source is %s\n", (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? \ "lost (inactive)" : "good"); USB_HUB_PRINTF("%sover-current condition exists\n", (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \ "" : "no "); usb_hub_power_on(hub); for (i = 0; i < dev->maxchild; i++) { ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus, portchange; int ret; ulong start = get_timer(0); /* * Wait for (whichever finishes first) * - A maximum of 10 seconds * This is a purely observational value driven by connecting * a few broken pen drives and taking the max * 1.5 approach * - connection_change and connection state to report same * state */ do { ret = usb_get_port_status(dev, i + 1, portsts); if (ret < 0) { USB_HUB_PRINTF("get_port_status failed\n"); break; } portstatus = le16_to_cpu(portsts->wPortStatus); portchange = le16_to_cpu(portsts->wPortChange); #ifdef CONFIG_MARVELL /* - USB3.0 issue with Avanta-LP/Armada-375: * If usb device was already connected before detection ('usb start'), * port connect status bit is set (USB_PORT_STAT_CONNECTION), * but port connect status change bit (USB_PORT_STAT_C_CONNECTION) is not set. * - Added WA (aligned with kernel driver): instead of checking port change status, * to be satisfied with checking USB_PORT_STAT_CONNECTION Bit on portstatus only" */ if (((portchange & USB_PORT_STAT_C_CONNECTION) == (portstatus & USB_PORT_STAT_CONNECTION)) || (portstatus & USB_PORT_STAT_CONNECTION)) #else if ((portchange & USB_PORT_STAT_C_CONNECTION) == (portstatus & USB_PORT_STAT_CONNECTION)) #endif break; mdelay(100); } while (get_timer(start) < CONFIG_SYS_HZ * 10); if (ret < 0) continue; USB_HUB_PRINTF("Port %d Status %X Change %X\n", i + 1, portstatus, portchange); #ifdef CONFIG_MARVELL /* - USB3.0 issue with Avanta-LP/Armada-375: * If usb device was already connected before detection ('usb start'), * port connect status bit is set (USB_PORT_STAT_CONNECTION), * but port connect status change bit (USB_PORT_STAT_C_CONNECTION) is not set. * - Added WA (aligned with kernel driver): instead of checking port change status, * to be satisfied with checking USB_PORT_STAT_CONNECTION Bit on portstatus only" */ if ((portchange & USB_PORT_STAT_C_CONNECTION) || (portstatus & USB_PORT_STAT_CONNECTION)) { #else if (portchange & USB_PORT_STAT_C_CONNECTION) { #endif USB_HUB_PRINTF("port %d connection change\n", i + 1); usb_hub_port_connect_change(dev, i); } if (portchange & USB_PORT_STAT_C_ENABLE) { USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); /* EM interference sometimes causes bad shielded USB * devices to be shutdown by the hub, this hack enables * them again. Works at least with mouse driver */ if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && ((dev->children[i]))) { USB_HUB_PRINTF("already running port %i " \ "disabled by hub (EMI?), " \ "re-enabling...\n", i + 1); usb_hub_port_connect_change(dev, i); } } if (portstatus & USB_PORT_STAT_SUSPEND) { USB_HUB_PRINTF("port %d suspend change\n", i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); } if (portchange & USB_PORT_STAT_C_OVERCURRENT) { USB_HUB_PRINTF("port %d over-current change\n", i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); usb_hub_power_on(hub); } if (portchange & USB_PORT_STAT_C_RESET) { USB_HUB_PRINTF("port %d reset change\n", i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); } } /* end for i all ports */ return 0; } int usb_hub_probe(struct usb_device *dev, int ifnum) { struct usb_interface *iface; struct usb_endpoint_descriptor *ep; int ret; iface = &dev->config.if_desc[ifnum]; /* Is it a hub? */ if (iface->desc.bInterfaceClass != USB_CLASS_HUB) return 0; /* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((iface->desc.bInterfaceSubClass != 0) && (iface->desc.bInterfaceSubClass != 1)) return 0; /* Multiple endpoints? What kind of mutant ninja-hub is this? */ if (iface->desc.bNumEndpoints != 1) return 0; ep = &iface->ep_desc[0]; /* Output endpoint? Curiousier and curiousier.. */ if (!(ep->bEndpointAddress & USB_DIR_IN)) return 0; /* If it's not an interrupt endpoint, we'd better punt! */ if ((ep->bmAttributes & 3) != 3) return 0; /* We found a hub */ USB_HUB_PRINTF("USB hub found\n"); ret = usb_hub_configure(dev); return ret; }