From 6eb66891e94ff6ef35ca5ef487d10d5d7998e858 Mon Sep 17 00:00:00 2001
From: Jon Sturm <jonimoose@gmail.com>
Date: Sat, 16 Jul 2011 22:23:39 -0500
Subject: [PATCH 2/2] USB: sholes: enable usb accessory mode for sholes and
 fix build with it enabled

---
 arch/arm/mach-omap2/board-sholes.c    |   33 +++++++++++++++++++++++++++++++++
 drivers/usb/gadget/android.c          |   14 ++++++++++++++
 drivers/usb/gadget/composite.c        |   24 ++++++++++++++++++++++++
 include/linux/usb/android_composite.h |    1 +
 include/linux/usb/composite.h         |    4 ++++
 5 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-sholes.c b/arch/arm/mach-omap2/board-sholes.c
index 1b687d8..21e0d88 100644
--- a/arch/arm/mach-omap2/board-sholes.c
+++ b/arch/arm/mach-omap2/board-sholes.c
@@ -52,6 +52,7 @@
 #include <plat/control.h>
 #include <mach/system.h>
 #include <linux/usb/android_composite.h>
+#include <linux/usb/f_accessory.h>
 #include <linux/wakelock.h>
 
 #include "cm-regbits-34xx.h"
@@ -495,11 +496,29 @@ static char *usb_functions_rndis_adb[] = {
 	"rndis",
 	"adb",
 };
+static char *usb_functions_accessory[] = {
+#ifdef CONFIG_USB_ANDROID_ACCESSORY
+"accessory",
+#endif
+};
+static char *usb_functions_accessory_adb[] = {
+#ifdef CONFIG_USB_ANDROID_ACCESSORY
+"accessory",
+#endif
+#ifdef CONFIG_USB_ANDROID_ADB
+"adb",
+#endif
+};
+
+
 
 static char *usb_functions_all[] = {
 #ifdef CONFIG_USB_ANDROID_RNDIS
 	"rndis",
 #endif
+#ifdef CONFIG_USB_ANDROID_ACCESSORY
+  "accessory",
+#endif
 	"usb_mass_storage",
 	"adb",
 #ifdef CONFIG_USB_ANDROID_ACM
@@ -528,6 +547,20 @@ static struct android_usb_product usb_products[] = {
 		.num_functions	= ARRAY_SIZE(usb_functions_rndis_adb),
 		.functions	= usb_functions_rndis_adb,
 	},
+#ifdef CONFIG_USB_ANDROID_ACCESSORY
+	{
+		.vendor_id = USB_ACCESSORY_VENDOR_ID,
+		.product_id = USB_ACCESSORY_PRODUCT_ID,
+		.num_functions = ARRAY_SIZE(usb_functions_accessory),
+		.functions = usb_functions_accessory,
+	},
+	{
+		.vendor_id = USB_ACCESSORY_VENDOR_ID,
+		.product_id = USB_ACCESSORY_ADB_PRODUCT_ID,
+		.num_functions = ARRAY_SIZE(usb_functions_accessory_adb),
+		.functions = usb_functions_accessory_adb,
+	},
+#endif
 };
 
 static char *factory_usb_functions[] = {
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 25860ca..f1f11d1 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -65,6 +65,7 @@ struct android_dev {
 	int num_functions;
 	char **functions;
 
+	int vender_id;
 	int product_id;
 	int version;
 };
@@ -366,6 +367,19 @@ void android_enable_function(struct usb_function *f, int enable)
 			}
         }
 #endif
+#ifdef CONFIG_USB_ANDROID_ACCESSORY
+		if (!strcmp(f->name, "accessory") && enable) {
+			struct usb_function		*func;
+
+		    /* disable everything else (and keep adb for now) */
+			list_for_each_entry(func, &android_config_driver.functions, list) {
+				if (strcmp(func->name, "accessory")
+					&& strcmp(func->name, "adb")) {
+					usb_function_set_enabled(func, 0);
+				}
+			}
+        }
+#endif
 
 		product_id = get_product_id(dev);
 		device_desc.idProduct = __constant_cpu_to_le16(product_id);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 821cc17..7c09092 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -97,6 +97,30 @@ static ssize_t enable_store(
 
 static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
 
+void usb_function_set_enabled(struct usb_function *f, int enabled)
+{
+	f->disabled = !enabled;
+	kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
+}
+
+
+void usb_composite_force_reset(struct usb_composite_dev *cdev)
+{
+unsigned long flags;
+
+	spin_lock_irqsave(&cdev->lock, flags);
+	/* force reenumeration */
+	if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {
+		spin_unlock_irqrestore(&cdev->lock, flags);
+
+		usb_gadget_disconnect(cdev->gadget);
+		msleep(10);
+		usb_gadget_connect(cdev->gadget);
+	} else {
+		spin_unlock_irqrestore(&cdev->lock, flags);
+	}
+}
+
 
 /**
  * usb_add_function() - add a function to a configuration
diff --git a/include/linux/usb/android_composite.h b/include/linux/usb/android_composite.h
index 50889ba..32aa3f3 100644
--- a/include/linux/usb/android_composite.h
+++ b/include/linux/usb/android_composite.h
@@ -28,6 +28,7 @@ struct android_usb_function {
 
 struct android_usb_product {
 	/* Default product ID. */
+	__u16 vendor_id;
 	__u16 product_id;
 
 	/* List of function names associated with this product.
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 2b7775f..e145b73 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -103,6 +103,9 @@ struct usb_function {
 	struct usb_configuration	*config;
 	int				hidden;
 
+	/* disabled is zero if the function is enabled */
+	int disabled;
+
 	/* REVISIT:  bind() functions can be marked __init, which
 	 * makes trouble for section mismatch analysis.  See if
 	 * we can't restructure things to avoid mismatching.
@@ -138,6 +141,7 @@ int usb_function_deactivate(struct usb_function *);
 int usb_function_activate(struct usb_function *);
 
 int usb_interface_id(struct usb_configuration *, struct usb_function *);
+void usb_function_set_enabled(struct usb_function *, int);
 
 /**
  * ep_choose - select descriptor endpoint at current device speed
-- 
1.7.6

