diff options
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 231 |
1 files changed, 133 insertions, 98 deletions
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index ffedf4d1b747..dc0e3233b0e9 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -141,6 +141,8 @@ static const char *const ep_name [] = { | |||
141 | }; | 141 | }; |
142 | #define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) | 142 | #define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) |
143 | 143 | ||
144 | /*-------------------------------------------------------------------------*/ | ||
145 | |||
144 | #define FIFO_SIZE 64 | 146 | #define FIFO_SIZE 64 |
145 | 147 | ||
146 | struct urbp { | 148 | struct urbp { |
@@ -189,6 +191,11 @@ static inline struct device *dummy_dev (struct dummy *dum) | |||
189 | return dummy_to_hcd(dum)->self.controller; | 191 | return dummy_to_hcd(dum)->self.controller; |
190 | } | 192 | } |
191 | 193 | ||
194 | static inline struct device *udc_dev (struct dummy *dum) | ||
195 | { | ||
196 | return dum->gadget.dev.parent; | ||
197 | } | ||
198 | |||
192 | static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) | 199 | static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) |
193 | { | 200 | { |
194 | return container_of (ep->gadget, struct dummy, gadget); | 201 | return container_of (ep->gadget, struct dummy, gadget); |
@@ -208,19 +215,6 @@ static struct dummy *the_controller; | |||
208 | 215 | ||
209 | /*-------------------------------------------------------------------------*/ | 216 | /*-------------------------------------------------------------------------*/ |
210 | 217 | ||
211 | /* | ||
212 | * This "hardware" may look a bit odd in diagnostics since it's got both | ||
213 | * host and device sides; and it binds different drivers to each side. | ||
214 | */ | ||
215 | static struct platform_device the_pdev; | ||
216 | |||
217 | static struct device_driver dummy_driver = { | ||
218 | .name = (char *) driver_name, | ||
219 | .bus = &platform_bus_type, | ||
220 | }; | ||
221 | |||
222 | /*-------------------------------------------------------------------------*/ | ||
223 | |||
224 | /* SLAVE/GADGET SIDE DRIVER | 218 | /* SLAVE/GADGET SIDE DRIVER |
225 | * | 219 | * |
226 | * This only tracks gadget state. All the work is done when the host | 220 | * This only tracks gadget state. All the work is done when the host |
@@ -324,7 +318,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) | |||
324 | _ep->maxpacket = max; | 318 | _ep->maxpacket = max; |
325 | ep->desc = desc; | 319 | ep->desc = desc; |
326 | 320 | ||
327 | dev_dbg (dummy_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", | 321 | dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", |
328 | _ep->name, | 322 | _ep->name, |
329 | desc->bEndpointAddress & 0x0f, | 323 | desc->bEndpointAddress & 0x0f, |
330 | (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | 324 | (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", |
@@ -379,7 +373,7 @@ static int dummy_disable (struct usb_ep *_ep) | |||
379 | nuke (dum, ep); | 373 | nuke (dum, ep); |
380 | spin_unlock_irqrestore (&dum->lock, flags); | 374 | spin_unlock_irqrestore (&dum->lock, flags); |
381 | 375 | ||
382 | dev_dbg (dummy_dev(dum), "disabled %s\n", _ep->name); | 376 | dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name); |
383 | return retval; | 377 | return retval; |
384 | } | 378 | } |
385 | 379 | ||
@@ -474,7 +468,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, int mem_flags) | |||
474 | return -ESHUTDOWN; | 468 | return -ESHUTDOWN; |
475 | 469 | ||
476 | #if 0 | 470 | #if 0 |
477 | dev_dbg (dummy_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", | 471 | dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", |
478 | ep, _req, _ep->name, _req->length, _req->buf); | 472 | ep, _req, _ep->name, _req->length, _req->buf); |
479 | #endif | 473 | #endif |
480 | 474 | ||
@@ -537,7 +531,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) | |||
537 | spin_unlock_irqrestore (&dum->lock, flags); | 531 | spin_unlock_irqrestore (&dum->lock, flags); |
538 | 532 | ||
539 | if (retval == 0) { | 533 | if (retval == 0) { |
540 | dev_dbg (dummy_dev(dum), | 534 | dev_dbg (udc_dev(dum), |
541 | "dequeued req %p from %s, len %d buf %p\n", | 535 | "dequeued req %p from %s, len %d buf %p\n", |
542 | req, _ep->name, _req->length, _req->buf); | 536 | req, _ep->name, _req->length, _req->buf); |
543 | _req->complete (_ep, _req); | 537 | _req->complete (_ep, _req); |
@@ -661,38 +655,6 @@ DEVICE_ATTR (function, S_IRUGO, show_function, NULL); | |||
661 | * for each driver that registers: just add to a big root hub. | 655 | * for each driver that registers: just add to a big root hub. |
662 | */ | 656 | */ |
663 | 657 | ||
664 | /* This doesn't need to do anything because the udc device structure is | ||
665 | * stored inside the hcd and will be deallocated along with it. */ | ||
666 | static void | ||
667 | dummy_udc_release (struct device *dev) {} | ||
668 | |||
669 | /* This doesn't need to do anything because the pdev structure is | ||
670 | * statically allocated. */ | ||
671 | static void | ||
672 | dummy_pdev_release (struct device *dev) {} | ||
673 | |||
674 | static int | ||
675 | dummy_register_udc (struct dummy *dum) | ||
676 | { | ||
677 | int rc; | ||
678 | |||
679 | strcpy (dum->gadget.dev.bus_id, "udc"); | ||
680 | dum->gadget.dev.parent = dummy_dev(dum); | ||
681 | dum->gadget.dev.release = dummy_udc_release; | ||
682 | |||
683 | rc = device_register (&dum->gadget.dev); | ||
684 | if (rc == 0) | ||
685 | device_create_file (&dum->gadget.dev, &dev_attr_function); | ||
686 | return rc; | ||
687 | } | ||
688 | |||
689 | static void | ||
690 | dummy_unregister_udc (struct dummy *dum) | ||
691 | { | ||
692 | device_remove_file (&dum->gadget.dev, &dev_attr_function); | ||
693 | device_unregister (&dum->gadget.dev); | ||
694 | } | ||
695 | |||
696 | int | 658 | int |
697 | usb_gadget_register_driver (struct usb_gadget_driver *driver) | 659 | usb_gadget_register_driver (struct usb_gadget_driver *driver) |
698 | { | 660 | { |
@@ -711,12 +673,6 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
711 | * SLAVE side init ... the layer above hardware, which | 673 | * SLAVE side init ... the layer above hardware, which |
712 | * can't enumerate without help from the driver we're binding. | 674 | * can't enumerate without help from the driver we're binding. |
713 | */ | 675 | */ |
714 | dum->gadget.name = gadget_name; | ||
715 | dum->gadget.ops = &dummy_ops; | ||
716 | dum->gadget.is_dualspeed = 1; | ||
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 | 676 | ||
721 | dum->devstatus = 0; | 677 | dum->devstatus = 0; |
722 | dum->resuming = 0; | 678 | dum->resuming = 0; |
@@ -745,7 +701,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
745 | 701 | ||
746 | dum->driver = driver; | 702 | dum->driver = driver; |
747 | dum->gadget.dev.driver = &driver->driver; | 703 | dum->gadget.dev.driver = &driver->driver; |
748 | dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n", | 704 | dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", |
749 | driver->driver.name); | 705 | driver->driver.name); |
750 | if ((retval = driver->bind (&dum->gadget)) != 0) { | 706 | if ((retval = driver->bind (&dum->gadget)) != 0) { |
751 | dum->driver = NULL; | 707 | dum->driver = NULL; |
@@ -798,7 +754,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
798 | if (!driver || driver != dum->driver) | 754 | if (!driver || driver != dum->driver) |
799 | return -EINVAL; | 755 | return -EINVAL; |
800 | 756 | ||
801 | dev_dbg (dummy_dev(dum), "unregister gadget driver '%s'\n", | 757 | dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", |
802 | driver->driver.name); | 758 | driver->driver.name); |
803 | 759 | ||
804 | spin_lock_irqsave (&dum->lock, flags); | 760 | spin_lock_irqsave (&dum->lock, flags); |
@@ -826,6 +782,64 @@ int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode) | |||
826 | } | 782 | } |
827 | EXPORT_SYMBOL (net2280_set_fifo_mode); | 783 | EXPORT_SYMBOL (net2280_set_fifo_mode); |
828 | 784 | ||
785 | |||
786 | /* The gadget structure is stored inside the hcd structure and will be | ||
787 | * released along with it. */ | ||
788 | static void | ||
789 | dummy_gadget_release (struct device *dev) | ||
790 | { | ||
791 | #if 0 /* usb_bus_put isn't EXPORTed! */ | ||
792 | struct dummy *dum = gadget_dev_to_dummy (dev); | ||
793 | |||
794 | usb_bus_put (&dummy_to_hcd (dum)->self); | ||
795 | #endif | ||
796 | } | ||
797 | |||
798 | static int dummy_udc_probe (struct device *dev) | ||
799 | { | ||
800 | struct dummy *dum = the_controller; | ||
801 | int rc; | ||
802 | |||
803 | dum->gadget.name = gadget_name; | ||
804 | dum->gadget.ops = &dummy_ops; | ||
805 | dum->gadget.is_dualspeed = 1; | ||
806 | |||
807 | /* maybe claim OTG support, though we won't complete HNP */ | ||
808 | dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); | ||
809 | |||
810 | strcpy (dum->gadget.dev.bus_id, "gadget"); | ||
811 | dum->gadget.dev.parent = dev; | ||
812 | dum->gadget.dev.release = dummy_gadget_release; | ||
813 | rc = device_register (&dum->gadget.dev); | ||
814 | if (rc < 0) | ||
815 | return rc; | ||
816 | |||
817 | #if 0 /* usb_bus_get isn't EXPORTed! */ | ||
818 | usb_bus_get (&dummy_to_hcd (dum)->self); | ||
819 | #endif | ||
820 | |||
821 | dev_set_drvdata (dev, dum); | ||
822 | device_create_file (&dum->gadget.dev, &dev_attr_function); | ||
823 | return rc; | ||
824 | } | ||
825 | |||
826 | static int dummy_udc_remove (struct device *dev) | ||
827 | { | ||
828 | struct dummy *dum = dev_get_drvdata (dev); | ||
829 | |||
830 | dev_set_drvdata (dev, NULL); | ||
831 | device_remove_file (&dum->gadget.dev, &dev_attr_function); | ||
832 | device_unregister (&dum->gadget.dev); | ||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static struct device_driver dummy_udc_driver = { | ||
837 | .name = (char *) gadget_name, | ||
838 | .bus = &platform_bus_type, | ||
839 | .probe = dummy_udc_probe, | ||
840 | .remove = dummy_udc_remove, | ||
841 | }; | ||
842 | |||
829 | /*-------------------------------------------------------------------------*/ | 843 | /*-------------------------------------------------------------------------*/ |
830 | 844 | ||
831 | /* MASTER/HOST SIDE DRIVER | 845 | /* MASTER/HOST SIDE DRIVER |
@@ -1184,7 +1198,7 @@ restart: | |||
1184 | list_for_each_entry (req, &ep->queue, queue) { | 1198 | list_for_each_entry (req, &ep->queue, queue) { |
1185 | list_del_init (&req->queue); | 1199 | list_del_init (&req->queue); |
1186 | req->req.status = -EOVERFLOW; | 1200 | req->req.status = -EOVERFLOW; |
1187 | dev_dbg (dummy_dev(dum), "stale req = %p\n", | 1201 | dev_dbg (udc_dev(dum), "stale req = %p\n", |
1188 | req); | 1202 | req); |
1189 | 1203 | ||
1190 | spin_unlock (&dum->lock); | 1204 | spin_unlock (&dum->lock); |
@@ -1207,7 +1221,7 @@ restart: | |||
1207 | break; | 1221 | break; |
1208 | dum->address = setup.wValue; | 1222 | dum->address = setup.wValue; |
1209 | maybe_set_status (urb, 0); | 1223 | maybe_set_status (urb, 0); |
1210 | dev_dbg (dummy_dev(dum), "set_address = %d\n", | 1224 | dev_dbg (udc_dev(dum), "set_address = %d\n", |
1211 | setup.wValue); | 1225 | setup.wValue); |
1212 | value = 0; | 1226 | value = 0; |
1213 | break; | 1227 | break; |
@@ -1333,7 +1347,7 @@ restart: | |||
1333 | 1347 | ||
1334 | if (value < 0) { | 1348 | if (value < 0) { |
1335 | if (value != -EOPNOTSUPP) | 1349 | if (value != -EOPNOTSUPP) |
1336 | dev_dbg (dummy_dev(dum), | 1350 | dev_dbg (udc_dev(dum), |
1337 | "setup --> %d\n", | 1351 | "setup --> %d\n", |
1338 | value); | 1352 | value); |
1339 | maybe_set_status (urb, -EPIPE); | 1353 | maybe_set_status (urb, -EPIPE); |
@@ -1561,7 +1575,7 @@ static int dummy_hub_control ( | |||
1561 | | USB_PORT_STAT_LOW_SPEED | 1575 | | USB_PORT_STAT_LOW_SPEED |
1562 | | USB_PORT_STAT_HIGH_SPEED); | 1576 | | USB_PORT_STAT_HIGH_SPEED); |
1563 | if (dum->driver) { | 1577 | if (dum->driver) { |
1564 | dev_dbg (dummy_dev(dum), | 1578 | dev_dbg (udc_dev(dum), |
1565 | "disconnect\n"); | 1579 | "disconnect\n"); |
1566 | stop_activity (dum, dum->driver); | 1580 | stop_activity (dum, dum->driver); |
1567 | } | 1581 | } |
@@ -1643,7 +1657,6 @@ static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); | |||
1643 | static int dummy_start (struct usb_hcd *hcd) | 1657 | static int dummy_start (struct usb_hcd *hcd) |
1644 | { | 1658 | { |
1645 | struct dummy *dum; | 1659 | struct dummy *dum; |
1646 | int retval; | ||
1647 | 1660 | ||
1648 | dum = hcd_to_dummy (hcd); | 1661 | dum = hcd_to_dummy (hcd); |
1649 | 1662 | ||
@@ -1659,9 +1672,6 @@ static int dummy_start (struct usb_hcd *hcd) | |||
1659 | 1672 | ||
1660 | INIT_LIST_HEAD (&dum->urbp_list); | 1673 | INIT_LIST_HEAD (&dum->urbp_list); |
1661 | 1674 | ||
1662 | if ((retval = dummy_register_udc (dum)) != 0) | ||
1663 | return retval; | ||
1664 | |||
1665 | /* only show a low-power port: just 8mA */ | 1675 | /* only show a low-power port: just 8mA */ |
1666 | hcd->power_budget = 8; | 1676 | hcd->power_budget = 8; |
1667 | hcd->state = HC_STATE_RUNNING; | 1677 | hcd->state = HC_STATE_RUNNING; |
@@ -1682,10 +1692,7 @@ static void dummy_stop (struct usb_hcd *hcd) | |||
1682 | dum = hcd_to_dummy (hcd); | 1692 | dum = hcd_to_dummy (hcd); |
1683 | 1693 | ||
1684 | device_remove_file (dummy_dev(dum), &dev_attr_urbs); | 1694 | device_remove_file (dummy_dev(dum), &dev_attr_urbs); |
1685 | |||
1686 | usb_gadget_unregister_driver (dum->driver); | 1695 | usb_gadget_unregister_driver (dum->driver); |
1687 | dummy_unregister_udc (dum); | ||
1688 | |||
1689 | dev_info (dummy_dev(dum), "stopped\n"); | 1696 | dev_info (dummy_dev(dum), "stopped\n"); |
1690 | } | 1697 | } |
1691 | 1698 | ||
@@ -1715,7 +1722,7 @@ static const struct hc_driver dummy_hcd = { | |||
1715 | .hub_control = dummy_hub_control, | 1722 | .hub_control = dummy_hub_control, |
1716 | }; | 1723 | }; |
1717 | 1724 | ||
1718 | static int dummy_probe (struct device *dev) | 1725 | static int dummy_hcd_probe (struct device *dev) |
1719 | { | 1726 | { |
1720 | struct usb_hcd *hcd; | 1727 | struct usb_hcd *hcd; |
1721 | int retval; | 1728 | int retval; |
@@ -1735,7 +1742,7 @@ static int dummy_probe (struct device *dev) | |||
1735 | return retval; | 1742 | return retval; |
1736 | } | 1743 | } |
1737 | 1744 | ||
1738 | static void dummy_remove (struct device *dev) | 1745 | static int dummy_hcd_remove (struct device *dev) |
1739 | { | 1746 | { |
1740 | struct usb_hcd *hcd; | 1747 | struct usb_hcd *hcd; |
1741 | 1748 | ||
@@ -1743,35 +1750,41 @@ static void dummy_remove (struct device *dev) | |||
1743 | usb_remove_hcd (hcd); | 1750 | usb_remove_hcd (hcd); |
1744 | usb_put_hcd (hcd); | 1751 | usb_put_hcd (hcd); |
1745 | the_controller = NULL; | 1752 | the_controller = NULL; |
1753 | return 0; | ||
1746 | } | 1754 | } |
1747 | 1755 | ||
1748 | /*-------------------------------------------------------------------------*/ | 1756 | static struct device_driver dummy_hcd_driver = { |
1749 | 1757 | .name = (char *) driver_name, | |
1750 | static int dummy_pdev_detect (void) | 1758 | .bus = &platform_bus_type, |
1751 | { | 1759 | .probe = dummy_hcd_probe, |
1752 | int retval; | 1760 | .remove = dummy_hcd_remove, |
1753 | 1761 | }; | |
1754 | retval = driver_register (&dummy_driver); | ||
1755 | if (retval < 0) | ||
1756 | return retval; | ||
1757 | 1762 | ||
1758 | the_pdev.name = "hc"; | 1763 | /*-------------------------------------------------------------------------*/ |
1759 | the_pdev.dev.driver = &dummy_driver; | ||
1760 | the_pdev.dev.release = dummy_pdev_release; | ||
1761 | 1764 | ||
1762 | retval = platform_device_register (&the_pdev); | 1765 | /* These don't need to do anything because the pdev structures are |
1763 | if (retval < 0) | 1766 | * statically allocated. */ |
1764 | driver_unregister (&dummy_driver); | 1767 | static void |
1765 | return retval; | 1768 | dummy_udc_release (struct device *dev) {} |
1766 | } | ||
1767 | 1769 | ||
1768 | static void dummy_pdev_remove (void) | 1770 | static void |
1769 | { | 1771 | dummy_hcd_release (struct device *dev) {} |
1770 | platform_device_unregister (&the_pdev); | 1772 | |
1771 | driver_unregister (&dummy_driver); | 1773 | static struct platform_device the_udc_pdev = { |
1772 | } | 1774 | .name = (char *) gadget_name, |
1775 | .id = -1, | ||
1776 | .dev = { | ||
1777 | .release = dummy_udc_release, | ||
1778 | }, | ||
1779 | }; | ||
1773 | 1780 | ||
1774 | /*-------------------------------------------------------------------------*/ | 1781 | static struct platform_device the_hcd_pdev = { |
1782 | .name = (char *) driver_name, | ||
1783 | .id = -1, | ||
1784 | .dev = { | ||
1785 | .release = dummy_hcd_release, | ||
1786 | }, | ||
1787 | }; | ||
1775 | 1788 | ||
1776 | static int __init init (void) | 1789 | static int __init init (void) |
1777 | { | 1790 | { |
@@ -1779,17 +1792,39 @@ static int __init init (void) | |||
1779 | 1792 | ||
1780 | if (usb_disabled ()) | 1793 | if (usb_disabled ()) |
1781 | return -ENODEV; | 1794 | return -ENODEV; |
1782 | if ((retval = dummy_pdev_detect ()) != 0) | 1795 | |
1796 | retval = driver_register (&dummy_hcd_driver); | ||
1797 | if (retval < 0) | ||
1783 | return retval; | 1798 | return retval; |
1784 | if ((retval = dummy_probe (&the_pdev.dev)) != 0) | 1799 | |
1785 | dummy_pdev_remove (); | 1800 | retval = driver_register (&dummy_udc_driver); |
1801 | if (retval < 0) | ||
1802 | goto err_register_udc_driver; | ||
1803 | |||
1804 | retval = platform_device_register (&the_hcd_pdev); | ||
1805 | if (retval < 0) | ||
1806 | goto err_register_hcd; | ||
1807 | |||
1808 | retval = platform_device_register (&the_udc_pdev); | ||
1809 | if (retval < 0) | ||
1810 | goto err_register_udc; | ||
1811 | return retval; | ||
1812 | |||
1813 | err_register_udc: | ||
1814 | platform_device_unregister (&the_hcd_pdev); | ||
1815 | err_register_hcd: | ||
1816 | driver_unregister (&dummy_udc_driver); | ||
1817 | err_register_udc_driver: | ||
1818 | driver_unregister (&dummy_hcd_driver); | ||
1786 | return retval; | 1819 | return retval; |
1787 | } | 1820 | } |
1788 | module_init (init); | 1821 | module_init (init); |
1789 | 1822 | ||
1790 | static void __exit cleanup (void) | 1823 | static void __exit cleanup (void) |
1791 | { | 1824 | { |
1792 | dummy_remove (&the_pdev.dev); | 1825 | platform_device_unregister (&the_udc_pdev); |
1793 | dummy_pdev_remove (); | 1826 | platform_device_unregister (&the_hcd_pdev); |
1827 | driver_unregister (&dummy_udc_driver); | ||
1828 | driver_unregister (&dummy_hcd_driver); | ||
1794 | } | 1829 | } |
1795 | module_exit (cleanup); | 1830 | module_exit (cleanup); |