enable ADB function with DWC3 USB device driver
authorJiebing Li <jiebing.li@intel.com>
Tue, 8 May 2012 08:15:00 +0000 (16:15 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 16 May 2012 09:33:15 +0000 (02:33 -0700)
BZ: 35178

This patch makes the following changes to support ADB:
1. add super/full speed support in Android ADB function
2. modify PID and VID in order to re-use Medfield Windows tool
3. set OUT transfer length to multiple of MaxPacketSize

Change-Id: I304833a1b91a426ed64fef773a9f364f93555cb9
Signed-off-by: Jiebing Li <jiebing.li@intel.com>
Reviewed-on: http://android.intel.com:8080/47774
Reviewed-by: Meng, Zhe <zhe.meng@intel.com>
Tested-by: Meng, Zhe <zhe.meng@intel.com>
Reviewed-by: Gao, Yunpeng <yunpeng.gao@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
arch/x86/configs/i386_mrfl_defconfig
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/android.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_adb.c
include/linux/usb/composite.h

index ca3af20..ac0cc34 100644 (file)
@@ -2119,7 +2119,7 @@ CONFIG_USB_OTG=y
 CONFIG_USB_OTG_WHITELIST=y
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
 CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_DEBUG=y
+# CONFIG_USB_DWC3_DEBUG is not set
 # CONFIG_USB_MON is not set
 # CONFIG_USB_WUSB is not set
 # CONFIG_USB_WUSB_CBAF is not set
@@ -2208,7 +2208,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_YUREX is not set
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
+# CONFIG_USB_GADGET_DEBUG is not set
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
 # CONFIG_USB_GADGET_DEBUG_FS is not set
 CONFIG_USB_GADGET_VBUS_DRAW=2
@@ -2232,9 +2232,10 @@ CONFIG_USB_GADGET_SUPERSPEED=y
 # CONFIG_USB_GADGETFS is not set
 # CONFIG_USB_FUNCTIONFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
-CONFIG_USB_MASS_STORAGE=y
+# CONFIG_USB_MASS_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_G_ANDROID=y
 # CONFIG_USB_CDC_COMPOSITE is not set
 # CONFIG_USB_G_MULTI is not set
 # CONFIG_USB_G_HID is not set
@@ -2283,7 +2284,9 @@ CONFIG_MMC_SDHCI_PCI=y
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_NFC_DEVICES is not set
-# CONFIG_SWITCH is not set
+CONFIG_SWITCH=y
+# CONFIG_SWITCH_GPIO is not set
+# CONFIG_SWITCH_MID is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 # CONFIG_EDAC is not set
index f5e5678..4c2a035 100644 (file)
@@ -903,10 +903,12 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
        dev_vdbg(dwc->dev, "queing request %p to %s length %d\n",
                        request, ep->name, request->length);
 
-       /* workaround here to pad bulk-IN buffer to MaxPacketSize */
-       if (dep->number == 2)
-               if (request->length < 1024)
-                       request->length = 1024;
+       /* pad bulk-IN buffer to MaxPacketSize per databook requirement*/
+       if (dep->number == 2) {
+               int size = dep->desc->wMaxPacketSize;
+               if (request->length % size)
+                       request->length = (request->length / size + 1) * size;
+       }
 
        spin_lock_irqsave(&dwc->lock, flags);
        ret = __dwc3_gadget_ep_queue(dep, req);
index e03970c..62e6ed6 100644 (file)
@@ -66,8 +66,13 @@ MODULE_VERSION("1.0");
 static const char longname[] = "Gadget Android";
 
 /* Default vendor and product IDs, overridden by userspace */
+#ifdef CONFIG_USB_GADGET_DWC3
+#define VENDOR_ID              0x8087
+#define PRODUCT_ID             0x09EF
+#else
 #define VENDOR_ID              0x18D1
 #define PRODUCT_ID             0x0001
+#endif
 
 struct android_usb_function {
        char *name;
@@ -166,8 +171,13 @@ static struct usb_configuration android_config_driver = {
        .label          = "android",
        .unbind         = android_unbind_config,
        .bConfigurationValue = 1,
+#ifdef CONFIG_USB_GADGET_DWC3
+       .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+       .bMaxPower      = 0x1, /* 8ma */
+#else
        .bmAttributes   = USB_CONFIG_ATT_ONE,
        .bMaxPower      = 0xFA, /* 500ma */
+#endif
 };
 
 static void android_work(struct work_struct *data)
index db014e8..2014df7 100644 (file)
@@ -459,16 +459,6 @@ static int config_buf(struct usb_configuration *config,
                        continue;
                status = usb_descriptor_fillbuf(next, len,
                        (const struct usb_descriptor_header **) descriptors);
-#ifdef CONFIG_USB_GADGET_DWC3
-               /* workaround for issue of memcpy between DDR and SRAM */
-               *((u8 *)next + 7) = 0x50;
-               *((u8 *)next + 11) = 0x82;
-               *((u8 *)next + 12) = 0x2;
-               *((u8 *)next + 23) = 0x5;
-               *((u8 *)next + 24) = 0x1;
-               *((u8 *)next + 25) = 0x2;
-               *((u8 *)next + 31) = 0xF;
-#endif
                if (status < 0)
                        return status;
                len -= status;
@@ -784,6 +774,11 @@ static int set_config(struct usb_composite_dev *cdev,
                case USB_SPEED_LOW:     speed = "low"; break;
                case USB_SPEED_FULL:    speed = "full"; break;
                case USB_SPEED_HIGH:    speed = "high"; break;
+#ifdef CONFIG_USB_GADGET_DWC3
+               case USB_SPEED_SUPER:
+                       speed = "super";
+                       break;
+#endif
                default:                speed = "?"; break;
                } ; speed; }), number, c ? c->label : "unconfigured");
 
index 6ed2a99..56c596e 100644 (file)
@@ -88,6 +88,7 @@ static struct usb_endpoint_descriptor adb_fullspeed_in_desc = {
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_IN,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = __constant_cpu_to_le16(64),
 };
 
 static struct usb_endpoint_descriptor adb_fullspeed_out_desc = {
@@ -95,6 +96,7 @@ static struct usb_endpoint_descriptor adb_fullspeed_out_desc = {
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_OUT,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = __constant_cpu_to_le16(64),
 };
 
 static struct usb_descriptor_header *fs_adb_descs[] = {
@@ -111,6 +113,50 @@ static struct usb_descriptor_header *hs_adb_descs[] = {
        NULL,
 };
 
+#ifdef CONFIG_USB_GADGET_DWC3
+static struct usb_endpoint_descriptor adb_superspeed_in_desc = {
+       .bLength                = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType        = USB_DT_ENDPOINT,
+       .bEndpointAddress       = USB_DIR_IN,
+       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor adb_superspeed_in_comp_desc = {
+       .bLength =              sizeof(fsg_ss_bulk_in_comp_desc),
+       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+
+       .bMaxBurst =            0,
+       .bmAttributes =         0,
+       /* .wBytesPerInterval = cpu_to_le16(2), */
+};
+
+static struct usb_endpoint_descriptor adb_superspeed_out_desc = {
+       .bLength                = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType        = USB_DT_ENDPOINT,
+       .bEndpointAddress       = USB_DIR_OUT,
+       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor adb_superspeed_out_comp_desc = {
+       .bLength =              sizeof(fsg_ss_bulk_in_comp_desc),
+       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+
+       .bMaxBurst =            0,
+       .bmAttributes =         0,
+};
+
+static struct usb_descriptor_header *ss_adb_descs[] = {
+       (struct usb_descriptor_header *) &adb_interface_desc,
+       (struct usb_descriptor_header *) &adb_superspeed_in_desc,
+       (struct usb_descriptor_header *) &adb_superspeed_in_comp_desc,
+       (struct usb_descriptor_header *) &adb_superspeed_out_desc,
+       (struct usb_descriptor_header *) &adb_superspeed_out_comp_desc,
+       NULL,
+};
+#endif
+
 
 int fastboot;
 module_param(fastboot, int, S_IRUGO);
@@ -493,6 +539,23 @@ adb_function_bind(struct usb_configuration *c, struct usb_function *f)
                        adb_fullspeed_out_desc.bEndpointAddress;
        }
 
+#ifdef CONFIG_USB_GADGET_DWC3
+       if (gadget_is_superspeed(c->cdev->gadget)) {
+               unsigned        max_burst;
+
+               /* Calculate bMaxBurst, we know packet size is 1024 */
+               max_burst = min_t(unsigned, ADB_BULK_BUFFER_SIZE / 1024, 15);
+
+               adb_superspeed_in_desc.bEndpointAddress =
+                       adb_fullspeed_in_desc.bEndpointAddress;
+               /* fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; */
+
+               adb_superspeed_out_desc.bEndpointAddress =
+                       adb_fullspeed_out_desc.bEndpointAddress;
+               /* fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; */
+       }
+#endif
+
        DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
                        gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
                        f->name, dev->ep_in->name, dev->ep_out->name);
@@ -524,6 +587,20 @@ static int adb_function_set_alt(struct usb_function *f,
        int ret;
 
        DBG(cdev, "adb_function_set_alt intf: %d alt: %d\n", intf, alt);
+#ifdef CONFIG_USB_GADGET_DWC3
+       ret = usb_ep_enable(dev->ep_in,
+                       ep_choose_ss(cdev->gadget,
+                               &adb_superspeed_in_desc,
+                               &adb_highspeed_in_desc,
+                               &adb_fullspeed_in_desc));
+       if (ret)
+               return ret;
+       ret = usb_ep_enable(dev->ep_out,
+                       ep_choose_ss(cdev->gadget,
+                               &adb_superspeed_out_desc,
+                               &adb_highspeed_out_desc,
+                               &adb_fullspeed_out_desc));
+#else
        ret = usb_ep_enable(dev->ep_in,
                        ep_choose(cdev->gadget,
                                &adb_highspeed_in_desc,
@@ -534,6 +611,7 @@ static int adb_function_set_alt(struct usb_function *f,
                        ep_choose(cdev->gadget,
                                &adb_highspeed_out_desc,
                                &adb_fullspeed_out_desc));
+#endif
        if (ret) {
                usb_ep_disable(dev->ep_in);
                return ret;
@@ -572,6 +650,9 @@ static int adb_bind_config(struct usb_configuration *c)
        dev->function.name = "adb";
        dev->function.descriptors = fs_adb_descs;
        dev->function.hs_descriptors = hs_adb_descs;
+#ifdef CONFIG_USB_GADGET_DWC3
+       dev->function.ss_descriptors = ss_adb_descs;
+#endif
        dev->function.bind = adb_function_bind;
        dev->function.unbind = adb_function_unbind;
        dev->function.set_alt = adb_function_set_alt;
index 9a94e8f..5d6cdbd 100644 (file)
@@ -164,6 +164,20 @@ int usb_interface_id(struct usb_configuration *, struct usb_function *);
  * @hs: descriptor to use for high speed operation
  * @fs: descriptor to use for full or low speed operation
  */
+#ifdef CONFIG_USB_GADGET_DWC3
+static inline struct usb_endpoint_descriptor *
+ep_choose_ss(struct usb_gadget *g, struct usb_endpoint_descriptor *ss,
+               struct usb_endpoint_descriptor *hs,
+               struct usb_endpoint_descriptor *fs)
+{
+       if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
+               return ss;
+       if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+               return hs;
+       return fs;
+}
+#endif
+
 static inline struct usb_endpoint_descriptor *
 ep_choose(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
                struct usb_endpoint_descriptor *fs)