diff options
-rw-r--r-- | drivers/usb/gadget/android.c | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/composite.c | 29 | ||||
-rw-r--r-- | include/linux/usb/composite.h | 4 |
3 files changed, 33 insertions, 11 deletions
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index 7618a073de58..c7a54787a044 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -337,7 +337,7 @@ void android_enable_function(struct usb_function *f, int enable) */ list_for_each_entry(func, &android_config_driver.functions, list) { if (!strcmp(func->name, "usb_mass_storage")) { - usb_function_set_enabled(f, !enable); + usb_function_set_enabled(func, !enable); break; } } @@ -348,14 +348,7 @@ void android_enable_function(struct usb_function *f, int enable) device_desc.idProduct = __constant_cpu_to_le16(product_id); if (dev->cdev) dev->cdev->desc.idProduct = device_desc.idProduct; - - /* force reenumeration */ - if (dev->cdev && dev->cdev->gadget && - dev->cdev->gadget->speed != USB_SPEED_UNKNOWN) { - usb_gadget_disconnect(dev->cdev->gadget); - msleep(10); - usb_gadget_connect(dev->cdev->gadget); - } + usb_composite_force_reset(dev->cdev); } } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index cb35adc59f89..a56322c33dff 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -231,6 +231,27 @@ void usb_function_set_enabled(struct usb_function *f, int enabled) kobject_uevent(&f->dev->kobj, KOBJ_CHANGE); } + +void usb_composite_force_reset(struct usb_composite_dev *cdev) +{ + unsigned long flags; + + spin_lock_irqsave(&cdev->lock, flags); + /* force reenumeration */ + if (cdev && cdev->gadget && + cdev->gadget->speed != USB_SPEED_UNKNOWN) { + /* avoid sending a disconnect switch event until after we disconnect */ + cdev->mute_switch = 1; + spin_unlock_irqrestore(&cdev->lock, flags); + + usb_gadget_disconnect(cdev->gadget); + msleep(10); + usb_gadget_connect(cdev->gadget); + } else { + spin_unlock_irqrestore(&cdev->lock, flags); + } +} + /** * usb_add_function() - add a function to a configuration * @config: the configuration @@ -1426,11 +1447,15 @@ static void composite_disconnect(struct usb_gadget *gadget) spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) reset_config(cdev); + if (composite->disconnect) composite->disconnect(cdev); - spin_unlock_irqrestore(&cdev->lock, flags); - schedule_work(&cdev->switch_work); + if (cdev->mute_switch) + cdev->mute_switch = 0; + else + schedule_work(&cdev->switch_work); + spin_unlock_irqrestore(&cdev->lock, flags); } /*-------------------------------------------------------------------------*/ diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 9405ea22f566..32a84bcecd3d 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -47,6 +47,7 @@ */ #define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */ +struct usb_composite_dev; struct usb_configuration; /** @@ -164,6 +165,7 @@ int usb_function_activate(struct usb_function *); int usb_interface_id(struct usb_configuration *, struct usb_function *); void usb_function_set_enabled(struct usb_function *, int); +void usb_composite_force_reset(struct usb_composite_dev *); int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, struct usb_ep *_ep); @@ -376,6 +378,8 @@ struct usb_composite_dev { spinlock_t lock; struct switch_dev sdev; + /* used by usb_composite_force_reset to avoid signalling switch changes */ + bool mute_switch; struct work_struct switch_work; }; |