aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2010-12-10 16:30:15 -0800
committerMike Lockwood <lockwood@android.com>2010-12-14 09:24:54 -0800
commita05f03bf6ece7619877d6b3ccfbc7597f6df7b40 (patch)
tree63c2e44bc26739545d37e2847e4212364044e8e6
parent1cfb26afa1528c3c148f59aa0f6764d77c02659a (diff)
downloadqemu-a05f03bf6ece7619877d6b3ccfbc7597f6df7b40.tar.gz
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>
-rw-r--r--drivers/usb/gadget/composite.c45
-rw-r--r--include/linux/usb/composite.h10
2 files changed, 39 insertions, 16 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a664e299462..3afbf523259 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -110,10 +110,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);
@@ -885,6 +882,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
@@ -1103,10 +1108,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);
}
@@ -1169,7 +1172,8 @@ composite_unbind(struct usb_gadget *gadget)
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);
kfree(cdev);
set_gadget_data(gadget, NULL);
device_remove_file(&gadget->dev, &dev_attr_suspended);
@@ -1204,11 +1208,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)
@@ -1262,8 +1277,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);
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index f491e48b21e..cb28d430278 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -357,9 +357,13 @@ struct usb_composite_dev {
/* protects at least deactivation count */
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;
};