usb: gadget: fsl_udc_core: Properly return the self-powered bit
ahcheng [Wed, 22 Feb 2012 09:26:09 +0000 (17:26 +0800)]
This patch fixes the GetStatus always reports self powered.
As per USB compliance update, a device that is actively drawing
more than 100mA from USB must report itself as bus-powered in
the GetStatus(DEVICE) call.

Bug 928340

Change-Id: Iefd1577a2ff2f301add98b14a402ed8eacc3aa28
Signed-off-by: ahcheng <ahcheng@nvidia.com>
Reviewed-on: http://git-master/r/91404
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>

drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/fsl_usb2_udc.h

index 8737f80..a406e32 100644 (file)
@@ -1352,6 +1352,14 @@ static int can_pullup(struct fsl_udc *udc)
        return udc->driver && udc->softconnect && udc->vbus_active;
 }
 
+static int fsl_set_selfpowered(struct usb_gadget * gadget, int is_on)
+{
+       struct fsl_udc *udc;
+       udc = container_of(gadget, struct fsl_udc, gadget);
+       udc->selfpowered = (is_on != 0);
+       return 0;
+}
+
 /* Notify controller that VBUS is powered, Called by whatever
    detects VBUS sessions */
 static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
@@ -1477,7 +1485,7 @@ static struct usb_gadget_ops fsl_gadget_ops = {
 #ifndef CONFIG_USB_ANDROID
        .wakeup = fsl_wakeup,
 #endif
-/*     .set_selfpowered = fsl_set_selfpowered, */ /* Always selfpowered */
+       .set_selfpowered = fsl_set_selfpowered,
        .vbus_session = fsl_vbus_session,
        .vbus_draw = fsl_vbus_draw,
        .pullup = fsl_pullup,
@@ -1571,7 +1579,8 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 
        if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
                /* Get device status */
-               tmp = 1 << USB_DEVICE_SELF_POWERED;
+               if (udc->selfpowered)
+                       tmp = 1 << USB_DEVICE_SELF_POWERED;
                tmp |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
        } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
                /* Get interface status */
index 0386be6..62b26ed 100644 (file)
@@ -620,6 +620,7 @@ struct fsl_udc {
        unsigned stopped:1;
        unsigned remote_wakeup:1;
        unsigned big_endian_desc:1;
+       unsigned selfpowered:1;
 
        struct ep_queue_head *ep_qh;    /* Endpoints Queue-Head */
        struct fsl_req *status_req;     /* ep0 status request */