summaryrefslogtreecommitdiff
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c74
1 files changed, 72 insertions, 2 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 694476ea22ac..ea6cd7feea01 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -165,7 +165,50 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
+#ifdef CONFIG_FSL_USB_TEST_MODE
+static u8 usb_device_white_list[] = {
+ USB_CLASS_HID,
+ USB_CLASS_HUB,
+ USB_CLASS_MASS_STORAGE
+};
+
+static inline int in_white_list(u8 interfaceclass)
+{
+ int i;
+ for (i = 0; i < sizeof(usb_device_white_list); i++) {
+ if (interfaceclass == usb_device_white_list[i])
+ return 1;
+ }
+ return 0;
+}
+
+static inline int device_in_white_list(struct usb_device *udev)
+{
+ int i;
+ int num_configs;
+ struct usb_host_config *c;
+
+ /* for test fixture, we always return 1 */
+ if (udev->descriptor.idVendor == 0x1A0A)
+ return 1;
+
+ c = udev->config;
+ num_configs = udev->descriptor.bNumConfigurations;
+ for (i = 0; i < num_configs; (i++, c++)) {
+ struct usb_interface_descriptor *desc = NULL;
+
+ /* It's possible that a config has no interfaces! */
+ if (c->desc.bNumInterfaces > 0)
+ desc = &c->intf_cache[0]->altsetting->desc;
+
+ if (desc && !in_white_list((u8)desc->bInterfaceClass))
+ continue;
+ return 1;
+ }
+ return 0;
+}
+#endif
static int usb_reset_and_verify_device(struct usb_device *udev);
static inline char *portspeed(struct usb_hub *hub, int portstatus)
@@ -1696,7 +1739,18 @@ void usb_disconnect(struct usb_device **pdev)
* for de-configuring the device and invoking the remove-device
* notifier chain (used by usbfs and possibly others).
*/
- device_del(&udev->dev);
+/* device_del(&udev->dev); */
+ /* If error occur during enumeration, maybe the device_add
+ * will not call at all, so we need to identify whether this
+ * device has been added or not, here we use dev.driver to
+ * tell it
+ */
+ if (udev->dev.driver) {
+ device_del(&udev->dev);
+ printk(KERN_DEBUG "device_del called\n");
+ } else {
+ printk(KERN_DEBUG "device_del not need to call\n");
+ }
/* Free the device number and delete the parent's children[]
* (or root_hub) pointer.
@@ -1914,6 +1968,14 @@ int usb_new_device(struct usb_device *udev)
udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
+#ifdef CONFIG_FSL_USB_TEST_MODE
+ if (!device_in_white_list(udev)) {
+ printk(KERN_ERR "unsupported device: not in white list\n");
+ goto fail;
+ } else {
+ printk(KERN_DEBUG "supported device\n");
+ }
+#endif
/* Tell the world! */
announce_device(udev);
@@ -2645,7 +2707,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_device *udev;
udev = hdev->children [port1-1];
- if (udev && udev->can_submit) {
+ if (udev && udev->can_submit && udev->dev.driver) {
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
if (msg.event & PM_EVENT_AUTO)
return -EBUSY;
@@ -3300,6 +3362,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
usb_set_device_state(udev, USB_STATE_POWERED);
udev->bus_mA = hub->mA_per_port;
udev->level = hdev->level + 1;
+#ifdef CONFIG_FSL_USB_TEST_MODE
+ printk(KERN_INFO "+++ %s:udev->level :%d", __func__,
+ udev->level);
+#endif
udev->wusb = hub_is_wusb(hub);
/* Only USB 3.0 devices are connected to SuperSpeed hubs. */
@@ -3518,6 +3584,10 @@ static void hub_events(void)
if (ret < 0)
continue;
+#ifdef CONFIG_FSL_USB_TEST_MODE
+ if (portstatus & USB_PORT_STAT_TEST)
+ continue;
+#endif
if (portchange & USB_PORT_STAT_C_CONNECTION) {
clear_port_feature(hdev, i,
USB_PORT_FEAT_C_CONNECTION);