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; }
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; }
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; }