summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-08-12 14:44:06 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-08-12 14:44:06 -0600
commit3b04d08043742b9e65cf38d45988b35bff91daed (patch)
treeca74e5710a1564da64e94e52b34210f6d8401947
parentd5cee29af56c68dceeb8e26f6f4081c9d3c66988 (diff)
downloadnuttx-3b04d08043742b9e65cf38d45988b35bff91daed.tar.gz
nuttx-3b04d08043742b9e65cf38d45988b35bff91daed.tar.bz2
nuttx-3b04d08043742b9e65cf38d45988b35bff91daed.zip
First of several changes needed to support multiple USB host root hubs
-rw-r--r--nuttx/ChangeLog10
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html10
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c17
-rw-r--r--nuttx/arch/arm/src/sama5/chip/sam_ohci.h55
-rw-r--r--nuttx/arch/arm/src/sama5/sam_ohci.c284
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfshost.c17
-rw-r--r--nuttx/configs/cloudctrl/src/up_usb.c4
-rw-r--r--nuttx/configs/mikroe-stm32f4/src/up_usb.c4
-rw-r--r--nuttx/configs/olimex-lpc1766stk/src/up_nsh.c4
-rw-r--r--nuttx/configs/open1788/src/lpc17_nsh.c4
-rw-r--r--nuttx/configs/pic32-starterkit/src/up_nsh.c4
-rw-r--r--nuttx/configs/pic32mx7mmb/src/up_nsh.c4
-rw-r--r--nuttx/configs/sama5d3x-ek/src/sam_usb.c17
-rw-r--r--nuttx/configs/sama5d3x-ek/src/sama5d3x-ek.h2
-rw-r--r--nuttx/configs/shenzhou/src/up_usb.c4
-rw-r--r--nuttx/configs/stm3220g-eval/src/up_usb.c4
-rw-r--r--nuttx/configs/stm3240g-eval/src/up_usb.c4
-rw-r--r--nuttx/configs/stm32f4discovery/src/up_usb.c4
-rw-r--r--nuttx/configs/sure-pic32mx/src/pic32mx_nsh.c6
-rw-r--r--nuttx/include/nuttx/usb/usbhost.h67
20 files changed, 314 insertions, 211 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 6ee8926fe..689c64d28 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5369,4 +5369,12 @@
* arch/arm/src/sama5/sam_ohci.c and sam_usbhost.h (was sam_ohci.h), and
configs/sama5d3x-ek/src/sam_usb.c, and sama5d3x-ek.h: Add controls
to enable VBUS power in OHCI host most (2013-8-12).
-
+ * includes/nuttx/usb/usbhost.h, all USB host drivers in arch/, and all
+ USB host-side connection monitoring threads in configs/*/src: The
+ SAMA5 has three downstream ports; all of the other USB host
+ implementations have only one. This will require significant changes
+ to the USB host interfaces starting with these chnages to monitor
+ connections on a port-by-port basis. This effects a lot of files and
+ more changes are coming for this issues. Changes are being blindly
+ incorporated into other architrectures. I am being careful to avoid
+ breakage, but I expect some (2013-8-12).
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html
index a77df7f0f..71bb5842c 100644
--- a/nuttx/Documentation/NuttxPortingGuide.html
+++ b/nuttx/Documentation/NuttxPortingGuide.html
@@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i>
</font></big></h1>
- <p>Last Updated: July 26, 2013</p>
+ <p>Last Updated: August 12, 2013</p>
</td>
</tr>
</table>
@@ -3433,6 +3433,8 @@ extern void up_ledoff(int led);
<p>
<b>Examples</b>:
<code>arch/arm/src/lpc17xx/lpc17_usbhost.c</code>.
+ <code>arch/arm/src/stm32/stm32_otgfshost.c</code>.
+ <code>arch/arm/src/sama5/sam_ohci.c</code>.
</p>
</li>
<li>
@@ -3469,7 +3471,7 @@ extern void up_ledoff(int led);
<ul>
<li>
<p>
- <code>int (*wait)(FAR struct usbhost_driver_s *drvr, bool connected);</code>
+ <code>int (*wait)(FAR struct usbhost_driver_s *drvr, FAR const bool *connected);</code>
</p>
<p>
Wait for a device to be connected or disconnected.
@@ -3477,10 +3479,10 @@ extern void up_ledoff(int led);
</li>
<li>
<p>
- <code>int (*enumerate)(FAR struct usbhost_driver_s *drvr);</code>
+ <code>int (*enumerate)(FAR struct usbhost_driver_s *drvr, int rhpndx);</code>
</p>
<p>
- Enumerate the connected device.
+ Enumerate the device connected to a root hub port.
As part of this enumeration process, the driver will
(1) get the device's configuration descriptor,
(2) extract the class ID info from the configuration descriptor,
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
index b0e9958e9..2fb5eb34c 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -294,8 +294,8 @@ static int lpc17_usbinterrupt(int irq, FAR void *context);
/* USB host controller operations **********************************************/
-static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected);
-static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr);
+static int lpc17_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected);
+static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx);
static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize);
static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
@@ -1518,8 +1518,8 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
- * connected - TRUE: Wait for device to be connected; FALSE: wait for device
- * to be disconnected
+ * connected - A pointer to a boolean value: TRUE: Wait for device to be
+ * connected; FALSE: wait for device to be disconnected
*
* Returned Values:
* Zero (OK) is returned when a device in connected. This function will not
@@ -1533,7 +1533,7 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
*
*******************************************************************************/
-static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
+static int lpc17_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
irqstate_t flags;
@@ -1541,13 +1541,14 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
/* Are we already connected? */
flags = irqsave();
- while (priv->connected == connected)
+ while (priv->connected == *connected)
{
/* No... wait for the connection/disconnection */
priv->rhswait = true;
lpc17_takesem(&priv->rhssem);
}
+
irqrestore(flags);
udbg("Connected:%s\n", priv->connected ? "YES" : "NO");
@@ -1570,6 +1571,7 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
@@ -1582,9 +1584,10 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
*
*******************************************************************************/
-static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
+static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr, int rphndx)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+ DEBUGASSERT(priv && rhpndx == 0);
/* Are we connected to a device? The caller should have called the wait()
* method first to be assured that a device is connected.
diff --git a/nuttx/arch/arm/src/sama5/chip/sam_ohci.h b/nuttx/arch/arm/src/sama5/chip/sam_ohci.h
index f784b929d..9a1d72900 100644
--- a/nuttx/arch/arm/src/sama5/chip/sam_ohci.h
+++ b/nuttx/arch/arm/src/sama5/chip/sam_ohci.h
@@ -49,45 +49,50 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-
+/* The SAMA5 supports 3 root hub ports */
+
+#define SAM_USBHOST_NRHPORT 3
+
/* Register offsets *********************************************************/
/* See nuttx/usb/ohci.h */
/* Register addresses *******************************************************/
-#define SAM_USBHOST_HCIREV (SAM_UHPOHCI_VSECTION+OHCI_HCIREV_OFFSET)
-#define SAM_USBHOST_CTRL (SAM_UHPOHCI_VSECTION+OHCI_CTRL_OFFSET)
-#define SAM_USBHOST_CMDST (SAM_UHPOHCI_VSECTION+OHCI_CMDST_OFFSET)
-#define SAM_USBHOST_INTST (SAM_UHPOHCI_VSECTION+OHCI_INTST_OFFSET)
-#define SAM_USBHOST_INTEN (SAM_UHPOHCI_VSECTION+OHCI_INTEN_OFFSET)
-#define SAM_USBHOST_INTDIS (SAM_UHPOHCI_VSECTION+OHCI_INTDIS_OFFSET)
+#define SAM_USBHOST_HCIREV (SAM_UHPOHCI_VSECTION+OHCI_HCIREV_OFFSET)
+#define SAM_USBHOST_CTRL (SAM_UHPOHCI_VSECTION+OHCI_CTRL_OFFSET)
+#define SAM_USBHOST_CMDST (SAM_UHPOHCI_VSECTION+OHCI_CMDST_OFFSET)
+#define SAM_USBHOST_INTST (SAM_UHPOHCI_VSECTION+OHCI_INTST_OFFSET)
+#define SAM_USBHOST_INTEN (SAM_UHPOHCI_VSECTION+OHCI_INTEN_OFFSET)
+#define SAM_USBHOST_INTDIS (SAM_UHPOHCI_VSECTION+OHCI_INTDIS_OFFSET)
/* Memory pointers (section 7.2) */
-#define SAM_USBHOST_HCCA (SAM_UHPOHCI_VSECTION+OHCI_HCCA_OFFSET)
-#define SAM_USBHOST_PERED (SAM_UHPOHCI_VSECTION+OHCI_PERED_OFFSET)
-#define SAM_USBHOST_CTRLHEADED (SAM_UHPOHCI_VSECTION+OHCI_CTRLHEADED_OFFSET)
-#define SAM_USBHOST_CTRLED (SAM_UHPOHCI_VSECTION+OHCI_CTRLED_OFFSET)
-#define SAM_USBHOST_BULKHEADED (SAM_UHPOHCI_VSECTION+OHCI_BULKHEADED_OFFSET)
-#define SAM_USBHOST_BULKED (SAM_UHPOHCI_VSECTION+OHCI_BULKED_OFFSET)
-#define SAM_USBHOST_DONEHEAD (SAM_UHPOHCI_VSECTION+OHCI_DONEHEAD_OFFSET)
+#define SAM_USBHOST_HCCA (SAM_UHPOHCI_VSECTION+OHCI_HCCA_OFFSET)
+#define SAM_USBHOST_PERED (SAM_UHPOHCI_VSECTION+OHCI_PERED_OFFSET)
+#define SAM_USBHOST_CTRLHEADED (SAM_UHPOHCI_VSECTION+OHCI_CTRLHEADED_OFFSET)
+#define SAM_USBHOST_CTRLED (SAM_UHPOHCI_VSECTION+OHCI_CTRLED_OFFSET)
+#define SAM_USBHOST_BULKHEADED (SAM_UHPOHCI_VSECTION+OHCI_BULKHEADED_OFFSET)
+#define SAM_USBHOST_BULKED (SAM_UHPOHCI_VSECTION+OHCI_BULKED_OFFSET)
+#define SAM_USBHOST_DONEHEAD (SAM_UHPOHCI_VSECTION+OHCI_DONEHEAD_OFFSET)
/* Frame counters (section 7.3) */
-#define SAM_USBHOST_FMINT (SAM_UHPOHCI_VSECTION+OHCI_FMINT_OFFSET)
-#define SAM_USBHOST_FMREM (SAM_UHPOHCI_VSECTION+OHCI_FMREM_OFFSET)
-#define SAM_USBHOST_FMNO (SAM_UHPOHCI_VSECTION+OHCI_FMNO_OFFSET)
-#define SAM_USBHOST_PERSTART (SAM_UHPOHCI_VSECTION+OHCI_PERSTART_OFFSET)
+#define SAM_USBHOST_FMINT (SAM_UHPOHCI_VSECTION+OHCI_FMINT_OFFSET)
+#define SAM_USBHOST_FMREM (SAM_UHPOHCI_VSECTION+OHCI_FMREM_OFFSET)
+#define SAM_USBHOST_FMNO (SAM_UHPOHCI_VSECTION+OHCI_FMNO_OFFSET)
+#define SAM_USBHOST_PERSTART (SAM_UHPOHCI_VSECTION+OHCI_PERSTART_OFFSET)
/* Root hub ports (section 7.4) */
-#define SAM_USBHOST_LSTHRES (SAM_UHPOHCI_VSECTION+OHCI_LSTHRES_OFFSET)
-#define SAM_USBHOST_RHDESCA (SAM_UHPOHCI_VSECTION+OHCI_RHDESCA_OFFSET)
-#define SAM_USBHOST_RHDESCB (SAM_UHPOHCI_VSECTION+OHCI_RHDESCB_OFFSET)
-#define SAM_USBHOST_RHSTATUS (SAM_UHPOHCI_VSECTION+OHCI_RHSTATUS_OFFSET)
-#define SAM_USBHOST_RHPORTST1 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST1_OFFSET)
-#define SAM_USBHOST_RHPORTST2 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST2_OFFSET)
-#define SAM_USBHOST_MODID (SAM_UHPOHCI_VSECTION+SAM_USBHOST_MODID_OFFSET)
+#define SAM_USBHOST_LSTHRES (SAM_UHPOHCI_VSECTION+OHCI_LSTHRES_OFFSET)
+#define SAM_USBHOST_RHDESCA (SAM_UHPOHCI_VSECTION+OHCI_RHDESCA_OFFSET)
+#define SAM_USBHOST_RHDESCB (SAM_UHPOHCI_VSECTION+OHCI_RHDESCB_OFFSET)
+#define SAM_USBHOST_RHSTATUS (SAM_UHPOHCI_VSECTION+OHCI_RHSTATUS_OFFSET)
+
+#define SAM_USBHOST_RHPORTST(n) (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST_OFFSET(n))
+#define SAM_USBHOST_RHPORTST1 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST1_OFFSET)
+#define SAM_USBHOST_RHPORTST2 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST2_OFFSET)
+#define SAM_USBHOST_RHPORTST3 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST3_OFFSET)
/* Register bit definitions *************************************************/
/* See include/nuttx/usb/ohci.h */
diff --git a/nuttx/arch/arm/src/sama5/sam_ohci.c b/nuttx/arch/arm/src/sama5/sam_ohci.c
index 40ff3dea0..10c75558a 100644
--- a/nuttx/arch/arm/src/sama5/sam_ohci.c
+++ b/nuttx/arch/arm/src/sama5/sam_ohci.c
@@ -176,6 +176,13 @@
/*******************************************************************************
* Private Types
*******************************************************************************/
+/* This structure retins the state of one root hub port */
+
+struct sam_rhport_s
+{
+ volatile bool connected; /* Connected to device */
+ volatile bool lowspeed; /* Low speed device attached. */
+};
/* This structure retains the state of the USB host controller */
@@ -194,9 +201,8 @@ struct sam_ohci_s
/* Driver status */
- volatile bool connected; /* Connected to device */
- volatile bool lowspeed; /* Low speed device attached. */
volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */
+
#ifndef CONFIG_USBHOST_INT_DISABLE
uint8_t ininterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
uint8_t outinterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
@@ -204,6 +210,10 @@ struct sam_ohci_s
sem_t exclsem; /* Support mutually exclusive access */
sem_t rhssem; /* Semaphore to wait Writeback Done Head event */
+ /* Root hub ports */
+
+ struct sam_rhport_s rhport[SAM_USBHOST_NRHPORT];
+
/* Debug stuff */
#ifdef CONFIG_SAMA5_SPI_REGDEBUG
@@ -337,8 +347,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context);
/* USB host controller operations **********************************************/
-static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected);
-static int sam_enumerate(FAR struct usbhost_driver_s *drvr);
+static int sam_wait(FAR struct usbhost_driver_s *drvr, FAR const bool *connected);
+static int sam_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx);
static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize);
static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
@@ -1231,7 +1241,9 @@ static int sam_wdhwait(struct sam_ohci_s *priv, struct sam_ed_s *ed)
/* Is the device still connected? */
+#if 0 /* REVISIT */
if (priv->connected)
+#endif
{
/* Yes.. then set wdhwait to indicate that we expect to be informed when
* either (1) the device is disconnected, or (2) the transfer completed.
@@ -1339,6 +1351,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
uint32_t intst;
uint32_t pending;
uint32_t regval;
+ uint32_t regaddr;
+ int rhpndx;
/* Read Interrupt Status and mask out interrupts that are not enabled. */
@@ -1353,105 +1367,125 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
if ((pending & OHCI_INT_RHSC) != 0)
{
- uint32_t rhportst1 = sam_getreg(SAM_USBHOST_RHPORTST1);
- ullvdbg("Root Hub Status Change, RHPORTST1: %08x\n", rhportst1);
+ /* Hand root hub status change on each root port */
- if ((rhportst1 & OHCI_RHPORTST_CSC) != 0)
+ ullvdbg("Root Hub Status Change\n");
+ for (rhpndx = 0; rhpndx < SAM_USBHOST_NRHPORT; rhpndx++)
{
- uint32_t rhstatus = sam_getreg(SAM_USBHOST_RHSTATUS);
- ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus);
+ uint32_t rhportst;
+
+ regaddr = SAM_USBHOST_RHPORTST(rhpndx+1);
+ rhportst = sam_getreg(regaddr);
- /* If DRWE is set, Connect Status Change indicates a remote wake-up event */
+ ullvdbg("RHPORTST%d: %08x\n",
+ rhpndx + 1, rhportst);
- if (rhstatus & OHCI_RHSTATUS_DRWE)
+ if ((rhportst & OHCI_RHPORTST_CSC) != 0)
{
- ullvdbg("DRWE: Remote wake-up\n");
- }
+ uint32_t rhstatus = sam_getreg(SAM_USBHOST_RHSTATUS);
+ ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus);
- /* Otherwise... Not a remote wake-up event */
+ /* If DRWE is set, Connect Status Change indicates a remote
+ * wake-up event
+ */
- else
- {
- /* Check current connect status */
+ if (rhstatus & OHCI_RHSTATUS_DRWE)
+ {
+ ullvdbg("DRWE: Remote wake-up\n");
+ }
- if ((rhportst1 & OHCI_RHPORTST_CCS) != 0)
+ /* Otherwise... Not a remote wake-up event */
+
+ else
{
- /* Connected ... Did we just become connected? */
+ /* Check current connect status */
- if (!priv->connected)
+ if ((rhportst & OHCI_RHPORTST_CCS) != 0)
{
- /* Yes.. connected. */
+ /* Connected ... Did we just become connected? */
- ullvdbg("Connected\n");
- priv->connected = true;
+ if (!priv->rhport[rhpndx].connected)
+ {
+ /* Yes.. connected. */
- /* Notify any waiters */
+ priv->rhport[rhpndx].connected = true;
- if (priv->rhswait)
+ ullvdbg("RHPort%d connected, rhswait: %d\n",
+ rhpndx + 1, priv->rhswait);
+
+ /* Notify any waiters */
+
+ if (priv->rhswait)
+ {
+ sam_givesem(&priv->rhssem);
+ priv->rhswait = false;
+ }
+ }
+ else
{
- sam_givesem(&priv->rhssem);
- priv->rhswait = false;
+ ulldbg("Spurious status change (connected)\n");
}
- }
- else
- {
- ulldbg("Spurious status change (connected)\n");
- }
- /* The LSDA (Low speed device attached) bit is valid
- * when CCS == 1.
- */
+ /* The LSDA (Low speed device attached) bit is valid
+ * when CCS == 1.
+ */
- priv->lowspeed = (rhportst1 & OHCI_RHPORTST_LSDA) != 0;
- ullvdbg("Speed:%s\n", priv->lowspeed ? "LOW" : "FULL");
- }
+ priv->rhport[rhpndx].lowspeed =
+ (rhportst & OHCI_RHPORTST_LSDA) != 0;
- /* Check if we are now disconnected */
+ ullvdbg("Speed: %s\n",
+ priv->rhport[rhpndx].lowspeed ? "LOW" : "FULL");
+ }
- else if (priv->connected)
- {
- /* Yes.. disconnect the device */
+ /* Check if we are now disconnected */
- ullvdbg("Disconnected\n");
- priv->connected = false;
- priv->lowspeed = false;
+ else if (priv->rhport[rhpndx].connected)
+ {
+ /* Yes.. disconnect the device */
- /* Are we bound to a class instance? */
+ ullvdbg("RHport%d disconnected\n", rhpndx+1);
+ priv->rhport[rhpndx].connected = false;
+ priv->rhport[rhpndx].lowspeed = false;
- if (priv->class)
- {
- /* Yes.. Disconnect the class */
+ /* Are we bound to a class instance? */
- CLASS_DISCONNECTED(priv->class);
- priv->class = NULL;
- }
+ if (priv->class)
+ {
+ /* Yes.. Disconnect the class */
+
+ CLASS_DISCONNECTED(priv->class);
+ priv->class = NULL;
+ }
- /* Notify any waiters for the Root Hub Status change event */
+ /* Notify any waiters for the Root Hub Status change
+ * event.
+ */
- if (priv->rhswait)
+ if (priv->rhswait)
+ {
+ sam_givesem(&priv->rhssem);
+ priv->rhswait = false;
+ }
+ }
+ else
{
- sam_givesem(&priv->rhssem);
- priv->rhswait = false;
+ ulldbg("Spurious status change (disconnected)\n");
}
}
- else
- {
- ulldbg("Spurious status change (disconnected)\n");
- }
- }
- /* Clear the status change interrupt */
+ /* Clear the status change interrupt */
- sam_putreg(OHCI_RHPORTST_CSC, SAM_USBHOST_RHPORTST1);
- }
+ sam_putreg(OHCI_RHPORTST_CSC, regaddr);
+ }
- /* Check for port reset status change */
+ /* Check for port reset status change */
- if ((rhportst1 & OHCI_RHPORTST_PRSC) != 0)
- {
- /* Release the RH port from reset */
+ if ((rhportst & OHCI_RHPORTST_PRSC) != 0)
+ {
+ /* Release the RH port from reset */
- sam_putreg(OHCI_RHPORTST_PRSC, SAM_USBHOST_RHPORTST1);
+ sam_putreg(OHCI_RHPORTST_PRSC, regaddr);
+ }
}
}
@@ -1495,9 +1529,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
{
/* The transfer failed for some reason... dump some diagnostic info. */
- ulldbg("ERROR: ED xfrtype:%d TD CTRL:%08x/CC:%d RHPORTST1:%08x\n",
- ed->xfrtype, td->hw.ctrl, ed->tdstatus,
- sam_getreg(SAM_USBHOST_RHPORTST1));
+ ulldbg("ERROR: ED xfrtype: %d TD CTRL: %08x/CC: %d\n",
+ ed->xfrtype, td->hw.ctrl, ed->tdstatus);
}
#endif
@@ -1519,7 +1552,7 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
#ifdef CONFIG_DEBUG_USB
if ((pending & SAM_DEBUG_INTS) != 0)
{
- ulldbg("ERROR: Unhandled interrupts INTST:%08x\n", intst);
+ ulldbg("ERROR: Unhandled interrupts INTST: %08x\n", intst);
}
#endif
@@ -1539,17 +1572,21 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
* Name: sam_wait
*
* Description:
- * Wait for a device to be connected or disconneced.
+ * Wait for a device to be connected or disconnected to/from a root hub port.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call
* to the class create() method.
- * connected - TRUE: Wait for device to be connected; FALSE: wait for device
- * to be disconnected
+ * connected - A pointer to an array of 3 boolean values corresponding to
+ * root hubs 1, 2, and 3. For each boolean value: TRUE: Wait for a device
+ * to be connected on the root hub; FALSE: wait for device to be
+ * disconnected from the root hub.
*
* 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.
+ * And index [0, 1, or 2} corresponding to the root hub port number {1, 2,
+ * or 3} is returned when a device is connected or disconnected. This
+ * function will not return until either (1) a device is connected or
+ * disconnected to/from any root hub port or until (2) some failure occurs.
* On a failure, a negated errno value is returned indicating the nature of
* the failure
*
@@ -1559,25 +1596,47 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
*
*******************************************************************************/
-static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected)
+static int sam_wait(FAR struct usbhost_driver_s *drvr, FAR const bool *connected)
{
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
irqstate_t flags;
+ int rhpndx;
- /* Are we already connected? */
+ /* Loop until a change in the connection state changes on one of the root hub
+ * ports or until an error occurs.
+ */
flags = irqsave();
- while (priv->connected == connected)
+ for (;;)
{
- /* No... wait for the connection/disconnection */
+ /* Check for a change in the connection state on any root hub port */
+
+ for (rhpndx = 0; rhpndx < SAM_USBHOST_NRHPORT; rhpndx++)
+ {
+ /* Has the connection state changed on the RH port? */
+
+ while (priv->rhport[rhpndx].connected != connected[rhpndx])
+ {
+ /* Yes.. break out and return the RH port number */
+
+ break;
+ }
+ }
+
+ /* No changes on any port. Wait for a connection/disconnection event
+ * and check again
+ */
priv->rhswait = true;
sam_takesem(&priv->rhssem);
}
+
irqrestore(flags);
- udbg("Connected:%s\n", priv->connected ? "YES" : "NO");
- return OK;
+ udbg("RHPort%d connected: %s\n",
+ rhpndx + 1, priv->rhport[rhpndx].connected ? "YES" : "NO");
+
+ return rhpndx;
}
/*******************************************************************************
@@ -1596,6 +1655,7 @@ static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
@@ -1608,15 +1668,16 @@ static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected)
*
*******************************************************************************/
-static int sam_enumerate(FAR struct usbhost_driver_s *drvr)
+static int sam_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx)
{
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
+ uint32_t regaddr;
/* 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)
+ while (!priv->rhport[rhpndx].connected)
{
/* No, return an error */
@@ -1628,25 +1689,26 @@ static int sam_enumerate(FAR struct usbhost_driver_s *drvr)
up_mdelay(100);
- /* Put RH port 1 in reset (the LPC176x supports only a single downstream port) */
+ /* Put the root hub port in reset (the SAMA5 supports three downstream ports) */
- sam_putreg(OHCI_RHPORTST_PRS, SAM_USBHOST_RHPORTST1);
+ regaddr = SAM_USBHOST_RHPORTST(rhpndx+1);
+ sam_putreg(OHCI_RHPORTST_PRS, regaddr);
/* Wait for the port reset to complete */
- while ((sam_getreg(SAM_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0);
+ while ((sam_getreg(regaddr) & OHCI_RHPORTST_PRS) != 0);
/* Release RH port 1 from reset and wait a bit */
- sam_putreg(OHCI_RHPORTST_PRSC, SAM_USBHOST_RHPORTST1);
+ sam_putreg(OHCI_RHPORTST_PRSC, regaddr);
up_mdelay(200);
/* Let the common usbhost_enumerate do all of the real work. Note that the
- * FunctionAddress (USB address) is hardcoded to one.
+ * FunctionAddress (USB address) is set to the root hub port number for now.
*/
uvdbg("Enumerate the device\n");
- return usbhost_enumerate(drvr, 1, &priv->class);
+ return usbhost_enumerate(drvr, rhpndx+1, &priv->class);
}
/************************************************************************************
@@ -1678,8 +1740,10 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize)
{
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
+ int rhpndx = (int)funcaddr - 1;
- DEBUGASSERT(drvr && funcaddr < 128 && maxpacketsize < 2048);
+ DEBUGASSERT(drvr && funcaddr > 0 && funcaddr <= SAM_USBHOST_NRHPORT &&
+ maxpacketsize < 2048);
/* We must have exclusive access to EP0 and the control list */
@@ -1688,9 +1752,9 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
/* Set the EP0 ED control word */
g_edctrl.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->rhport[rhpndx].lowspeed)
{
g_edctrl.hw.ctrl |= ED_CONTROL_S;
}
@@ -1700,7 +1764,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
g_edctrl.xfrtype = USB_EP_ATTR_XFER_CONTROL;
sam_givesem(&priv->exclsem);
- uvdbg("EP0 CTRL:%08x\n", g_edctrl.hw.ctrl);
+ uvdbg("EP0 CTRL: %08x\n", g_edctrl.hw.ctrl);
return OK;
}
@@ -1731,13 +1795,16 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
{
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
struct sam_ed_s *ed;
+ int rhpndx = (int)epdesc->funcaddr - 1;
int ret = -ENOMEM;
/* Sanity check. NOTE that this method should only be called if a device is
* connected (because we need a valid low speed indication).
*/
- DEBUGASSERT(priv && epdesc && ep && priv->connected);
+ DEBUGASSERT(priv && epdesc && ep &&
+ rhpndx >= 0 && rhpndx < SAM_USBHOST_NRHPORT &&
+ priv->rhport[rhpndx].connected);
/* We must have exclusive access to the ED pool, the bulk list, the periodic list
* and the interrupt table.
@@ -1776,7 +1843,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
/* Check for a low-speed device */
- if (priv->lowspeed)
+ if (priv->rhport[rhpndx].lowspeed)
{
ed->hw.ctrl |= ED_CONTROL_S;
}
@@ -1793,7 +1860,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
ed->hw.ctrl |= ED_CONTROL_F;
}
#endif
- uvdbg("EP%d CTRL:%08x\n", epdesc->addr, ed->hw.ctrl);
+ uvdbg("EP%d CTRL: %08x\n", epdesc->addr, ed->hw.ctrl);
/* Initialize the semaphore that is used to wait for the endpoint
* WDH event.
@@ -2124,7 +2191,7 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr,
int ret;
DEBUGASSERT(drvr && req);
- 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->index[1], req->index[0], req->len[1], req->len[0]);
@@ -2160,7 +2227,7 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr,
int ret;
DEBUGASSERT(drvr && req);
- 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->index[1], req->index[0], req->len[1], req->len[0]);
@@ -2241,7 +2308,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
DEBUGASSERT(priv && ed && buffer && buflen > 0);
in = (ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN;
- uvdbg("EP%d %s toggle:%d maxpacket:%d buflen:%d\n",
+ uvdbg("EP%d %s toggle: %d maxpacket: %d buflen: %d\n",
(ed->hw.ctrl & ED_CONTROL_EN_MASK) >> ED_CONTROL_EN_SHIFT,
in ? "IN" : "OUT",
(ed->hw.headp & ED_HEADP_C) != 0 ? 1 : 0,
@@ -2583,8 +2650,14 @@ FAR struct usbhost_driver_s *sam_ohci_initialize(int controller)
* connected. We need to set the initial connected state accordingly.
*/
- regval = sam_getreg(SAM_USBHOST_RHPORTST1);
- priv->connected = ((regval & OHCI_RHPORTST_CCS) != 0);
+ for (i = 0; i < SAM_USBHOST_NRHPORT; i++)
+ {
+ regval = sam_getreg(SAM_USBHOST_RHPORTST(i));
+ priv->rhport[i].connected = ((regval & OHCI_RHPORTST_CCS) != 0);
+
+ uvdbg("RHPort%d Device connected: %s\n",
+ i+1, priv->rhport[i].connected ? "YES" : "NO");
+ }
/* Drive Vbus +5V (the smoke test). Should be done elsewhere in OTG
* mode.
@@ -2595,8 +2668,7 @@ FAR struct usbhost_driver_s *sam_ohci_initialize(int controller)
/* Enable interrupts at the interrupt controller */
up_enable_irq(SAM_IRQ_UHPHS); /* enable USB interrupt */
- udbg("USB host Initialized, Device connected:%s\n",
- priv->connected ? "YES" : "NO");
+ uvdbg("USB OHCI Initialized\n");
return &priv->drvr;
}
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
index 831bde5bc..d1b4f5f54 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
@@ -358,8 +358,8 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx);
/* USB host controller operations **********************************************/
-static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected);
-static int stm32_enumerate(FAR struct usbhost_driver_s *drvr);
+static int stm32_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected);
+static int stm32_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx);
static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize);
static int stm32_epalloc(FAR struct usbhost_driver_s *drvr,
@@ -3013,8 +3013,8 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx)
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
- * connected - TRUE: Wait for device to be connected; FALSE: wait for device
- * to be disconnected
+ * connected - A pointer to a boolean value. TRUE: Wait for device to be
+ * connected; FALSE: wait for device to be disconnected
*
* Returned Values:
* Zero (OK) is returned when a device in connected. This function will not
@@ -3028,7 +3028,7 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx)
*
*******************************************************************************/
-static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
+static int stm32_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected)
{
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
irqstate_t flags;
@@ -3036,7 +3036,7 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
/* Are we already connected? */
flags = irqsave();
- while (priv->connected == connected)
+ while (priv->connected == *connected)
{
/* No... wait for the connection/disconnection */
@@ -3066,6 +3066,7 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
@@ -3078,13 +3079,15 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
*
*******************************************************************************/
-static int stm32_enumerate(FAR struct usbhost_driver_s *drvr)
+static int stm32_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx)
{
struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
uint32_t regval;
int chidx;
int ret;
+ DEBUGASSERT(priv && rhpndx == 0);
+
/* Are we connected to a device? The caller should have called the wait()
* method first to be assured that a device is connected.
*/
diff --git a/nuttx/configs/cloudctrl/src/up_usb.c b/nuttx/configs/cloudctrl/src/up_usb.c
index 98f015dee..2407285c5 100644
--- a/nuttx/configs/cloudctrl/src/up_usb.c
+++ b/nuttx/configs/cloudctrl/src/up_usb.c
@@ -109,7 +109,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -121,7 +121,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/mikroe-stm32f4/src/up_usb.c b/nuttx/configs/mikroe-stm32f4/src/up_usb.c
index f8debe5ab..cb94e5cbe 100644
--- a/nuttx/configs/mikroe-stm32f4/src/up_usb.c
+++ b/nuttx/configs/mikroe-stm32f4/src/up_usb.c
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/olimex-lpc1766stk/src/up_nsh.c b/nuttx/configs/olimex-lpc1766stk/src/up_nsh.c
index 4ca474c65..e893ba27e 100644
--- a/nuttx/configs/olimex-lpc1766stk/src/up_nsh.c
+++ b/nuttx/configs/olimex-lpc1766stk/src/up_nsh.c
@@ -169,7 +169,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -181,7 +181,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/open1788/src/lpc17_nsh.c b/nuttx/configs/open1788/src/lpc17_nsh.c
index 3dca28b2f..fa6e086ed 100644
--- a/nuttx/configs/open1788/src/lpc17_nsh.c
+++ b/nuttx/configs/open1788/src/lpc17_nsh.c
@@ -193,7 +193,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -205,7 +205,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/pic32-starterkit/src/up_nsh.c b/nuttx/configs/pic32-starterkit/src/up_nsh.c
index 71909f92e..7c8e21412 100644
--- a/nuttx/configs/pic32-starterkit/src/up_nsh.c
+++ b/nuttx/configs/pic32-starterkit/src/up_nsh.c
@@ -197,7 +197,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -209,7 +209,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/pic32mx7mmb/src/up_nsh.c b/nuttx/configs/pic32mx7mmb/src/up_nsh.c
index 37ecc3095..5e59af564 100644
--- a/nuttx/configs/pic32mx7mmb/src/up_nsh.c
+++ b/nuttx/configs/pic32mx7mmb/src/up_nsh.c
@@ -196,7 +196,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -208,7 +208,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/sama5d3x-ek/src/sam_usb.c b/nuttx/configs/sama5d3x-ek/src/sam_usb.c
index 3b009bb41..3ab5d3c39 100644
--- a/nuttx/configs/sama5d3x-ek/src/sam_usb.c
+++ b/nuttx/configs/sama5d3x-ek/src/sam_usb.c
@@ -54,6 +54,7 @@
#include "up_arch.h"
#include "sam_pio.h"
#include "sam_usbhost.h"
+#include "chip/sam_ohci.h"
#include "sama5d3x-ek.h"
#if defined(CONFIG_SAMA5_UHPHS) || defined(CONFIG_SAMA5_UDPHS)
@@ -97,25 +98,29 @@ static struct usbhost_driver_s *g_ehci;
#if HAVE_USBHOST
static int usbhost_waiter(struct usbhost_driver_s *dev)
{
- bool connected = false;
+ bool connected[SAM_USBHOST_NRHPORT] = {false, false, false};
+ int rhpndx;
uvdbg("Running\n");
for (;;)
{
/* Wait for the device to change state */
- DEBUGVERIFY(DRVR_WAIT(dev, connected) == OK);
+ rhpndx = DRVR_WAIT(dev, connected);
+ DEBUGASSERT(rhpndx >= 0 && rhpndx < SAM_USBHOST_NRHPORT);
- connected = !connected;
- uvdbg("%s\n", connected ? "connected" : "disconnected");
+ connected[rhpndx] = !connected[rhpndx];
+
+ uvdbg("RHport%d %s\n",
+ rhpndx + 1, connected[rhpndx] ? "connected" : "disconnected");
/* Did we just become connected? */
- if (connected)
+ if (connected[rhpndx])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(dev);
+ (void)DRVR_ENUMERATE(dev, rhpndx);
}
}
diff --git a/nuttx/configs/sama5d3x-ek/src/sama5d3x-ek.h b/nuttx/configs/sama5d3x-ek/src/sama5d3x-ek.h
index 0cf87b2e4..9f91aee92 100644
--- a/nuttx/configs/sama5d3x-ek/src/sama5d3x-ek.h
+++ b/nuttx/configs/sama5d3x-ek/src/sama5d3x-ek.h
@@ -293,7 +293,7 @@
PIO_PORT_PIOD | PIO_PIN27)
/* Both Ports B and C
- *
+ *
* PIO Signal Name Function
* ---- ----------- -------------------------------------------------------
* PD28 OVCUR_USB Combined overrcurrent indication from port A and B
diff --git a/nuttx/configs/shenzhou/src/up_usb.c b/nuttx/configs/shenzhou/src/up_usb.c
index 0ae1d8c52..88f6d96ba 100644
--- a/nuttx/configs/shenzhou/src/up_usb.c
+++ b/nuttx/configs/shenzhou/src/up_usb.c
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/stm3220g-eval/src/up_usb.c b/nuttx/configs/stm3220g-eval/src/up_usb.c
index b16bdb6aa..4de02df96 100644
--- a/nuttx/configs/stm3220g-eval/src/up_usb.c
+++ b/nuttx/configs/stm3220g-eval/src/up_usb.c
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/stm3240g-eval/src/up_usb.c b/nuttx/configs/stm3240g-eval/src/up_usb.c
index b9082cbe7..c69a017bb 100644
--- a/nuttx/configs/stm3240g-eval/src/up_usb.c
+++ b/nuttx/configs/stm3240g-eval/src/up_usb.c
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/stm32f4discovery/src/up_usb.c b/nuttx/configs/stm32f4discovery/src/up_usb.c
index 4a5268155..166f4e7a9 100644
--- a/nuttx/configs/stm32f4discovery/src/up_usb.c
+++ b/nuttx/configs/stm32f4discovery/src/up_usb.c
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/configs/sure-pic32mx/src/pic32mx_nsh.c b/nuttx/configs/sure-pic32mx/src/pic32mx_nsh.c
index 294afcb79..b9ea90dba 100644
--- a/nuttx/configs/sure-pic32mx/src/pic32mx_nsh.c
+++ b/nuttx/configs/sure-pic32mx/src/pic32mx_nsh.c
@@ -1,7 +1,7 @@
/****************************************************************************
* config/sure-pic32mx/src/pic32mx_nsh.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -188,7 +188,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Wait for the device to change state */
- ret = DRVR_WAIT(g_drvr, connected);
+ ret = DRVR_WAIT(g_drvr, &connected);
DEBUGASSERT(ret == OK);
connected = !connected;
@@ -200,7 +200,7 @@ static int nsh_waiter(int argc, char *argv[])
{
/* Yes.. enumerate the newly connected device */
- (void)DRVR_ENUMERATE(g_drvr);
+ (void)DRVR_ENUMERATE(g_drvr, 0);
}
}
diff --git a/nuttx/include/nuttx/usb/usbhost.h b/nuttx/include/nuttx/usb/usbhost.h
index e8a5a9636..d357e0b9b 100644
--- a/nuttx/include/nuttx/usb/usbhost.h
+++ b/nuttx/include/nuttx/usb/usbhost.h
@@ -1,7 +1,7 @@
/************************************************************************************
* include/nuttx/usb/usbhost.h
*
- * Copyright (C) 2010-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2010-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
@@ -155,22 +155,26 @@
* Name: DRVR_WAIT
*
* Description:
- * Wait for a device to be connected or disconneced.
+ * Wait for a device to be connected or disconnected to/from a root hub port.
*
* Input Parameters:
- * drvr - The USB host driver instance obtained as a parameter from the call to
- * the class create() method.
- * connected - TRUE: Wait for device to be connected; FALSE: wait for device to
- * be disconnected
+ * drvr - The USB host driver instance obtained as a parameter from the call
+ * to the class create() method.
+ * connected - A pointer to an array of n boolean values corresponding to
+ * root hubs 1 through n. For each boolean value: TRUE: Wait for a device
+ * to be connected on the root hub; FALSE: wait for device to be
+ * disconnected from the root hub.
*
* 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
+ * And index [0..(n-1)} corresponding to the root hub port number {1..n} is
+ * returned when a device in connected or disconnectd. This function will not
+ * return until either (1) a device is connected or disconntect to/from any
+ * root hub port or until (2) some failure occurs. 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.
+ * - Called from a single thread so no mutual exclusion is required.
+ * - Never called from an interrupt handler.
*
*******************************************************************************/
@@ -192,6 +196,7 @@
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
@@ -202,7 +207,7 @@
*
************************************************************************************/
-#define DRVR_ENUMERATE(drvr) ((drvr)->enumerate(drvr))
+#define DRVR_ENUMERATE(drvr,rhpndx) ((drvr)->enumerate(drvr,rhpndx))
/************************************************************************************
* Name: DRVR_EP0CONFIGURE
@@ -589,19 +594,19 @@ struct usbhost_driver_s
{
/* Wait for a device to connect or disconnect. */
- int (*wait)(FAR struct usbhost_driver_s *drvr, bool connected);
+ int (*wait)(FAR struct usbhost_driver_s *drvr, FAR const bool *connected);
- /* Enumerate the connected device. As part of this enumeration process,
- * the driver will (1) get the device's configuration descriptor, (2)
- * extract the class ID info from the configuration descriptor, (3) call
- * usbhost_findclass() to find the class that supports this device, (4)
- * call the create() method on the struct usbhost_registry_s interface
- * to get a class instance, and finally (5) call the connect() method
- * of the struct usbhost_class_s interface. After that, the class is in
- * charge of the sequence of operations.
+ /* Enumerate the device connected on a root hub port. As part of this
+ * enumeration process, the driver will (1) get the device's configuration
+ * descriptor, (2) extract the class ID info from the configuration
+ * descriptor, (3) call usbhost_findclass() to find the class that supports
+ * this device, (4) call the create() method on the struct usbhost_registry_s
+ * interface to get a class instance, and finally (5) call the connect()
+ * method of the struct usbhost_class_s interface. After that, the class is
+ * in charge of the sequence of operations.
*/
- int (*enumerate)(FAR struct usbhost_driver_s *drvr);
+ int (*enumerate)(FAR struct usbhost_driver_s *drvr, int rhpndx);
/* Configure endpoint 0. This method is normally used internally by the
* enumerate() method but is made available at the interface to support
@@ -689,7 +694,8 @@ struct usbhost_driver_s
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
@@ -718,7 +724,7 @@ extern "C" {
*
************************************************************************************/
-EXTERN int usbhost_registerclass(struct usbhost_registry_s *class);
+int usbhost_registerclass(struct usbhost_registry_s *class);
/************************************************************************************
* Name: usbhost_findclass
@@ -740,7 +746,7 @@ EXTERN int usbhost_registerclass(struct usbhost_registry_s *class);
*
************************************************************************************/
-EXTERN const struct usbhost_registry_s *usbhost_findclass(const struct usbhost_id_s *id);
+const struct usbhost_registry_s *usbhost_findclass(const struct usbhost_id_s *id);
/****************************************************************************
* Name: usbhost_storageinit
@@ -759,7 +765,7 @@ EXTERN const struct usbhost_registry_s *usbhost_findclass(const struct usbhost_i
*
****************************************************************************/
-EXTERN int usbhost_storageinit(void);
+int usbhost_storageinit(void);
/****************************************************************************
* Name: usbhost_kbdinit
@@ -778,7 +784,7 @@ EXTERN int usbhost_storageinit(void);
*
****************************************************************************/
-EXTERN int usbhost_kbdinit(void);
+int usbhost_kbdinit(void);
/****************************************************************************
* Name: usbhost_wlaninit
@@ -797,7 +803,7 @@ EXTERN int usbhost_kbdinit(void);
*
****************************************************************************/
-EXTERN int usbhost_wlaninit(void);
+int usbhost_wlaninit(void);
/*******************************************************************************
* Name: usbhost_enumerate
@@ -836,9 +842,8 @@ EXTERN int usbhost_wlaninit(void);
*
*******************************************************************************/
-EXTERN int usbhost_enumerate(FAR struct usbhost_driver_s *drvr,
- uint8_t funcaddr,
- FAR struct usbhost_class_s **class);
+int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
+ FAR struct usbhost_class_s **class);
#undef EXTERN
#if defined(__cplusplus)