summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-26 17:42:44 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-26 17:42:44 +0000
commitcaa1beb0c7e4e7c6d6d3b8faad483305bd5640a9 (patch)
treee0f215106e62f5a99e6fdd5e44d88fa6dbfcbc57
parent40ff317c5b2da14dfec26a313a3355977c1290e5 (diff)
downloadnuttx-caa1beb0c7e4e7c6d6d3b8faad483305bd5640a9.tar.gz
nuttx-caa1beb0c7e4e7c6d6d3b8faad483305bd5640a9.tar.bz2
nuttx-caa1beb0c7e4e7c6d6d3b8faad483305bd5640a9.zip
Major restructuring of CLASS<->driver interface to better support composite USB devices
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4339 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/drivers/usbdev/cdcacm.c77
-rw-r--r--nuttx/drivers/usbdev/composite.c120
-rw-r--r--nuttx/drivers/usbdev/composite.h17
-rw-r--r--nuttx/drivers/usbdev/pl2303.c119
-rw-r--r--nuttx/drivers/usbdev/usbmsc.c68
-rw-r--r--nuttx/include/nuttx/usb/usbdev.h33
6 files changed, 296 insertions, 138 deletions
diff --git a/nuttx/drivers/usbdev/cdcacm.c b/nuttx/drivers/usbdev/cdcacm.c
index 021136f90..4023d2f2d 100644
--- a/nuttx/drivers/usbdev/cdcacm.c
+++ b/nuttx/drivers/usbdev/cdcacm.c
@@ -63,6 +63,10 @@
#include "cdcacm.h"
+#ifdef CONFIG_USBMSC_COMPOSITE
+# include "composite.h"
+#endif
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -172,14 +176,17 @@ static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
/* USB class device ********************************************************/
-static int cdcacm_bind(FAR struct usbdev_s *dev,
- FAR struct usbdevclass_driver_s *driver);
-static void cdcacm_unbind(FAR struct usbdev_s *dev);
-static int cdcacm_setup(FAR struct usbdev_s *dev,
- const struct usb_ctrlreq_s *ctrl);
-static void cdcacm_disconnect(FAR struct usbdev_s *dev);
+static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl);
+static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
-/* UART Operationt **********************************************************/
+/* UART Operations **********************************************************/
static int cdcuart_setup(FAR struct uart_dev_s *dev);
static void cdcuart_shutdown(FAR struct uart_dev_s *dev);
@@ -732,7 +739,7 @@ errout:
****************************************************************************/
static void cdcacm_ep0incomplete(FAR struct usbdev_ep_s *ep,
- FAR struct usbdev_req_s *req)
+ FAR struct usbdev_req_s *req)
{
if (req->result || req->xfrd != req->len)
{
@@ -878,9 +885,10 @@ static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
*
****************************************************************************/
-static int cdcacm_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
- FAR struct cdcacm_dev_s *priv = ((struct cdcacm_driver_s*)driver)->dev;
+ FAR struct cdcacm_dev_s *priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
FAR struct cdcacm_req_s *reqcontainer;
irqstate_t flags;
uint16_t reqlen;
@@ -892,7 +900,16 @@ static int cdcacm_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
/* Bind the structures */
priv->usbdev = dev;
+
+ /* Save the reference to our private data structure in EP0 so that it
+ * can be recovered in ep0 completion events (Unless we are part of
+ * a composite device and, in that case, the composite device owns
+ * EP0).
+ */
+
+#ifndef CONFIG_USBMSC_COMPOSITE
dev->ep0->priv = priv;
+#endif
/* Preallocate control request */
@@ -1010,7 +1027,7 @@ static int cdcacm_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
return OK;
errout:
- cdcacm_unbind(dev);
+ cdcacm_unbind(driver, dev);
return ret;
}
@@ -1022,7 +1039,8 @@ errout:
*
****************************************************************************/
-static void cdcacm_unbind(FAR struct usbdev_s *dev)
+static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct cdcacm_dev_s *priv;
FAR struct cdcacm_req_s *reqcontainer;
@@ -1032,7 +1050,7 @@ static void cdcacm_unbind(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSUNBIND, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
return;
@@ -1041,7 +1059,7 @@ static void cdcacm_unbind(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct cdcacm_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -1146,7 +1164,9 @@ static void cdcacm_unbind(FAR struct usbdev_s *dev)
*
****************************************************************************/
-static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ctrl)
+static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl)
{
FAR struct cdcacm_dev_s *priv;
FAR struct usbdev_req_s *ctrlreq;
@@ -1156,7 +1176,7 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
int ret = -EOPNOTSUPP;
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0 || !ctrl)
+ if (!driver || !dev || !ctrl)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
return -EIO;
@@ -1166,7 +1186,7 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
/* Extract reference to private data */
usbtrace(TRACE_CLASSSETUP, ctrl->req);
- priv = (FAR struct cdcacm_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv || !priv->ctrlreq)
@@ -1465,9 +1485,21 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
if (ret >= 0)
{
+ /* Configure the response */
+
ctrlreq->len = MIN(len, ret);
ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
- ret = EP_SUBMIT(dev->ep0, ctrlreq);
+
+ /* Send the response -- either directly to the USB controller or
+ * indirectly in the case where this class is a member of a composite
+ * device.
+ */
+
+#ifndef CONFIG_CDCACM_COMPOSITE
+ ret = EP_SUBMIT(dev->ep0, ctrlreq);
+#else
+ ret = composite_ep0submit(driver, dev, ctrlreq);
+#endif
if (ret < 0)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPRESPQ), (uint16_t)-ret);
@@ -1488,7 +1520,8 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
*
****************************************************************************/
-static void cdcacm_disconnect(FAR struct usbdev_s *dev)
+static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct cdcacm_dev_s *priv;
irqstate_t flags;
@@ -1496,7 +1529,7 @@ static void cdcacm_disconnect(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSDISCONNECT, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev || !dev->ep0)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
return;
@@ -1505,7 +1538,7 @@ static void cdcacm_disconnect(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct cdcacm_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -2092,7 +2125,7 @@ void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev)
if (priv->usbdev)
{
- cdcacm_unbind(Fpriv->usbdev);
+ cdcacm_unbind(classdev, priv->usbdev);
}
/* Unregister the driver (unless we are a part of a composite device */
diff --git a/nuttx/drivers/usbdev/composite.c b/nuttx/drivers/usbdev/composite.c
index 75f0fbed1..c689f1b66 100644
--- a/nuttx/drivers/usbdev/composite.c
+++ b/nuttx/drivers/usbdev/composite.c
@@ -67,7 +67,7 @@
struct composite_dev_s
{
- FAR struct usbdev_s *usbdev; /* usbdev driver pointer */
+ FAR struct usbdev_s *usbdev; /* usbdev driver pointer */
uint8_t config; /* Configuration number */
FAR struct usbdev_req_s *ctrlreq; /* Allocated control request */
struct usbdevclass_driver_s *dev1; /* Device 1 class object */
@@ -107,14 +107,19 @@ static void composite_freereq(FAR struct usbdev_ep_s *ep,
/* USB class device ********************************************************/
-static int composite_bind(FAR struct usbdev_s *dev,
- FAR struct usbdevclass_driver_s *driver);
-static void composite_unbind(FAR struct usbdev_s *dev);
-static int composite_setup(FAR struct usbdev_s *dev,
+static int composite_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
+static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static int composite_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
FAR const struct usb_ctrlreq_s *ctrl);
-static void composite_disconnect(FAR struct usbdev_s *dev);
-static void composite_suspend(FAR struct usbdev_s *dev);
-static void composite_resume(FAR struct usbdev_s *dev);
+static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void composite_resume(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
/****************************************************************************
* Private Data
@@ -150,13 +155,15 @@ const char g_compserialstr[] = CONFIG_COMPOSITE_SERIALSTR;
* Name: composite_ep0incomplete
*
* Description:
- * Handle completion of EP0 control operations
+ * Handle completion of the composite driver's EP0 control operations
*
****************************************************************************/
static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep,
FAR struct usbdev_req_s *req)
{
+ /* Just check the result of the transfer */
+
if (req->result || req->xfrd != req->len)
{
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_REQRESULT), (uint16_t)-req->result);
@@ -254,9 +261,10 @@ static void composite_freereq(FAR struct usbdev_ep_s *ep,
*
****************************************************************************/
-static int composite_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int composite_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
- FAR struct composite_dev_s *priv = ((struct composite_driver_s*)driver)->dev;
+ FAR struct composite_dev_s *priv = ((FAR struct composite_driver_s*)driver)->dev;
int ret;
usbtrace(TRACE_CLASSBIND, 0);
@@ -264,9 +272,14 @@ static int composite_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_drive
/* Bind the structures */
priv->usbdev = dev;
+
+ /* Save the reference to our private data structure in EP0 so that it
+ * can be recovered in ep0 completion events.
+ */
+
dev->ep0->priv = priv;
- /* Preallocate control request */
+ /* Preallocate one control request */
priv->ctrlreq = composite_allocreq(dev->ep0, COMPOSITE_CFGDESCSIZE);
if (priv->ctrlreq == NULL)
@@ -318,7 +331,8 @@ errout:
*
****************************************************************************/
-static void composite_unbind(FAR struct usbdev_s *dev)
+static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct composite_dev_s *priv;
irqstate_t flags;
@@ -326,7 +340,7 @@ static void composite_unbind(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSUNBIND, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev || !dev->ep0)
{
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
return;
@@ -335,7 +349,7 @@ static void composite_unbind(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct composite_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -376,7 +390,8 @@ static void composite_unbind(FAR struct usbdev_s *dev)
*
****************************************************************************/
-static int composite_setup(FAR struct usbdev_s *dev,
+static int composite_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
FAR const struct usb_ctrlreq_s *ctrl)
{
FAR struct composite_dev_s *priv;
@@ -388,7 +403,7 @@ static int composite_setup(FAR struct usbdev_s *dev,
int ret = -EOPNOTSUPP;
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0 || !ctrl)
+ if (!driver || !dev || !dev->ep0 || !ctrl)
{
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_SETUPINVALIDARGS), 0);
return -EIO;
@@ -398,7 +413,7 @@ static int composite_setup(FAR struct usbdev_s *dev,
/* Extract a reference to private data */
usbtrace(TRACE_CLASSSETUP, ctrl->req);
- priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct composite_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -562,9 +577,14 @@ static int composite_setup(FAR struct usbdev_s *dev,
if (ret >= 0 && !dispatched)
{
+ /* Setup the request */
+
ctrlreq->len = MIN(len, ret);
ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
- ret = EP_SUBMIT(dev->ep0, ctrlreq);
+
+ /* And submit the request to the USB controller driver */
+
+ ret = EP_SUBMIT(dev->ep0, ctrlreq);
if (ret < 0)
{
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EPRESPQ), (uint16_t)-ret);
@@ -585,7 +605,8 @@ static int composite_setup(FAR struct usbdev_s *dev,
*
****************************************************************************/
-static void composite_disconnect(FAR struct usbdev_s *dev)
+static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct composite_dev_s *priv;
irqstate_t flags;
@@ -593,7 +614,7 @@ static void composite_disconnect(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSDISCONNECT, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev)
{
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
return;
@@ -602,7 +623,7 @@ static void composite_disconnect(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct composite_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -637,7 +658,8 @@ static void composite_disconnect(FAR struct usbdev_s *dev)
*
****************************************************************************/
-static void composite_suspend(FAR struct usbdev_s *dev)
+static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct composite_dev_s *priv;
irqstate_t flags;
@@ -645,7 +667,7 @@ static void composite_suspend(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSSUSPEND, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0 || !dev->ep0->priv)
+ if (!dev)
{
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
return;
@@ -654,7 +676,15 @@ static void composite_suspend(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct composite_driver_s*)driver)->dev;
+
+#ifdef CONFIG_DEBUG
+ if (!priv)
+ {
+ usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
+ return;
+ }
+#endif
/* Forward the suspend event to the constituent devices */
@@ -672,15 +702,14 @@ static void composite_suspend(FAR struct usbdev_s *dev)
*
****************************************************************************/
-static void composite_resume(FAR struct usbdev_s *dev)
+static void composite_resume(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct composite_dev_s *priv = NULL;
irqstate_t flags;
- if (!dev || !dev->ep0 || !dev->ep0->priv)
-
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!dev)
{
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
return;
@@ -689,7 +718,15 @@ static void composite_resume(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct composite_driver_s*)driver)->dev;
+
+#ifdef CONFIG_DEBUG
+ if (!priv)
+ {
+ usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
+ return;
+ }
+#endif
/* Forward the resume event to the constituent devices */
@@ -784,4 +821,27 @@ errout_with_alloc:
return ret;
}
+/****************************************************************************
+ * Name: composite_ep0submit
+ *
+ * Description:
+ * Members of the composite cannot send on EP0 directly because EP0 is
+ * is "owned" by the composite device. Instead, when configured as members
+ * of a composite device, those classes should call this method so that
+ * the composite device can send on EP0 onbehalf of the class.
+ *
+ ****************************************************************************/
+
+int composite_ep0submit(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
+ FAR struct usbdev_req_s *ctrlreq)
+{
+ /* This function is not really necessary in the current design. However,
+ * keeping this will provide us a little flexibility in the future if
+ * it becomes necessary to manage the completion callbacks.
+ */
+
+ return EP_SUBMIT(dev->ep0, ctrlreq);
+}
+
#endif /* CONFIG_USBDEV_COMPOSITE */
diff --git a/nuttx/drivers/usbdev/composite.h b/nuttx/drivers/usbdev/composite.h
index 114754ec4..4cd3ac606 100644
--- a/nuttx/drivers/usbdev/composite.h
+++ b/nuttx/drivers/usbdev/composite.h
@@ -253,7 +253,22 @@ extern const char g_compserialstr[];
****************************************************************************/
/****************************************************************************
- * Name: usbmsc_mkstrdesc
+ * Name: composite_ep0submit
+ *
+ * Description:
+ * Members of the composite cannot send on EP0 directly because EP0 is
+ * is "owned" by the composite device. Instead, when configured as members
+ * of a composite device, those classes should call this method so that
+ * the composite device can send on EP0 onbehalf of the class.
+ *
+ ****************************************************************************/
+
+int composite_ep0submit(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
+ FAR struct usbdev_req_s *ctrlreq);
+
+/****************************************************************************
+ * Name: composite_mkstrdesc
*
* Description:
* Construct a string descriptor
diff --git a/nuttx/drivers/usbdev/pl2303.c b/nuttx/drivers/usbdev/pl2303.c
index 9759b714d..81c3376dc 100644
--- a/nuttx/drivers/usbdev/pl2303.c
+++ b/nuttx/drivers/usbdev/pl2303.c
@@ -303,7 +303,7 @@ static inline int usbclass_recvpacket(FAR struct pl2303_dev_s *priv,
/* Request helpers *********************************************************/
-static struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep,
+static struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep,
uint16_t len);
static void usbclass_freereq(FAR struct usbdev_ep_s *ep,
FAR struct usbdev_req_s *req);
@@ -333,22 +333,25 @@ static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep,
/* USB class device ********************************************************/
-static int usbclass_bind(FAR struct usbdev_s *dev,
- FAR struct usbdevclass_driver_s *driver);
-static void usbclass_unbind(FAR struct usbdev_s *dev);
-static int usbclass_setup(FAR struct usbdev_s *dev,
- const struct usb_ctrlreq_s *ctrl);
-static void usbclass_disconnect(FAR struct usbdev_s *dev);
+static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl);
+static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
/* Serial port *************************************************************/
-static int pl2303_setup(FAR struct uart_dev_s *dev);
-static void pl2303_shutdown(FAR struct uart_dev_s *dev);
-static int pl2303_attach(FAR struct uart_dev_s *dev);
-static void pl2303_detach(FAR struct uart_dev_s *dev);
-static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable);
-static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable);
-static bool pl2303_txempty(FAR struct uart_dev_s *dev);
+static int usbser_setup(FAR struct uart_dev_s *dev);
+static void usbser_shutdown(FAR struct uart_dev_s *dev);
+static int usbser_attach(FAR struct uart_dev_s *dev);
+static void usbser_detach(FAR struct uart_dev_s *dev);
+static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable);
+static void usbser_txint(FAR struct uart_dev_s *dev, bool enable);
+static bool usbser_txempty(FAR struct uart_dev_s *dev);
/****************************************************************************
* Private Variables
@@ -370,18 +373,18 @@ static const struct usbdevclass_driverops_s g_driverops =
static const struct uart_ops_s g_uartops =
{
- pl2303_setup, /* setup */
- pl2303_shutdown, /* shutdown */
- pl2303_attach, /* attach */
- pl2303_detach, /* detach */
+ usbser_setup, /* setup */
+ usbser_shutdown, /* shutdown */
+ usbser_attach, /* attach */
+ usbser_detach, /* detach */
NULL, /* ioctl */
NULL, /* receive */
- pl2303_rxint, /* rxinit */
+ usbser_rxint, /* rxinit */
NULL, /* rxavailable */
NULL, /* send */
- pl2303_txint, /* txinit */
+ usbser_txint, /* txinit */
NULL, /* txready */
- pl2303_txempty /* txempty */
+ usbser_txempty /* txempty */
};
/* USB descriptor templates these will be copied and modified **************/
@@ -1265,9 +1268,10 @@ static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep,
*
****************************************************************************/
-static int usbclass_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
- FAR struct pl2303_dev_s *priv = ((struct pl2303_driver_s*)driver)->dev;
+ FAR struct pl2303_dev_s *priv = ((FAR struct pl2303_driver_s*)driver)->dev;
FAR struct pl2303_req_s *reqcontainer;
irqstate_t flags;
uint16_t reqlen;
@@ -1279,6 +1283,13 @@ static int usbclass_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver
/* Bind the structures */
priv->usbdev = dev;
+
+ /* Save the reference to our private data structure in EP0 so that it
+ * can be recovered in ep0 completion events (Unless we are part of
+ * a composite device and, in that case, the composite device owns
+ * EP0).
+ */
+
dev->ep0->priv = priv;
/* Preallocate control request */
@@ -1393,7 +1404,7 @@ static int usbclass_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver
return OK;
errout:
- usbclass_unbind(dev);
+ usbclass_unbind(driver, dev);
return ret;
}
@@ -1405,7 +1416,8 @@ errout:
*
****************************************************************************/
-static void usbclass_unbind(FAR struct usbdev_s *dev)
+static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct pl2303_dev_s *priv;
FAR struct pl2303_req_s *reqcontainer;
@@ -1415,7 +1427,7 @@ static void usbclass_unbind(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSUNBIND, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev || !dev->ep0)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
return;
@@ -1424,7 +1436,7 @@ static void usbclass_unbind(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct pl2303_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct pl2303_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -1529,7 +1541,9 @@ static void usbclass_unbind(FAR struct usbdev_s *dev)
*
****************************************************************************/
-static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ctrl)
+static int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl)
{
FAR struct pl2303_dev_s *priv;
FAR struct usbdev_req_s *ctrlreq;
@@ -1539,7 +1553,7 @@ static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *
int ret = -EOPNOTSUPP;
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0 || !ctrl)
+ if (!driver || !dev || !dev->ep0 || !ctrl)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
return -EIO;
@@ -1549,7 +1563,7 @@ static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *
/* Extract reference to private data */
usbtrace(TRACE_CLASSSETUP, ctrl->req);
- priv = (FAR struct pl2303_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct pl2303_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv || !priv->ctrlreq)
@@ -1791,7 +1805,8 @@ static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *
*
****************************************************************************/
-static void usbclass_disconnect(FAR struct usbdev_s *dev)
+static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct pl2303_dev_s *priv;
irqstate_t flags;
@@ -1799,7 +1814,7 @@ static void usbclass_disconnect(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSDISCONNECT, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev || !dev->ep0)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
return;
@@ -1808,7 +1823,7 @@ static void usbclass_disconnect(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct pl2303_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct pl2303_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -1841,14 +1856,14 @@ static void usbclass_disconnect(FAR struct usbdev_s *dev)
****************************************************************************/
/****************************************************************************
- * Name: pl2303_setup
+ * Name: usbser_setup
*
* Description:
* This method is called the first time that the serial port is opened.
*
****************************************************************************/
-static int pl2303_setup(FAR struct uart_dev_s *dev)
+static int usbser_setup(FAR struct uart_dev_s *dev)
{
FAR struct pl2303_dev_s *priv;
@@ -1880,18 +1895,18 @@ static int pl2303_setup(FAR struct uart_dev_s *dev)
}
/****************************************************************************
- * Name: pl2303_shutdown
+ * Name: usbser_shutdown
*
* Description:
* This method is called when the serial port is closed. This operation
* is very simple for the USB serial backend because the serial driver
* has already assured that the TX data has full drained -- it calls
- * pl2303_txempty() until that function returns true before calling this
+ * usbser_txempty() until that function returns true before calling this
* function.
*
****************************************************************************/
-static void pl2303_shutdown(FAR struct uart_dev_s *dev)
+static void usbser_shutdown(FAR struct uart_dev_s *dev)
{
usbtrace(PL2303_CLASSASPI_SHUTDOWN, 0);
@@ -1906,50 +1921,50 @@ static void pl2303_shutdown(FAR struct uart_dev_s *dev)
}
/****************************************************************************
- * Name: pl2303_attach
+ * Name: usbser_attach
*
* Description:
* Does not apply to the USB serial class device
*
****************************************************************************/
-static int pl2303_attach(FAR struct uart_dev_s *dev)
+static int usbser_attach(FAR struct uart_dev_s *dev)
{
usbtrace(PL2303_CLASSASPI_ATTACH, 0);
return OK;
}
/****************************************************************************
- * Name: pl2303_detach
+ * Name: usbser_detach
*
* Description:
* Does not apply to the USB serial class device
*
****************************************************************************/
-static void pl2303_detach(FAR struct uart_dev_s *dev)
+static void usbser_detach(FAR struct uart_dev_s *dev)
{
usbtrace(PL2303_CLASSASPI_DETACH, 0);
}
/****************************************************************************
- * Name: pl2303_rxint
+ * Name: usbser_rxint
*
* Description:
* Called by the serial driver to enable or disable RX interrupts. We, of
* course, have no RX interrupts but must behave consistently. This method
* is called under the conditions:
*
- * 1. With enable==true when the port is opened (just after pl2303_setup
- * and pl2303_attach are called called)
+ * 1. With enable==true when the port is opened (just after usbser_setup
+ * and usbser_attach are called called)
* 2. With enable==false while transferring data from the RX buffer
* 2. With enable==true while waiting for more incoming data
- * 3. With enable==false when the port is closed (just before pl2303_detach
- * and pl2303_shutdown are called).
+ * 3. With enable==false when the port is closed (just before usbser_detach
+ * and usbser_shutdown are called).
*
****************************************************************************/
-static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable)
+static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable)
{
FAR struct pl2303_dev_s *priv;
FAR uart_dev_t *serdev;
@@ -2029,7 +2044,7 @@ static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable)
}
/****************************************************************************
- * Name: pl2303_txint
+ * Name: usbser_txint
*
* Description:
* Called by the serial driver to enable or disable TX interrupts. We, of
@@ -2042,7 +2057,7 @@ static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable)
*
****************************************************************************/
-static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable)
+static void usbser_txint(FAR struct uart_dev_s *dev, bool enable)
{
FAR struct pl2303_dev_s *priv;
@@ -2076,7 +2091,7 @@ static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable)
}
/****************************************************************************
- * Name: pl2303_txempty
+ * Name: usbser_txempty
*
* Description:
* Return true when all data has been sent. This is called from the
@@ -2087,7 +2102,7 @@ static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable)
*
****************************************************************************/
-static bool pl2303_txempty(FAR struct uart_dev_s *dev)
+static bool usbser_txempty(FAR struct uart_dev_s *dev)
{
FAR struct pl2303_dev_s *priv = (FAR struct pl2303_dev_s*)dev->priv;
diff --git a/nuttx/drivers/usbdev/usbmsc.c b/nuttx/drivers/usbdev/usbmsc.c
index e99342abc..3efa1e3db 100644
--- a/nuttx/drivers/usbdev/usbmsc.c
+++ b/nuttx/drivers/usbdev/usbmsc.c
@@ -82,6 +82,10 @@
#include "usbmsc.h"
+#ifdef CONFIG_USBMSC_COMPOSITE
+# include "composite.h"
+#endif
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -121,12 +125,15 @@ static void usbmsc_freereq(FAR struct usbdev_ep_s *ep,
/* Class Driver Operations (most at interrupt level) ************************/
-static int usbmsc_bind(FAR struct usbdev_s *dev,
- FAR struct usbdevclass_driver_s *driver);
-static void usbmsc_unbind(FAR struct usbdev_s *dev);
-static int usbmsc_setup(FAR struct usbdev_s *dev,
+static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
FAR const struct usb_ctrlreq_s *ctrl);
-static void usbmsc_disconnect(FAR struct usbdev_s *dev);
+static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
/* Initialization/Uninitialization ******************************************/
@@ -235,9 +242,10 @@ static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
*
****************************************************************************/
-static int usbmsc_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
- FAR struct usbmsc_dev_s *priv = ((struct usbmsc_driver_s*)driver)->dev;
+ FAR struct usbmsc_dev_s *priv = ((FAR struct usbmsc_driver_s*)driver)->dev;
FAR struct usbmsc_req_s *reqcontainer;
irqstate_t flags;
int ret = OK;
@@ -248,7 +256,16 @@ static int usbmsc_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
/* Bind the structures */
priv->usbdev = dev;
+
+ /* Save the reference to our private data structure in EP0 so that it
+ * can be recovered in ep0 completion events (Unless we are part of
+ * a composite device and, in that case, the composite device owns
+ * EP0).
+ */
+
+#ifndef CONFIG_USBMSC_COMPOSITE
dev->ep0->priv = priv;
+#endif
/* The configured EP0 size should match the reported EP0 size. We could
* easily adapt to the reported EP0 size, but then we could not use the
@@ -351,7 +368,7 @@ static int usbmsc_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
return OK;
errout:
- usbmsc_unbind(dev);
+ usbmsc_unbind(driver, dev);
return ret;
}
@@ -363,7 +380,8 @@ errout:
*
****************************************************************************/
-static void usbmsc_unbind(FAR struct usbdev_s *dev)
+static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
FAR struct usbmsc_dev_s *priv;
FAR struct usbmsc_req_s *reqcontainer;
@@ -373,7 +391,7 @@ static void usbmsc_unbind(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSUNBIND, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev || !dev->ep0)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDINVALIDARGS), 0);
return;
@@ -382,7 +400,7 @@ static void usbmsc_unbind(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct usbmsc_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct usbmsc_driver_s*)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
@@ -477,7 +495,8 @@ static void usbmsc_unbind(FAR struct usbdev_s *dev)
*
****************************************************************************/
-static int usbmsc_setup(FAR struct usbdev_s *dev,
+static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev,
FAR const struct usb_ctrlreq_s *ctrl)
{
FAR struct usbmsc_dev_s *priv;
@@ -488,7 +507,7 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
int ret = -EOPNOTSUPP;
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0 || !ctrl)
+ if (!driver || !dev || !dev->ep0 || !ctrl)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SETUPINVALIDARGS), 0);
return -EIO;
@@ -498,7 +517,7 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
/* Extract reference to private data */
usbtrace(TRACE_CLASSSETUP, ctrl->req);
- priv = (FAR struct usbmsc_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv || !priv->ctrlreq)
@@ -763,9 +782,21 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
if (ret >= 0)
{
+ /* Configure the response */
+
ctrlreq->len = MIN(len, ret);
ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
- ret = EP_SUBMIT(dev->ep0, ctrlreq);
+
+ /* Send the response -- either directly to the USB controller or
+ * indirectly in the case where this class is a member of a composite
+ * device.
+ */
+
+#ifndef CONFIG_USBMSC_COMPOSITE
+ ret = EP_SUBMIT(dev->ep0, ctrlreq);
+#else
+ ret = composite_ep0submit(driver, dev, ctrlreq);
+#endif
if (ret < 0)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPRESPQ), (uint16_t)-ret);
@@ -789,7 +820,8 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
*
****************************************************************************/
-static void usbmsc_disconnect(FAR struct usbdev_s *dev)
+static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
{
struct usbmsc_dev_s *priv;
irqstate_t flags;
@@ -797,7 +829,7 @@ static void usbmsc_disconnect(FAR struct usbdev_s *dev)
usbtrace(TRACE_CLASSDISCONNECT, 0);
#ifdef CONFIG_DEBUG
- if (!dev || !dev->ep0)
+ if (!driver || !dev || !dev->ep0)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DISCONNECTINVALIDARGS), 0);
return;
@@ -806,7 +838,7 @@ static void usbmsc_disconnect(FAR struct usbdev_s *dev)
/* Extract reference to private data */
- priv = (FAR struct usbmsc_dev_s *)dev->ep0->priv;
+ priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
#ifdef CONFIG_DEBUG
if (!priv)
diff --git a/nuttx/include/nuttx/usb/usbdev.h b/nuttx/include/nuttx/usb/usbdev.h
index 8e89eddab..a727573c3 100644
--- a/nuttx/include/nuttx/usb/usbdev.h
+++ b/nuttx/include/nuttx/usb/usbdev.h
@@ -1,8 +1,8 @@
/************************************************************************************
* include/nuttx/usb/usbdev.h
*
- * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* NOTE: This interface was inspired by the Linux gadget interface by
* David Brownell. That work was very helpful in determining a usable
@@ -151,29 +151,29 @@
/* Invoked when the driver is bound to a USB device driver. */
-#define CLASS_BIND(drvr,dev) (drvr)->ops->bind(dev, drvr)
+#define CLASS_BIND(drvr,dev) (drvr)->ops->bind(drvr,dev)
/* Invoked when the driver is unbound from a USB device driver */
-#define CLASS_UNBIND(drvr,dev) (drvr)->ops->unbind(dev)
+#define CLASS_UNBIND(drvr,dev) (drvr)->ops->unbind(drvr,dev)
/* Invoked after all transfers have been stopped, when the host is disconnected. */
-#define CLASS_DISCONNECT(drvr,dev) (drvr)->ops->disconnect(dev)
+#define CLASS_DISCONNECT(drvr,dev) (drvr)->ops->disconnect(drvr,dev)
/* Invoked for ep0 control requests */
-#define CLASS_SETUP(drvr,dev,ctrl) (drvr)->ops->setup(dev, ctrl)
+#define CLASS_SETUP(drvr,dev,ctrl) (drvr)->ops->setup(drvr,dev,ctrl)
/* Invoked on USB suspend. */
#define CLASS_SUSPEND(drvr,dev) \
- do { if ((drvr)->ops->suspend) (drvr)->ops->suspend(dev); } while (0)
+ do { if ((drvr)->ops->suspend) (drvr)->ops->suspend(drvr,dev); } while (0)
/* Invoked on USB resume */
#define CLASS_RESUME(drvr,dev) \
- do { if ((drvr)->ops->resume) (drvr)->ops->resume(dev); } while (0)
+ do { if ((drvr)->ops->resume) (drvr)->ops->resume(drvr,dev); } while (0)
/* Device speeds */
@@ -260,7 +260,8 @@ struct usbdev_ops_s
{
/* Allocate and free endpoints */
- FAR struct usbdev_ep_s *(*allocep)(FAR struct usbdev_s *dev, uint8_t epphy, bool in, uint8_t eptype);
+ FAR struct usbdev_ep_s *(*allocep)(FAR struct usbdev_s *dev, uint8_t epphy,
+ bool in, uint8_t eptype);
void (*freeep)(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep);
/* Get the frame number from the last SOF */
@@ -291,12 +292,14 @@ struct usbdev_s
struct usbdevclass_driver_s;
struct usbdevclass_driverops_s
{
- int (*bind)(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver);
- void (*unbind)(FAR struct usbdev_s *dev);
- int (*setup)(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ctrl);
- void (*disconnect)(FAR struct usbdev_s *dev);
- void (*suspend)(FAR struct usbdev_s *dev);
- void (*resume)(FAR struct usbdev_s *dev);
+ int (*bind)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+ void (*unbind)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+ int (*setup)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl);
+ void (*disconnect)(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+ void (*suspend)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+ void (*resume)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
};
struct usbdevclass_driver_s