#define DEBUG
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
-#include <linux/version.h>
-
+#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb_gadget.h>
/* or like sa1100: two fixed function endpoints */
"ep1out-bulk", "ep2in-bulk",
};
-#define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *))
+#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
/*-------------------------------------------------------------------------*/
return NULL;
ep = usb_ep_to_dummy_ep (_ep);
- req = kmalloc (sizeof *req, mem_flags);
+ req = kzalloc(sizeof(*req), mem_flags);
if (!req)
return NULL;
- memset (req, 0, sizeof *req);
INIT_LIST_HEAD (&req->queue);
return &req->req;
}
if (!dum->driver)
return -ESHUTDOWN;
- spin_lock_irqsave (&dum->lock, flags);
+ local_irq_save (flags);
+ spin_lock (&dum->lock);
list_for_each_entry (req, &ep->queue, queue) {
if (&req->req == _req) {
list_del_init (&req->queue);
break;
}
}
- spin_unlock_irqrestore (&dum->lock, flags);
+ spin_unlock (&dum->lock);
if (retval == 0) {
dev_dbg (udc_dev(dum),
req, _ep->name, _req->length, _req->buf);
_req->complete (_ep, _req);
}
+ local_irq_restore (flags);
return retval;
}
return -EINVAL;
if (dum->driver)
return -EBUSY;
- if (!driver->bind || !driver->unbind || !driver->setup
+ if (!driver->bind || !driver->setup
|| driver->speed == USB_SPEED_UNKNOWN)
return -EINVAL;
dum->gadget.dev.driver = &driver->driver;
dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
driver->driver.name);
- if ((retval = driver->bind (&dum->gadget)) != 0) {
- dum->driver = NULL;
- dum->gadget.dev.driver = NULL;
- return retval;
- }
+ if ((retval = driver->bind (&dum->gadget)) != 0)
+ goto err_bind_gadget;
driver->driver.bus = dum->gadget.dev.parent->bus;
- driver_register (&driver->driver);
- device_bind_driver (&dum->gadget.dev);
+ if ((retval = driver_register (&driver->driver)) != 0)
+ goto err_register;
+ if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
+ goto err_bind_driver;
/* khubd will enumerate this in a while */
spin_lock_irq (&dum->lock);
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
+
+err_bind_driver:
+ driver_unregister (&driver->driver);
+err_register:
+ if (driver->unbind)
+ driver->unbind (&dum->gadget);
+ spin_lock_irq (&dum->lock);
+ dum->pullup = 0;
+ set_link_state (dum);
+ spin_unlock_irq (&dum->lock);
+err_bind_gadget:
+ dum->driver = NULL;
+ dum->gadget.dev.driver = NULL;
+ return retval;
}
EXPORT_SYMBOL (usb_gadget_register_driver);
if (!dum)
return -ENODEV;
- if (!driver || driver != dum->driver)
+ if (!driver || driver != dum->driver || !driver->unbind)
return -EINVAL;
dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
static void
dummy_gadget_release (struct device *dev)
{
-#if 0 /* usb_bus_put isn't EXPORTed! */
struct dummy *dum = gadget_dev_to_dummy (dev);
- usb_bus_put (&dummy_to_hcd (dum)->self);
-#endif
+ usb_put_hcd (dummy_to_hcd (dum));
}
-static int dummy_udc_probe (struct device *dev)
+static int dummy_udc_probe (struct platform_device *pdev)
{
struct dummy *dum = the_controller;
int rc;
dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
strcpy (dum->gadget.dev.bus_id, "gadget");
- dum->gadget.dev.parent = dev;
+ dum->gadget.dev.parent = &pdev->dev;
dum->gadget.dev.release = dummy_gadget_release;
rc = device_register (&dum->gadget.dev);
if (rc < 0)
return rc;
-#if 0 /* usb_bus_get isn't EXPORTed! */
- usb_bus_get (&dummy_to_hcd (dum)->self);
-#endif
+ usb_get_hcd (dummy_to_hcd (dum));
- dev_set_drvdata (dev, dum);
- device_create_file (&dum->gadget.dev, &dev_attr_function);
+ platform_set_drvdata (pdev, dum);
+ rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
+ if (rc < 0)
+ device_unregister (&dum->gadget.dev);
return rc;
}
-static int dummy_udc_remove (struct device *dev)
+static int dummy_udc_remove (struct platform_device *pdev)
{
- struct dummy *dum = dev_get_drvdata (dev);
+ struct dummy *dum = platform_get_drvdata (pdev);
- dev_set_drvdata (dev, NULL);
+ platform_set_drvdata (pdev, NULL);
device_remove_file (&dum->gadget.dev, &dev_attr_function);
device_unregister (&dum->gadget.dev);
return 0;
}
-static int dummy_udc_suspend (struct device *dev, pm_message_t state)
+static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
{
- struct dummy *dum = dev_get_drvdata(dev);
+ struct dummy *dum = platform_get_drvdata(pdev);
- dev_dbg (dev, "%s\n", __FUNCTION__);
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 1;
set_link_state (dum);
spin_unlock_irq (&dum->lock);
- dev->power.power_state = state;
+ pdev->dev.power.power_state = state;
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
-static int dummy_udc_resume (struct device *dev)
+static int dummy_udc_resume (struct platform_device *pdev)
{
- struct dummy *dum = dev_get_drvdata(dev);
+ struct dummy *dum = platform_get_drvdata(pdev);
- dev_dbg (dev, "%s\n", __FUNCTION__);
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 0;
set_link_state (dum);
spin_unlock_irq (&dum->lock);
- dev->power.power_state = PMSG_ON;
+ pdev->dev.power.power_state = PMSG_ON;
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
-static struct device_driver dummy_udc_driver = {
- .name = (char *) gadget_name,
- .bus = &platform_bus_type,
+static struct platform_driver dummy_udc_driver = {
.probe = dummy_udc_probe,
.remove = dummy_udc_remove,
.suspend = dummy_udc_suspend,
.resume = dummy_udc_resume,
+ .driver = {
+ .name = (char *) gadget_name,
+ .owner = THIS_MODULE,
+ },
};
/*-------------------------------------------------------------------------*/
ep->already_seen = ep->setup_stage = 0;
spin_unlock (&dum->lock);
- usb_hcd_giveback_urb (dummy_to_hcd(dum), urb, NULL);
+ usb_hcd_giveback_urb (dummy_to_hcd(dum), urb);
spin_lock (&dum->lock);
goto restart;
dum = hcd_to_dummy (hcd);
spin_lock_irqsave (&dum->lock, flags);
- if (hcd->state != HC_STATE_RUNNING)
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
goto done;
if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
int retval = 0;
unsigned long flags;
- if (hcd->state != HC_STATE_RUNNING)
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
return -ETIMEDOUT;
dum = hcd_to_dummy (hcd);
{
struct dummy *dum = hcd_to_dummy (hcd);
+ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+
spin_lock_irq (&dum->lock);
dum->rh_state = DUMMY_RH_SUSPENDED;
set_link_state (dum);
+ hcd->state = HC_STATE_SUSPENDED;
spin_unlock_irq (&dum->lock);
return 0;
}
static int dummy_bus_resume (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
+ int rc = 0;
+
+ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
- dum->rh_state = DUMMY_RH_RUNNING;
- set_link_state (dum);
- if (!list_empty(&dum->urbp_list))
- mod_timer (&dum->timer, jiffies);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
+ rc = -ENODEV;
+ } else {
+ dum->rh_state = DUMMY_RH_RUNNING;
+ set_link_state (dum);
+ if (!list_empty(&dum->urbp_list))
+ mod_timer (&dum->timer, jiffies);
+ hcd->state = HC_STATE_RUNNING;
+ }
spin_unlock_irq (&dum->lock);
- return 0;
+ return rc;
}
/*-------------------------------------------------------------------------*/
#endif
/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
- device_create_file (dummy_dev(dum), &dev_attr_urbs);
- return 0;
+ return device_create_file (dummy_dev(dum), &dev_attr_urbs);
}
static void dummy_stop (struct usb_hcd *hcd)
.bus_resume = dummy_bus_resume,
};
-static int dummy_hcd_probe (struct device *dev)
+static int dummy_hcd_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
int retval;
- dev_info (dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+ dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
- hcd = usb_create_hcd (&dummy_hcd, dev, dev->bus_id);
+ hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
if (!hcd)
return -ENOMEM;
the_controller = hcd_to_dummy (hcd);
return retval;
}
-static int dummy_hcd_remove (struct device *dev)
+static int dummy_hcd_remove (struct platform_device *pdev)
{
struct usb_hcd *hcd;
- hcd = dev_get_drvdata (dev);
+ hcd = platform_get_drvdata (pdev);
usb_remove_hcd (hcd);
usb_put_hcd (hcd);
the_controller = NULL;
return 0;
}
-static int dummy_hcd_suspend (struct device *dev, pm_message_t state)
+static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd;
+ struct dummy *dum;
+ int rc = 0;
- dev_dbg (dev, "%s\n", __FUNCTION__);
- hcd = dev_get_drvdata (dev);
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
- hcd->state = HC_STATE_SUSPENDED;
- return 0;
+ hcd = platform_get_drvdata (pdev);
+ dum = hcd_to_dummy (hcd);
+ if (dum->rh_state == DUMMY_RH_RUNNING) {
+ dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
+ rc = -EBUSY;
+ } else
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ return rc;
}
-static int dummy_hcd_resume (struct device *dev)
+static int dummy_hcd_resume (struct platform_device *pdev)
{
struct usb_hcd *hcd;
- dev_dbg (dev, "%s\n", __FUNCTION__);
- hcd = dev_get_drvdata (dev);
- hcd->state = HC_STATE_RUNNING;
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+ hcd = platform_get_drvdata (pdev);
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
usb_hcd_poll_rh_status (hcd);
return 0;
}
-static struct device_driver dummy_hcd_driver = {
- .name = (char *) driver_name,
- .bus = &platform_bus_type,
+static struct platform_driver dummy_hcd_driver = {
.probe = dummy_hcd_probe,
.remove = dummy_hcd_remove,
.suspend = dummy_hcd_suspend,
.resume = dummy_hcd_resume,
+ .driver = {
+ .name = (char *) driver_name,
+ .owner = THIS_MODULE,
+ },
};
/*-------------------------------------------------------------------------*/
if (usb_disabled ())
return -ENODEV;
- retval = driver_register (&dummy_hcd_driver);
+ retval = platform_driver_register (&dummy_hcd_driver);
if (retval < 0)
return retval;
- retval = driver_register (&dummy_udc_driver);
+ retval = platform_driver_register (&dummy_udc_driver);
if (retval < 0)
goto err_register_udc_driver;
err_register_udc:
platform_device_unregister (&the_hcd_pdev);
err_register_hcd:
- driver_unregister (&dummy_udc_driver);
+ platform_driver_unregister (&dummy_udc_driver);
err_register_udc_driver:
- driver_unregister (&dummy_hcd_driver);
+ platform_driver_unregister (&dummy_hcd_driver);
return retval;
}
module_init (init);
{
platform_device_unregister (&the_udc_pdev);
platform_device_unregister (&the_hcd_pdev);
- driver_unregister (&dummy_udc_driver);
- driver_unregister (&dummy_hcd_driver);
+ platform_driver_unregister (&dummy_udc_driver);
+ platform_driver_unregister (&dummy_hcd_driver);
}
module_exit (cleanup);