summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/android.c11
-rw-r--r--drivers/usb/gadget/composite.c29
-rw-r--r--include/linux/usb/composite.h4
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;
};