usb: gadget: accessory: Add Android Accessory function
USB accessory mode allows users to connect USB host hardware
specifically designed for Android-powered devices. The accessories
must adhere to the Android accessory protocol outlined in the
http://accessories.android.com documentation. This allows
Android devices that cannot act as a USB host to still interact with
USB hardware. When an Android device is in USB accessory mode, the
attached Android USB accessory acts as the host, provides power
to the USB bus, and enumerates connected devices.
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index b9cb65d..b39ae67 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -47,6 +47,7 @@
#include "f_acm.c"
#include "f_adb.c"
#include "f_mtp.c"
+#include "f_accessory.c"
#define USB_ETH_RNDIS y
#include "f_rndis.c"
#include "rndis.c"
@@ -633,6 +634,39 @@
};
+static int accessory_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ return acc_setup();
+}
+
+static void accessory_function_cleanup(struct android_usb_function *f)
+{
+ acc_cleanup();
+}
+
+static int accessory_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ return acc_bind_config(c);
+}
+
+static int accessory_function_ctrlrequest(struct android_usb_function *f,
+ struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *c)
+{
+ return acc_ctrlrequest(cdev, c);
+}
+
+static struct android_usb_function accessory_function = {
+ .name = "accessory",
+ .init = accessory_function_init,
+ .cleanup = accessory_function_cleanup,
+ .bind_config = accessory_function_bind_config,
+ .ctrlrequest = accessory_function_ctrlrequest,
+};
+
+
static struct android_usb_function *supported_functions[] = {
&adb_function,
&acm_function,
@@ -640,6 +674,7 @@
&ptp_function,
&rndis_function,
&mass_storage_function,
+ &accessory_function,
NULL
};
@@ -825,6 +860,10 @@
struct usb_composite_dev *cdev = dev->cdev;
int enabled = 0;
+
+ if (!cdev)
+ return -ENODEV;
+
mutex_lock(&dev->mutex);
sscanf(buff, "%d", &enabled);
@@ -1072,6 +1111,12 @@
}
}
+ /* Special case the accessory function.
+ * It needs to handle control requests before it is enabled.
+ */
+ if (value < 0)
+ value = acc_ctrlrequest(cdev, c);
+
if (value < 0)
value = composite_setup(gadget, c);