USB: gadget: composite: Use separate switches for connected and config state

Also remove disconnect debouncing, which didn't actually work on some platforms

Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2010-12-10 16:30:15 -08:00
committed by Colin Cross
parent 00bc4089ef
commit e6be8941f4
2 changed files with 39 additions and 16 deletions

View File

@@ -114,10 +114,7 @@ void usb_composite_force_reset(struct usb_composite_dev *cdev)
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;
if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {
spin_unlock_irqrestore(&cdev->lock, flags);
usb_gadget_disconnect(cdev->gadget);
@@ -924,6 +921,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
u16 w_length = le16_to_cpu(ctrl->wLength);
struct usb_function *f = NULL;
u8 endp;
unsigned long flags;
spin_lock_irqsave(&cdev->lock, flags);
if (!cdev->connected) {
cdev->connected = 1;
schedule_work(&cdev->switch_work);
}
spin_unlock_irqrestore(&cdev->lock, flags);
/* partial re-init of the response message; the function or the
* gadget might need to intercept e.g. a control-OUT completion
@@ -1154,10 +1159,8 @@ static void composite_disconnect(struct usb_gadget *gadget)
if (composite->disconnect)
composite->disconnect(cdev);
if (cdev->mute_switch)
cdev->mute_switch = 0;
else
schedule_work(&cdev->switch_work);
cdev->connected = 0;
schedule_work(&cdev->switch_work);
spin_unlock_irqrestore(&cdev->lock, flags);
}
@@ -1219,7 +1222,8 @@ composite_unbind(struct usb_gadget *gadget)
kfree(cdev->req->buf);
usb_ep_free_request(gadget->ep0, cdev->req);
}
switch_dev_unregister(&cdev->sdev);
switch_dev_unregister(&cdev->sw_connected);
switch_dev_unregister(&cdev->sw_config);
device_remove_file(&gadget->dev, &dev_attr_suspended);
kfree(cdev);
set_gadget_data(gadget, NULL);
@@ -1245,11 +1249,22 @@ composite_switch_work(struct work_struct *data)
struct usb_composite_dev *cdev =
container_of(data, struct usb_composite_dev, switch_work);
struct usb_configuration *config = cdev->config;
int connected;
unsigned long flags;
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->connected != cdev->sw_connected.state) {
connected = cdev->connected;
spin_unlock_irqrestore(&cdev->lock, flags);
switch_set_state(&cdev->sw_connected, connected);
} else {
spin_unlock_irqrestore(&cdev->lock, flags);
}
if (config)
switch_set_state(&cdev->sdev, config->bConfigurationValue);
switch_set_state(&cdev->sw_config, config->bConfigurationValue);
else
switch_set_state(&cdev->sdev, 0);
switch_set_state(&cdev->sw_config, 0);
}
static int composite_bind(struct usb_gadget *gadget)
@@ -1301,8 +1316,12 @@ static int composite_bind(struct usb_gadget *gadget)
if (status < 0)
goto fail;
cdev->sdev.name = "usb_configuration";
status = switch_dev_register(&cdev->sdev);
cdev->sw_connected.name = "usb_connected";
status = switch_dev_register(&cdev->sw_connected);
if (status < 0)
goto fail;
cdev->sw_config.name = "usb_configuration";
status = switch_dev_register(&cdev->sw_config);
if (status < 0)
goto fail;
INIT_WORK(&cdev->switch_work, composite_switch_work);

View File

@@ -373,9 +373,13 @@ struct usb_composite_dev {
/* protects deactivations and delayed_status counts*/
spinlock_t lock;
struct switch_dev sdev;
/* used by usb_composite_force_reset to avoid signalling switch changes */
bool mute_switch;
/* switch indicating connected/disconnected state */
struct switch_dev sw_connected;
/* switch indicating current configuration */
struct switch_dev sw_config;
/* current connected state for sw_connected */
bool connected;
struct work_struct switch_work;
};