USB: composite: Add usb_composite_force_reset utility to force enumeration
Use this rather than calling usb_gadget_disconnect and usb_gadget_connect directly to avoid sending USB disconnect events to userspace when resetting the bus. Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
committed by
Colin Cross
parent
4a4414416d
commit
28acc1a88c
@@ -337,7 +337,7 @@ void android_enable_function(struct usb_function *f, int enable)
|
|||||||
*/
|
*/
|
||||||
list_for_each_entry(func, &android_config_driver.functions, list) {
|
list_for_each_entry(func, &android_config_driver.functions, list) {
|
||||||
if (!strcmp(func->name, "usb_mass_storage")) {
|
if (!strcmp(func->name, "usb_mass_storage")) {
|
||||||
usb_function_set_enabled(f, !enable);
|
usb_function_set_enabled(func, !enable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,14 +348,7 @@ void android_enable_function(struct usb_function *f, int enable)
|
|||||||
device_desc.idProduct = __constant_cpu_to_le16(product_id);
|
device_desc.idProduct = __constant_cpu_to_le16(product_id);
|
||||||
if (dev->cdev)
|
if (dev->cdev)
|
||||||
dev->cdev->desc.idProduct = device_desc.idProduct;
|
dev->cdev->desc.idProduct = device_desc.idProduct;
|
||||||
|
usb_composite_force_reset(dev->cdev);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,27 @@ void usb_function_set_enabled(struct usb_function *f, int enabled)
|
|||||||
kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
|
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
|
* usb_add_function() - add a function to a configuration
|
||||||
* @config: the configuration
|
* @config: the configuration
|
||||||
@@ -1114,11 +1135,15 @@ static void composite_disconnect(struct usb_gadget *gadget)
|
|||||||
spin_lock_irqsave(&cdev->lock, flags);
|
spin_lock_irqsave(&cdev->lock, flags);
|
||||||
if (cdev->config)
|
if (cdev->config)
|
||||||
reset_config(cdev);
|
reset_config(cdev);
|
||||||
|
|
||||||
if (composite->disconnect)
|
if (composite->disconnect)
|
||||||
composite->disconnect(cdev);
|
composite->disconnect(cdev);
|
||||||
spin_unlock_irqrestore(&cdev->lock, flags);
|
|
||||||
|
|
||||||
|
if (cdev->mute_switch)
|
||||||
|
cdev->mute_switch = 0;
|
||||||
|
else
|
||||||
schedule_work(&cdev->switch_work);
|
schedule_work(&cdev->switch_work);
|
||||||
|
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
*/
|
*/
|
||||||
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
|
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
|
||||||
|
|
||||||
|
struct usb_composite_dev;
|
||||||
struct usb_configuration;
|
struct usb_configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,6 +152,7 @@ int usb_function_activate(struct usb_function *);
|
|||||||
int usb_interface_id(struct usb_configuration *, struct usb_function *);
|
int usb_interface_id(struct usb_configuration *, struct usb_function *);
|
||||||
|
|
||||||
void usb_function_set_enabled(struct usb_function *, int);
|
void usb_function_set_enabled(struct usb_function *, int);
|
||||||
|
void usb_composite_force_reset(struct usb_composite_dev *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ep_choose - select descriptor endpoint at current device speed
|
* ep_choose - select descriptor endpoint at current device speed
|
||||||
@@ -372,6 +374,8 @@ struct usb_composite_dev {
|
|||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
struct switch_dev sdev;
|
struct switch_dev sdev;
|
||||||
|
/* used by usb_composite_force_reset to avoid signalling switch changes */
|
||||||
|
bool mute_switch;
|
||||||
struct work_struct switch_work;
|
struct work_struct switch_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user