From 56991a648db670d4696e3cdeda9e6f3d513c95b8 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Mon, 20 Dec 2010 21:48:16 +0000
Subject: [PATCH] Finishes first cut

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3202 42af7a65-404d-4744-a932-0658087f49c3
---
 arch/arm/src/lpc17xx/lpc17_usbhost.c | 188 ++++++++++++++++++++++++---
 1 file changed, 171 insertions(+), 17 deletions(-)

diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c
index d2bc45dde4..fb2b4f9bfa 100755
--- a/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -112,14 +112,6 @@
 
 #define TD_DELAY(n) (uint32_t)((n) << GTD_STATUS_DI_SHIFT)
 
-/* Debug ***********************************************************************/
-
-/* Trace error codes */
-#warning "To be provided"
-
-/* Trace interrupt codes */
-#warning "To be provided"
-
 /*******************************************************************************
  * Private Types
  *******************************************************************************/
@@ -912,8 +904,159 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
 
 static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
 {
-# warning "Not Implemented"
-  return -ENOSYS;
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  struct usb_ctrlreq_s *ctrlreq;
+  unsigned int len;
+  uint8_t *td;
+  int  ret;
+
+  ulldbg("Enumerate device\n");
+
+  /* Allocate a TD buffer for use in this function */
+
+  td = lpc17_tdalloc(priv);
+  if (!td)
+    {
+      return -ENOMEM;
+    }
+  ctrlreq = (struct usb_ctrlreq_s *)td;
+
+  /* Are we already connected? */
+
+  while (!priv->connected)
+    {
+      /* No, wait for the connection */
+
+      lpc17_takesem(&priv->rhssem);
+    }
+
+  /* USB 2.0 spec says at least 50ms delay before port reset */
+
+  up_mdelay(100);
+
+  /* Put the RH port in reset */
+
+  lpc17_putreg(OHCI_RHPORTST_PRS, LPC17_USBHOST_RHPORTST1);
+
+  /* Wait for the port reset to complete */
+
+  while ((lpc17_getreg(LPC17_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0);
+
+  /* Release the RH port from reset and wait a bit */
+
+  lpc17_putreg(OHCI_RHPORTST_PRSC, LPC17_USBHOST_RHPORTST1);
+  up_mdelay(200);
+
+  /* Set max pkt size = 8 */
+
+  EDCTRL->ctrl = 8 << ED_CONTROL_MPS_SHIFT;
+
+  /* Read first 8 bytes of the device descriptor */
+
+  ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE;
+  ctrlreq->req  = USB_REQ_GETDESCRIPTOR;
+  lpc17_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8));
+  lpc17_putle16(ctrlreq->index, 0);
+  lpc17_putle16(ctrlreq->len, 8);
+
+  ret = lpc17_ctrlin(drvr, ctrlreq, td);
+  if (ret != OK)
+    {
+      ulldbg("ERROR: lpc17_ctrlin returned %d\n", ret);
+      goto errout;
+    }
+
+  /* Extract the max packetsize for endpoint 0 */
+
+  EDCTRL->ctrl = (uint32_t)(((struct usb_devdesc_s *)td)->mxpacketsize) << ED_CONTROL_MPS_SHIFT;
+
+  /* Set the device address to 1 */
+
+  ctrlreq->type = USB_REQ_DIR_OUT|USB_REQ_RECIPIENT_DEVICE;
+  ctrlreq->req  = USB_REQ_SETADDRESS;
+  lpc17_putle16(ctrlreq->value, (1 << 8));
+  lpc17_putle16(ctrlreq->index, 0);
+  lpc17_putle16(ctrlreq->len, 0);
+
+  ret = lpc17_ctrlout(drvr, ctrlreq, NULL);
+  if (ret != OK)
+    {
+      ulldbg("ERROR: lpc17_ctrlout returned %d\n", ret);
+      goto errout;
+    }
+  up_mdelay(2);
+
+  /* Modify control pipe with address 1 */
+
+  EDCTRL->ctrl = (EDCTRL->ctrl) | 1;
+
+ /* Get the configuration descriptor (only) */
+
+  ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE;
+  ctrlreq->req  = USB_REQ_GETDESCRIPTOR;
+  lpc17_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8));
+  lpc17_putle16(ctrlreq->index, 0);
+  lpc17_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC);
+
+  ret = lpc17_ctrlin(drvr, ctrlreq, td);
+  if (ret != OK)
+   {
+      ulldbg("ERROR: lpc17_ctrlin returned %d\n", ret);
+      goto errout;
+    }
+
+  /* Extract the full size of the configuration data */
+
+  len = ((struct usb_cfgdesc_s *)td)->len;
+
+  /* Get all of the configuration data */
+
+  ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_DEVICE;
+  ctrlreq->req  = USB_REQ_GETDESCRIPTOR;
+  lpc17_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8));
+  lpc17_putle16(ctrlreq->index, 0);
+  lpc17_putle16(ctrlreq->len, len);
+
+  ret = lpc17_ctrlin(drvr, ctrlreq, td);
+  if (ret != OK)
+    {
+      ulldbg("ERROR: lpc17_ctrlin returned %d\n", ret);
+      goto errout;
+    }
+
+  /* Parse the configuration descriptor and bind to the class instance for the
+   * device.
+   */
+
+  ret = lpc17_classbind(priv, td, len);
+  if (ret != OK)
+    {
+      ulldbg("ERROR: MS_ParseConfiguration returned %d\n", ret);
+      goto errout;
+    }
+
+  /* Select device configuration 1 */
+
+  ctrlreq->type = USB_REQ_DIR_OUT|USB_REQ_RECIPIENT_DEVICE;
+  ctrlreq->req  = USB_REQ_SETCONFIGURATION;
+  lpc17_putle16(ctrlreq->value, 1);
+  lpc17_putle16(ctrlreq->index, 0);
+  lpc17_putle16(ctrlreq->len, 0);
+
+  ret = lpc17_ctrlout(drvr, ctrlreq, NULL);
+  if (ret != OK)
+    {
+      ulldbg("ERROR: lpc17_ctrlout returned %d\n", ret);
+      goto errout;
+    }
+
+  /* Some devices may require this delay */
+
+  up_mdelay(100);
+
+errout:
+  lpc17_tdfree(priv, td);
+  return ret;
 }
 
 /*******************************************************************************
@@ -942,11 +1085,19 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
  *
  *******************************************************************************/
 
- static int lpc17_alloc(FAR struct usbhost_driver_s *drvr,
-                        FAR uint8_t **buffer, FAR size_t *maxlen)
+static int lpc17_alloc(FAR struct usbhost_driver_s *drvr,
+                       FAR uint8_t **buffer, FAR size_t *maxlen)
 {
-# warning "Not Implemented"
-  return -ENOSYS;
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  DEBUGASSERT(priv && buffer && maxlen);
+
+  *buffer = lpc17_tdalloc(priv);
+  if (*buffer)
+    {
+      *maxlen = CONFIG_USBHOST_TDBUFSIZE;
+      return OK;
+    }
+  return -ENOMEM;
 }
 
 /*******************************************************************************
@@ -974,8 +1125,10 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
 
 static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
 {
-# warning "Not Implemented"
-  return -ENOSYS;
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  DEBUGASSERT(priv && buffer);
+  lpc17_tdfree(priv, buffer);
+  return OK;
 }
 
 /*******************************************************************************
@@ -1179,7 +1332,8 @@ static int lpc17_transfer(FAR struct usbhost_driver_s *drvr,
 
 static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr)
 {
-# warning "Not Implemented"
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  priv->class = NULL;
 }
   
 /*******************************************************************************
-- 
GitLab