예제 #1
0
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 *)kmm_malloc(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:
  kmm_free(alloc);
  return NULL;
}
예제 #2
0
파일: stm32_usbdev.c 프로젝트: a1ien/nuttx
int stm32_usbpullup(FAR struct usbdev_s *dev, bool enable)
{
    usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
    stm32_gpiowrite(GPIO_USB_PULLUP, !enable);
    return OK;
}
예제 #3
0
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;
}
예제 #4
0
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(USBCOMPOSITE_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(USBCOMPOSITE_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);
  UNUSED(index);

  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(USBCOMPOSITE_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(USBCOMPOSITE_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(USBCOMPOSITE_TRACEERR_EPRESPQ), (uint16_t)-ret);
          ctrlreq->result = OK;
          composite_ep0incomplete(dev->ep0, ctrlreq);
        }
    }

  return ret;
}
예제 #5
0
int kinetis_usbpullup(FAR struct usbdev_s *dev, bool enable)
{
  usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
# warning "Missing logic"
  return OK;
}
예제 #6
0
파일: apb-es1.c 프로젝트: KimMui/GDMAC
static int usbclass_bind(struct usbdevclass_driver_s *driver,
                         struct usbdev_s *dev)
{
    struct apbridge_dev_s *priv = ((struct apbridge_driver_s *)driver)->dev;
    struct apbridge_req_s *reqcontainer;
    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 (Unless we are part of
     * a composite device and, in that case, the composite device owns
     * EP0).
     */

    dev->ep0->priv = priv;

    /* Preallocate control request */

    priv->ctrlreq = usbclass_allocreq(dev->ep0, APBRIDGE_MXDESCLEN);
    if (priv->ctrlreq == NULL) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALLOCCTRLREQ), 0);
        ret = -ENOMEM;
        goto errout;
    }
    priv->ctrlreq->callback = usbclass_ep0incomplete;

    /* Pre-allocate all endpoints... the endpoints will not be functional
     * until the SET CONFIGURATION request is processed in usbclass_setconfig.
     * This is done here because there may be calls to kmm_malloc and the SET
     * CONFIGURATION processing probably occurrs within interrupt handling
     * logic where kmm_malloc calls will fail.
     */

    /* Pre-allocate the IN interrupt endpoint */

    priv->epintin =
        DEV_ALLOCEP(dev, APBRIDGE_EPINTIN_ADDR, true, USB_EP_ATTR_XFER_INT);
    if (!priv->epintin) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINALLOCFAIL), 0);
        ret = -ENODEV;
        goto errout;
    }
    priv->epintin->priv = priv;

    /* Pre-allocate the IN bulk endpoint */

    priv->epbulkin =
        DEV_ALLOCEP(dev, APBRIDGE_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK);
    if (!priv->epbulkin) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINALLOCFAIL), 0);
        ret = -ENODEV;
        goto errout;
    }
    priv->epbulkin->priv = priv;

    /* Pre-allocate the OUT bulk endpoint */

    priv->epbulkout =
        DEV_ALLOCEP(dev, APBRIDGE_EPOUTBULK_ADDR, false,
                    USB_EP_ATTR_XFER_BULK);
    if (!priv->epbulkout) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTALLOCFAIL), 0);
        ret = -ENODEV;
        goto errout;
    }
    priv->epbulkout->priv = priv;

    reqcontainer = &priv->intreq;
    reqcontainer->req =
        usbclass_allocreq(priv->epintin, APBRIDGE_EPINTIN_MXPACKET);
    reqcontainer->req->priv = reqcontainer;
    reqcontainer->req->callback = usbclass_intcomplete;
    reqcontainer = &priv->rdreq;
    reqcontainer->req =
        usbclass_allocreq(priv->epbulkout, APBRIDGE_BULK_MXPACKET);
    reqcontainer->req->priv = reqcontainer;
    reqcontainer->req->callback = usbclass_rdcomplete;
    reqcontainer = &priv->wrreq;
    reqcontainer->req =
        usbclass_allocreq(priv->epbulkin, APBRIDGE_BULK_MXPACKET);
    reqcontainer->req->priv = reqcontainer;
    reqcontainer->req->callback = usbclass_wrcomplete;

    /* 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:

    /* 
     * One endpoint allocation fail.
     * Release the endpoints which were allocated.
     */

    usbclass_unbind(driver, dev);
    return ret;
}
예제 #7
0
파일: apb-es1.c 프로젝트: KimMui/GDMAC
static int usbclass_setconfig(struct apbridge_dev_s *priv, uint8_t config)
{
    struct usbdev_req_s *req;
    struct usb_epdesc_s epdesc;
    uint16_t mxpacket;
//  int i;
    int ret = 0;

#if CONFIG_DEBUG
    if (priv == NULL) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
        return -EIO;
    }
#endif

    if (config == priv->config) {
        /* Already configured -- Do nothing */

        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALREADYCONFIGURED), 0);
        return 0;
    }

    /* Discard the previous configuration data */

    usbclass_resetconfig(priv);

    /* Was this a request to simply discard the current configuration? */

    if (config == APBRIDGE_CONFIGIDNONE) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONFIGNONE), 0);
        return 0;
    }

    /* We only accept one configuration */

    if (config != APBRIDGE_CONFIGID) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_CONFIGIDBAD), 0);
        return -EINVAL;
    }

    /* Configure the IN interrupt endpoint */

    if (priv->usbdev->speed == USB_SPEED_HIGH) {
        mxpacket = APBRIDGE_EPINTIN_MXPACKET;
    } else {
        mxpacket = 64;
    }

    usbclass_mkepdesc(&g_epintindesc, mxpacket, &epdesc);
    ret = EP_CONFIGURE(priv->epintin, &epdesc, false);
    if (ret < 0) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINCONFIGFAIL), 0);
        goto errout;
    }
    priv->epintin->priv = priv;

    /* Configure the IN bulk endpoint */

    if (priv->usbdev->speed == USB_SPEED_HIGH) {
        mxpacket = APBRIDGE_BULK_MXPACKET;
    } else {
        mxpacket = 64;
    }

    usbclass_mkepdesc(&g_epbulkindesc, mxpacket, &epdesc);
    ret = EP_CONFIGURE(priv->epbulkin, &epdesc, false);
    if (ret < 0) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINCONFIGFAIL), 0);
        goto errout;
    }

    priv->epbulkin->priv = priv;

    /* Configure the OUT bulk endpoint */

    usbclass_mkepdesc(&g_epbulkoutdesc, mxpacket, &epdesc);
    ret = EP_CONFIGURE(priv->epbulkout, &epdesc, true);
    if (ret < 0) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTCONFIGFAIL), 0);
        goto errout;
    }

    priv->epbulkout->priv = priv;

    /* Queue read requests in the bulk OUT endpoint */
    req = priv->rdreq.req;
    req->callback = usbclass_rdcomplete;
    ret = EP_SUBMIT(priv->epbulkout, priv->rdreq.req);

    if (ret != OK) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t) - ret);
        goto errout;
    }

    /* We are successfully configured */

    priv->config = config;

    return OK;

 errout:
    usbclass_resetconfig(priv);
    return ret;
}
예제 #8
0
파일: apb-es1.c 프로젝트: KimMui/GDMAC
static int usbclass_setup(struct usbdevclass_driver_s *driver,
                          struct usbdev_s *dev,
                          const struct usb_ctrlreq_s *ctrl,
                          uint8_t * dataout, size_t outlen)
{
    struct apbridge_dev_s *priv;
    struct usbdev_req_s *ctrlreq;
    uint16_t value;
    uint16_t index;
    uint16_t len;
    int ret = -EOPNOTSUPP;

#ifdef CONFIG_DEBUG
    if (!driver || !dev || !dev->ep0 || !ctrl) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
        return -EIO;
    }
#endif

    /* Extract reference to private data */

    usbtrace(TRACE_CLASSSETUP, ctrl->req);
    priv = ((struct apbridge_driver_s *)driver)->dev;

#ifdef CONFIG_DEBUG
    if (!priv || !priv->ctrlreq) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0);
        return -ENODEV;
    }
#endif
    ctrlreq = priv->ctrlreq;
    ctrlreq->priv = (void *)USB_REQ;

    /* 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);

    switch (ctrl->type & USB_REQ_TYPE_MASK) {
     /***********************************************************************
      * Standard Requests
      ***********************************************************************/

    case USB_REQ_TYPE_STANDARD:
        {
            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, &g_devdesc, ret);
                        }
                        break;

                    case USB_DESC_TYPE_DEVICEQUALIFIER:
                        {
                            ret = USB_SIZEOF_QUALDESC;
                            memcpy(ctrlreq->buf, &g_qualdesc, ret);
                        }
                        break;

                    case USB_DESC_TYPE_OTHERSPEEDCONFIG:
                    case USB_DESC_TYPE_CONFIG:
                        {
                            ret =
                                usbclass_mkcfgdesc(ctrlreq->buf, dev->speed,
                                                   ctrl->req);
                        }
                        break;

                    case USB_DESC_TYPE_STRING:
                        {
                            /* index == language code. */

                            ret =
                                usbclass_mkstrdesc(ctrl->value[0],
                                                   (struct usb_strdesc_s *)
                                                   ctrlreq->buf);
                        }
                        break;

                    default:
                        {
                            usbtrace(TRACE_CLSERROR
                                     (USBSER_TRACEERR_GETUNKNOWNDESC), value);
                        }
                        break;
                    }
                }
                break;

            case USB_REQ_SETCONFIGURATION:
                {
                    if (ctrl->type == 0) {
                        ret = usbclass_setconfig(priv, value);
                    }
                }
                break;

            case USB_REQ_GETCONFIGURATION:
                {
                    if (ctrl->type == USB_DIR_IN) {
                        *(uint8_t *) ctrlreq->buf = priv->config;
                        ret = 1;
                    }
                }
                break;

            case USB_REQ_SETINTERFACE:
                {
                    if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE) {
                        if (priv->config == APBRIDGE_CONFIGID &&
                            index == APBRIDGE_INTERFACEID &&
                            value == APBRIDGE_ALTINTERFACEID) {
                            usbclass_resetconfig(priv);
                            usbclass_setconfig(priv, priv->config);
                            ret = 0;
                        }
                    }
                }
                break;

            case USB_REQ_GETINTERFACE:
                {
                    if (ctrl->type ==
                        (USB_DIR_IN | USB_REQ_RECIPIENT_INTERFACE)
                        && priv->config == APBRIDGE_CONFIGIDNONE) {
                        if (index != APBRIDGE_INTERFACEID) {
                            ret = -EDOM;
                        } else {
                            *(uint8_t *) ctrlreq->buf =
                                APBRIDGE_ALTINTERFACEID;
                            ret = 1;
                        }
                    }
                }
                break;

            default:
                usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDSTDREQ),
                         ctrl->req);
                break;
            }
        }
        break;

        /* Put here vendor request */
    case USB_REQ_TYPE_VENDOR:
        {
            if ((ctrl->type & USB_REQ_RECIPIENT_MASK) ==
                USB_REQ_RECIPIENT_INTERFACE) {
                if (ctrl->req == APBRIDGE_RWREQUEST_SVC) {
                    if ((ctrl->type & USB_DIR_IN) != 0) {
                        *(uint32_t *) ctrlreq->buf = 0xdeadbeef;
                        ret = 4;
                    } else {
                        ctrlreq->priv = (void *)GREYBUS_SVC_REQ;
                        ret = len;
                    }
                } else if (ctrl->req == APBRIDGE_RWREQUEST_LOG) {
                    if ((ctrl->type & USB_DIR_IN) == 0) {
                    } else {
#if defined(CONFIG_APB_USB_LOG)
                        ctrlreq->priv = (void *)GREYBUS_LOG;
                        ret = usb_get_log(ctrlreq->buf, len);
#else
                        ret = 0;
#endif
                    }
                } else {
                    usbtrace(TRACE_CLSERROR
                             (USBSER_TRACEERR_UNSUPPORTEDCLASSREQ),
                             ctrl->type);
                }
            }
        }
        break;

    default:
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDTYPE), ctrl->type);
        break;
    }

    /* Respond to the setup command if data was returned.  On an error return
     * value (ret < 0), the USB driver will stall.
     */

    if (ret >= 0) {
        ctrlreq->len = min(len, ret);
        ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
        ret = EP_SUBMIT(dev->ep0, ctrlreq);
        if (ret < 0) {
            usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPRESPQ),
                     (uint16_t) - ret);
            ctrlreq->result = OK;
            usbclass_ep0incomplete(dev->ep0, ctrlreq);
        }
    }

    return ret;
}
예제 #9
0
파일: apb-es1.c 프로젝트: KimMui/GDMAC
static void usbclass_unbind(struct usbdevclass_driver_s *driver,
                            struct usbdev_s *dev)
{
    struct apbridge_dev_s *priv;

    usbtrace(TRACE_CLASSUNBIND, 0);

#ifdef CONFIG_DEBUG
    if (!driver || !dev || !dev->ep0) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
        return;
    }
#endif

    /* Extract reference to private data */

    priv = ((struct apbridge_driver_s *)driver)->dev;

#ifdef CONFIG_DEBUG
    if (!priv) {
        usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0);
        return;
    }
#endif

    /* Make sure that we are not already unbound */

    if (priv != NULL) {
        /* Make sure that the endpoints have been unconfigured.  If
         * we were terminated gracefully, then the configuration should
         * already have been reset.  If not, then calling usbclass_resetconfig
         * should cause the endpoints to immediately terminate all
         * transfers and return the requests to us (with result == -ESHUTDOWN)
         */

        usbclass_resetconfig(priv);
        up_mdelay(50);

        /* Free the interrupt IN endpoint */

        if (priv->epintin) {
            DEV_FREEEP(dev, priv->epintin);
            priv->epintin = NULL;
        }

        /* Free the bulk IN endpoint */

        if (priv->epbulkin) {
            DEV_FREEEP(dev, priv->epbulkin);
            priv->epbulkin = NULL;
        }

        /* Free the pre-allocated control request */

        if (priv->ctrlreq != NULL) {
            usbclass_freereq(dev->ep0, priv->ctrlreq);
            priv->ctrlreq = NULL;
        }

        /* Free the bulk OUT endpoint */

        if (priv->epbulkout) {
            DEV_FREEEP(dev, priv->epbulkout);
            priv->epbulkout = NULL;
        }
    }
}