Separate waiting for a device and enumerating a device

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3204 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2010-12-21 01:41:03 +00:00
parent b0536844c6
commit 91fe0544dc
3 changed files with 78 additions and 30 deletions

View File

@ -164,7 +164,5 @@ void up_initialize(void)
/* Initialize USB -- device and/or host */ /* Initialize USB -- device and/or host */
up_usbinitialize(); up_usbinitialize();
up_usbhostinitialize();
up_ledon(LED_IRQSENABLED); up_ledon(LED_IRQSENABLED);
} }

View File

@ -275,12 +275,6 @@ extern void up_usbuninitialize(void);
# define up_usbuninitialize() # define up_usbuninitialize()
#endif #endif
#ifdef CONFIG_USBHOST
extern void up_usbhostinitialize(void);
#else
# define up_usbhostinitialize()
#endif
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __UP_INTERNAL_H */ #endif /* __UP_INTERNAL_H */

View File

@ -250,6 +250,7 @@ static int lpc17_usbinterrupt(int irq, FAR void *context);
/* USB host controller operations **********************************************/ /* USB host controller operations **********************************************/
static int lpc17_wait(FAR struct usbhost_driver_s *drvr);
static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr); static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr);
static int lpc17_alloc(FAR struct usbhost_driver_s *drvr, static int lpc17_alloc(FAR struct usbhost_driver_s *drvr,
FAR uint8_t **buffer, FAR size_t *maxlen); FAR uint8_t **buffer, FAR size_t *maxlen);
@ -284,6 +285,7 @@ static struct lpc17_usbhost_s g_usbhost =
{ {
.drvr = .drvr =
{ {
.wait = lpc17_wait,
.enumerate = lpc17_enumerate, .enumerate = lpc17_enumerate,
.alloc = lpc17_alloc, .alloc = lpc17_alloc,
.free = lpc17_free, .free = lpc17_free,
@ -938,19 +940,56 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
* USB Host Controller Operations * USB Host Controller Operations
*******************************************************************************/ *******************************************************************************/
/*******************************************************************************
* Name: lpc17_wait
*
* Description:
* Wait for a device to be connected.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
*
* Returned Values:
* Zero (OK) is returned when a device in connected. This function will not
* return until either (1) a device is connected or (2) some failure occurs.
* On a failure, a negated errno value is returned indicating the nature of
* the failure
*
* Assumptions:
* - Called from a single thread so no mutual exclusion is required.
* - Never called from an interrupt handler.
*
*******************************************************************************/
static int lpc17_wait(FAR struct usbhost_driver_s *drvr)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
/* Are we already connected? */
while (!priv->connected)
{
/* No, wait for the connection */
lpc17_takesem(&priv->rhssem);
}
return OK;
}
/******************************************************************************* /*******************************************************************************
* Name: lpc17_enumerate * Name: lpc17_enumerate
* *
* Description: * Description:
* Enumerate the connected device. This function will enqueue the * Enumerate the connected device. As part of this enumeration process,
* enumeration process. As part of this enumeration process, the driver * the driver will (1) get the device's configuration descriptor, (2)
* will (1) get the device's configuration descriptor, (2) extract the class * extract the class ID info from the configuration descriptor, (3) call
* ID info from the configuration descriptor, (3) call usbhost_findclass() * usbhost_findclass() to find the class that supports this device, (4)
* to find the class that supports this device, (4) call the create() * call the create() method on the struct usbhost_registry_s interface
* method on the struct usbhost_registry_s interface to get a class * to get a class instance, and finally (5) call the configdesc() method
* instance, and finally (5) call the configdesc() method of the struct * of the struct usbhost_class_s interface. After that, the class is in
* usbhost_class_s interface. After that, the class is in charge of the * charge of the sequence of operations.
* sequence of operations.
* *
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to * drvr - The USB host driver instance obtained as a parameter from the call to
@ -975,7 +1014,17 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
uint8_t *td; uint8_t *td;
int ret; int ret;
ulldbg("Enumerate device\n"); /* Are we connected to a device? The caller should have called the wait()
* method first to be assured that a device is connected.
*/
while (!priv->connected)
{
/* No, return an error */
return -ENODEV;
}
ulldbg("Enumerate the device\n");
/* Allocate a TD buffer for use in this function */ /* Allocate a TD buffer for use in this function */
@ -986,15 +1035,6 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
} }
ctrlreq = (struct usb_ctrlreq_s *)td; ctrlreq = (struct usb_ctrlreq_s *)td;
/* Are we already connected? */
while (!priv->connected)
{
/* No, wait for the connection */
lpc17_takesem(&priv->rhssem);
}
/* USB 2.0 spec says at least 50ms delay before port reset */ /* USB 2.0 spec says at least 50ms delay before port reset */
up_mdelay(100); up_mdelay(100);
@ -1499,13 +1539,26 @@ static void lpc17_hccainit(volatile struct lpc17_hcca_s *hcca)
* Description: * Description:
* Initialize USB host device controller hardware. * Initialize USB host device controller hardware.
* *
* Input Parameters:
* controller -- If the device supports more than USB host controller, then
* this identifies which controller is being intialized. Normally, this
* is just zero.
*
* Returned Value:
* And instance of the USB host interface. The controlling task should
* use this interface to (1) call the wait() method to wait for a device
* to be connected, and (2) call the enumerate() method to bind the device
* to a class driver.
*
* Assumptions: * Assumptions:
* This function is called very early in the initialization sequence in order * - This function should called in the initialization sequence in order
* to initialize the USB device functionality. * to initialize the USB device functionality.
* - Class drivers should be initialized prior to calling this function.
* Otherwise, there is a race condition if the device is already connected.
* *
*******************************************************************************/ *******************************************************************************/
void up_usbhostinitialize(void) FAR struct usbhost_driver_s *up_usbhostinitialize(int controller)
{ {
struct lpc17_usbhost_s *priv = &g_usbhost; struct lpc17_usbhost_s *priv = &g_usbhost;
uint32_t regval; uint32_t regval;
@ -1513,6 +1566,8 @@ void up_usbhostinitialize(void)
irqstate_t flags; irqstate_t flags;
int i; int i;
DEBUGASSERT(controller == 0);
/* Initialize the state data structure */ /* Initialize the state data structure */
sem_init(&priv->rhssem, 0, 0); sem_init(&priv->rhssem, 0, 0);
@ -1627,7 +1682,7 @@ void up_usbhostinitialize(void)
if (irq_attach(LPC17_IRQ_USB, lpc17_usbinterrupt) != 0) if (irq_attach(LPC17_IRQ_USB, lpc17_usbinterrupt) != 0)
{ {
udbg("Failed to attach IRQ\n"); udbg("Failed to attach IRQ\n");
return; return NULL;
} }
/* Enable USB interrupts at the SYCON controller */ /* Enable USB interrupts at the SYCON controller */
@ -1642,4 +1697,5 @@ void up_usbhostinitialize(void)
up_enable_irq(LPC17_IRQ_USB); /* enable USB interrupt */ up_enable_irq(LPC17_IRQ_USB); /* enable USB interrupt */
udbg("USB host Initialized\n"); udbg("USB host Initialized\n");
return &priv->drvr;
} }