LPC17 USB HCD: Adapted to new interface

This commit is contained in:
Gregory Nutt 2015-04-21 13:11:32 -06:00
parent fde0bf650e
commit 2afe696012

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
* arch/arm/src/lpc17xx/lpc17_usbhost.c * arch/arm/src/lpc17xx/lpc17_usbhost.c
* *
* Copyright (C) 2010-2012, 2014 Gregory Nutt. All rights reserved. * Copyright (C) 2010-2012, 2014-2015 Gregory Nutt. All rights reserved.
* Authors: Rafael Noronha <rafael@pdsolucoes.com.br> * Authors: Rafael Noronha <rafael@pdsolucoes.com.br>
* Gregory Nutt <gnutt@nuttx.org> * Gregory Nutt <gnutt@nuttx.org>
* *
@ -54,6 +54,7 @@
#include <nuttx/usb/usb.h> #include <nuttx/usb/usb.h>
#include <nuttx/usb/ohci.h> #include <nuttx/usb/ohci.h>
#include <nuttx/usb/usbhost.h> #include <nuttx/usb/usbhost.h>
#include <nuttx/usb/usbhost_devaddr.h>
#include <arch/irq.h> #include <arch/irq.h>
@ -153,6 +154,10 @@ struct lpc17_usbhost_s
struct usbhost_driver_s drvr; struct usbhost_driver_s drvr;
/* This is the hub port description understood by class drivers */
struct usbhost_roothubport_s hport;
/* The bound device class driver */ /* The bound device class driver */
struct usbhost_class_s *class; struct usbhost_class_s *class;
@ -271,13 +276,13 @@ static void lpc17_setinttab(uint32_t value, unsigned int interval, unsigned int
#endif #endif
static inline int lpc17_addinted(struct lpc17_usbhost_s *priv, static inline int lpc17_addinted(struct lpc17_usbhost_s *priv,
FAR const struct usbhost_epdesc_s *epdesc, const struct usbhost_epdesc_s *epdesc,
struct lpc17_ed_s *ed); struct lpc17_ed_s *ed);
static inline int lpc17_reminted(struct lpc17_usbhost_s *priv, static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
struct lpc17_ed_s *ed); struct lpc17_ed_s *ed);
static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv, static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
FAR const struct usbhost_epdesc_s *epdesc, const struct usbhost_epdesc_s *epdesc,
struct lpc17_ed_s *ed); struct lpc17_ed_s *ed);
static inline int lpc17_remisoced(struct lpc17_usbhost_s *priv, static inline int lpc17_remisoced(struct lpc17_usbhost_s *priv,
struct lpc17_ed_s *ed); struct lpc17_ed_s *ed);
@ -288,41 +293,40 @@ static int lpc17_enqueuetd(struct lpc17_usbhost_s *priv,
struct lpc17_ed_s *ed, uint32_t dirpid, struct lpc17_ed_s *ed, uint32_t dirpid,
uint32_t toggle, volatile uint8_t *buffer, uint32_t toggle, volatile uint8_t *buffer,
size_t buflen); size_t buflen);
static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid, static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, struct lpc17_ed_s *ed,
uint8_t *buffer, size_t buflen); uint32_t dirpid, uint8_t *buffer, size_t buflen);
/* Interrupt handling **********************************************************/ /* Interrupt handling **********************************************************/
static int lpc17_usbinterrupt(int irq, FAR void *context); static int lpc17_usbinterrupt(int irq, void *context);
/* USB host controller operations **********************************************/ /* USB host controller operations **********************************************/
static int lpc17_wait(FAR struct usbhost_connection_s *conn, static int lpc17_wait(struct usbhost_connection_s *conn,
FAR const bool *connected); const bool *connected);
static int lpc17_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); static int lpc17_enumerate(struct usbhost_connection_s *conn, int rhpndx);
static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, static int lpc17_ep0configure(struct usbhost_driver_s *drvr,
usbhost_ep_t ep0, uint8_t funcaddr,
uint16_t maxpacketsize); uint16_t maxpacketsize);
static int lpc17_getdevinfo(FAR struct usbhost_driver_s *drvr, static int lpc17_epalloc(struct usbhost_driver_s *drvr,
FAR struct usbhost_devinfo_s *devinfo); const struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep);
static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr, static int lpc17_epfree(struct usbhost_driver_s *drvr, usbhost_ep_t ep);
FAR const struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); static int lpc17_alloc(struct usbhost_driver_s *drvr,
static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); uint8_t **buffer, size_t *maxlen);
static int lpc17_alloc(FAR struct usbhost_driver_s *drvr, static int lpc17_free(struct usbhost_driver_s *drvr, uint8_t *buffer);
FAR uint8_t **buffer, FAR size_t *maxlen); static int lpc17_ioalloc(struct usbhost_driver_s *drvr,
static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); uint8_t **buffer, size_t buflen);
static int lpc17_ioalloc(FAR struct usbhost_driver_s *drvr, static int lpc17_iofree(struct usbhost_driver_s *drvr, uint8_t *buffer);
FAR uint8_t **buffer, size_t buflen); static int lpc17_ctrlin(struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
static int lpc17_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); const struct usb_ctrlreq_s *req,
static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr, uint8_t *buffer);
FAR const struct usb_ctrlreq_s *req, static int lpc17_ctrlout(struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR uint8_t *buffer); const struct usb_ctrlreq_s *req,
static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr, const uint8_t *buffer);
FAR const struct usb_ctrlreq_s *req, static int lpc17_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR const uint8_t *buffer); uint8_t *buffer, size_t buflen);
static int lpc17_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static void lpc17_disconnect(struct usbhost_driver_s *drvr);
FAR uint8_t *buffer, size_t buflen);
static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr);
/* Initialization **************************************************************/ /* Initialization **************************************************************/
@ -337,25 +341,7 @@ static inline void lpc17_ep0init(struct lpc17_usbhost_s *priv);
* instance. * instance.
*/ */
static struct lpc17_usbhost_s g_usbhost = static struct lpc17_usbhost_s g_usbhost;
{
.drvr =
{
.ep0configure = lpc17_ep0configure,
.getdevinfo = lpc17_getdevinfo,
.epalloc = lpc17_epalloc,
.epfree = lpc17_epfree,
.alloc = lpc17_alloc,
.free = lpc17_free,
.ioalloc = lpc17_ioalloc,
.iofree = lpc17_iofree,
.ctrlin = lpc17_ctrlin,
.ctrlout = lpc17_ctrlout,
.transfer = lpc17_transfer,
.disconnect = lpc17_disconnect,
},
.class = NULL,
};
/* This is the connection/enumeration interface */ /* This is the connection/enumeration interface */
@ -893,7 +879,7 @@ static void lpc17_setinttab(uint32_t value, unsigned int interval, unsigned int
*******************************************************************************/ *******************************************************************************/
static inline int lpc17_addinted(struct lpc17_usbhost_s *priv, static inline int lpc17_addinted(struct lpc17_usbhost_s *priv,
FAR const struct usbhost_epdesc_s *epdesc, const struct usbhost_epdesc_s *epdesc,
struct lpc17_ed_s *ed) struct lpc17_ed_s *ed)
{ {
#ifndef CONFIG_USBHOST_INT_DISABLE #ifndef CONFIG_USBHOST_INT_DISABLE
@ -1129,7 +1115,7 @@ static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
*******************************************************************************/ *******************************************************************************/
static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv, static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
FAR const struct usbhost_epdesc_s *epdesc, const struct usbhost_epdesc_s *epdesc,
struct lpc17_ed_s *ed) struct lpc17_ed_s *ed)
{ {
#ifndef CONFIG_USBHOST_ISOC_DISABLE #ifndef CONFIG_USBHOST_ISOC_DISABLE
@ -1249,8 +1235,8 @@ static int lpc17_wdhwait(struct lpc17_usbhost_s *priv, struct lpc17_ed_s *ed)
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid, static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, struct lpc17_ed_s *ed,
uint8_t *buffer, size_t buflen) uint32_t dirpid, uint8_t *buffer, size_t buflen)
{ {
uint32_t toggle; uint32_t toggle;
uint32_t regval; uint32_t regval;
@ -1260,7 +1246,7 @@ static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
* transfer. * transfer.
*/ */
ret = lpc17_wdhwait(priv, EDCTRL); ret = lpc17_wdhwait(priv, ed);
if (ret != OK) if (ret != OK)
{ {
udbg("ERROR: Device disconnected\n"); udbg("ERROR: Device disconnected\n");
@ -1280,8 +1266,8 @@ static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
/* Then enqueue the transfer */ /* Then enqueue the transfer */
EDCTRL->tdstatus = TD_CC_NOERROR; ed->tdstatus = TD_CC_NOERROR;
ret = lpc17_enqueuetd(priv, EDCTRL, dirpid, toggle, buffer, buflen); ret = lpc17_enqueuetd(priv, ed, dirpid, toggle, buffer, buflen);
if (ret == OK) if (ret == OK)
{ {
/* Set ControlListFilled. This bit is used to indicate whether there are /* Set ControlListFilled. This bit is used to indicate whether there are
@ -1294,24 +1280,24 @@ static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
/* Wait for the Writeback Done Head interrupt */ /* Wait for the Writeback Done Head interrupt */
lpc17_takesem(&EDCTRL->wdhsem); lpc17_takesem(&ed->wdhsem);
/* Check the TD completion status bits */ /* Check the TD completion status bits */
if (EDCTRL->tdstatus == TD_CC_NOERROR) if (ed->tdstatus == TD_CC_NOERROR)
{ {
ret = OK; ret = OK;
} }
else else
{ {
uvdbg("Bad TD completion status: %d\n", EDCTRL->tdstatus); uvdbg("Bad TD completion status: %d\n", ed->tdstatus);
ret = EDCTRL->tdstatus == TD_CC_STALL ? -EPERM : -EIO; ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO;
} }
} }
/* Make sure that there is no outstanding request on this endpoint */ /* Make sure that there is no outstanding request on this endpoint */
EDCTRL->wdhwait = false; ed->wdhwait = false;
return ret; return ret;
} }
@ -1323,7 +1309,7 @@ static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_usbinterrupt(int irq, FAR void *context) static int lpc17_usbinterrupt(int irq, void *context)
{ {
struct lpc17_usbhost_s *priv = &g_usbhost; struct lpc17_usbhost_s *priv = &g_usbhost;
uint32_t intst; uint32_t intst;
@ -1549,8 +1535,8 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_wait(FAR struct usbhost_connection_s *conn, static int lpc17_wait(struct usbhost_connection_s *conn,
FAR const bool *connected) const bool *connected)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)&g_usbhost; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)&g_usbhost;
irqstate_t flags; irqstate_t flags;
@ -1601,7 +1587,7 @@ static int lpc17_wait(FAR struct usbhost_connection_s *conn,
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_enumerate(FAR struct usbhost_connection_s *conn, int rphndx) static int lpc17_enumerate(struct usbhost_connection_s *conn, int rphndx)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)&g_usbhost; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)&g_usbhost;
DEBUGASSERT(priv && rphndx == 0); DEBUGASSERT(priv && rphndx == 0);
@ -1640,7 +1626,7 @@ static int lpc17_enumerate(FAR struct usbhost_connection_s *conn, int rphndx)
*/ */
uvdbg("Enumerate the device\n"); uvdbg("Enumerate the device\n");
return usbhost_enumerate(&g_usbhost.drvr, 1, &priv->class); return usbhost_enumerate(&g_usbhost.hport.hport, &priv->class);
} }
/************************************************************************************ /************************************************************************************
@ -1654,9 +1640,10 @@ static int lpc17_enumerate(FAR struct usbhost_connection_s *conn, int rphndx)
* 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
* the class create() method. * the class create() method.
* ep0 - The (opaque) EP0 endpoint instance
* funcaddr - The USB address of the function containing the endpoint that EP0 * funcaddr - The USB address of the function containing the endpoint that EP0
* controls * controls
* maxpacketsize - The maximum number of bytes that can be sent to or * mps (maxpacketsize) - The maximum number of bytes that can be sent to or
* received from the endpoint in a single data packet * received from the endpoint in a single data packet
* *
* Returned Values: * Returned Values:
@ -1668,12 +1655,15 @@ static int lpc17_enumerate(FAR struct usbhost_connection_s *conn, int rphndx)
* *
************************************************************************************/ ************************************************************************************/
static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, static int lpc17_ep0configure(struct usbhost_driver_s *drvr,
usbhost_ep_t ep0, uint8_t funcaddr,
uint16_t maxpacketsize) uint16_t maxpacketsize)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed;
DEBUGASSERT(drvr && funcaddr < 128 && maxpacketsize < 2048); DEBUGASSERT(drvr != NULL && ep0 != NULL && funcaddr < 128 && maxpacketsize < 2048);
ed = (struct lpc17_ed_s *)ep0;
/* We must have exclusive access to EP0 and the control list */ /* We must have exclusive access to EP0 and the control list */
@ -1681,51 +1671,20 @@ static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcadd
/* Set the EP0 ED control word */ /* Set the EP0 ED control word */
EDCTRL->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | ed->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT |
(uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT;
if (priv->lowspeed) if (priv->lowspeed)
{ {
EDCTRL->hw.ctrl |= ED_CONTROL_S; ed->hw.ctrl |= ED_CONTROL_S;
} }
/* Set the transfer type to control */ /* Set the transfer type to control */
EDCTRL->xfrtype = USB_EP_ATTR_XFER_CONTROL; ed->xfrtype = USB_EP_ATTR_XFER_CONTROL;
lpc17_givesem(&priv->exclsem); lpc17_givesem(&priv->exclsem);
uvdbg("EP0 CTRL:%08x\n", EDCTRL->hw.ctrl); uvdbg("EP0 CTRL:%08x\n", ed->hw.ctrl);
return OK;
}
/************************************************************************************
* Name: lpc17_getdevinfo
*
* Description:
* Get information about the connected device.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* devinfo - A pointer to memory provided by the caller in which to return the
* device information.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* This function will *not* be called from an interrupt handler.
*
************************************************************************************/
static int lpc17_getdevinfo(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_devinfo_s *devinfo)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
DEBUGASSERT(drvr && devinfo);
devinfo->speed = priv->lowspeed ? DEVINFO_SPEED_LOW : DEVINFO_SPEED_FULL;
return OK; return OK;
} }
@ -1751,10 +1710,11 @@ static int lpc17_getdevinfo(FAR struct usbhost_driver_s *drvr,
* *
************************************************************************************/ ************************************************************************************/
static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr, static int lpc17_epalloc(struct usbhost_driver_s *drvr,
FAR const struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep) const struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct usbhost_hubport_s *hport;
struct lpc17_ed_s *ed; struct lpc17_ed_s *ed;
int ret = -ENOMEM; int ret = -ENOMEM;
@ -1782,7 +1742,9 @@ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
/* Configure the endpoint descriptor. */ /* Configure the endpoint descriptor. */
memset((void*)ed, 0, sizeof(struct lpc17_ed_s)); memset((void*)ed, 0, sizeof(struct lpc17_ed_s));
ed->hw.ctrl = (uint32_t)(epdesc->funcaddr) << ED_CONTROL_FA_SHIFT |
hport = epdesc->hport;
ed->hw.ctrl = (uint32_t)(hport->funcaddr) << ED_CONTROL_FA_SHIFT |
(uint32_t)(epdesc->addr) << ED_CONTROL_EN_SHIFT | (uint32_t)(epdesc->addr) << ED_CONTROL_EN_SHIFT |
(uint32_t)(epdesc->mxpacketsize) << ED_CONTROL_MPS_SHIFT; (uint32_t)(epdesc->mxpacketsize) << ED_CONTROL_MPS_SHIFT;
@ -1893,7 +1855,7 @@ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
* *
************************************************************************************/ ************************************************************************************/
static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) static int lpc17_epfree(struct usbhost_driver_s *drvr, usbhost_ep_t ep)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep; struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep;
@ -1974,8 +1936,8 @@ static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_alloc(FAR struct usbhost_driver_s *drvr, static int lpc17_alloc(struct usbhost_driver_s *drvr,
FAR uint8_t **buffer, FAR size_t *maxlen) uint8_t **buffer, size_t *maxlen)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
DEBUGASSERT(priv && buffer && maxlen); DEBUGASSERT(priv && buffer && maxlen);
@ -2019,7 +1981,7 @@ static int lpc17_alloc(FAR struct usbhost_driver_s *drvr,
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) static int lpc17_free(struct usbhost_driver_s *drvr, uint8_t *buffer)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
DEBUGASSERT(buffer); DEBUGASSERT(buffer);
@ -2059,15 +2021,15 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
* *
************************************************************************************/ ************************************************************************************/
static int lpc17_ioalloc(FAR struct usbhost_driver_s *drvr, static int lpc17_ioalloc(struct usbhost_driver_s *drvr,
FAR uint8_t **buffer, size_t buflen) uint8_t **buffer, size_t buflen)
{ {
DEBUGASSERT(drvr && buffer); DEBUGASSERT(drvr && buffer);
#if LPC17_IOBUFFERS > 0 #if LPC17_IOBUFFERS > 0
if (buflen <= CONFIG_USBHOST_IOBUFSIZE) if (buflen <= CONFIG_USBHOST_IOBUFSIZE)
{ {
FAR uint8_t *alloc = lpc17_allocio(); uint8_t *alloc = lpc17_allocio();
if (alloc) if (alloc)
{ {
*buffer = alloc; *buffer = alloc;
@ -2103,7 +2065,7 @@ static int lpc17_ioalloc(FAR struct usbhost_driver_s *drvr,
* *
************************************************************************************/ ************************************************************************************/
static int lpc17_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) static int lpc17_iofree(struct usbhost_driver_s *drvr, uint8_t *buffer)
{ {
DEBUGASSERT(drvr && buffer); DEBUGASSERT(drvr && buffer);
@ -2119,6 +2081,7 @@ static int lpc17_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
* Name: lpc17_ctrlin and lpc17_ctrlout * Name: lpc17_ctrlin and lpc17_ctrlout
* *
* Description: * Description:
* Description:
* Process a IN or OUT request on the control endpoint. These methods * Process a IN or OUT request on the control endpoint. These methods
* will enqueue the request and wait for it to complete. Only one transfer may be * will enqueue the request and wait for it to complete. Only one transfer may be
* queued; Neither these methods nor the transfer() method can be called again * queued; Neither these methods nor the transfer() method can be called again
@ -2130,11 +2093,12 @@ static int lpc17_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
* 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
* the class create() method. * the class create() method.
* ep0 - The control endpoint to send/receive the control request.
* req - Describes the request to be sent. This request must lie in memory * req - Describes the request to be sent. This request must lie in memory
* created by DRVR_ALLOC. * created by DRVR_ALLOC.
* buffer - A buffer used for sending the request and for returning any * buffer - A buffer used for sending the request and for returning any
* responses. This buffer must be large enough to hold the length value * responses. This buffer must be large enough to hold the length value
* in the request description. buffer must have been allocated using DRVR_ALLOC * in the request description. buffer must have been allocated using DRVR_ALLOC.
* *
* NOTE: On an IN transaction, req and buffer may refer to the same allocated * NOTE: On an IN transaction, req and buffer may refer to the same allocated
* memory. * memory.
@ -2144,21 +2108,22 @@ static int lpc17_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
* returned indicating the nature of the failure * returned indicating the nature of the failure
* *
* Assumptions: * Assumptions:
* - Only a single class bound to a single device is supported.
* - Called from a single thread so no mutual exclusion is required. * - Called from a single thread so no mutual exclusion is required.
* - Never called from an interrupt handler. * - Never called from an interrupt handler.
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr, static int lpc17_ctrlin(struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, const struct usb_ctrlreq_s *req,
FAR uint8_t *buffer) uint8_t *buffer)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep0;
uint16_t len; uint16_t len;
int ret; int ret;
DEBUGASSERT(drvr && req); DEBUGASSERT(priv != NULL && ed != NULL && req!= NULL);
uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n", uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n",
req->type, req->req, req->value[1], req->value[0], req->type, req->req, req->value[1], req->value[0],
req->index[1], req->index[0], req->len[1], req->len[0]); req->index[1], req->index[0], req->len[1], req->len[0]);
@ -2168,17 +2133,17 @@ static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr,
lpc17_takesem(&priv->exclsem); lpc17_takesem(&priv->exclsem);
len = lpc17_getle16(req->len); len = lpc17_getle16(req->len);
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ); ret = lpc17_ctrltd(priv, ed, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
if (ret == OK) if (ret == OK)
{ {
if (len) if (len)
{ {
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_IN, buffer, len); ret = lpc17_ctrltd(priv, ed, GTD_STATUS_DP_IN, buffer, len);
} }
if (ret == OK) if (ret == OK)
{ {
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_OUT, NULL, 0); ret = lpc17_ctrltd(priv, ed, GTD_STATUS_DP_OUT, NULL, 0);
} }
} }
@ -2186,15 +2151,17 @@ static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr,
return ret; return ret;
} }
static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr, static int lpc17_ctrlout(struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, const struct usb_ctrlreq_s *req,
FAR const uint8_t *buffer) const uint8_t *buffer)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep0;
uint16_t len; uint16_t len;
int ret; int ret;
DEBUGASSERT(drvr && req); DEBUGASSERT(priv != NULL && ed != NULL && req!= NULL);
uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n", uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n",
req->type, req->req, req->value[1], req->value[0], req->type, req->req, req->value[1], req->value[0],
req->index[1], req->index[0], req->len[1], req->len[0]); req->index[1], req->index[0], req->len[1], req->len[0]);
@ -2204,17 +2171,17 @@ static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
lpc17_takesem(&priv->exclsem); lpc17_takesem(&priv->exclsem);
len = lpc17_getle16(req->len); len = lpc17_getle16(req->len);
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ); ret = lpc17_ctrltd(priv, ed, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
if (ret == OK) if (ret == OK)
{ {
if (len) if (len)
{ {
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_OUT, (uint8_t*)buffer, len); ret = lpc17_ctrltd(priv, ed, GTD_STATUS_DP_OUT, (uint8_t*)buffer, len);
} }
if (ret == OK) if (ret == OK)
{ {
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_IN, NULL, 0); ret = lpc17_ctrltd(priv, ed, GTD_STATUS_DP_IN, NULL, 0);
} }
} }
@ -2260,8 +2227,8 @@ static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int lpc17_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen) uint8_t *buffer, size_t buflen)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep; struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep;
@ -2436,7 +2403,7 @@ errout:
* *
*******************************************************************************/ *******************************************************************************/
static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr) static void lpc17_disconnect(struct usbhost_driver_s *drvr)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
DEBUGASSERT(priv); DEBUGASSERT(priv);
@ -2468,7 +2435,7 @@ static inline void lpc17_ep0init(struct lpc17_usbhost_s *priv)
/* Set up some default values */ /* Set up some default values */
(void)lpc17_ep0configure(&priv->drvr, 1, 8); (void)lpc17_ep0configure(&priv->drvr, (usbhost_ep_t)EDCTRL, 1, 8);
/* Initialize the common tail TD. */ /* Initialize the common tail TD. */
@ -2527,9 +2494,11 @@ static inline void lpc17_ep0init(struct lpc17_usbhost_s *priv)
* *
*******************************************************************************/ *******************************************************************************/
FAR struct usbhost_connection_s *lpc17_usbhost_initialize(int controller) struct usbhost_connection_s *lpc17_usbhost_initialize(int controller)
{ {
struct lpc17_usbhost_s *priv = &g_usbhost; struct lpc17_usbhost_s *priv = &g_usbhost;
struct usbhost_driver_s *drvr;
struct usbhost_hubport_s *hport;
uint32_t regval; uint32_t regval;
uint8_t *buffer; uint8_t *buffer;
irqstate_t flags; irqstate_t flags;
@ -2544,6 +2513,36 @@ FAR struct usbhost_connection_s *lpc17_usbhost_initialize(int controller)
DEBUGASSERT(sizeof(struct lpc17_gtd_s) <= LPC17_TD_SIZE); DEBUGASSERT(sizeof(struct lpc17_gtd_s) <= LPC17_TD_SIZE);
/* Initialize the state data structure */ /* Initialize the state data structure */
/* Initialize the device operations */
drvr = &priv->drvr;
drvr->ep0configure = lpc17_ep0configure;
drvr->epalloc = lpc17_epalloc;
drvr->epfree = lpc17_epfree;
drvr->alloc = lpc17_alloc;
drvr->free = lpc17_free;
drvr->ioalloc = lpc17_ioalloc;
drvr->iofree = lpc17_iofree;
drvr->ctrlin = lpc17_ctrlin;
drvr->ctrlout = lpc17_ctrlout;
drvr->transfer = lpc17_transfer;
drvr->disconnect = lpc17_disconnect;
/* Initialize the public port representation */
hport = &priv->hport.hport;
hport->drvr = drvr;
#ifdef CONFIG_USBHOST_HUB
hport->parent = NULL;
#endif
hport->ep0 = EDCTRL;
hport->speed = USB_SPEED_FULL;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->hport);
/* Initialize semaphores */
sem_init(&priv->rhssem, 0, 0); sem_init(&priv->rhssem, 0, 0);
sem_init(&priv->exclsem, 0, 1); sem_init(&priv->exclsem, 0, 1);
@ -2710,7 +2709,7 @@ FAR struct usbhost_connection_s *lpc17_usbhost_initialize(int controller)
lpc17_putreg((uint32_t)HCCA, LPC17_USBHOST_HCCA); lpc17_putreg((uint32_t)HCCA, LPC17_USBHOST_HCCA);
/* Set up EP0 */ /* Set up the root hub port EP0 */
lpc17_ep0init(priv); lpc17_ep0init(priv);