diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-05-02 11:25:17 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-27 17:43:51 -0400 |
commit | 5742b0c95026c817d9c266174ca39a909e8d38ca (patch) | |
tree | 4f94fd2d99c134e9d600983b834014b933fca7c6 /drivers | |
parent | 65111084c63d7674dc37833e8eb59cfdaa4d0bda (diff) |
[PATCH] USB dummy_hcd: Partial OTG emulation
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 1918d10f7569..e9b95df5b23d 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -601,8 +601,10 @@ static int dummy_wakeup (struct usb_gadget *_gadget) | |||
601 | struct dummy *dum; | 601 | struct dummy *dum; |
602 | 602 | ||
603 | dum = gadget_to_dummy (_gadget); | 603 | dum = gadget_to_dummy (_gadget); |
604 | if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0 | 604 | if (!(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) |
605 | || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))) | 605 | || !(dum->devstatus & |
606 | ( (1 << USB_DEVICE_B_HNP_ENABLE) | ||
607 | | (1 << USB_DEVICE_REMOTE_WAKEUP)))) | ||
606 | return -EINVAL; | 608 | return -EINVAL; |
607 | 609 | ||
608 | /* hub notices our request, issues downstream resume, etc */ | 610 | /* hub notices our request, issues downstream resume, etc */ |
@@ -713,6 +715,9 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
713 | dum->gadget.ops = &dummy_ops; | 715 | dum->gadget.ops = &dummy_ops; |
714 | dum->gadget.is_dualspeed = 1; | 716 | dum->gadget.is_dualspeed = 1; |
715 | 717 | ||
718 | /* maybe claim OTG support, though we won't complete HNP */ | ||
719 | dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); | ||
720 | |||
716 | dum->devstatus = 0; | 721 | dum->devstatus = 0; |
717 | dum->resuming = 0; | 722 | dum->resuming = 0; |
718 | 723 | ||
@@ -1215,6 +1220,16 @@ restart: | |||
1215 | switch (setup.wValue) { | 1220 | switch (setup.wValue) { |
1216 | case USB_DEVICE_REMOTE_WAKEUP: | 1221 | case USB_DEVICE_REMOTE_WAKEUP: |
1217 | break; | 1222 | break; |
1223 | case USB_DEVICE_B_HNP_ENABLE: | ||
1224 | dum->gadget.b_hnp_enable = 1; | ||
1225 | break; | ||
1226 | case USB_DEVICE_A_HNP_SUPPORT: | ||
1227 | dum->gadget.a_hnp_support = 1; | ||
1228 | break; | ||
1229 | case USB_DEVICE_A_ALT_HNP_SUPPORT: | ||
1230 | dum->gadget.a_alt_hnp_support | ||
1231 | = 1; | ||
1232 | break; | ||
1218 | default: | 1233 | default: |
1219 | value = -EOPNOTSUPP; | 1234 | value = -EOPNOTSUPP; |
1220 | } | 1235 | } |
@@ -1533,6 +1548,13 @@ static int dummy_hub_control ( | |||
1533 | spin_unlock (&dum->lock); | 1548 | spin_unlock (&dum->lock); |
1534 | dum->driver->suspend (&dum->gadget); | 1549 | dum->driver->suspend (&dum->gadget); |
1535 | spin_lock (&dum->lock); | 1550 | spin_lock (&dum->lock); |
1551 | /* HNP would happen here; for now we | ||
1552 | * assume b_bus_req is always true. | ||
1553 | */ | ||
1554 | if (((1 << USB_DEVICE_B_HNP_ENABLE) | ||
1555 | & dum->devstatus) != 0) | ||
1556 | dev_dbg (dummy_dev(dum), | ||
1557 | "no HNP yet!\n"); | ||
1536 | } | 1558 | } |
1537 | } | 1559 | } |
1538 | break; | 1560 | break; |
@@ -1648,6 +1670,10 @@ static int dummy_start (struct usb_hcd *hcd) | |||
1648 | hcd->power_budget = 8; | 1670 | hcd->power_budget = 8; |
1649 | hcd->state = HC_STATE_RUNNING; | 1671 | hcd->state = HC_STATE_RUNNING; |
1650 | 1672 | ||
1673 | #ifdef CONFIG_USB_OTG | ||
1674 | hcd->self.otg_port = 1; | ||
1675 | #endif | ||
1676 | |||
1651 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ | 1677 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ |
1652 | device_create_file (dummy_dev(dum), &dev_attr_urbs); | 1678 | device_create_file (dummy_dev(dum), &dev_attr_urbs); |
1653 | return 0; | 1679 | return 0; |