USB: gadget: Add test mode support for ci13xxx_udc
authorPavankumar Kondeti <pkondeti@codeaurora.org>
Fri, 18 Feb 2011 12:13:18 +0000 (17:43 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 25 Feb 2011 19:33:57 +0000 (11:33 -0800)
Implement the test modes mentioned in 7.1.20 section of USB 2.0
specification.  High-speed capable devices must support these test
modes to facilitate compliance testing.

Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/ci13xxx_udc.c
drivers/usb/gadget/ci13xxx_udc.h

index 17526759c9ce0b62f730c8d075e6458ac18b372c..e09178bc1450a54b46a9a12ab68abd6a96ba2b2d 100644 (file)
@@ -1783,6 +1783,28 @@ __acquires(mEp->lock)
        return retval;
 }
 
+/**
+ * isr_setup_status_complete: setup_status request complete function
+ * @ep:  endpoint
+ * @req: request handled
+ *
+ * Caller must release lock. Put the port in test mode if test mode
+ * feature is selected.
+ */
+static void
+isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct ci13xxx *udc = req->context;
+       unsigned long flags;
+
+       trace("%p, %p", ep, req);
+
+       spin_lock_irqsave(udc->lock, flags);
+       if (udc->test_mode)
+               hw_port_test_set(udc->test_mode);
+       spin_unlock_irqrestore(udc->lock, flags);
+}
+
 /**
  * isr_setup_status_phase: queues the status phase of a setup transation
  * @udc: udc struct
@@ -1799,6 +1821,8 @@ __acquires(mEp->lock)
        trace("%p", udc);
 
        mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
+       udc->status->context = udc;
+       udc->status->complete = isr_setup_status_complete;
 
        spin_unlock(mEp->lock);
        retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
@@ -1859,6 +1883,7 @@ __releases(udc->lock)
 __acquires(udc->lock)
 {
        unsigned i;
+       u8 tmode = 0;
 
        trace("%p", udc);
 
@@ -1982,14 +2007,33 @@ __acquires(udc->lock)
                                err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
                                spin_lock(udc->lock);
                                if (!err)
-                                       err = isr_setup_status_phase(udc);
-                       } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
-                                       le16_to_cpu(req.wValue) ==
-                                       USB_DEVICE_REMOTE_WAKEUP) {
+                                       isr_setup_status_phase(udc);
+                       } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
                                if (req.wLength != 0)
                                        break;
-                               udc->remote_wakeup = 1;
-                               err = isr_setup_status_phase(udc);
+                               switch (le16_to_cpu(req.wValue)) {
+                               case USB_DEVICE_REMOTE_WAKEUP:
+                                       udc->remote_wakeup = 1;
+                                       err = isr_setup_status_phase(udc);
+                                       break;
+                               case USB_DEVICE_TEST_MODE:
+                                       tmode = le16_to_cpu(req.wIndex) >> 8;
+                                       switch (tmode) {
+                                       case TEST_J:
+                                       case TEST_K:
+                                       case TEST_SE0_NAK:
+                                       case TEST_PACKET:
+                                       case TEST_FORCE_EN:
+                                               udc->test_mode = tmode;
+                                               err = isr_setup_status_phase(
+                                                               udc);
+                                               break;
+                                       default:
+                                               break;
+                                       }
+                               default:
+                                       goto delegate;
+                               }
                        } else {
                                goto delegate;
                        }
index 6cfab20db6bd3cdda6cbf085364ba9e3d167e10e..23707775cb434f5ac93c2221fda10ba57804b6e4 100644 (file)
@@ -131,6 +131,7 @@ struct ci13xxx {
        u8                         remote_wakeup; /* Is remote wakeup feature
                                                        enabled by the host? */
        u8                         suspended;  /* suspended by the host */
+       u8                         test_mode;  /* the selected test mode */
 
        struct usb_gadget_driver  *driver;     /* 3rd party gadget driver */
        struct ci13xxx_udc_driver *udc_driver; /* device controller driver */