mirror of
https://github.com/apache/nuttx.git
synced 2026-06-01 07:45:16 +08:00
First of several changes needed to support multiple USB host root hubs
This commit is contained in:
@@ -5369,4 +5369,12 @@
|
|||||||
* arch/arm/src/sama5/sam_ohci.c and sam_usbhost.h (was sam_ohci.h), and
|
* 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
|
configs/sama5d3x-ek/src/sam_usb.c, and sama5d3x-ek.h: Add controls
|
||||||
to enable VBUS power in OHCI host most (2013-8-12).
|
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).
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<h1><big><font color="#3c34ec">
|
<h1><big><font color="#3c34ec">
|
||||||
<i>NuttX RTOS Porting Guide</i>
|
<i>NuttX RTOS Porting Guide</i>
|
||||||
</font></big></h1>
|
</font></big></h1>
|
||||||
<p>Last Updated: July 26, 2013</p>
|
<p>Last Updated: August 12, 2013</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -3433,6 +3433,8 @@ extern void up_ledoff(int led);
|
|||||||
<p>
|
<p>
|
||||||
<b>Examples</b>:
|
<b>Examples</b>:
|
||||||
<code>arch/arm/src/lpc17xx/lpc17_usbhost.c</code>.
|
<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>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -3469,7 +3471,7 @@ extern void up_ledoff(int led);
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>
|
<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>
|
||||||
<p>
|
<p>
|
||||||
Wait for a device to be connected or disconnected.
|
Wait for a device to be connected or disconnected.
|
||||||
@@ -3477,10 +3479,10 @@ extern void up_ledoff(int led);
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>
|
<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>
|
||||||
<p>
|
<p>
|
||||||
Enumerate the connected device.
|
Enumerate the device connected to a root hub port.
|
||||||
As part of this enumeration process, the driver will
|
As part of this enumeration process, the driver will
|
||||||
(1) get the device's configuration descriptor,
|
(1) get the device's configuration descriptor,
|
||||||
(2) extract the class ID info from the configuration descriptor,
|
(2) extract the class ID info from the configuration descriptor,
|
||||||
|
|||||||
@@ -294,8 +294,8 @@ 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, bool connected);
|
static int lpc17_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected);
|
||||||
static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr);
|
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,
|
static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
||||||
uint16_t maxpacketsize);
|
uint16_t maxpacketsize);
|
||||||
static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
|
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:
|
* 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.
|
||||||
* connected - TRUE: Wait for device to be connected; FALSE: wait for device
|
* connected - A pointer to a boolean value: TRUE: Wait for device to be
|
||||||
* to be disconnected
|
* connected; FALSE: wait for device to be disconnected
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* Zero (OK) is returned when a device in connected. This function will not
|
* 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;
|
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
@@ -1541,13 +1541,14 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
|
|||||||
/* Are we already connected? */
|
/* Are we already connected? */
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
while (priv->connected == connected)
|
while (priv->connected == *connected)
|
||||||
{
|
{
|
||||||
/* No... wait for the connection/disconnection */
|
/* No... wait for the connection/disconnection */
|
||||||
|
|
||||||
priv->rhswait = true;
|
priv->rhswait = true;
|
||||||
lpc17_takesem(&priv->rhssem);
|
lpc17_takesem(&priv->rhssem);
|
||||||
}
|
}
|
||||||
|
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
|
||||||
udbg("Connected:%s\n", priv->connected ? "YES" : "NO");
|
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:
|
* 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.
|
||||||
|
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
* 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;
|
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()
|
/* Are we connected to a device? The caller should have called the wait()
|
||||||
* method first to be assured that a device is connected.
|
* method first to be assured that a device is connected.
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
/* The SAMA5 supports 3 root hub ports */
|
||||||
|
|
||||||
|
#define SAM_USBHOST_NRHPORT 3
|
||||||
|
|
||||||
/* Register offsets *********************************************************/
|
/* Register offsets *********************************************************/
|
||||||
/* See nuttx/usb/ohci.h */
|
/* See nuttx/usb/ohci.h */
|
||||||
@@ -85,9 +88,11 @@
|
|||||||
#define SAM_USBHOST_RHDESCA (SAM_UHPOHCI_VSECTION+OHCI_RHDESCA_OFFSET)
|
#define SAM_USBHOST_RHDESCA (SAM_UHPOHCI_VSECTION+OHCI_RHDESCA_OFFSET)
|
||||||
#define SAM_USBHOST_RHDESCB (SAM_UHPOHCI_VSECTION+OHCI_RHDESCB_OFFSET)
|
#define SAM_USBHOST_RHDESCB (SAM_UHPOHCI_VSECTION+OHCI_RHDESCB_OFFSET)
|
||||||
#define SAM_USBHOST_RHSTATUS (SAM_UHPOHCI_VSECTION+OHCI_RHSTATUS_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_RHPORTST1 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST1_OFFSET)
|
||||||
#define SAM_USBHOST_RHPORTST2 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST2_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_RHPORTST3 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST3_OFFSET)
|
||||||
|
|
||||||
/* Register bit definitions *************************************************/
|
/* Register bit definitions *************************************************/
|
||||||
/* See include/nuttx/usb/ohci.h */
|
/* See include/nuttx/usb/ohci.h */
|
||||||
|
|||||||
+124
-52
@@ -176,6 +176,13 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Private Types
|
* 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 */
|
/* This structure retains the state of the USB host controller */
|
||||||
|
|
||||||
@@ -194,9 +201,8 @@ struct sam_ohci_s
|
|||||||
|
|
||||||
/* Driver status */
|
/* 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 */
|
volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */
|
||||||
|
|
||||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||||
uint8_t ininterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
|
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 */
|
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 exclsem; /* Support mutually exclusive access */
|
||||||
sem_t rhssem; /* Semaphore to wait Writeback Done Head event */
|
sem_t rhssem; /* Semaphore to wait Writeback Done Head event */
|
||||||
|
|
||||||
|
/* Root hub ports */
|
||||||
|
|
||||||
|
struct sam_rhport_s rhport[SAM_USBHOST_NRHPORT];
|
||||||
|
|
||||||
/* Debug stuff */
|
/* Debug stuff */
|
||||||
|
|
||||||
#ifdef CONFIG_SAMA5_SPI_REGDEBUG
|
#ifdef CONFIG_SAMA5_SPI_REGDEBUG
|
||||||
@@ -337,8 +347,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context);
|
|||||||
|
|
||||||
/* USB host controller operations **********************************************/
|
/* USB host controller operations **********************************************/
|
||||||
|
|
||||||
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);
|
||||||
static int sam_enumerate(FAR struct usbhost_driver_s *drvr);
|
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,
|
static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
||||||
uint16_t maxpacketsize);
|
uint16_t maxpacketsize);
|
||||||
static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
|
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? */
|
/* Is the device still connected? */
|
||||||
|
|
||||||
|
#if 0 /* REVISIT */
|
||||||
if (priv->connected)
|
if (priv->connected)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* Yes.. then set wdhwait to indicate that we expect to be informed when
|
/* Yes.. then set wdhwait to indicate that we expect to be informed when
|
||||||
* either (1) the device is disconnected, or (2) the transfer completed.
|
* 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 intst;
|
||||||
uint32_t pending;
|
uint32_t pending;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
uint32_t regaddr;
|
||||||
|
int rhpndx;
|
||||||
|
|
||||||
/* Read Interrupt Status and mask out interrupts that are not enabled. */
|
/* Read Interrupt Status and mask out interrupts that are not enabled. */
|
||||||
|
|
||||||
@@ -1353,15 +1367,27 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
|
|||||||
|
|
||||||
if ((pending & OHCI_INT_RHSC) != 0)
|
if ((pending & OHCI_INT_RHSC) != 0)
|
||||||
{
|
{
|
||||||
uint32_t rhportst1 = sam_getreg(SAM_USBHOST_RHPORTST1);
|
/* Hand root hub status change on each root port */
|
||||||
ullvdbg("Root Hub Status Change, RHPORTST1: %08x\n", rhportst1);
|
|
||||||
|
|
||||||
if ((rhportst1 & OHCI_RHPORTST_CSC) != 0)
|
ullvdbg("Root Hub Status Change\n");
|
||||||
|
for (rhpndx = 0; rhpndx < SAM_USBHOST_NRHPORT; rhpndx++)
|
||||||
|
{
|
||||||
|
uint32_t rhportst;
|
||||||
|
|
||||||
|
regaddr = SAM_USBHOST_RHPORTST(rhpndx+1);
|
||||||
|
rhportst = sam_getreg(regaddr);
|
||||||
|
|
||||||
|
ullvdbg("RHPORTST%d: %08x\n",
|
||||||
|
rhpndx + 1, rhportst);
|
||||||
|
|
||||||
|
if ((rhportst & OHCI_RHPORTST_CSC) != 0)
|
||||||
{
|
{
|
||||||
uint32_t rhstatus = sam_getreg(SAM_USBHOST_RHSTATUS);
|
uint32_t rhstatus = sam_getreg(SAM_USBHOST_RHSTATUS);
|
||||||
ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus);
|
ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus);
|
||||||
|
|
||||||
/* If DRWE is set, Connect Status Change indicates a remote wake-up event */
|
/* If DRWE is set, Connect Status Change indicates a remote
|
||||||
|
* wake-up event
|
||||||
|
*/
|
||||||
|
|
||||||
if (rhstatus & OHCI_RHSTATUS_DRWE)
|
if (rhstatus & OHCI_RHSTATUS_DRWE)
|
||||||
{
|
{
|
||||||
@@ -1374,16 +1400,18 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
/* Check current connect status */
|
/* Check current connect status */
|
||||||
|
|
||||||
if ((rhportst1 & OHCI_RHPORTST_CCS) != 0)
|
if ((rhportst & OHCI_RHPORTST_CCS) != 0)
|
||||||
{
|
{
|
||||||
/* Connected ... Did we just become connected? */
|
/* Connected ... Did we just become connected? */
|
||||||
|
|
||||||
if (!priv->connected)
|
if (!priv->rhport[rhpndx].connected)
|
||||||
{
|
{
|
||||||
/* Yes.. connected. */
|
/* Yes.. connected. */
|
||||||
|
|
||||||
ullvdbg("Connected\n");
|
priv->rhport[rhpndx].connected = true;
|
||||||
priv->connected = true;
|
|
||||||
|
ullvdbg("RHPort%d connected, rhswait: %d\n",
|
||||||
|
rhpndx + 1, priv->rhswait);
|
||||||
|
|
||||||
/* Notify any waiters */
|
/* Notify any waiters */
|
||||||
|
|
||||||
@@ -1402,19 +1430,22 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
|
|||||||
* when CCS == 1.
|
* when CCS == 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv->lowspeed = (rhportst1 & OHCI_RHPORTST_LSDA) != 0;
|
priv->rhport[rhpndx].lowspeed =
|
||||||
ullvdbg("Speed:%s\n", priv->lowspeed ? "LOW" : "FULL");
|
(rhportst & OHCI_RHPORTST_LSDA) != 0;
|
||||||
|
|
||||||
|
ullvdbg("Speed: %s\n",
|
||||||
|
priv->rhport[rhpndx].lowspeed ? "LOW" : "FULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we are now disconnected */
|
/* Check if we are now disconnected */
|
||||||
|
|
||||||
else if (priv->connected)
|
else if (priv->rhport[rhpndx].connected)
|
||||||
{
|
{
|
||||||
/* Yes.. disconnect the device */
|
/* Yes.. disconnect the device */
|
||||||
|
|
||||||
ullvdbg("Disconnected\n");
|
ullvdbg("RHport%d disconnected\n", rhpndx+1);
|
||||||
priv->connected = false;
|
priv->rhport[rhpndx].connected = false;
|
||||||
priv->lowspeed = false;
|
priv->rhport[rhpndx].lowspeed = false;
|
||||||
|
|
||||||
/* Are we bound to a class instance? */
|
/* Are we bound to a class instance? */
|
||||||
|
|
||||||
@@ -1426,7 +1457,9 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
|
|||||||
priv->class = NULL;
|
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)
|
||||||
{
|
{
|
||||||
@@ -1442,16 +1475,17 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
|
|||||||
|
|
||||||
/* 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)
|
if ((rhportst & OHCI_RHPORTST_PRSC) != 0)
|
||||||
{
|
{
|
||||||
/* Release the RH port from reset */
|
/* 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. */
|
/* The transfer failed for some reason... dump some diagnostic info. */
|
||||||
|
|
||||||
ulldbg("ERROR: ED xfrtype:%d TD CTRL:%08x/CC:%d RHPORTST1:%08x\n",
|
ulldbg("ERROR: ED xfrtype: %d TD CTRL: %08x/CC: %d\n",
|
||||||
ed->xfrtype, td->hw.ctrl, ed->tdstatus,
|
ed->xfrtype, td->hw.ctrl, ed->tdstatus);
|
||||||
sam_getreg(SAM_USBHOST_RHPORTST1));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1539,17 +1572,21 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
|
|||||||
* Name: sam_wait
|
* Name: sam_wait
|
||||||
*
|
*
|
||||||
* Description:
|
* 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:
|
* Input Parameters:
|
||||||
* drvr - The USB host driver instance obtained as a parameter from the call
|
* drvr - The USB host driver instance obtained as a parameter from the call
|
||||||
* to the class create() method.
|
* to the class create() method.
|
||||||
* connected - TRUE: Wait for device to be connected; FALSE: wait for device
|
* connected - A pointer to an array of 3 boolean values corresponding to
|
||||||
* to be disconnected
|
* 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:
|
* Returned Values:
|
||||||
* Zero (OK) is returned when a device in connected. This function will not
|
* And index [0, 1, or 2} corresponding to the root hub port number {1, 2,
|
||||||
* return until either (1) a device is connected or (2) some failure occurs.
|
* 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
|
* On a failure, a negated errno value is returned indicating the nature of
|
||||||
* the failure
|
* 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;
|
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
|
||||||
irqstate_t flags;
|
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();
|
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;
|
priv->rhswait = true;
|
||||||
sam_takesem(&priv->rhssem);
|
sam_takesem(&priv->rhssem);
|
||||||
}
|
}
|
||||||
|
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
|
||||||
udbg("Connected:%s\n", priv->connected ? "YES" : "NO");
|
udbg("RHPort%d connected: %s\n",
|
||||||
return OK;
|
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:
|
* 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.
|
||||||
|
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
* 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;
|
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()
|
/* Are we connected to a device? The caller should have called the wait()
|
||||||
* method first to be assured that a device is connected.
|
* method first to be assured that a device is connected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (!priv->connected)
|
while (!priv->rhport[rhpndx].connected)
|
||||||
{
|
{
|
||||||
/* No, return an error */
|
/* No, return an error */
|
||||||
|
|
||||||
@@ -1628,25 +1689,26 @@ static int sam_enumerate(FAR struct usbhost_driver_s *drvr)
|
|||||||
|
|
||||||
up_mdelay(100);
|
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 */
|
/* 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 */
|
/* 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);
|
up_mdelay(200);
|
||||||
|
|
||||||
/* Let the common usbhost_enumerate do all of the real work. Note that the
|
/* 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");
|
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)
|
uint16_t maxpacketsize)
|
||||||
{
|
{
|
||||||
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
|
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 */
|
/* We must have exclusive access to EP0 and the control list */
|
||||||
|
|
||||||
@@ -1690,7 +1754,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
|||||||
g_edctrl.hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT |
|
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;
|
g_edctrl.hw.ctrl |= ED_CONTROL_S;
|
||||||
}
|
}
|
||||||
@@ -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_ohci_s *priv = (struct sam_ohci_s *)drvr;
|
||||||
struct sam_ed_s *ed;
|
struct sam_ed_s *ed;
|
||||||
|
int rhpndx = (int)epdesc->funcaddr - 1;
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
/* Sanity check. NOTE that this method should only be called if a device is
|
/* Sanity check. NOTE that this method should only be called if a device is
|
||||||
* connected (because we need a valid low speed indication).
|
* 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
|
/* We must have exclusive access to the ED pool, the bulk list, the periodic list
|
||||||
* and the interrupt table.
|
* and the interrupt table.
|
||||||
@@ -1776,7 +1843,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
|
|||||||
|
|
||||||
/* Check for a low-speed device */
|
/* Check for a low-speed device */
|
||||||
|
|
||||||
if (priv->lowspeed)
|
if (priv->rhport[rhpndx].lowspeed)
|
||||||
{
|
{
|
||||||
ed->hw.ctrl |= ED_CONTROL_S;
|
ed->hw.ctrl |= ED_CONTROL_S;
|
||||||
}
|
}
|
||||||
@@ -2583,8 +2650,14 @@ FAR struct usbhost_driver_s *sam_ohci_initialize(int controller)
|
|||||||
* connected. We need to set the initial connected state accordingly.
|
* connected. We need to set the initial connected state accordingly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
regval = sam_getreg(SAM_USBHOST_RHPORTST1);
|
for (i = 0; i < SAM_USBHOST_NRHPORT; i++)
|
||||||
priv->connected = ((regval & OHCI_RHPORTST_CCS) != 0);
|
{
|
||||||
|
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
|
/* Drive Vbus +5V (the smoke test). Should be done elsewhere in OTG
|
||||||
* mode.
|
* mode.
|
||||||
@@ -2595,8 +2668,7 @@ FAR struct usbhost_driver_s *sam_ohci_initialize(int controller)
|
|||||||
/* Enable interrupts at the interrupt controller */
|
/* Enable interrupts at the interrupt controller */
|
||||||
|
|
||||||
up_enable_irq(SAM_IRQ_UHPHS); /* enable USB interrupt */
|
up_enable_irq(SAM_IRQ_UHPHS); /* enable USB interrupt */
|
||||||
udbg("USB host Initialized, Device connected:%s\n",
|
uvdbg("USB OHCI Initialized\n");
|
||||||
priv->connected ? "YES" : "NO");
|
|
||||||
|
|
||||||
return &priv->drvr;
|
return &priv->drvr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -358,8 +358,8 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx);
|
|||||||
|
|
||||||
/* USB host controller operations **********************************************/
|
/* USB host controller operations **********************************************/
|
||||||
|
|
||||||
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);
|
||||||
static int stm32_enumerate(FAR struct usbhost_driver_s *drvr);
|
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,
|
static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
||||||
uint16_t maxpacketsize);
|
uint16_t maxpacketsize);
|
||||||
static int stm32_epalloc(FAR struct usbhost_driver_s *drvr,
|
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:
|
* 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.
|
||||||
* connected - TRUE: Wait for device to be connected; FALSE: wait for device
|
* connected - A pointer to a boolean value. TRUE: Wait for device to be
|
||||||
* to be disconnected
|
* connected; FALSE: wait for device to be disconnected
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* Zero (OK) is returned when a device in connected. This function will not
|
* 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;
|
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
@@ -3036,7 +3036,7 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
|
|||||||
/* Are we already connected? */
|
/* Are we already connected? */
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
while (priv->connected == connected)
|
while (priv->connected == *connected)
|
||||||
{
|
{
|
||||||
/* No... wait for the connection/disconnection */
|
/* No... wait for the connection/disconnection */
|
||||||
|
|
||||||
@@ -3066,6 +3066,7 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
|
|||||||
* 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.
|
||||||
|
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
* 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;
|
struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
int chidx;
|
int chidx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv && rhpndx == 0);
|
||||||
|
|
||||||
/* Are we connected to a device? The caller should have called the wait()
|
/* Are we connected to a device? The caller should have called the wait()
|
||||||
* method first to be assured that a device is connected.
|
* method first to be assured that a device is connected.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -121,7 +121,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -181,7 +181,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -205,7 +205,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -209,7 +209,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -208,7 +208,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
#include "up_arch.h"
|
#include "up_arch.h"
|
||||||
#include "sam_pio.h"
|
#include "sam_pio.h"
|
||||||
#include "sam_usbhost.h"
|
#include "sam_usbhost.h"
|
||||||
|
#include "chip/sam_ohci.h"
|
||||||
#include "sama5d3x-ek.h"
|
#include "sama5d3x-ek.h"
|
||||||
|
|
||||||
#if defined(CONFIG_SAMA5_UHPHS) || defined(CONFIG_SAMA5_UDPHS)
|
#if defined(CONFIG_SAMA5_UHPHS) || defined(CONFIG_SAMA5_UDPHS)
|
||||||
@@ -97,25 +98,29 @@ static struct usbhost_driver_s *g_ehci;
|
|||||||
#if HAVE_USBHOST
|
#if HAVE_USBHOST
|
||||||
static int usbhost_waiter(struct usbhost_driver_s *dev)
|
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");
|
uvdbg("Running\n");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* 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;
|
connected[rhpndx] = !connected[rhpndx];
|
||||||
uvdbg("%s\n", connected ? "connected" : "disconnected");
|
|
||||||
|
uvdbg("RHport%d %s\n",
|
||||||
|
rhpndx + 1, connected[rhpndx] ? "connected" : "disconnected");
|
||||||
|
|
||||||
/* Did we just become connected? */
|
/* Did we just become connected? */
|
||||||
|
|
||||||
if (connected)
|
if (connected[rhpndx])
|
||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(dev);
|
(void)DRVR_ENUMERATE(dev, rhpndx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -120,7 +120,7 @@ static int usbhost_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* config/sure-pic32mx/src/pic32mx_nsh.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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 */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, &connected);
|
||||||
DEBUGASSERT(ret == OK);
|
DEBUGASSERT(ret == OK);
|
||||||
|
|
||||||
connected = !connected;
|
connected = !connected;
|
||||||
@@ -200,7 +200,7 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
/* Yes.. enumerate the newly connected device */
|
/* Yes.. enumerate the newly connected device */
|
||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-30
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* include/nuttx/usb/usbhost.h
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* References:
|
* References:
|
||||||
@@ -155,22 +155,26 @@
|
|||||||
* Name: DRVR_WAIT
|
* Name: DRVR_WAIT
|
||||||
*
|
*
|
||||||
* Description:
|
* 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:
|
* 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
|
||||||
* the class create() method.
|
* to the class create() method.
|
||||||
* connected - TRUE: Wait for device to be connected; FALSE: wait for device to
|
* connected - A pointer to an array of n boolean values corresponding to
|
||||||
* be disconnected
|
* 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:
|
* Returned Values:
|
||||||
* Zero (OK) is returned when a device in connected. This function will not
|
* And index [0..(n-1)} corresponding to the root hub port number {1..n} is
|
||||||
* return until either (1) a device is connected or (2) some failure occurs.
|
* returned when a device in connected or disconnectd. This function will not
|
||||||
* On a failure, a negated errno value is returned indicating the nature of
|
* return until either (1) a device is connected or disconntect to/from any
|
||||||
* the failure
|
* 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:
|
* 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:
|
* 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.
|
||||||
|
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
* 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
|
* Name: DRVR_EP0CONFIGURE
|
||||||
@@ -589,19 +594,19 @@ struct usbhost_driver_s
|
|||||||
{
|
{
|
||||||
/* Wait for a device to connect or disconnect. */
|
/* 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,
|
/* Enumerate the device connected on a root hub port. As part of this
|
||||||
* the driver will (1) get the device's configuration descriptor, (2)
|
* enumeration process, the driver will (1) get the device's configuration
|
||||||
* extract the class ID info from the configuration descriptor, (3) call
|
* descriptor, (2) extract the class ID info from the configuration
|
||||||
* usbhost_findclass() to find the class that supports this device, (4)
|
* descriptor, (3) call usbhost_findclass() to find the class that supports
|
||||||
* call the create() method on the struct usbhost_registry_s interface
|
* this device, (4) call the create() method on the struct usbhost_registry_s
|
||||||
* to get a class instance, and finally (5) call the connect() method
|
* interface to get a class instance, and finally (5) call the connect()
|
||||||
* of the struct usbhost_class_s interface. After that, the class is in
|
* method of the struct usbhost_class_s interface. After that, the class is
|
||||||
* charge of the sequence of operations.
|
* 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
|
/* Configure endpoint 0. This method is normally used internally by the
|
||||||
* enumerate() method but is made available at the interface to support
|
* enumerate() method but is made available at the interface to support
|
||||||
@@ -689,7 +694,8 @@ struct usbhost_driver_s
|
|||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#define EXTERN extern "C"
|
#define EXTERN extern "C"
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#else
|
#else
|
||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#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
|
* 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
|
* 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
|
* Name: usbhost_kbdinit
|
||||||
@@ -778,7 +784,7 @@ EXTERN int usbhost_storageinit(void);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
EXTERN int usbhost_kbdinit(void);
|
int usbhost_kbdinit(void);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: usbhost_wlaninit
|
* Name: usbhost_wlaninit
|
||||||
@@ -797,7 +803,7 @@ EXTERN int usbhost_kbdinit(void);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
EXTERN int usbhost_wlaninit(void);
|
int usbhost_wlaninit(void);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Name: usbhost_enumerate
|
* Name: usbhost_enumerate
|
||||||
@@ -836,8 +842,7 @@ EXTERN int usbhost_wlaninit(void);
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
EXTERN int usbhost_enumerate(FAR struct usbhost_driver_s *drvr,
|
int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
||||||
uint8_t funcaddr,
|
|
||||||
FAR struct usbhost_class_s **class);
|
FAR struct usbhost_class_s **class);
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
|
|||||||
Reference in New Issue
Block a user