[PATCH] USB dummy_hcd: Partial OTG emulation
authorAlan Stern <stern@rowland.harvard.edu>
Mon, 2 May 2005 15:25:17 +0000 (11:25 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 27 Jun 2005 21:43:51 +0000 (14:43 -0700)
Partial OTG support for dummy_hcd, mostly as a framework for further work.
It emulates the new OTG flags in the host and peripheral frameworks, if
that option is configured.  But it's incomplete:

  - Resetting the peripheral needs to clear the OTG state bits;
    a second enumeration won't work correctly.

  - This stops modeling HNP right when roles should switch the first time.
    It should probably disconnect, then set the usb_bus.is_b_host and
    usb_gadget.is_a_peripheral flags; then it'd enumerate almost normally,
    except for the role reversal.  Roles could then switch a second time,
    back to "normal" (with those flags cleared).

  - SRP should be modeled as "resume from port-unpowered", which is
    a state that usbcore doesn't yet use.

HNP can be triggered by enabling the OTG whitelist and configuring a
gadget driver that's not in that list; or by configuring Gadget Zero
to identify itself as the HNP test device.

Sent-by: David Brownell <david-b@pacbell.net>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/dummy_hcd.c

index 1918d10f75697024f1acb400b03a136a06c3d59c..e9b95df5b23db4bd1b559d166b7e7bee600b97c6 100644 (file)
@@ -601,8 +601,10 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
        struct dummy    *dum;
 
        dum = gadget_to_dummy (_gadget);
-       if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0
-                       || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)))
+       if (!(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))
+                       || !(dum->devstatus &
+                               ( (1 << USB_DEVICE_B_HNP_ENABLE)
+                               | (1 << USB_DEVICE_REMOTE_WAKEUP))))
                return -EINVAL;
 
        /* hub notices our request, issues downstream resume, etc */
@@ -713,6 +715,9 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
        dum->gadget.ops = &dummy_ops;
        dum->gadget.is_dualspeed = 1;
 
+       /* maybe claim OTG support, though we won't complete HNP */
+       dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
+
        dum->devstatus = 0;
        dum->resuming = 0;
 
@@ -1215,6 +1220,16 @@ restart:
                                        switch (setup.wValue) {
                                        case USB_DEVICE_REMOTE_WAKEUP:
                                                break;
+                                       case USB_DEVICE_B_HNP_ENABLE:
+                                               dum->gadget.b_hnp_enable = 1;
+                                               break;
+                                       case USB_DEVICE_A_HNP_SUPPORT:
+                                               dum->gadget.a_hnp_support = 1;
+                                               break;
+                                       case USB_DEVICE_A_ALT_HNP_SUPPORT:
+                                               dum->gadget.a_alt_hnp_support
+                                                       = 1;
+                                               break;
                                        default:
                                                value = -EOPNOTSUPP;
                                        }
@@ -1533,6 +1548,13 @@ static int dummy_hub_control (
                                        spin_unlock (&dum->lock);
                                        dum->driver->suspend (&dum->gadget);
                                        spin_lock (&dum->lock);
+                                       /* HNP would happen here; for now we
+                                        * assume b_bus_req is always true.
+                                        */
+                                       if (((1 << USB_DEVICE_B_HNP_ENABLE)
+                                                       & dum->devstatus) != 0)
+                                               dev_dbg (dummy_dev(dum),
+                                                       "no HNP yet!\n");
                                }
                        }
                        break;
@@ -1648,6 +1670,10 @@ static int dummy_start (struct usb_hcd *hcd)
        hcd->power_budget = 8;
        hcd->state = HC_STATE_RUNNING;
 
+#ifdef CONFIG_USB_OTG
+       hcd->self.otg_port = 1;
+#endif
+
        /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
        device_create_file (dummy_dev(dum), &dev_attr_urbs);
        return 0;