diff options
author | Benoit Goby <benoit@android.com> | 2012-03-23 12:52:10 -0700 |
---|---|---|
committer | Benoit Goby <benoit@android.com> | 2012-03-23 12:52:10 -0700 |
commit | 25aa939c33749752b811d0c631789e4e3cf4371f (patch) | |
tree | d7716aa2f8bbab2d6bc6a0747554c5e5e757f421 /drivers/usb/gadget | |
parent | b43c0161fbca901e586e9ade321a5d8e616f94b9 (diff) | |
parent | d993be54c164ea473816f04745ae4f0504dbccfb (diff) | |
download | kernel_samsung_aries-25aa939c33749752b811d0c631789e4e3cf4371f.zip kernel_samsung_aries-25aa939c33749752b811d0c631789e4e3cf4371f.tar.gz kernel_samsung_aries-25aa939c33749752b811d0c631789e4e3cf4371f.tar.bz2 |
Merge branch 'android-3.0' into android-samsung-3.0-wip
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/android.c | 118 | ||||
-rw-r--r-- | drivers/usb/gadget/f_adb.c | 11 |
2 files changed, 120 insertions, 9 deletions
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index 8df739c..1d661ad 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -82,6 +82,11 @@ struct android_usb_function { int (*init)(struct android_usb_function *, struct usb_composite_dev *); /* Optional: cleanup during gadget unbind */ void (*cleanup)(struct android_usb_function *); + /* Optional: called when the function is added the list of + * enabled functions */ + void (*enable)(struct android_usb_function *); + /* Optional: called when it is removed */ + void (*disable)(struct android_usb_function *); int (*bind_config)(struct android_usb_function *, struct usb_configuration *); @@ -100,6 +105,7 @@ struct android_dev { struct device *dev; bool enabled; + int disable_depth; struct mutex mutex; bool connected; bool sw_connected; @@ -182,18 +188,55 @@ static void android_work(struct work_struct *data) } } +static void android_enable(struct android_dev *dev) +{ + struct usb_composite_dev *cdev = dev->cdev; + + BUG_ON(!mutex_is_locked(&dev->mutex)); + BUG_ON(!dev->disable_depth); + + if (--dev->disable_depth == 0) { + usb_add_config(cdev, &android_config_driver, + android_bind_config); + usb_gadget_connect(cdev->gadget); + } +} + +static void android_disable(struct android_dev *dev) +{ + struct usb_composite_dev *cdev = dev->cdev; + + BUG_ON(!mutex_is_locked(&dev->mutex)); + + if (dev->disable_depth++ == 0) { + usb_gadget_disconnect(cdev->gadget); + /* Cancel pending control requests */ + usb_ep_dequeue(cdev->gadget->ep0, cdev->req); + usb_remove_config(cdev, &android_config_driver); + } +} /*-------------------------------------------------------------------------*/ /* Supported functions initialization */ +struct adb_data { + bool opened; + bool enabled; +}; + static int adb_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev) { + f->config = kzalloc(sizeof(struct adb_data), GFP_KERNEL); + if (!f->config) + return -ENOMEM; + return adb_setup(); } static void adb_function_cleanup(struct android_usb_function *f) { adb_cleanup(); + kfree(f->config); } static int adb_function_bind_config(struct android_usb_function *f, struct usb_configuration *c) @@ -201,13 +244,69 @@ static int adb_function_bind_config(struct android_usb_function *f, struct usb_c return adb_bind_config(c); } +static void adb_android_function_enable(struct android_usb_function *f) +{ + struct android_dev *dev = _android_dev; + struct adb_data *data = f->config; + + data->enabled = true; + + /* Disable the gadget until adbd is ready */ + if (!data->opened) + android_disable(dev); +} + +static void adb_android_function_disable(struct android_usb_function *f) +{ + struct android_dev *dev = _android_dev; + struct adb_data *data = f->config; + + data->enabled = false; + + /* Balance the disable that was called in closed_callback */ + if (!data->opened) + android_enable(dev); +} + static struct android_usb_function adb_function = { .name = "adb", + .enable = adb_android_function_enable, + .disable = adb_android_function_disable, .init = adb_function_init, .cleanup = adb_function_cleanup, .bind_config = adb_function_bind_config, }; +static void adb_ready_callback(void) +{ + struct android_dev *dev = _android_dev; + struct adb_data *data = adb_function.config; + + mutex_lock(&dev->mutex); + + data->opened = true; + + if (data->enabled) + android_enable(dev); + + mutex_unlock(&dev->mutex); +} + +static void adb_closed_callback(void) +{ + struct android_dev *dev = _android_dev; + struct adb_data *data = adb_function.config; + + mutex_lock(&dev->mutex); + + data->opened = false; + + if (data->enabled) + android_disable(dev); + + mutex_unlock(&dev->mutex); +} + #define MAX_ACM_INSTANCES 4 struct acm_function_config { @@ -832,6 +931,7 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, { struct android_dev *dev = dev_get_drvdata(pdev); struct usb_composite_dev *cdev = dev->cdev; + struct android_usb_function *f; int enabled = 0; mutex_lock(&dev->mutex); @@ -845,15 +945,18 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, cdev->desc.bDeviceClass = device_desc.bDeviceClass; cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass; cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol; - usb_add_config(cdev, &android_config_driver, - android_bind_config); - usb_gadget_connect(cdev->gadget); + list_for_each_entry(f, &dev->enabled_functions, enabled_list) { + if (f->enable) + f->enable(f); + } + android_enable(dev); dev->enabled = true; } else if (!enabled && dev->enabled) { - usb_gadget_disconnect(cdev->gadget); - /* Cancel pending control requests */ - usb_ep_dequeue(cdev->gadget->ep0, cdev->req); - usb_remove_config(cdev, &android_config_driver); + android_disable(dev); + list_for_each_entry(f, &dev->enabled_functions, enabled_list) { + if (f->disable) + f->disable(f); + } dev->enabled = false; } else { pr_err("android_usb: already %s\n", @@ -1148,6 +1251,7 @@ static int __init init(void) if (!dev) return -ENOMEM; + dev->disable_depth = 1; dev->functions = supported_functions; INIT_LIST_HEAD(&dev->enabled_functions); INIT_WORK(&dev->work, android_work); diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c index fe4455e..1c0166c 100644 --- a/drivers/usb/gadget/f_adb.c +++ b/drivers/usb/gadget/f_adb.c @@ -111,6 +111,8 @@ static struct usb_descriptor_header *hs_adb_descs[] = { NULL, }; +static void adb_ready_callback(void); +static void adb_closed_callback(void); /* temporary variable used between adb_open() and adb_gadget_bind() */ static struct adb_dev *_adb_dev; @@ -406,7 +408,7 @@ static ssize_t adb_write(struct file *fp, const char __user *buf, static int adb_open(struct inode *ip, struct file *fp) { - printk(KERN_INFO "adb_open\n"); + pr_info("adb_open\n"); if (!_adb_dev) return -ENODEV; @@ -418,12 +420,17 @@ static int adb_open(struct inode *ip, struct file *fp) /* clear the error latch */ _adb_dev->error = 0; + adb_ready_callback(); + return 0; } static int adb_release(struct inode *ip, struct file *fp) { - printk(KERN_INFO "adb_release\n"); + pr_info("adb_release\n"); + + adb_closed_callback(); + adb_unlock(&_adb_dev->open_excl); return 0; } |