From caa1beb0c7e4e7c6d6d3b8faad483305bd5640a9 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 26 Jan 2012 17:42:44 +0000 Subject: 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 --- nuttx/drivers/usbdev/cdcacm.c | 77 ++++++++++++++++++------- nuttx/drivers/usbdev/composite.c | 120 +++++++++++++++++++++++++++++---------- nuttx/drivers/usbdev/composite.h | 17 +++++- nuttx/drivers/usbdev/pl2303.c | 119 +++++++++++++++++++++----------------- nuttx/drivers/usbdev/usbmsc.c | 68 ++++++++++++++++------ 5 files changed, 278 insertions(+), 123 deletions(-) (limited to 'nuttx/drivers') 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) -- cgit v1.2.3