diff options
Diffstat (limited to 'nuttx/drivers/usbdev/composite.c')
-rw-r--r-- | nuttx/drivers/usbdev/composite.c | 933 |
1 files changed, 0 insertions, 933 deletions
diff --git a/nuttx/drivers/usbdev/composite.c b/nuttx/drivers/usbdev/composite.c deleted file mode 100644 index 530d64416..000000000 --- a/nuttx/drivers/usbdev/composite.c +++ /dev/null @@ -1,933 +0,0 @@ -/**************************************************************************** - * drivers/usbdev/composite.c - * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <gnutt@nuttx.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <nuttx/config.h> - -#include <sys/types.h> -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <debug.h> - -#include <nuttx/arch.h> -#include <nuttx/kmalloc.h> -#include <nuttx/usb/usb.h> -#include <nuttx/usb/usbdev.h> -#include <nuttx/usb/usbdev_trace.h> - -#include "composite.h" - -#ifdef CONFIG_USBDEV_COMPOSITE - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* This structure describes the internal state of the driver */ - -struct composite_dev_s -{ - 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 */ - struct usbdevclass_driver_s *dev2; /* Device 2 class object */ -}; - -/* The internal version of the class driver */ - -struct composite_driver_s -{ - struct usbdevclass_driver_s drvr; - FAR struct composite_dev_s *dev; -}; - -/* This is what is allocated */ - -struct composite_alloc_s -{ - struct composite_dev_s dev; - struct composite_driver_s drvr; -}; - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ -/* USB helps ****************************************************************/ - -static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep, - FAR struct usbdev_req_s *req); -static int composite_classsetup(FAR struct composite_dev_s *priv, - FAR struct usbdev_s *dev, - FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, - size_t outlen); -static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep, - uint16_t len); -static void composite_freereq(FAR struct usbdev_ep_s *ep, - FAR struct usbdev_req_s *req); - -/* USB class device ********************************************************/ - -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, FAR uint8_t *dataout, - size_t outlen); -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 - ****************************************************************************/ -/* USB class device *********************************************************/ - -static const struct usbdevclass_driverops_s g_driverops = -{ - composite_bind, /* bind */ - composite_unbind, /* unbind */ - composite_setup, /* setup */ - composite_disconnect, /* disconnect */ - composite_suspend, /* suspend */ - composite_resume, /* resume */ -}; - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -const char g_compvendorstr[] = CONFIG_COMPOSITE_VENDORSTR; -const char g_compproductstr[] = CONFIG_COMPOSITE_PRODUCTSTR; -const char g_compserialstr[] = CONFIG_COMPOSITE_SERIALSTR; - - /**************************************************************************** - * Private Functions - ****************************************************************************/ -/**************************************************************************** - * Helpers - ****************************************************************************/ - -/**************************************************************************** - * Name: composite_ep0incomplete - * - * Description: - * 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); - } -} - -/**************************************************************************** - * Name: composite_classsetup - * - * Description: - * Forward a setup command to the appropriate component device - * - ****************************************************************************/ - -static int composite_classsetup(FAR struct composite_dev_s *priv, - FAR struct usbdev_s *dev, - FAR const struct usb_ctrlreq_s *ctrl, - FAR uint8_t *dataout, size_t outlen) -{ - uint16_t index; - uint8_t interface; - int ret = -EOPNOTSUPP; - - index = GETUINT16(ctrl->index); - interface = (uint8_t)(index & 0xff); - - if (interface >= DEV1_FIRSTINTERFACE && interface < (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES)) - { - ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen); - } - else if (interface >= DEV2_FIRSTINTERFACE && interface < (DEV2_FIRSTINTERFACE + DEV2_NINTERFACES)) - { - ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen); - } - - return ret; -} - -/**************************************************************************** - * Name: composite_allocreq - * - * Description: - * Allocate a request instance along with its buffer - * - ****************************************************************************/ - -static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep, - uint16_t len) -{ - FAR struct usbdev_req_s *req; - - req = EP_ALLOCREQ(ep); - if (req != NULL) - { - req->len = len; - req->buf = EP_ALLOCBUFFER(ep, len); - if (!req->buf) - { - EP_FREEREQ(ep, req); - req = NULL; - } - } - return req; -} - -/**************************************************************************** - * Name: composite_freereq - * - * Description: - * Free a request instance along with its buffer - * - ****************************************************************************/ - -static void composite_freereq(FAR struct usbdev_ep_s *ep, - FAR struct usbdev_req_s *req) -{ - if (ep != NULL && req != NULL) - { - if (req->buf != NULL) - { - EP_FREEBUFFER(ep, req->buf); - } - EP_FREEREQ(ep, req); - } -} - -/**************************************************************************** - * USB Class Driver Methods - ****************************************************************************/ - -/**************************************************************************** - * Name: composite_bind - * - * Description: - * Invoked when the driver is bound to a USB device driver - * - ****************************************************************************/ - -static int composite_bind(FAR struct usbdevclass_driver_s *driver, - FAR struct usbdev_s *dev) -{ - FAR struct composite_dev_s *priv = ((FAR struct composite_driver_s*)driver)->dev; - int ret; - - usbtrace(TRACE_CLASSBIND, 0); - - /* 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 one control request */ - - priv->ctrlreq = composite_allocreq(dev->ep0, COMPOSITE_CFGDESCSIZE); - if (priv->ctrlreq == NULL) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCCTRLREQ), 0); - ret = -ENOMEM; - goto errout; - } - - /* Initialize the pre-allocated control request */ - - priv->ctrlreq->callback = composite_ep0incomplete; - - /* Then bind each of the constituent class drivers */ - - ret = CLASS_BIND(priv->dev1, dev); - if (ret < 0) - { - goto errout; - } - - ret = CLASS_BIND(priv->dev2, dev); - if (ret < 0) - { - goto errout; - } - - /* Report if we are selfpowered */ - -#ifdef CONFIG_USBDEV_SELFPOWERED - DEV_SETSELFPOWERED(dev); -#endif - - /* And pull-up the data line for the soft connect function */ - - DEV_CONNECT(dev); - return OK; - -errout: - composite_unbind(driver, dev); - return ret; -} - -/**************************************************************************** - * Name: composite_unbind - * - * Description: - * Invoked when the driver is unbound from a USB device driver - * - ****************************************************************************/ - -static void composite_unbind(FAR struct usbdevclass_driver_s *driver, - FAR struct usbdev_s *dev) -{ - FAR struct composite_dev_s *priv; - irqstate_t flags; - - usbtrace(TRACE_CLASSUNBIND, 0); - -#ifdef CONFIG_DEBUG - if (!driver || !dev || !dev->ep0) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); - return; - } -#endif - - /* Extract reference to private data */ - - priv = ((FAR struct composite_driver_s*)driver)->dev; - -#ifdef CONFIG_DEBUG - if (!priv) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0); - return; - } -#endif - - /* Make sure that we are not already unbound */ - - if (priv != NULL) - { - /* Unbind the constituent class drivers */ - - flags = irqsave(); - CLASS_UNBIND(priv->dev1, dev); - CLASS_UNBIND(priv->dev2, dev); - - /* Free the pre-allocated control request */ - - priv->config = COMPOSITE_CONFIGIDNONE; - if (priv->ctrlreq != NULL) - { - composite_freereq(dev->ep0, priv->ctrlreq); - priv->ctrlreq = NULL; - } - irqrestore(flags); - } -} - -/**************************************************************************** - * Name: composite_setup - * - * Description: - * Invoked for ep0 control requests. This function probably executes - * in the context of an interrupt handler. - * - ****************************************************************************/ - -static int composite_setup(FAR struct usbdevclass_driver_s *driver, - FAR struct usbdev_s *dev, - FAR const struct usb_ctrlreq_s *ctrl, - FAR uint8_t *dataout, size_t outlen) -{ - FAR struct composite_dev_s *priv; - FAR struct usbdev_req_s *ctrlreq; - uint16_t value; - uint16_t index; - uint16_t len; - bool dispatched = false; - int ret = -EOPNOTSUPP; - -#ifdef CONFIG_DEBUG - if (!driver || !dev || !dev->ep0 || !ctrl) - { - usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_SETUPINVALIDARGS), 0); - return -EIO; - } -#endif - - /* Extract a reference to private data */ - - usbtrace(TRACE_CLASSSETUP, ctrl->req); - priv = ((FAR struct composite_driver_s*)driver)->dev; - -#ifdef CONFIG_DEBUG - if (!priv) - { - usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EP0NOTBOUND2), 0); - return -ENODEV; - } -#endif - ctrlreq = priv->ctrlreq; - - /* Extract the little-endian 16-bit values to host order */ - - value = GETUINT16(ctrl->value); - index = GETUINT16(ctrl->index); - len = GETUINT16(ctrl->len); - - uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n", - ctrl->type, ctrl->req, value, index, len); - - if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) - { - /********************************************************************** - * Standard Requests - **********************************************************************/ - - switch (ctrl->req) - { - case USB_REQ_GETDESCRIPTOR: - { - /* The value field specifies the descriptor type in the MS byte and the - * descriptor index in the LS byte (order is little endian) - */ - - switch (ctrl->value[1]) - { - case USB_DESC_TYPE_DEVICE: - { - ret = USB_SIZEOF_DEVDESC; - memcpy(ctrlreq->buf, composite_getdevdesc(), ret); - } - break; - -#ifdef CONFIG_USBDEV_DUALSPEED - case USB_DESC_TYPE_DEVICEQUALIFIER: - { - ret = USB_SIZEOF_QUALDESC; - memcpy(ctrlreq->buf, composite_getqualdesc(), ret); - } - break; - - case USB_DESC_TYPE_OTHERSPEEDCONFIG: -#endif - - case USB_DESC_TYPE_CONFIG: - { -#ifdef CONFIG_USBDEV_DUALSPEED - ret = composite_mkcfgdesc(ctrlreq->buf, dev->speed, - ctrl->value[1]); -#else - ret = composite_mkcfgdesc(ctrlreq->buf); -#endif - } - break; - - case USB_DESC_TYPE_STRING: - { - /* value == string index. Zero is the language ID. */ - - uint8_t strid = ctrl->value[0]; - FAR struct usb_strdesc_s *buf = (FAR struct usb_strdesc_s *)ctrlreq->buf; - - if (strid <= COMPOSITE_NSTRIDS) - { - ret = composite_mkstrdesc(strid, buf); - } -#if DEV1_NSTRIDS > 0 - else if (strid <= DEV1_STRIDBASE + DEV1_NSTRIDS) - { - ret = DEV1_MKSTRDESC(strid, buf); - } -#endif -#if DEV2_NSTRIDS > 0 - else if (strid <= DEV2_STRIDBASE + DEV2_NSTRIDS) - { - ret = DEV2_MKSTRDESC(strid, buf); - } -#endif - } - break; - - default: - { - usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_GETUNKNOWNDESC), value); - } - break; - } - } - break; - - case USB_REQ_SETCONFIGURATION: - { - if (ctrl->type == 0) - { - /* Save the configuration and inform the constituent classes */ - - ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen); - dispatched = true; - - if (ret >= 0) - { - ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen); - if (ret >= 0) - { - priv->config = value; - } - } - } - } - break; - - case USB_REQ_GETCONFIGURATION: - { - if (ctrl->type == USB_DIR_IN) - { - ctrlreq->buf[0] = priv->config; - ret = 1; - } - } - break; - - case USB_REQ_SETINTERFACE: - { - if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE && - priv->config == COMPOSITE_CONFIGID) - { - ret = composite_classsetup(priv, dev, ctrl, dataout, outlen); - dispatched = true; - } - } - break; - - case USB_REQ_GETINTERFACE: - { - if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) && - priv->config == COMPOSITE_CONFIGIDNONE) - { - ret = composite_classsetup(priv, dev, ctrl, dataout, outlen); - dispatched = true; - } - } - break; - - default: - usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req); - break; - } - } - else - { - uint8_t recipient; - - /********************************************************************** - * Non-Standard Class Requests - **********************************************************************/ - - /* Class implementations should handle there own interface and endpoint - * requests. - */ - - recipient = ctrl->type & USB_REQ_RECIPIENT_MASK; - if (recipient == USB_REQ_RECIPIENT_INTERFACE || recipient == USB_REQ_RECIPIENT_ENDPOINT) - { - ret = composite_classsetup(priv, dev, ctrl, dataout, outlen); - dispatched = true; - } - } - - - /* Respond to the setup command if (1) data was returned, and (2) the request was - * NOT successfully dispatched to the component class driver. On an error return - * value (ret < 0), the USB driver will stall EP0. - */ - - if (ret >= 0 && !dispatched) - { - /* Setup the request */ - - ctrlreq->len = MIN(len, ret); - ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT; - - /* 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); - ctrlreq->result = OK; - composite_ep0incomplete(dev->ep0, ctrlreq); - } - } - - return ret; -} - -/**************************************************************************** - * Name: composite_disconnect - * - * Description: - * Invoked after all transfers have been stopped, when the host is - * disconnected. This function is probably called from the context of an - * interrupt handler. - * - ****************************************************************************/ - -static void composite_disconnect(FAR struct usbdevclass_driver_s *driver, - FAR struct usbdev_s *dev) -{ - FAR struct composite_dev_s *priv; - irqstate_t flags; - - usbtrace(TRACE_CLASSDISCONNECT, 0); - -#ifdef CONFIG_DEBUG - if (!driver || !dev) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); - return; - } -#endif - - /* Extract reference to private data */ - - priv = ((FAR struct composite_driver_s*)driver)->dev; - -#ifdef CONFIG_DEBUG - if (!priv) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0); - return; - } -#endif - - /* Reset the configuration and inform the constituent class drivers of - * the disconnection. - */ - - flags = irqsave(); - priv->config = COMPOSITE_CONFIGIDNONE; - CLASS_DISCONNECT(priv->dev1, dev); - CLASS_DISCONNECT(priv->dev2, dev); - irqrestore(flags); - - /* Perform the soft connect function so that we will we can be - * re-enumerated. - */ - - DEV_CONNECT(dev); -} - -/**************************************************************************** - * Name: composite_suspend - * - * Description: - * Invoked on a USB suspend event. - * - ****************************************************************************/ - -static void composite_suspend(FAR struct usbdevclass_driver_s *driver, - FAR struct usbdev_s *dev) -{ - FAR struct composite_dev_s *priv; - irqstate_t flags; - - usbtrace(TRACE_CLASSSUSPEND, 0); - -#ifdef CONFIG_DEBUG - if (!dev) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); - return; - } -#endif - - /* Extract reference to private data */ - - 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 */ - - flags = irqsave(); - CLASS_SUSPEND(priv->dev1, priv->usbdev); - CLASS_SUSPEND(priv->dev2, priv->usbdev); - irqrestore(flags); -} - -/**************************************************************************** - * Name: composite_resume - * - * Description: - * Invoked on a USB resume event. - * - ****************************************************************************/ - -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; - -#ifdef CONFIG_DEBUG - if (!dev) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0); - return; - } -#endif - - /* Extract reference to private data */ - - 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 */ - - flags = irqsave(); - CLASS_RESUME(priv->dev1, priv->usbdev); - CLASS_RESUME(priv->dev2, priv->usbdev); - irqrestore(flags); -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ -/**************************************************************************** - * Name: composite_initialize - * - * Description: - * Register USB composite device as configured. This function will call - * board-specific implementations in order to obtain the class objects for - * each of the members of the composite (see board_mscclassobject(), - * board_cdcclassobjec(), ...) - * - * Input Parameter: - * None - * - * Returned Value: - * A non-NULL "handle" is returned on success. This handle may be used - * later with composite_uninitialize() in order to removed the composite - * device. This handle is the (untyped) internal representation of the - * the class driver instance. - * - * NULL is returned on any failure. - * - ****************************************************************************/ - -FAR void *composite_initialize(void) -{ - FAR struct composite_alloc_s *alloc; - FAR struct composite_dev_s *priv; - FAR struct composite_driver_s *drvr; - int ret; - - /* Allocate the structures needed */ - - alloc = (FAR struct composite_alloc_s*)kmalloc(sizeof(struct composite_alloc_s)); - if (!alloc) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCDEVSTRUCT), 0); - return NULL; - } - - /* Convenience pointers into the allocated blob */ - - priv = &alloc->dev; - drvr = &alloc->drvr; - - /* Initialize the USB composite driver structure */ - - memset(priv, 0, sizeof(struct composite_dev_s)); - - /* Get the constitueat class driver objects */ - - ret = DEV1_CLASSOBJECT(&priv->dev1); - if (ret < 0) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret); - goto errout_with_alloc; - } - - ret = DEV2_CLASSOBJECT(&priv->dev2); - if (ret < 0) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret); - goto errout_with_alloc; - } - - /* Initialize the USB class driver structure */ - -#ifdef CONFIG_USBDEV_DUALSPEED - drvr->drvr.speed = USB_SPEED_HIGH; -#else - drvr->drvr.speed = USB_SPEED_FULL; -#endif - drvr->drvr.ops = &g_driverops; - drvr->dev = priv; - - /* Register the USB composite class driver */ - - ret = usbdev_register(&drvr->drvr); - if (ret) - { - usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_DEVREGISTER), (uint16_t)-ret); - goto errout_with_alloc; - } - - return (FAR void *)alloc; - -errout_with_alloc: - kfree(alloc); - return NULL; -} - -/**************************************************************************** - * Name: composite_uninitialize - * - * Description: - * Un-initialize the USB composite driver. The handle is the USB composite - * class' device object as was returned by composite_initialize(). This - * function will call board-specific implementations in order to free the - * class objects for each of the members of the composite (see - * board_mscuninitialize(), board_cdcuninitialize(), ...) - * - * Input Parameters: - * handle - The handle returned by a previous call to composite_initialize(). - * - * Returned Value: - * None - * - ***************************************************************************/ - -void composite_uninitialize(FAR void *handle) -{ - FAR struct composite_alloc_s *alloc = (FAR struct composite_alloc_s *)handle; - FAR struct composite_dev_s *priv; - - DEBUGASSERT(alloc != NULL); - - /* Uninitialize each of the member classes */ - - priv = &alloc->dev; - if (priv->dev1) - { - DEV1_UNINITIALIZE(priv->dev1); - priv->dev1 = NULL; - } - - if (priv->dev2) - { - DEV1_UNINITIALIZE(priv->dev2); - priv->dev2 = NULL; - } - - /* Then unregister and destroy the composite class */ - - usbdev_unregister(&alloc->drvr.drvr); - - /* Free any resources used by the composite driver */ - /* None */ - - /* Then free the composite driver state structure itself */ - - kfree(priv); -} - -/**************************************************************************** - * 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 */ |