summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/lpc17xx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-12-19 19:18:29 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-12-19 19:18:29 +0000
commit25818480a33a52791fc111167e738a3330ce4037 (patch)
tree27ced79550ca710f76de1b5f075746cef7708028 /nuttx/arch/arm/src/lpc17xx
parenta8017c26317f8f47e6684bed887ff8bc3993c5d0 (diff)
downloadpx4-nuttx-25818480a33a52791fc111167e738a3330ce4037.tar.gz
px4-nuttx-25818480a33a52791fc111167e738a3330ce4037.tar.bz2
px4-nuttx-25818480a33a52791fc111167e738a3330ce4037.zip
Add class binding logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3198 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/lpc17xx')
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c142
1 files changed, 140 insertions, 2 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
index c415794b4..8fb4d1df3 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -132,7 +132,7 @@ struct lpc17_usbhost_s
* to structlpc17_usbhost_s.
*/
- struct usbhost_driver_s usbhost;
+ struct usbhost_driver_s drvr;
/* The bound device class driver */
@@ -202,6 +202,14 @@ static void lpc17_enqueuetd(volatile struct lpc17_hced_s *ed, uint32_t dirpid,
uint32_t toggle, volatile uint8_t *buffer,
size_t buflen);
+/* Class helper functions ******************************************************/
+
+static int inline lpc17_configdesc(struct lpc17_usbhost_s *priv,
+ const uint8_t *configdesc, int desclen,
+ struct usbhost_id_s *id);
+static int lpc17_classbind(struct lpc17_usbhost_s *priv,
+ const uint8_t *configdesc, int desclen);
+
/* Interrupt handling **********************************************************/
static int lpc17_usbinterrupt(int irq, FAR void *context);
@@ -236,7 +244,7 @@ static void lpc17_hccainit(volatile struct lpc17_hcca_s *hcca);
static struct lpc17_usbhost_s g_usbhost =
{
- .usbhost =
+ .drvr =
{
.enumerate = lpc17_enumerate,
.alloc = lpc17_alloc,
@@ -440,6 +448,136 @@ static void lpc17_enqueuetd(volatile struct lpc17_hced_s *ed, uint32_t dirpid,
ed->next = 0;
}
+/****************************************************************************
+ * Name: lpc17_classbind
+ *
+ * Description:
+ * A configuration descriptor has been obtained from the device. Find the
+ * ID information for the class that supports this device.
+ *
+ ****************************************************************************/
+
+static inline int
+lpc17_configdesc(struct lpc17_usbhost_s *priv, const uint8_t *configdesc,
+ int desclen, struct usbhost_id_s *id)
+{
+ struct usb_cfgdesc_s *cfgdesc;
+ struct usb_ifdesc_s *ifdesc;
+ int remaining;
+
+ DEBUGASSERT(priv != NULL &&
+ configdesc != NULL &&
+ desclen >= sizeof(struct usb_cfgdesc_s));
+
+ /* Verify that we were passed a configuration descriptor */
+
+ cfgdesc = (struct usb_cfgdesc_s *)configdesc;
+ if (cfgdesc->type != USB_DESC_TYPE_CONFIG)
+ {
+ return -EINVAL;
+ }
+
+ /* Get the total length of the configuration descriptor (little endian).
+ * It might be a good check to get the number of interfaces here too.
+ */
+
+ remaining = (int)lpc17_getle16(cfgdesc->totallen);
+
+ /* Skip to the next entry descriptor */
+
+ configdesc += cfgdesc->len;
+ remaining -= cfgdesc->len;
+
+ /* Loop where there are more dscriptors to examine */
+
+ memset(&id, 0, sizeof(FAR struct usb_desc_s));
+ while (remaining >= sizeof(struct usb_desc_s))
+ {
+ /* What is the next descriptor? Is it an interface descriptor? */
+
+ ifdesc = (struct usb_ifdesc_s *)configdesc;
+ if (ifdesc->type == USB_DESC_TYPE_INTERFACE)
+ {
+ /* Yes, extract the class information from the interface descriptor.
+ * (We are going to need to do more than this here in the future:
+ * ID information might lie elsewhere and we will need the VID and
+ * PID as well).
+ */
+
+ DEBUGASSERT(remaining >= sizeof(struct usb_ifdesc_s));
+ id->base = ifdesc->class;
+ id->subclass = ifdesc->subclass;
+ id->proto = ifdesc->protocol;
+ return OK;
+ }
+
+ /* Increment the address of the next descriptor */
+
+ configdesc += ifdesc->len;
+ remaining -= ifdesc->len;
+ }
+
+ return -ENOENT;
+}
+
+/****************************************************************************
+ * Name: lpc17_classbind
+ *
+ * Description:
+ * A configuration descriptor has been obtained from the device. Try to
+ * bind this configuration descriptor with a supported class.
+ *
+ ****************************************************************************/
+
+static int lpc17_classbind(struct lpc17_usbhost_s *priv,
+ const uint8_t *configdesc, int desclen)
+{
+ struct usbhost_id_s id;
+ int ret;
+
+ DEBUGASSERT(priv && priv->class == NULL);
+
+ /* Get the class identification information for this device. */
+
+ ret = lpc17_configdesc(priv, configdesc, desclen, &id);
+ uvdbg("lpc17_configdesc: %d\n", ret);
+ if (ret)
+ {
+ /* So if there is a class implementation registered to support this
+ * device.
+ */
+
+ ret = -EINVAL;
+ const struct usbhost_registry_s *reg = usbhost_findclass(&id);
+ uvdbg("usbhost_findclass: %p\n", reg);
+ if (reg)
+ {
+ /* Yes.. there is a class for this device. Get an instance of
+ * its interface.
+ */
+
+ ret = -ENOMEM;
+ priv->class = CLASS_CREATE(reg, &priv->drvr, &id);
+ uvdbg("CLASS_CREATE: %p\n", priv->class);
+ if (priv->class)
+ {
+ /* Then initialize the newly instantiated class instance */
+
+ ret = CLASS_CONFIGDESC(priv->class, configdesc, desclen);
+ if (ret != OK)
+ {
+ udbg("CLASS_CONFIGDESC failed: %d\n", ret);
+ CLASS_DISCONNECTED(priv->class);
+ priv->class = NULL;
+ }
+ }
+ }
+ }
+
+ uvdbg("Returning: %d\n", ret);
+ return ret;
+}
+
/*******************************************************************************
* Name: lpc17_usbinterrupt
*