USB: gadget: android: android USB gadget improvements:
USB: android gadget: add remote wakeup attribute to android function
Add remote wakeup attribute to configuration descriptor of android
function to advertise remote wakeup capability to host
Acked-by: Allam, Suresh Reddy <sallam@qualcomm.com>
Signed-off-by: Mike Lockwood <lockwood@android.com>
USB: gadget: android: Allow functions to handle setup requests.
Signed-off-by: Mike Lockwood <lockwood@android.com>
Support for specifying the list of USB functions from platform data.
The main android.c gadget driver no longer has hard coded references
to the mass_storage and adb functions.
Support for computing the product ID based on tables in platform data
and the currently enabled functions.
Moved the adb enable/disable logic from android.c to f_adb.c.
Change-Id: I6259d3fb1473ed973f700e55d17744956f3527bb
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index 2eaaada..04dd451 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -30,11 +30,7 @@
#include <linux/device.h>
#include <linux/miscdevice.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/composite.h>
-#include <linux/usb/gadget.h>
-
-#include "f_adb.h"
+#include <linux/usb/android_composite.h>
#define BULK_BUFFER_SIZE 4096
@@ -126,15 +122,12 @@
NULL,
};
-/* used when adb function is disabled */
-static struct usb_descriptor_header *null_adb_descs[] = {
- NULL,
-};
-
/* temporary variable used between adb_open() and adb_gadget_bind() */
static struct adb_dev *_adb_dev;
+static atomic_t adb_enable_excl;
+
static inline struct adb_dev *func_to_dev(struct usb_function *f)
{
return container_of(f, struct adb_dev, function);
@@ -489,7 +482,40 @@
.fops = &adb_fops,
};
-static int __init
+static int adb_enable_open(struct inode *ip, struct file *fp)
+{
+ if (atomic_inc_return(&adb_enable_excl) != 1) {
+ atomic_dec(&adb_enable_excl);
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO "enabling adb\n");
+ android_enable_function(&_adb_dev->function, 1);
+
+ return 0;
+}
+
+static int adb_enable_release(struct inode *ip, struct file *fp)
+{
+ printk(KERN_INFO "disabling adb\n");
+ android_enable_function(&_adb_dev->function, 0);
+ atomic_dec(&adb_enable_excl);
+ return 0;
+}
+
+static const struct file_operations adb_enable_fops = {
+ .owner = THIS_MODULE,
+ .open = adb_enable_open,
+ .release = adb_enable_release,
+};
+
+static struct miscdevice adb_enable_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "android_adb_enable",
+ .fops = &adb_enable_fops,
+};
+
+static int
adb_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@@ -544,6 +570,7 @@
spin_unlock_irq(&dev->lock);
misc_deregister(&adb_device);
+ misc_deregister(&adb_enable_device);
kfree(_adb_dev);
_adb_dev = NULL;
}
@@ -594,13 +621,12 @@
VDBG(cdev, "%s disabled\n", dev->function.name);
}
-int __init adb_function_add(struct usb_composite_dev *cdev,
- struct usb_configuration *c)
+static int adb_bind_config(struct usb_configuration *c)
{
struct adb_dev *dev;
int ret;
- printk(KERN_INFO "adb_function_add\n");
+ printk(KERN_INFO "adb_bind_config\n");
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -619,27 +645,36 @@
INIT_LIST_HEAD(&dev->rx_done);
INIT_LIST_HEAD(&dev->tx_idle);
- dev->cdev = cdev;
+ dev->cdev = c->cdev;
dev->function.name = "adb";
- dev->function.descriptors = null_adb_descs;
- dev->function.hs_descriptors = null_adb_descs;
+ dev->function.descriptors = fs_adb_descs;
+ dev->function.hs_descriptors = hs_adb_descs;
dev->function.bind = adb_function_bind;
dev->function.unbind = adb_function_unbind;
dev->function.set_alt = adb_function_set_alt;
dev->function.disable = adb_function_disable;
+ /* start disabled */
+ dev->function.hidden = 1;
+
/* _adb_dev must be set before calling usb_gadget_register_driver */
_adb_dev = dev;
ret = misc_register(&adb_device);
if (ret)
goto err1;
- ret = usb_add_function(c, &dev->function);
+ ret = misc_register(&adb_enable_device);
if (ret)
goto err2;
+ ret = usb_add_function(c, &dev->function);
+ if (ret)
+ goto err3;
+
return 0;
+err3:
+ misc_deregister(&adb_enable_device);
err2:
misc_deregister(&adb_device);
err1:
@@ -648,21 +683,15 @@
return ret;
}
-void adb_function_enable(int enable)
+static struct android_usb_function adb_function = {
+ .name = "adb",
+ .bind_config = adb_bind_config,
+};
+
+static int __init init(void)
{
- struct adb_dev *dev = _adb_dev;
-
- if (dev) {
- DBG(dev->cdev, "adb_function_enable(%s)\n",
- enable ? "true" : "false");
-
- if (enable) {
- dev->function.descriptors = fs_adb_descs;
- dev->function.hs_descriptors = hs_adb_descs;
- } else {
- dev->function.descriptors = null_adb_descs;
- dev->function.hs_descriptors = null_adb_descs;
- }
- }
+ printk(KERN_INFO "f_adb init\n");
+ android_register_function(&adb_function);
+ return 0;
}
-
+module_init(init);