summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-01-16 14:02:42 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-01-16 14:02:42 +0000
commitb7145b509d269f4a5ffcecad9a969c6a0a480f20 (patch)
tree035ba62000a7edb601c2a7b5243176dd8228c096 /nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
parent979c0410e02cb6217fdc87bff44d17c3182ed1d7 (diff)
downloadpx4-nuttx-b7145b509d269f4a5ffcecad9a969c6a0a480f20.tar.gz
px4-nuttx-b7145b509d269f4a5ffcecad9a969c6a0a480f20.tar.bz2
px4-nuttx-b7145b509d269f4a5ffcecad9a969c6a0a480f20.zip
Make space for int/isoc endpoint support
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3254 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c')
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c300
1 files changed, 240 insertions, 60 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
index 0f4091114..6c056b1dc 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -174,9 +174,9 @@ struct lpc17_ed_s
/* Software specific fields */
uint8_t xfrtype; /* Transfer type. See SB_EP_ATTR_XFER_* in usb.h */
+ uint8_t period; /* Periodic EP polling frequency 1, 2, 4, 6, 16, or 32 */
volatile uint8_t tdstatus; /* TD control status bits from last Writeback Done Head event */
volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */
- uint8_t pad;
sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */
/* Unused bytes follow, depending on the size of sem_t */
};
@@ -233,7 +233,7 @@ static void lpc17_takesem(sem_t *sem);
static inline uint16_t lpc17_getle16(const uint8_t *val);
static void lpc17_putle16(uint8_t *dest, uint16_t val);
-/* Descriptor helper functions *************************************************/
+/* OHCI memory pool helper functions *******************************************/
static inline void lpc17_edfree(struct lpc17_ed_s *ed);
static struct lpc17_gtd_s *lpc17_tdalloc(void);
@@ -244,6 +244,24 @@ static void lpc17_tbfree(uint8_t *buffer);
static uint8_t *lpc17_ioalloc(void);
static void lpc17_iofree(uint8_t *buffer);
#endif
+
+/* ED list helper functions ****************************************************/
+
+static inline int lpc17_addbulked(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed);
+static inline int lpc17_rembulked(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed);
+static inline int lpc17_addinted(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed);
+static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed);
+static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed);
+static inline int lpc17_remisoced(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed);
+
+/* Descriptor helper functions *************************************************/
+
static int lpc17_enqueuetd(struct lpc17_usbhost_s *priv,
struct lpc17_ed_s *ed, uint32_t dirpid,
uint32_t toggle, volatile uint8_t *buffer,
@@ -660,6 +678,173 @@ static void lpc17_iofree(uint8_t *buffer)
#endif
/*******************************************************************************
+ * Name: lpc17_addbulked
+ *
+ * Description:
+ * Helper function to add an ED to the bulk list.
+ *
+ *******************************************************************************/
+
+static inline int lpc17_addbulked(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_BULK_DISABLE
+ uint32_t regval;
+
+ /* Add the new bulk ED to the head of the bulk list */
+
+ ed->hw.nexted = lpc17_getreg(LPC17_USBHOST_BULKHEADED);
+ lpc17_putreg((uint32_t)ed, LPC17_USBHOST_BULKHEADED);
+
+ /* BulkListEnable. This bit is set to enable the processing of the
+ * Bulk list. Note: once enabled, it remains. We really should
+ * never modify the bulk list while BLE is set.
+ */
+
+ regval = lpc17_getreg(LPC17_USBHOST_CTRL);
+ regval |= OHCI_CTRL_BLE;
+ lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: lpc17_rembulked
+ *
+ * Description:
+ * Helper function remove an ED from the bulk list.
+ *
+ *******************************************************************************/
+
+static inline int lpc17_rembulked(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_BULK_DISABLE
+ struct lpc17_ed_s *curr = NULL;
+ struct lpc17_ed_s *prev = NULL;
+ uint32_t regval;
+
+ /* Find the ED in the bulk list. NOTE: We really should never be mucking
+ * with the bulk list while BLE is set.
+ */
+
+ for (curr = (struct lpc17_ed_s *)lpc17_getreg(LPC17_USBHOST_BULKHEADED),
+ prev = NULL;
+ curr && curr != ed;
+ prev = curr, curr = (struct lpc17_ed_s *)curr->hw.nexted);
+
+ /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */
+
+ DEBUGASSERT(curr != NULL);
+
+ /* Remove the ED from the bulk list */
+
+ if (curr != NULL)
+ {
+ /* Is this ED the first on in the bulk list? */
+
+ if (prev == NULL)
+ {
+ /* Yes... set the head of the bulk list to skip over this ED */
+
+ lpc17_putreg(ed->hw.nexted, LPC17_USBHOST_BULKHEADED);
+
+ /* If the bulk list is now empty, then disable it */
+
+ regval = lpc17_getreg(LPC17_USBHOST_CTRL);
+ regval &= ~OHCI_CTRL_BLE;
+ lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+ }
+ else
+ {
+ /* No.. set the forward link of the previous ED in the list
+ * skip over this ED.
+ */
+
+ prev->hw.nexted = ed->hw.nexted;
+ }
+ }
+
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: lpc17_addinted
+ *
+ * Description:
+ * Helper function to add an ED to the HCCA interrupt table.
+ *
+ *******************************************************************************/
+
+static inline int lpc17_addinted(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_INT_DISABLE
+# warning "Interrupt endpoints not yet supported"
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: lpc17_addbulked
+ *
+ * Description:
+ * Helper function to remove an ED from the HCCA interrupt table.
+ *
+ *******************************************************************************/
+
+static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_INT_DISABLE
+# warning "Interrupt endpoints not yet supported"
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: lpc17_addbulked
+ *
+ * Description:
+ * Helper functions to add an ED to the periodic table.
+ *
+ *******************************************************************************/
+
+static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_ISOC_DISABLE
+# warning "Isochronous endpoints not yet supported"
+#endif
+ return -ENOSYS;
+
+}
+
+/*******************************************************************************
+ * Name: lpc17_addbulked
+ *
+ * Description:
+ * Helper functions to remove an ED from the periodic table.
+ *
+ *******************************************************************************/
+
+static inline int lpc17_remisoced(struct lpc17_usbhost_s *priv,
+ struct lpc17_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_ISOC_DISABLE
+# warning "Isochronous endpoints not yet supported"
+#endif
+ return -ENOSYS;
+}
+
+/*******************************************************************************
* Name: lpc17_enqueuetd
*
* Description:
@@ -1224,7 +1409,6 @@ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed;
- uint32_t regval;
int ret = -ENOMEM;
/* Sanity check. NOTE that this method should only be called if a device is
@@ -1293,32 +1477,49 @@ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
sem_init(&ed->wdhsem, 0, 0);
- /* Now add the endpoint descriptor to the appropriate list */
-#warning "Missing logic for other endpoint types"
-
/* Link the common tail TD to the ED's TD list */
ed->hw.headp = (uint32_t)TDTAIL;
ed->hw.tailp = (uint32_t)TDTAIL;
- /* Add the new bulk ED to the head of the bulk list */
+ /* Now add the endpoint descriptor to the appropriate list */
- ed->hw.nexted = lpc17_getreg(LPC17_USBHOST_BULKHEADED);
- lpc17_putreg((uint32_t)ed, LPC17_USBHOST_BULKHEADED);
+ switch (ed->xfrtype)
+ {
+ case USB_EP_ATTR_XFER_BULK:
+ ret = lpc17_addbulked(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_INT:
+ ret = lpc17_addinted(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_ISOC:
+ ret = lpc17_addisoced(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_CONTROL:
+ default:
+ ret = -EINVAL;
+ break;
+ }
- /* BulkListEnable. This bit is set to enable the processing of the Bulk
- * list. Note: once enabled, it remains. We really should never modify
- * the bulk list while BLE is set.
- */
+ /* Was the ED successfully added? */
- regval = lpc17_getreg(LPC17_USBHOST_CTRL);
- regval |= OHCI_CTRL_BLE;
- lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+ if (ret != OK)
+ {
+ /* No.. destroy it and report the error */
- /* Return an opaque reference to the ED */
+ udbg("ERROR: Failed to queue ED for transfer type: %d\n", ed->xfrtype);
+ sem_destroy(&ed->wdhsem);
+ lpc17_edfree(ed);
+ }
+ else
+ {
+ /* Yes.. return an opaque reference to the ED */
- *ep = (usbhost_ep_t)ed;
- ret = OK;
+ *ep = (usbhost_ep_t)ed;
+ }
}
lpc17_givesem(&priv->exclsem);
@@ -1349,9 +1550,7 @@ static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep;
- struct lpc17_ed_s *curr = NULL;
- struct lpc17_ed_s *prev = NULL;
- uint32_t regval;
+ int ret;
/* There should not be any pending, real TDs linked to this ED */
@@ -1363,45 +1562,26 @@ static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
lpc17_takesem(&priv->exclsem);
- /* Find the ED in the bulk list. NOTE: We really should never be mucking
- * with the bulk list while BLE is set.
- */
-
- for (curr = (struct lpc17_ed_s *)lpc17_getreg(LPC17_USBHOST_BULKHEADED),
- prev = NULL;
- curr && curr != ed;
- prev = curr, curr = (struct lpc17_ed_s *)curr->hw.nexted);
-
- /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */
-
- DEBUGASSERT(curr != NULL);
+ /* Remove the ED to the correct list depending on the trasfer type */
- /* Remove the ED from the bulk list */
-
- if (curr != NULL)
+ switch (ed->xfrtype)
{
- /* Is this ED the first on in the bulk list? */
-
- if (prev == NULL)
- {
- /* Yes... set the head of the bulk list to skip over this ED */
-
- lpc17_putreg(ed->hw.nexted, LPC17_USBHOST_BULKHEADED);
-
- /* If the bulk list is now empty, then disable it */
-
- regval = lpc17_getreg(LPC17_USBHOST_CTRL);
- regval &= ~OHCI_CTRL_BLE;
- lpc17_putreg(regval, LPC17_USBHOST_CTRL);
- }
- else
- {
- /* No.. set the forward link of the previous ED in the list
- * skip over this ED.
- */
-
- prev->hw.nexted = ed->hw.nexted;
- }
+ case USB_EP_ATTR_XFER_BULK:
+ ret = lpc17_rembulked(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_INT:
+ ret = lpc17_reminted(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_ISOC:
+ ret = lpc17_remisoced(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_CONTROL:
+ default:
+ ret = -EINVAL;
+ break;
}
/* Destroy the semaphore */
@@ -1412,7 +1592,7 @@ static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
lpc17_edfree(ed);
lpc17_givesem(&priv->exclsem);
- return OK;
+ return ret;
}
/*******************************************************************************