summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-08-12 16:29:33 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-08-12 16:29:33 -0600
commita9aab75d3c0903c8cfb75b4abfc44d2fc82ef2df (patch)
tree1503588f076c2528d287ba96dc2da1b8543e0f1b
parent3a469a7a7a10d28fb81f53b4494ff137a998bd30 (diff)
downloadnuttx-a9aab75d3c0903c8cfb75b4abfc44d2fc82ef2df.tar.gz
nuttx-a9aab75d3c0903c8cfb75b4abfc44d2fc82ef2df.tar.bz2
nuttx-a9aab75d3c0903c8cfb75b4abfc44d2fc82ef2df.zip
More changes to USB host interface to support multiple downstream ports
-rw-r--r--nuttx/ChangeLog5
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c7
-rw-r--r--nuttx/arch/arm/src/sama5/sam_ohci.c59
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfshost.c7
-rw-r--r--nuttx/drivers/usbhost/usbhost_hidkbd.c12
-rw-r--r--nuttx/drivers/usbhost/usbhost_skeleton.c14
-rw-r--r--nuttx/drivers/usbhost/usbhost_storage.c12
-rw-r--r--nuttx/include/nuttx/usb/usbhost.h5
8 files changed, 86 insertions, 35 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index a33513a2e..71eb912a6 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5380,4 +5380,9 @@
breakage, but I expect some (2013-8-12).
* configs/olimex-stm32-p107/nsh/defconfig and appconfig: Converted to
use the kconfig-frontends tool. From Max Holtzberg (2013-8-12).
+ * includes/nuttx/usb/usbhost.h, et al: Continued changes to the USB
+ host interface to support multiple downstream ports. When a class
+ is disconnected, it needs to provide the FunctionAddress to the
+ USB HCD disconnect method so that the HCD will know which port
+ is being disconnected (2013-8-12).
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
index 2fb5eb34c..4983d1ec3 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -315,7 +315,7 @@ static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
FAR const uint8_t *buffer);
static int lpc17_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen);
-static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr);
+static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr);
/* Initialization **************************************************************/
@@ -2378,6 +2378,7 @@ errout:
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * funcaddr - Address of the function to be disconnected.
*
* Returned Values:
* None
@@ -2388,9 +2389,11 @@ errout:
*
*******************************************************************************/
-static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr)
+static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+ DEBUGASSERT(priv && funcaddr == 1);
+
priv->class = NULL;
}
diff --git a/nuttx/arch/arm/src/sama5/sam_ohci.c b/nuttx/arch/arm/src/sama5/sam_ohci.c
index 10c75558a..937689f8b 100644
--- a/nuttx/arch/arm/src/sama5/sam_ohci.c
+++ b/nuttx/arch/arm/src/sama5/sam_ohci.c
@@ -180,8 +180,14 @@
struct sam_rhport_s
{
+ /* Root hub port status */
+
volatile bool connected; /* Connected to device */
volatile bool lowspeed; /* Low speed device attached. */
+
+ /* The bound device class driver */
+
+ struct usbhost_class_s *class;
};
/* This structure retains the state of the USB host controller */
@@ -195,10 +201,6 @@ struct sam_ohci_s
struct usbhost_driver_s drvr;
- /* The bound device class driver */
-
- struct usbhost_class_s *class;
-
/* Driver status */
volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */
@@ -368,7 +370,7 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr,
FAR const uint8_t *buffer);
static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen);
-static void sam_disconnect(FAR struct usbhost_driver_s *drvr);
+static void sam_disconnect(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr);
/* Initialization **************************************************************/
@@ -401,7 +403,6 @@ static struct sam_ohci_s g_usbhost =
.transfer = sam_transfer,
.disconnect = sam_disconnect,
},
- .class = NULL,
};
/* This is a free list of EDs and TD buffers */
@@ -1372,13 +1373,13 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
ullvdbg("Root Hub Status Change\n");
for (rhpndx = 0; rhpndx < SAM_USBHOST_NRHPORT; rhpndx++)
{
+ struct sam_rhport_s *rhport = &priv->rhport[rhpndx];
uint32_t rhportst;
regaddr = SAM_USBHOST_RHPORTST(rhpndx+1);
rhportst = sam_getreg(regaddr);
- ullvdbg("RHPORTST%d: %08x\n",
- rhpndx + 1, rhportst);
+ ullvdbg("RHPORTST%d: %08x\n", rhpndx + 1, rhportst);
if ((rhportst & OHCI_RHPORTST_CSC) != 0)
{
@@ -1404,11 +1405,11 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
{
/* Connected ... Did we just become connected? */
- if (!priv->rhport[rhpndx].connected)
+ if (!rhport->connected)
{
/* Yes.. connected. */
- priv->rhport[rhpndx].connected = true;
+ rhport->connected = true;
ullvdbg("RHPort%d connected, rhswait: %d\n",
rhpndx + 1, priv->rhswait);
@@ -1430,31 +1431,31 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
* when CCS == 1.
*/
- priv->rhport[rhpndx].lowspeed =
+ rhport->lowspeed =
(rhportst & OHCI_RHPORTST_LSDA) != 0;
ullvdbg("Speed: %s\n",
- priv->rhport[rhpndx].lowspeed ? "LOW" : "FULL");
+ rhport->lowspeed ? "LOW" : "FULL");
}
/* Check if we are now disconnected */
- else if (priv->rhport[rhpndx].connected)
+ else if (rhport->connected)
{
/* Yes.. disconnect the device */
ullvdbg("RHport%d disconnected\n", rhpndx+1);
- priv->rhport[rhpndx].connected = false;
- priv->rhport[rhpndx].lowspeed = false;
+ rhport->connected = false;
+ rhport->lowspeed = false;
/* Are we bound to a class instance? */
- if (priv->class)
+ if (rhport->class)
{
/* Yes.. Disconnect the class */
- CLASS_DISCONNECTED(priv->class);
- priv->class = NULL;
+ CLASS_DISCONNECTED(rhport->class);
+ rhport->class = NULL;
}
/* Notify any waiters for the Root Hub Status change
@@ -1671,13 +1672,17 @@ 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)
{
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
+ struct sam_rhport_s *rhport;
uint32_t regaddr;
+ DEBUGASSERT(priv && rhpndx >= 0 && rhpndx < SAM_USBHOST_NRHPORT);
+ rhport = &priv->rhport[rhpndx];
+
/* 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->rhport[rhpndx].connected)
+ while (!rhport->connected)
{
/* No, return an error */
@@ -1708,7 +1713,7 @@ static int sam_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx)
*/
uvdbg("Enumerate the device\n");
- return usbhost_enumerate(drvr, rhpndx+1, &priv->class);
+ return usbhost_enumerate(drvr, rhpndx+1, &rhport->class);
}
/************************************************************************************
@@ -1740,10 +1745,11 @@ 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;
+ struct sam_rhport_s *rhport;
- DEBUGASSERT(drvr && funcaddr > 0 && funcaddr <= SAM_USBHOST_NRHPORT &&
+ DEBUGASSERT(priv && funcaddr > 0 && funcaddr <= SAM_USBHOST_NRHPORT &&
maxpacketsize < 2048);
+ rhport = &priv->rhport[funcaddr - 1];
/* We must have exclusive access to EP0 and the control list */
@@ -1754,7 +1760,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 |
(uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT;
- if (priv->rhport[rhpndx].lowspeed)
+ if (rhport->lowspeed)
{
g_edctrl.hw.ctrl |= ED_CONTROL_S;
}
@@ -2395,6 +2401,7 @@ errout:
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * funcaddr - Address of the function to be disconnected.
*
* Returned Values:
* None
@@ -2405,10 +2412,12 @@ errout:
*
*******************************************************************************/
-static void sam_disconnect(FAR struct usbhost_driver_s *drvr)
+static void sam_disconnect(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr)
{
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
- priv->class = NULL;
+ DEBUGASSERT(priv && funcaddr > 0 && funcaddr <= SAM_USBHOST_NRHPORT);
+
+ priv->rhport[funcaddr - 1].class = NULL;
}
/*******************************************************************************
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
index d1b4f5f54..4f3683177 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
@@ -380,7 +380,7 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
FAR const uint8_t *buffer);
static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen);
-static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
+static void stm32_disconnect(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr);
/* Initialization **************************************************************/
@@ -3795,6 +3795,7 @@ static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * funcaddr - Address of the function to be disconnected.
*
* Returned Values:
* None
@@ -3805,9 +3806,11 @@ static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
*
*******************************************************************************/
-static void stm32_disconnect(FAR struct usbhost_driver_s *drvr)
+static void stm32_disconnect(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr)
{
struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ DEBUGASSERT(priv && funcaddr == 1);
+
priv->class = NULL;
}
diff --git a/nuttx/drivers/usbhost/usbhost_hidkbd.c b/nuttx/drivers/usbhost/usbhost_hidkbd.c
index 1710a2bb8..6a83fb759 100644
--- a/nuttx/drivers/usbhost/usbhost_hidkbd.c
+++ b/nuttx/drivers/usbhost/usbhost_hidkbd.c
@@ -208,6 +208,7 @@ struct usbhost_state_s
volatile bool open; /* TRUE: The keyboard device is open */
volatile bool waiting; /* TRUE: waiting for keyboard data */
uint8_t ifno; /* Interface number */
+ uint8_t funcaddr; /* USB function address */
int16_t crefs; /* Reference count on the driver instance */
sem_t exclsem; /* Used to maintain mutual exclusive access */
sem_t waitsem; /* Used to wait for keyboard data */
@@ -797,7 +798,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
- DRVR_DISCONNECT(priv->drvr);
+ DRVR_DISCONNECT(priv->drvr, priv->funcaddr);
/* And free the class instance. Hmmm.. this may execute on the worker
* thread and the work structure is part of what is getting freed. That
@@ -1892,6 +1893,15 @@ static int usbhost_connect(FAR struct usbhost_class_s *class,
{
udbg("usbhost_devinit() failed: %d\n", ret);
}
+ else
+ {
+ /* Save the function address (We will need it when we disconnect).
+ * NOTE that address is available in the endpoint structures as
+ * well.
+ */
+
+ priv->funcaddr = funcaddr;
+ }
}
/* ERROR handling: Do nothing. If we return and error during connection,
diff --git a/nuttx/drivers/usbhost/usbhost_skeleton.c b/nuttx/drivers/usbhost/usbhost_skeleton.c
index bc30eedd7..a486f8768 100644
--- a/nuttx/drivers/usbhost/usbhost_skeleton.c
+++ b/nuttx/drivers/usbhost/usbhost_skeleton.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/usbhost/usbhost_skeleton.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -105,6 +105,7 @@ struct usbhost_state_s
char devchar; /* Character identifying the /dev/skel[n] device */
volatile bool disconnected; /* TRUE: Device has been disconnected */
uint8_t ifno; /* Interface number */
+ uint8_t funcaddr; /* USB function address */
int16_t crefs; /* Reference count on the driver instance */
sem_t exclsem; /* Used to maintain mutual exclusive access */
struct work_s work; /* For interacting with the worker thread */
@@ -368,7 +369,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
- DRVR_DISCONNECT(priv->drvr);
+ DRVR_DISCONNECT(priv->drvr, priv->funcaddr);
/* And free the class instance. Hmmm.. this may execute on the worker
* thread and the work structure is part of what is getting freed. That
@@ -954,6 +955,15 @@ static int usbhost_connect(FAR struct usbhost_class_s *class,
{
udbg("usbhost_devinit() failed: %d\n", ret);
}
+ else
+ {
+ /* Save the function address (We will need it when we disconnect).
+ * NOTE that address is available in the endpoint structures as
+ * well.
+ */
+
+ priv->funcaddr = funcaddr;
+ }
}
return ret;
diff --git a/nuttx/drivers/usbhost/usbhost_storage.c b/nuttx/drivers/usbhost/usbhost_storage.c
index 89ec6238f..bc0f78c75 100644
--- a/nuttx/drivers/usbhost/usbhost_storage.c
+++ b/nuttx/drivers/usbhost/usbhost_storage.c
@@ -128,6 +128,7 @@ struct usbhost_state_s
char sdchar; /* Character identifying the /dev/sd[n] device */
volatile bool disconnected; /* TRUE: Device has been disconnected */
uint8_t ifno; /* Interface number */
+ uint8_t funcaddr; /* USB function address */
int16_t crefs; /* Reference count on the driver instance */
uint16_t blocksize; /* Block size of USB mass storage device */
uint32_t nblocks; /* Number of blocks on the USB mass storage device */
@@ -929,7 +930,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
- DRVR_DISCONNECT(priv->drvr);
+ DRVR_DISCONNECT(priv->drvr, priv->funcaddr);
/* And free the class instance. Hmmm.. this may execute on the worker
* thread and the work structure is part of what is getting freed. That
@@ -1740,6 +1741,15 @@ static int usbhost_connect(FAR struct usbhost_class_s *class,
{
udbg("usbhost_initvolume() failed: %d\n", ret);
}
+ else
+ {
+ /* Save the function address (We will need it when we disconnect).
+ * NOTE that address is available in the endpoint structures as
+ * well.
+ */
+
+ priv->funcaddr = funcaddr;
+ }
}
return ret;
diff --git a/nuttx/include/nuttx/usb/usbhost.h b/nuttx/include/nuttx/usb/usbhost.h
index d357e0b9b..80b6f9cf6 100644
--- a/nuttx/include/nuttx/usb/usbhost.h
+++ b/nuttx/include/nuttx/usb/usbhost.h
@@ -481,6 +481,7 @@
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
+ * funcaddr - Address of the function to be disconnected.
*
* Returned Values:
* None
@@ -490,7 +491,7 @@
*
************************************************************************************/
-#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr))
+#define DRVR_DISCONNECT(drvr,funcaddr) ((drvr)->disconnect(drvr,funcaddr))
/************************************************************************************
* Public Types
@@ -684,7 +685,7 @@ struct usbhost_driver_s
* (until a new instance is received from the create() method).
*/
- void (*disconnect)(FAR struct usbhost_driver_s *drvr);
+ void (*disconnect)(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr);
};
/************************************************************************************