diff --git a/arch/arm/src/sama5/sam_ehci.c b/arch/arm/src/sama5/sam_ehci.c index 9dec514728..19dfecfd74 100644 --- a/arch/arm/src/sama5/sam_ehci.c +++ b/arch/arm/src/sama5/sam_ehci.c @@ -224,10 +224,12 @@ struct sam_rhport_s /* Root hub port status */ volatile bool connected; /* Connected to device */ - volatile bool lowspeed; /* Low speed device attached */ - uint8_t rhpndx; /* Root hub port index */ struct sam_epinfo_s ep0; /* EP0 endpoint info */ + /* This is the hub port description understood by class drivers */ + + struct usbhost_hubport_s hport; + /* The bound device class driver */ struct usbhost_class_s *class; @@ -366,10 +368,8 @@ static int sam_wait(FAR struct usbhost_connection_s *conn, FAR const bool *connected); static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); -static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, - uint16_t maxpacketsize); -static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, - FAR struct usbhost_devinfo_s *devinfo); +static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, + uint8_t funcaddr, uint16_t maxpacketsize); static int sam_epalloc(FAR struct usbhost_driver_s *drvr, const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); static int sam_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); @@ -379,10 +379,12 @@ static int sam_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); static int sam_ioalloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer, size_t buflen); static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); -static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, - FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer); -static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, - FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer); +static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer); +static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer); static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, FAR uint8_t *buffer, size_t buflen); static void sam_disconnect(FAR struct usbhost_driver_s *drvr); @@ -1423,6 +1425,7 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport, struct sam_epinfo_s *epinfo) { struct sam_qh_s *qh; + uint32_t rhpndx; uint32_t regval; /* Allocate a new queue head structure */ @@ -1452,9 +1455,9 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport, * RL NAK count reloaded 8 */ - regval = ((uint32_t)epinfo->devaddr << QH_EPCHAR_DEVADDR_SHIFT) | - ((uint32_t)epinfo->epno << QH_EPCHAR_ENDPT_SHIFT) | - ((uint32_t)epinfo->speed << QH_EPCHAR_EPS_SHIFT) | + regval = ((uint32_t)epinfo->devaddr << QH_EPCHAR_DEVADDR_SHIFT) | + ((uint32_t)epinfo->epno << QH_EPCHAR_ENDPT_SHIFT) | + ((uint32_t)EHCI_SPEED(epinfo->speed) << QH_EPCHAR_EPS_SHIFT) | QH_EPCHAR_DTC | ((uint32_t)epinfo->maxpacket << QH_EPCHAR_MAXPKT_SHIFT) | ((uint32_t)8 << QH_EPCHAR_RL_SHIFT); @@ -1465,7 +1468,7 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport, * Otherwise it should always set this bit to a zero." */ - if (epinfo->speed != EHCI_HIGH_SPEED && + if (epinfo->speed != USB_SPEED_HIGH && epinfo->xfrtype == USB_EP_ATTR_XFER_CONTROL) { regval |= QH_EPCHAR_C; @@ -1489,9 +1492,10 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport, * and HUB device address to be included here. */ - regval = ((uint32_t)0 << QH_EPCAPS_HUBADDR_SHIFT) | - ((uint32_t)(rhport->rhpndx + 1) << QH_EPCAPS_PORT_SHIFT) | - ((uint32_t)1 << QH_EPCAPS_MULT_SHIFT); + rhpndx = rhport->hport.port; + regval = ((uint32_t)0 << QH_EPCAPS_HUBADDR_SHIFT) | + ((uint32_t)(rhpndx + 1) << QH_EPCAPS_PORT_SHIFT) | + ((uint32_t)1 << QH_EPCAPS_MULT_SHIFT); #ifndef CONFIG_USBHOST_INT_DISABLE if (epinfo->xfrtype == USB_EP_ATTR_XFER_INT) @@ -1835,7 +1839,7 @@ static ssize_t sam_async_transfer(struct sam_rhport_s *rhport, usbhost_vtrace2(EHCI_VTRACE2_ASYNCXFR, epinfo->epno, buflen); #else uvdbg("RHport%d EP%d: buffer=%p, buflen=%d, req=%p\n", - rhport->rhpndx+1, epinfo->epno, buffer, buflen, req); + rhport->hport.port+1, epinfo->epno, buffer, buflen, req); #endif DEBUGASSERT(rhport && epinfo); @@ -2194,7 +2198,7 @@ static ssize_t sam_intr_transfer(struct sam_rhport_s *rhport, usbhost_vtrace2(EHCI_VTRACE2_INTRXFR, epinfo->epno, buflen); #else uvdbg("RHport%d EP%d: buffer=%p, buflen=%d\n", - rhport->rhpndx+1, epinfo->epno, buffer, buflen); + rhport->hport.port+1, epinfo->epno, buffer, buflen); #endif DEBUGASSERT(rhport && epinfo && buffer && buflen > 0); @@ -2669,7 +2673,6 @@ static inline void sam_portsc_bottomhalf(void) rhpndx+1, g_ehci.pscwait); rhport->connected = false; - rhport->lowspeed = false; /* Are we bound to a class instance? */ @@ -3141,7 +3144,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * repeat." */ - rhport->ep0.speed = EHCI_LOW_SPEED; + rhport->ep0.speed = USB_SPEED_LOW; regval |= EHCI_PORTSC_OWNER; sam_putreg(regval, &HCOR->portsc[rhpndx]); @@ -3164,7 +3167,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) { /* Assume full-speed for now */ - rhport->ep0.speed = EHCI_FULL_SPEED; + rhport->ep0.speed = USB_SPEED_FULL; } /* Put the root hub port in reset. @@ -3189,7 +3192,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * write a zero to the Port Enable bit." */ - regaddr = &HCOR->portsc[rhport->rhpndx]; + regaddr = &HCOR->portsc[rhport->hport.port]; regval = sam_getreg(regaddr); regval &= ~EHCI_PORTSC_PE; regval |= EHCI_PORTSC_RESET; @@ -3243,7 +3246,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) { /* High speed device */ - rhport->ep0.speed = EHCI_HIGH_SPEED; + rhport->ep0.speed = USB_SPEED_HIGH; } else { @@ -3291,7 +3294,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) */ usbhost_vtrace2(EHCI_VTRACE2_CLASSENUM, rhpndx+1, rhpndx+1); - ret = usbhost_enumerate(&g_ehci.rhport[rhpndx].drvr, rhpndx+1, &rhport->class); + ret = usbhost_enumerate(&g_ehci.rhport[rhpndx].hport, &rhport->class); if (ret < 0) { usbhost_trace2(EHCI_TRACE2_CLASSENUM_FAILED, rhpndx+1, -ret); @@ -3326,17 +3329,12 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * ************************************************************************************/ -static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, - uint16_t maxpacketsize) +static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, + uint8_t funcaddr, uint16_t maxpacketsize) { - struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; - struct sam_epinfo_s *epinfo; + struct sam_epinfo_s *epinfo = (struct sam_epinfo_s *)ep0; - DEBUGASSERT(rhport && - funcaddr >= 0 && funcaddr <= SAM_EHCI_NRHPORT && - maxpacketsize < 2048); - - epinfo = &rhport->ep0; + DEBUGASSERT(drvr != NULL && epinfo != NULL && maxpacketsize < 2048); /* We must have exclusive access to the EHCI data structures. */ @@ -3351,66 +3349,6 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, return OK; } -/************************************************************************************ - * Name: sam_getdevinfo - * - * Description: - * Get information about the connected device. - * - * Input Parameters: - * drvr - The USB host driver instance obtained as a parameter from the call to - * the class create() method. - * devinfo - A pointer to memory provided by the caller in which to return the - * device information. - * - * Returned Values: - * On success, zero (OK) is returned. On a failure, a negated errno value is - * returned indicating the nature of the failure - * - * Assumptions: - * This function will *not* be called from an interrupt handler. - * - ************************************************************************************/ - -static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, - FAR struct usbhost_devinfo_s *devinfo) -{ -#if 0 - struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; - struct sam_epinfo_s *epinfo; - - DEBUGASSERT(drvr && devinfo); - epinfo = &rhport->ep0; - - /* As implemented now, this driver supports only HIGH speed. All - * low or full speed devices are handed off to the OHCI driver. - */ - - switch (epinfo->speed) - { - case EHCI_LOW_SPEED: - devinfo->speed = DEVINFO_SPEED_LOW; - break; - - case EHCI_FULL_SPEED: - devinfo->speed = DEVINFO_SPEED_FULL; - break; - - default: - case EHCI_HIGH_SPEED: - devinfo->speed = DEVINFO_SPEED_HIGH; - break; - } - -#else - DEBUGASSERT(drvr && devinfo); - - devinfo->speed = DEVINFO_SPEED_HIGH; - -#endif - return OK; -} - /************************************************************************************ * Name: sam_epalloc * @@ -3436,14 +3374,15 @@ static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, static int sam_epalloc(FAR struct usbhost_driver_s *drvr, const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep) { - struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; struct sam_epinfo_s *epinfo; + struct usbhost_hubport_s *hport; /* Sanity check. NOTE that this method should only be called if a device is * connected (because we need a valid low speed indication). */ - DEBUGASSERT(drvr && epdesc && ep); + DEBUGASSERT(drvr != 0 && epdesc != NULL && epdesc->hport != NULL && ep != NULL); + hport = epdesc->hport; /* Terse output only if we are tracing */ @@ -3472,13 +3411,13 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr, epinfo->epno = epdesc->addr; epinfo->dirin = epdesc->in; - epinfo->devaddr = epdesc->funcaddr; + epinfo->devaddr = hport->funcaddr; #ifndef CONFIG_USBHOST_INT_DISABLE epinfo->interval = epdesc->interval; #endif epinfo->maxpacket = epdesc->mxpacketsize; epinfo->xfrtype = epdesc->xfrtype; - epinfo->speed = rhport->ep0.speed; + epinfo->speed = hport->speed; sem_init(&epinfo->iocsem, 0, 0); /* Success.. return an opaque reference to the endpoint information structure @@ -3683,10 +3622,11 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * Name: sam_ctrlin and sam_ctrlout * * Description: + * Description: * Process a IN or OUT request on the control endpoint. These methods - * will enqueue the request and wait for it to complete. Only one transfer may - * be queued; Neither these methods nor the transfer() method can be called - * again until the control transfer functions returns. + * will enqueue the request and wait for it to complete. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. * * These are blocking methods; these functions will not return until the * control transfer has completed. @@ -3694,12 +3634,12 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to * the class create() method. + * ep0 - The control endpoint to send/receive the control request. * req - Describes the request to be sent. This request must lie in memory * created by DRVR_ALLOC. * buffer - A buffer used for sending the request and for returning any * responses. This buffer must be large enough to hold the length value - * in the request description. buffer must have been allocated using - * DRVR_ALLOC + * in the request description. buffer must have been allocated using DRVR_ALLOC. * * NOTE: On an IN transaction, req and buffer may refer to the same allocated * memory. @@ -3709,31 +3649,31 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * returned indicating the nature of the failure * * Assumptions: - * - Only a single class bound to a single device is supported. * - Called from a single thread so no mutual exclusion is required. * - Never called from an interrupt handler. * *******************************************************************************/ -static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, +static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer) { struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; + struct sam_epinfo_s *ep0info = (struct sam_epinfo_s *)ep0; uint16_t len; ssize_t nbytes; - DEBUGASSERT(rhport && req); + DEBUGASSERT(rhport != NULL && epinfo != NULL && req != NULL); len = sam_read16(req->len); /* Terse output only if we are tracing */ #ifdef CONFIG_USBHOST_TRACE - usbhost_vtrace2(EHCI_VTRACE2_CTRLINOUT, rhport->rhpndx + 1, req->req); + usbhost_vtrace2(EHCI_VTRACE2_CTRLINOUT, rhport->hport.port + 1, req->req); #else uvdbg("RHPort%d type: %02x req: %02x value: %02x%02x index: %02x%02x len: %04x\n", - rhport->rhpndx + 1, req->type, req->req, req->value[1], req->value[0], + rhport->hport.port + 1, req->type, req->req, req->value[1], req->value[0], req->index[1], req->index[0], len); #endif @@ -3743,12 +3683,12 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, /* Now perform the transfer */ - nbytes = sam_async_transfer(rhport, &rhport->ep0, req, buffer, len); + nbytes = sam_async_transfer(rhport, ep0info, req, buffer, len); sam_givesem(&g_ehci.exclsem); return nbytes >=0 ? OK : (int)nbytes; } -static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, +static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer) { @@ -3756,7 +3696,7 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, * differences in the function signatures. */ - return sam_ctrlin(drvr, req, (uint8_t *)buffer); + return sam_ctrlin(drvr, ep0, req, (uint8_t *)buffer); } /******************************************************************************* @@ -4123,12 +4063,10 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller) for (i = 0; i < SAM_EHCI_NRHPORT; i++) { struct sam_rhport_s *rhport = &g_ehci.rhport[i]; - rhport->rhpndx = i; /* Initialize the device operations */ rhport->drvr.ep0configure = sam_ep0configure; - rhport->drvr.getdevinfo = sam_getdevinfo; rhport->drvr.epalloc = sam_epalloc; rhport->drvr.epfree = sam_epfree; rhport->drvr.alloc = sam_alloc; @@ -4143,9 +4081,19 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller) /* Initialize EP0 */ rhport->ep0.xfrtype = USB_EP_ATTR_XFER_CONTROL; - rhport->ep0.speed = EHCI_FULL_SPEED; + rhport->ep0.speed = USB_SPEED_FULL; rhport->ep0.maxpacket = 8; sem_init(&rhport->ep0.iocsem, 0, 0); + + /* Initialize the public port representation */ + + rhport->hport.drvr = &rhport->drvr; +#ifdef CONFIG_USBHOST_HUB + rhport->hport.parent = NULL; +#endif + rhport->hport.ep0 = &rhport->ep0; + rhport->hport.port = i; + rhport->hport.speed = USB_SPEED_FULL; } #ifndef CONFIG_SAMA5_EHCI_PREALLOCATE diff --git a/arch/arm/src/sama5/sam_ohci.c b/arch/arm/src/sama5/sam_ohci.c index 9785bef42c..0c393f27ea 100644 --- a/arch/arm/src/sama5/sam_ohci.c +++ b/arch/arm/src/sama5/sam_ohci.c @@ -1,7 +1,7 @@ /******************************************************************************* * arch/arm/src/sama5/sam_ohci.c * - * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2013, 2015 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -221,12 +221,15 @@ struct sam_rhport_s /* Root hub port status */ volatile bool connected; /* Connected to device */ - volatile bool lowspeed; /* Low speed device attached. */ uint8_t rhpndx; /* Root hub port index */ bool ep0init; /* True: EP0 initialized */ struct sam_eplist_s ep0; /* EP0 endpoint list */ + /* This is the hub port description understood by class drivers */ + + struct usbhost_hubport_s hport; + /* The bound device class driver */ struct usbhost_class_s *class; @@ -361,14 +364,14 @@ static inline int sam_remisoced(struct sam_ed_s *ed); /* Descriptor helper functions *************************************************/ -static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed, - uint32_t dirpid, uint32_t toggle, - volatile uint8_t *buffer, size_t buflen); +static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplist, + struct sam_ed_s *ed, uint32_t dirpid, uint32_t toggle, + volatile uint8_t *buffer, size_t buflen); static int sam_ep0enqueue(struct sam_rhport_s *rhport); static void sam_ep0dequeue(struct sam_rhport_s *rhport); static int sam_wdhwait(struct sam_rhport_s *rhport, struct sam_ed_s *ed); -static int sam_ctrltd(struct sam_rhport_s *rhport, uint32_t dirpid, - uint8_t *buffer, size_t buflen); +static int sam_ctrltd(struct sam_rhport_s *rhport, struct sam_eplist_s *ep0, + uint32_t dirpid, uint8_t *buffer, size_t buflen); /* Interrupt handling **********************************************************/ @@ -382,10 +385,8 @@ static int sam_wait(FAR struct usbhost_connection_s *conn, FAR const bool *connected); static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); -static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, - uint16_t maxpacketsize); -static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, - FAR struct usbhost_devinfo_s *devinfo); +static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, + uint8_t funcaddr, uint16_t maxpacketsize); static int sam_epalloc(FAR struct usbhost_driver_s *drvr, const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); static int sam_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); @@ -395,10 +396,10 @@ static int sam_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); static int sam_ioalloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer, size_t buflen); static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); -static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, +static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer); -static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, +static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer); static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, @@ -1276,8 +1277,8 @@ static inline int sam_remisoced(struct sam_ed_s *ed) * *******************************************************************************/ -static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed, - uint32_t dirpid, uint32_t toggle, +static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplist, + struct sam_ed_s *ed, uint32_t dirpid, uint32_t toggle, volatile uint8_t *buffer, size_t buflen) { struct sam_gtd_s *td; @@ -1298,15 +1299,15 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed, arch_clean_dcache((uintptr_t)ed, (uintptr_t)ed + sizeof(struct ohci_ed_s)); - /* Get the tail ED for this root hub port */ + /* Get the tail ED for this hub port */ - tdtail = rhport->ep0.tail; + tdtail = eplist->tail; /* Get physical addresses to support the DMA */ - phytd = sam_physramaddr((uintptr_t)td); - phytail = sam_physramaddr((uintptr_t)tdtail); - phybuf = sam_physramaddr((uintptr_t)buffer); + phytd = sam_physramaddr((uintptr_t)td); + phytail = sam_physramaddr((uintptr_t)tdtail); + phybuf = sam_physramaddr((uintptr_t)buffer); /* Initialize the allocated TD and link it before the common tail TD. */ @@ -1421,7 +1422,7 @@ static int sam_ep0enqueue(struct sam_rhport_s *rhport) */ memset(edctrl, 0, sizeof(struct sam_ed_s)); - (void)sam_ep0configure(&rhport->drvr, 0, 8); + (void)sam_ep0configure(&rhport->drvr, &rhport->ep0, 0, 8); edctrl->hw.ctrl |= ED_CONTROL_K; edctrl->eplist = &rhport->ep0; @@ -1626,10 +1627,9 @@ static int sam_wdhwait(struct sam_rhport_s *rhport, struct sam_ed_s *ed) * *******************************************************************************/ -static int sam_ctrltd(struct sam_rhport_s *rhport, uint32_t dirpid, - uint8_t *buffer, size_t buflen) +static int sam_ctrltd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplist, + uint32_t dirpid, uint8_t *buffer, size_t buflen) { - struct sam_eplist_s *eplist; struct sam_ed_s *edctrl; uint32_t toggle; uint32_t regval; @@ -1639,18 +1639,14 @@ static int sam_ctrltd(struct sam_rhport_s *rhport, uint32_t dirpid, * transfer. */ - edctrl = rhport->ep0.ed; + edctrl = eplist->ed; ret = sam_wdhwait(rhport, edctrl); if (ret != OK) { - usbhost_trace1(OHCI_TRACE1_DEVDISCONN, rhport->rhpndx + 1); + usbhost_trace1(OHCI_TRACE1_DEVDISCONN, rhport->hport.port + 1); return ret; } - /* Get the endpoint list structure for the ED */ - - eplist = &rhport->ep0; - /* Configure the toggle field in the TD */ if (dirpid == GTD_STATUS_DP_SETUP) @@ -1665,7 +1661,7 @@ static int sam_ctrltd(struct sam_rhport_s *rhport, uint32_t dirpid, /* Then enqueue the transfer */ edctrl->tdstatus = TD_CC_NOERROR; - ret = sam_enqueuetd(rhport, edctrl, dirpid, toggle, buffer, buflen); + ret = sam_enqueuetd(rhport, eplist, edctrl, dirpid, toggle, buffer, buflen); if (ret == OK) { /* Set ControlListFilled. This bit is used to indicate whether there are @@ -1711,7 +1707,7 @@ static int sam_ctrltd(struct sam_rhport_s *rhport, uint32_t dirpid, } else { - usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, rhport->rhpndx + 1, + usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, rhport->hport.port + 1, edctrl->tdstatus); ret = -EIO; } @@ -1799,8 +1795,16 @@ static void sam_rhsc_bottomhalf(void) * when CCS == 1. */ - rhport->lowspeed = (rhportst & OHCI_RHPORTST_LSDA) != 0; - usbhost_vtrace1(OHCI_VTRACE1_SPEED, rhport->lowspeed); + if ((rhportst & OHCI_RHPORTST_LSDA) != 0) + { + rhport->hport.speed = USB_SPEED_LOW; + } + else + { + rhport->hport.speed = USB_SPEED_FULL; + } + + usbhost_vtrace1(OHCI_VTRACE1_SPEED, rhport->hport.speed); } /* Check if we are now disconnected */ @@ -1812,8 +1816,8 @@ static void sam_rhsc_bottomhalf(void) usbhost_vtrace2(OHCI_VTRACE2_DISCONNECTED, rhpndx + 1, g_ohci.rhswait); - rhport->connected = false; - rhport->lowspeed = false; + rhport->connected = false; + rhport->hport.speed = USB_SPEED_FULL; /* Are we bound to a class instance? */ @@ -2166,7 +2170,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) { /* No, return an error */ - usbhost_vtrace1(OHCI_VTRACE1_ENUMDISCONN, rhport->rhpndx + 1); + usbhost_vtrace1(OHCI_VTRACE1_ENUMDISCONN, rhport->hport.port + 1); return -ENODEV; } @@ -2177,7 +2181,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) ret = sam_ep0enqueue(rhport); if (ret < 0) { - usbhost_trace2(OHCI_TRACE2_EP0ENQUEUE_FAILED, rhport->rhpndx + 1, + usbhost_trace2(OHCI_TRACE2_EP0ENQUEUE_FAILED, rhport->hport.port + 1, -ret); return ret; } @@ -2212,7 +2216,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) */ usbhost_vtrace2(OHCI_VTRACE2_CLASSENUM, rhpndx+1, rhpndx+1); - ret = usbhost_enumerate(&g_ohci.rhport[rhpndx].drvr, rhpndx+1, &rhport->class); + ret = usbhost_enumerate(&g_ohci.rhport[rhpndx].hport, &rhport->class); if (ret < 0) { usbhost_trace2(OHCI_TRACE2_CLASSENUM_FAILED, rhpndx+1, -ret); @@ -2247,17 +2251,16 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * ************************************************************************************/ -static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, - uint16_t maxpacketsize) +static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, + uint8_t funcaddr, uint16_t maxpacketsize) { struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; + struct sam_eplist_s *ep0list = (struct sam_eplist_s *)ep0; struct sam_ed_s *edctrl; - DEBUGASSERT(rhport && - funcaddr >= 0 && funcaddr <= SAM_OHCI_NRHPORT && - maxpacketsize < 2048); + DEBUGASSERT(rhport && maxpacketsize < 2048); - edctrl = rhport->ep0.ed; + edctrl = ep0list->ed; /* We must have exclusive access to EP0 and the control list */ @@ -2268,7 +2271,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, edctrl->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; - if (rhport->lowspeed) + if (rhport->hport.speed == USB_SPEED_LOW) { edctrl->hw.ctrl |= ED_CONTROL_S; } @@ -2284,38 +2287,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, sam_givesem(&g_ohci.exclsem); usbhost_vtrace2(OHCI_VTRACE2_EP0CONFIGURE, - rhport->rhpndx + 1, (uint16_t)edctrl->hw.ctrl); - return OK; -} - -/************************************************************************************ - * Name: sam_getdevinfo - * - * Description: - * Get information about the connected device. - * - * Input Parameters: - * drvr - The USB host driver instance obtained as a parameter from the call to - * the class create() method. - * devinfo - A pointer to memory provided by the caller in which to return the - * device information. - * - * Returned Values: - * On success, zero (OK) is returned. On a failure, a negated errno value is - * returned indicating the nature of the failure - * - * Assumptions: - * This function will *not* be called from an interrupt handler. - * - ************************************************************************************/ - -static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, - FAR struct usbhost_devinfo_s *devinfo) -{ - struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; - - DEBUGASSERT(drvr && devinfo); - devinfo->speed = rhport->lowspeed ? DEVINFO_SPEED_LOW : DEVINFO_SPEED_FULL; + rhport->hport.port + 1, (uint16_t)edctrl->hw.ctrl); return OK; } @@ -2346,6 +2318,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr, { struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; struct sam_eplist_s *eplist; + struct usbhost_hubport_s *hport; struct sam_ed_s *ed; struct sam_gtd_s *td; uintptr_t physaddr; @@ -2355,7 +2328,10 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr, * connected (because we need a valid low speed indication). */ - DEBUGASSERT(rhport && epdesc && ep && rhport->connected); + DEBUGASSERT(rhport != NULL && epdesc != NULL && epdesc->hport != NULL); + DEBUGASSERT(ep != NULL && rhport->connected); + + hport = epdesc->hport; /* Allocate a container for the endpoint data */ @@ -2400,7 +2376,8 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr, /* Configure the endpoint descriptor. */ memset((void*)ed, 0, sizeof(struct sam_ed_s)); - ed->hw.ctrl = (uint32_t)(epdesc->funcaddr) << ED_CONTROL_FA_SHIFT | + + ed->hw.ctrl = (uint32_t)(hport->funcaddr) << ED_CONTROL_FA_SHIFT | (uint32_t)(epdesc->addr) << ED_CONTROL_EN_SHIFT | (uint32_t)(epdesc->mxpacketsize) << ED_CONTROL_MPS_SHIFT; @@ -2417,7 +2394,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr, /* Check for a low-speed device */ - if (rhport->lowspeed) + if (rhport->hport.speed == USB_SPEED_LOW) { ed->hw.ctrl |= ED_CONTROL_S; } @@ -2745,10 +2722,11 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * Name: sam_ctrlin and sam_ctrlout * * Description: + * Description: * Process a IN or OUT request on the control endpoint. These methods - * will enqueue the request and wait for it to complete. Only one transfer may - * be queued; Neither these methods nor the transfer() method can be called - * again until the control transfer functions returns. + * will enqueue the request and wait for it to complete. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. * * These are blocking methods; these functions will not return until the * control transfer has completed. @@ -2756,12 +2734,12 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to * the class create() method. + * ep0 - The control endpoint to send/receive the control request. * req - Describes the request to be sent. This request must lie in memory * created by DRVR_ALLOC. * buffer - A buffer used for sending the request and for returning any * responses. This buffer must be large enough to hold the length value - * in the request description. buffer must have been allocated using - * DRVR_ALLOC + * in the request description. buffer must have been allocated using DRVR_ALLOC. * * NOTE: On an IN transaction, req and buffer may refer to the same allocated * memory. @@ -2771,28 +2749,29 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * returned indicating the nature of the failure * * Assumptions: - * - Only a single class bound to a single device is supported. * - Called from a single thread so no mutual exclusion is required. * - Never called from an interrupt handler. * *******************************************************************************/ -static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, +static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer) { struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; + struct sam_eplist_s *eplist = (struct sam_eplist_s *)ep0; uint16_t len; int ret; - DEBUGASSERT(rhport && req); + DEBUGASSERT(rhport != NULL && eplist != NULL && req != NULL); #ifdef CONFIG_USBHOST_TRACE - usbhost_vtrace2(OHCI_VTRACE2_CTRLIN, rhport->rhpndx + 1, req->req); + usbhost_vtrace2(OHCI_VTRACE2_CTRLIN, rhport->hport.port + 1, req->req); #else uvdbg("RHPort%d type: %02x req: %02x value: %02x%02x index: %02x%02x len: %02x%02x\n", - rhport->rhpndx + 1, req->type, req->req, req->value[1], req->value[0], - req->index[1], req->index[0], req->len[1], req->len[0]); + rhport->hport.port + 1, req->type, req->req, req->value[1], + req->value[0], req->index[1], req->index[0], req->len[1], + req->len[0]); #endif /* We must have exclusive access to EP0 and the control list */ @@ -2800,17 +2779,18 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, sam_takesem(&g_ohci.exclsem); len = sam_getle16(req->len); - ret = sam_ctrltd(rhport, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ); + ret = sam_ctrltd(rhport, eplist, GTD_STATUS_DP_SETUP, (uint8_t*)req, + USB_SIZEOF_CTRLREQ); if (ret == OK) { if (len) { - ret = sam_ctrltd(rhport, GTD_STATUS_DP_IN, buffer, len); + ret = sam_ctrltd(rhport, eplist, GTD_STATUS_DP_IN, buffer, len); } if (ret == OK) { - ret = sam_ctrltd(rhport, GTD_STATUS_DP_OUT, NULL, 0); + ret = sam_ctrltd(rhport, eplist, GTD_STATUS_DP_OUT, NULL, 0); } } @@ -2823,22 +2803,24 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, return ret; } -static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, +static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer) { struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; + struct sam_eplist_s *eplist = (struct sam_eplist_s *)ep0; uint16_t len; int ret; - DEBUGASSERT(rhport && req); + DEBUGASSERT(rhport != NULL && eplist != NULL && req != NULL); #ifdef CONFIG_USBHOST_TRACE - usbhost_vtrace2(OHCI_VTRACE2_CTRLOUT, rhport->rhpndx + 1, req->req); + usbhost_vtrace2(OHCI_VTRACE2_CTRLOUT, rhport->hport.port + 1, req->req); #else uvdbg("RHPort%d type: %02x req: %02x value: %02x%02x index: %02x%02x len: %02x%02x\n", - rhport->rhpndx + 1, req->type, req->req, req->value[1], req->value[0], - req->index[1], req->index[0], req->len[1], req->len[0]); + rhport->hport.port + 1, req->type, req->req, req->value[1], + req->value[0], req->index[1], req->index[0], req->len[1], + req->len[0]); #endif /* We must have exclusive access to EP0 and the control list */ @@ -2846,17 +2828,19 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, sam_takesem(&g_ohci.exclsem); len = sam_getle16(req->len); - ret = sam_ctrltd(rhport, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ); + ret = sam_ctrltd(rhport, eplist, GTD_STATUS_DP_SETUP, (uint8_t*)req, + USB_SIZEOF_CTRLREQ); if (ret == OK) { if (len) { - ret = sam_ctrltd(rhport, GTD_STATUS_DP_OUT, (uint8_t*)buffer, len); + ret = sam_ctrltd(rhport, eplist, GTD_STATUS_DP_OUT, + (uint8_t*)buffer, len); } if (ret == OK) { - ret = sam_ctrltd(rhport, GTD_STATUS_DP_IN, NULL, 0); + ret = sam_ctrltd(rhport, eplist, GTD_STATUS_DP_IN, NULL, 0); } } @@ -2945,7 +2929,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, ret = sam_wdhwait(rhport, ed); if (ret != OK) { - usbhost_trace1(OHCI_TRACE1_DEVDISCONN, rhport->rhpndx + 1); + usbhost_trace1(OHCI_TRACE1_DEVDISCONN, rhport->hport.port + 1); goto errout; } @@ -2963,7 +2947,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, /* Then enqueue the transfer */ ed->tdstatus = TD_CC_NOERROR; - ret = sam_enqueuetd(rhport, ed, dirpid, GTD_STATUS_T_TOGGLE, + ret = sam_enqueuetd(rhport, eplist, ed, dirpid, GTD_STATUS_T_TOGGLE, buffer, buflen); if (ret == OK) { @@ -3028,7 +3012,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, } else { - usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, rhport->rhpndx + 1, + usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, rhport->hport.port + 1, ed->tdstatus); ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO; } @@ -3234,9 +3218,7 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller) { struct sam_rhport_s *rhport = &g_ohci.rhport[i]; - rhport->rhpndx = i; rhport->drvr.ep0configure = sam_ep0configure; - rhport->drvr.getdevinfo = sam_getdevinfo; rhport->drvr.epalloc = sam_epalloc; rhport->drvr.epfree = sam_epfree; rhport->drvr.alloc = sam_alloc; @@ -3247,6 +3229,14 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller) rhport->drvr.ctrlout = sam_ctrlout; rhport->drvr.transfer = sam_transfer; rhport->drvr.disconnect = sam_disconnect; + + rhport->hport.drvr = &rhport->drvr; +#ifdef CONFIG_USBHOST_HUB + rhport->hport.parent = NULL; +#endif + rhport->hport.ep0 = &rhport->ep0; + rhport->hport.port = i; + rhport->hport.speed = USB_SPEED_FULL; } /* Wait 50MS then perform hardware reset */