Beispiel #1
0
static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *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;
	int i;

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

#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
	 * const, canned descriptors.
	 */

	DEBUGASSERT(CONFIG_USBMSC_EP0MAXPACKET == dev->ep0->maxpacket);

	/* Preallocate control request */

	priv->ctrlreq = usbmsc_allocreq(dev->ep0, USBMSC_MXDESCLEN);
	if (priv->ctrlreq == NULL) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCCTRLREQ), 0);
		ret = -ENOMEM;
		goto errout;
	}

	priv->ctrlreq->callback = usbmsc_ep0incomplete;

	/* Pre-allocate all endpoints... the endpoints will not be functional
	 * until the SET CONFIGURATION request is processed in usbmsc_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 bulk endpoint */

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

	priv->epbulkin->priv = priv;

	/* Pre-allocate the OUT bulk endpoint */

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

	priv->epbulkout->priv = priv;

	/* Pre-allocate read requests */

	for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++) {
		reqcontainer = &priv->rdreqs[i];
		reqcontainer->req = usbmsc_allocreq(priv->epbulkout, CONFIG_USBMSC_BULKOUTREQLEN);
		if (reqcontainer->req == NULL) {
			usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDALLOCREQ), (uint16_t)-ret);
			ret = -ENOMEM;
			goto errout;
		}
		reqcontainer->req->priv = reqcontainer;
		reqcontainer->req->callback = usbmsc_rdcomplete;
	}

	/* Pre-allocate write request containers and put in a free list */

	for (i = 0; i < CONFIG_USBMSC_NWRREQS; i++) {
		reqcontainer = &priv->wrreqs[i];
		reqcontainer->req = usbmsc_allocreq(priv->epbulkin, CONFIG_USBMSC_BULKINREQLEN);
		if (reqcontainer->req == NULL) {
			usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRALLOCREQ), (uint16_t)-ret);
			ret = -ENOMEM;
			goto errout;
		}
		reqcontainer->req->priv = reqcontainer;
		reqcontainer->req->callback = usbmsc_wrcomplete;

		flags = irqsave();
		sq_addlast((FAR sq_entry_t *)reqcontainer, &priv->wrreqlist);
		irqrestore(flags);
	}

	/* Report if we are selfpowered (unless we are part of a composite device) */

#ifndef CONFIG_USBMSC_COMPOSITE
#ifdef CONFIG_USBDEV_SELFPOWERED
	DEV_SETSELFPOWERED(dev);
#endif

	/* And pull-up the data line for the soft connect function (unless we are
	 * part of a composite device)
	 */

	DEV_CONNECT(dev);
#endif
	return OK;

errout:
	usbmsc_unbind(driver, dev);
	return ret;
}
Beispiel #2
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;
}
Beispiel #3
0
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;
}