Bring in more logic from https://github.com/kaushalparikh/nuttx
This commit is contained in:
parent
153ddf9007
commit
7fcfca40b5
@ -10253,3 +10253,6 @@
|
||||
Parikh. This initial commit is incomplete. This is quite a bit more
|
||||
hub logic that needs to come in before the port is complete
|
||||
(2015-04-18).
|
||||
* include/nuttx/usb/usbhost.h: Bring in more logic from
|
||||
https://github.com/kaushalparikh/nuttx (2015-04-19).
|
||||
|
||||
|
@ -127,7 +127,7 @@ static inline uint8_t usbhost_allocaddr(void);
|
||||
static inline void usbhost_freeaddr(uint8_t addr);
|
||||
static inline FAR struct usbhost_class_s *
|
||||
usbhost_allocclass(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_class_s *hclass, uint8_t speed,
|
||||
FAR struct usbhost_class_s *hubclass, uint8_t speed,
|
||||
uint8_t port);
|
||||
static inline void usbhost_freeclass(FAR struct usbhost_class_s *devclass);
|
||||
|
||||
@ -137,10 +137,10 @@ static void usbhost_destroy(FAR void *arg);
|
||||
|
||||
/* Helpers for usbhost_connect() */
|
||||
|
||||
static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hubclass,
|
||||
FAR const uint8_t *configdesc, int desclen);
|
||||
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hclass);
|
||||
static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hclass,
|
||||
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hubclass);
|
||||
static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hubclass,
|
||||
bool on);
|
||||
static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer);
|
||||
|
||||
@ -152,14 +152,14 @@ static void usbhost_callback(FAR struct usbhost_transfer_s *xfer);
|
||||
|
||||
/* struct usbhost_registry_s methods */
|
||||
|
||||
static int usbhost_create(FAR struct usbhost_class_s *hclass,
|
||||
static int usbhost_create(FAR struct usbhost_class_s *hubclass,
|
||||
FAR const struct usbhost_id_s *id);
|
||||
|
||||
/* struct usbhost_class_s methods */
|
||||
|
||||
static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
static int usbhost_connect(FAR struct usbhost_class_s *hubclass,
|
||||
FAR const uint8_t *configdesc, int desclen);
|
||||
static int usbhost_disconnected(FAR struct usbhost_class_s *hclass);
|
||||
static int usbhost_disconnected(FAR struct usbhost_class_s *hubclass);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@ -281,14 +281,14 @@ static inline void usbhost_freeaddr(uint8_t addr)
|
||||
|
||||
static inline FAR struct usbhost_class_s *
|
||||
usbhost_allocclass(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_class_s *hclass,
|
||||
FAR struct usbhost_class_s *hubclass,
|
||||
uint8_t speed, uint8_t port)
|
||||
{
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
FAR struct usbhost_class_s *devclass;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
/* We are not executing from an interrupt handler so we can just call
|
||||
* kmalloc() to get memory for the class instance.
|
||||
@ -309,7 +309,7 @@ static inline FAR struct usbhost_class_s *
|
||||
devclass->speed = speed;
|
||||
devclass->drvr = drvr;
|
||||
|
||||
devclass->parent = hclass;
|
||||
devclass->parent = hubclass;
|
||||
devclass->priv = NULL;
|
||||
|
||||
devclass->tt = NULL;
|
||||
@ -317,15 +317,15 @@ static inline FAR struct usbhost_class_s *
|
||||
|
||||
if (!ROOTHUB(devclass))
|
||||
{
|
||||
if (hclass->tt != NULL)
|
||||
if (hubclass->tt != NULL)
|
||||
{
|
||||
devclass->tt = hclass->tt;
|
||||
devclass->ttport = hclass->ttport;
|
||||
devclass->tt = hubclass->tt;
|
||||
devclass->ttport = hubclass->ttport;
|
||||
}
|
||||
else if ((devclass->speed != USB_SPEED_HIGH) &&
|
||||
(hclass->speed == USB_SPEED_HIGH))
|
||||
(hubclass->speed == USB_SPEED_HIGH))
|
||||
{
|
||||
devclass->tt = &hpriv->tt;
|
||||
devclass->tt = &priv->tt;
|
||||
devclass->ttport = port;
|
||||
}
|
||||
}
|
||||
@ -401,42 +401,42 @@ static inline void usbhost_freeclass(FAR struct usbhost_class_s *devclass)
|
||||
|
||||
static void usbhost_destroy(FAR void *arg)
|
||||
{
|
||||
FAR struct usbhost_class_s *hclass = (FAR struct usbhost_class_s *)arg;
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_class_s *hubclass = (FAR struct usbhost_class_s *)arg;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(hclass != NULL);
|
||||
DEBUGASSERT(hubclass != NULL);
|
||||
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
if (hpriv != NULL)
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
if (priv != NULL)
|
||||
{
|
||||
uvdbg("crefs: %d\n", hpriv->crefs);
|
||||
uvdbg("crefs: %d\n", priv->crefs);
|
||||
|
||||
if (hpriv->intxfer.ep)
|
||||
if (priv->intxfer.ep)
|
||||
{
|
||||
DRVR_EPFREE(hclass->drvr, hpriv->intxfer.ep);
|
||||
DRVR_EPFREE(hubclass->drvr, priv->intxfer.ep);
|
||||
}
|
||||
|
||||
/* Destroy the semaphores */
|
||||
|
||||
sem_destroy(&hpriv->exclsem);
|
||||
sem_destroy(&priv->exclsem);
|
||||
|
||||
/* Destroy allocated child classes */
|
||||
|
||||
for (i = 0; i < USBHUB_MAX_PORTS; i++)
|
||||
{
|
||||
if (hpriv->childclass[i] != NULL)
|
||||
if (priv->childclass[i] != NULL)
|
||||
{
|
||||
CLASS_DISCONNECTED(hpriv->childclass[i]);
|
||||
CLASS_DISCONNECTED(priv->childclass[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear priv class */
|
||||
|
||||
kfree(hclass->priv);
|
||||
kfree(hubclass->priv);
|
||||
}
|
||||
|
||||
usbhost_freeclass(hclass);
|
||||
usbhost_freeclass(hubclass);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -449,7 +449,7 @@ static void usbhost_destroy(FAR void *arg)
|
||||
* descriptor to the class so that the class may initialize properly
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - The USB host class instance.
|
||||
* hubclass - The USB host class instance.
|
||||
* configdesc - A pointer to a uint8_t buffer container the configuration
|
||||
* descriptor.
|
||||
* desclen - The length in bytes of the configuration descriptor.
|
||||
@ -463,10 +463,10 @@ static void usbhost_destroy(FAR void *arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hubclass,
|
||||
FAR const uint8_t *configdesc, int desclen)
|
||||
{
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
FAR struct usb_cfgdesc_s *cfgdesc;
|
||||
FAR struct usb_desc_s *desc;
|
||||
FAR struct usbhost_epdesc_s intindesc;
|
||||
@ -474,8 +474,8 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
uint8_t found = 0;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
DEBUGASSERT(configdesc != NULL &&
|
||||
desclen >= sizeof(struct usb_cfgdesc_s));
|
||||
@ -522,8 +522,8 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
|
||||
/* Save the interface number and mark ONLY the interface found */
|
||||
|
||||
hpriv->ifno = ifdesc->ifno;
|
||||
found = USBHOST_IFFOUND;
|
||||
priv->ifno = ifdesc->ifno;
|
||||
found = USBHOST_IFFOUND;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -562,7 +562,7 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
|
||||
/* Save the bulk IN endpoint information */
|
||||
|
||||
intindesc.devclass = hclass;
|
||||
intindesc.devclass = hubclass;
|
||||
intindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
|
||||
intindesc.in = 1;
|
||||
intindesc.xfrtype = USB_EP_ATTR_XFER_BULK;
|
||||
@ -609,11 +609,11 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
|
||||
/* We are good... Allocate the endpoints */
|
||||
|
||||
ret = DRVR_EPALLOC(hclass->drvr, &intindesc, &hpriv->intxfer.ep);
|
||||
ret = DRVR_EPALLOC(hubclass->drvr, &intindesc, &priv->intxfer.ep);
|
||||
if (ret != OK)
|
||||
{
|
||||
udbg("ERROR: Failed to allocate Interrupt IN endpoint\n");
|
||||
(void)DRVR_EPFREE(hclass->drvr, hpriv->intxfer.ep);
|
||||
(void)DRVR_EPFREE(hubclass->drvr, priv->intxfer.ep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -631,7 +631,7 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
* descriptor to the class so that the class may initialize properly
|
||||
*
|
||||
* Input Parameters:
|
||||
* hclass - The USB host class instance.
|
||||
* hubclass - The USB host class instance.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value
|
||||
@ -642,17 +642,17 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hclass,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hclass)
|
||||
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hubclass)
|
||||
{
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
struct usb_hubdesc_s hubdesc;
|
||||
uint16_t hubchar;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
ret = usbhost_ctrlxfer(hclass, (USB_REQ_DIR_IN | USBHUB_REQ_TYPE_HUB),
|
||||
ret = usbhost_ctrlxfer(hubclass, (USB_REQ_DIR_IN | USBHUB_REQ_TYPE_HUB),
|
||||
USB_REQ_GETDESCRIPTOR, USB_DESC_TYPE_HUB,
|
||||
0, USB_SIZEOF_HUBDESC, (uint8_t *)&hubdesc);
|
||||
if (ret != OK)
|
||||
@ -661,18 +661,16 @@ static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hclass)
|
||||
return ret;
|
||||
}
|
||||
|
||||
hpriv->nports = hubdesc.nports;
|
||||
priv->nports = hubdesc.nports;
|
||||
|
||||
hubchar = usbhost_getle16(hubdesc.characteristics);
|
||||
hpriv->lpsm = (hubchar & USBHUB_CHAR_LPSM_MASK) >> USBHUB_CHAR_LPSM_SHIFT;
|
||||
hpriv->compounddev = (hubchar & USBHUB_CHAR_COMPOUND) ? true : false;
|
||||
hpriv->ocmode = (hubchar & USBHUB_CHAR_OCPM_MASK) >> USBHUB_CHAR_OCPM_SHIFT;
|
||||
/* priv->ttthinktime = (((hubchar & USBHUB_CHAR_TTTT_MASK) >> USBHUB_CHAR_TTTT_SHIFT) + 1) * 666; */
|
||||
/* 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
|
||||
hpriv->indicator = (hubchar & USBHUB_CHAR_PORTIND) ? true : false;
|
||||
hubchar = usbhost_getle16(hubdesc.characteristics);
|
||||
priv->lpsm = (hubchar & USBHUB_CHAR_LPSM_MASK) >> USBHUB_CHAR_LPSM_SHIFT;
|
||||
priv->compounddev = (hubchar & USBHUB_CHAR_COMPOUND) ? true : false;
|
||||
priv->ocmode = (hubchar & USBHUB_CHAR_OCPM_MASK) >> USBHUB_CHAR_OCPM_SHIFT;
|
||||
priv->indicator = (hubchar & USBHUB_CHAR_PORTIND) ? true : false;
|
||||
|
||||
hpriv->pwrondelay = (2 * hubdesc.pwrondelay);
|
||||
hpriv->ctrlcurrent = hubdesc.ctrlcurrent;
|
||||
priv->pwrondelay = (2 * hubdesc.pwrondelay);
|
||||
priv->ctrlcurrent = hubdesc.ctrlcurrent;
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -687,7 +685,7 @@ static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hclass)
|
||||
* descriptor to the class so that the class may initialize properly
|
||||
*
|
||||
* Input Parameters:
|
||||
* hclass - The USB host class instance.
|
||||
* hubclass - The USB host class instance.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
@ -698,14 +696,14 @@ static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hclass)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hclass, bool on)
|
||||
static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hubclass, bool on)
|
||||
{
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
if (on || ROOTHUB(hclass))
|
||||
if (on || ROOTHUB(hubclass))
|
||||
{
|
||||
uint16_t req;
|
||||
int port, ret;
|
||||
@ -719,9 +717,9 @@ static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hclass, bool on)
|
||||
req = USB_REQ_CLEARFEATURE;
|
||||
}
|
||||
|
||||
for (port = 1; port <= hpriv->nports; port++)
|
||||
for (port = 1; port <= priv->nports; port++)
|
||||
{
|
||||
ret = usbhost_ctrlxfer(hclass, USBHUB_REQ_TYPE_PORT,
|
||||
ret = usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
||||
req, USBHUB_PORT_FEAT_POWER,
|
||||
port, 0, NULL);
|
||||
if (ret != OK)
|
||||
@ -758,8 +756,8 @@ static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hclass, bool on)
|
||||
|
||||
static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
{
|
||||
FAR struct usbhost_class_s *hclass;
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_class_s *hubclass;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
struct usb_portstatus_s portstatus;
|
||||
uint16_t status;
|
||||
uint16_t change;
|
||||
@ -770,14 +768,14 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(xfer != NULL && xfer->devclass != NULL);
|
||||
hclass = (FAR struct usbhost_class_s *)xfer->devclass;
|
||||
hubclass = (FAR struct usbhost_class_s *)xfer->devclass;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
statusmap = xfer->buffer[0];
|
||||
|
||||
for (port = 1; port <= hpriv->nports; port++)
|
||||
for (port = 1; port <= priv->nports; port++)
|
||||
{
|
||||
/* Check if port status has changed */
|
||||
|
||||
@ -792,7 +790,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
/* Read hub port status */
|
||||
|
||||
ret = usbhost_ctrlxfer(hclass,
|
||||
ret = usbhost_ctrlxfer(hubclass,
|
||||
(USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT),
|
||||
USB_REQ_GETSTATUS, 0, port,
|
||||
USB_SIZEOF_PORTSTS, (uint8_t *)&portstatus);
|
||||
@ -813,7 +811,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
{
|
||||
if (change & mask)
|
||||
{
|
||||
ret = usbhost_ctrlxfer(hclass, USBHUB_REQ_TYPE_PORT,
|
||||
ret = usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
||||
USB_REQ_CLEARFEATURE, feat,
|
||||
port, 0, NULL);
|
||||
if (ret != OK)
|
||||
@ -844,7 +842,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
while (debouncetime < 1500)
|
||||
{
|
||||
ret = usbhost_ctrlxfer(hclass,
|
||||
ret = usbhost_ctrlxfer(hubclass,
|
||||
(USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT),
|
||||
USB_REQ_GETSTATUS, 0, port,
|
||||
USB_SIZEOF_PORTSTS, (uint8_t *)&portstatus);
|
||||
@ -873,7 +871,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
if (change & USBHUB_PORT_STAT_CCONNECTION)
|
||||
{
|
||||
(void)usbhost_ctrlxfer(hclass, USBHUB_REQ_TYPE_PORT,
|
||||
(void)usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
||||
USB_REQ_CLEARFEATURE, USBHUB_PORT_FEAT_CCONNECTION,
|
||||
port, 0, NULL);
|
||||
}
|
||||
@ -892,7 +890,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
{
|
||||
/* Connect */
|
||||
|
||||
ret = usbhost_ctrlxfer(hclass, USBHUB_REQ_TYPE_PORT,
|
||||
ret = usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
||||
USB_REQ_SETFEATURE,
|
||||
USBHUB_PORT_FEAT_RESET, port, 0, NULL);
|
||||
if (ret != OK)
|
||||
@ -903,7 +901,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
up_mdelay(100);
|
||||
|
||||
ret = usbhost_ctrlxfer(hclass,
|
||||
ret = usbhost_ctrlxfer(hubclass,
|
||||
(USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT),
|
||||
USB_REQ_GETSTATUS, 0, port,
|
||||
USB_SIZEOF_PORTSTS, (uint8_t *)&portstatus);
|
||||
@ -926,7 +924,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
if (change & USBHUB_PORT_STAT_CRESET)
|
||||
{
|
||||
(void)usbhost_ctrlxfer(hclass, USBHUB_REQ_TYPE_PORT,
|
||||
(void)usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
||||
USB_REQ_CLEARFEATURE,
|
||||
USBHUB_PORT_FEAT_CRESET,
|
||||
port, 0, NULL);
|
||||
@ -947,15 +945,15 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
/* Allocate new class and enumerate */
|
||||
|
||||
hpriv->childclass[port] =
|
||||
usbhost_allocclass(hclass->drvr, hclass, speed, port);
|
||||
priv->childclass[port] =
|
||||
usbhost_allocclass(hubclass->drvr, hubclass, speed, port);
|
||||
|
||||
if (hpriv->childclass[port] != NULL)
|
||||
if (priv->childclass[port] != NULL)
|
||||
{
|
||||
udbg("enumerate port %d speed %d\n", port, speed);
|
||||
|
||||
#if 0
|
||||
ret = usbhost_enumerate(hpriv->childclass[port]);
|
||||
ret = usbhost_enumerate(priv->childclass[port]);
|
||||
if (ret != OK)
|
||||
{
|
||||
udbg("failed to enumerate port %d\n", port);
|
||||
@ -990,7 +988,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
||||
|
||||
xfer->status = -EIO;
|
||||
|
||||
ret = usbhost_intxfer(hclass, xfer, usbhost_callback);
|
||||
ret = usbhost_intxfer(hubclass, xfer, usbhost_callback);
|
||||
if (ret != OK)
|
||||
{
|
||||
udbg("failed to queue interrupt endpoint\n");
|
||||
@ -1093,50 +1091,50 @@ static void usbhost_callback(FAR struct usbhost_transfer_s *xfer)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int usbhost_create(FAR struct usbhost_class_s *hclass,
|
||||
static int usbhost_create(FAR struct usbhost_class_s *hubclass,
|
||||
FAR const struct usbhost_id_s *id)
|
||||
{
|
||||
struct usbhost_hub_s *hpriv;
|
||||
struct usbhost_hub_s *priv;
|
||||
int child;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
/* Allocate a USB host class instance */
|
||||
|
||||
hpriv = kmalloc(sizeof(struct usbhost_hub_s));
|
||||
priv = kmalloc(sizeof(struct usbhost_hub_s));
|
||||
|
||||
if (hpriv != NULL)
|
||||
if (priv != NULL)
|
||||
{
|
||||
/* Initialize the allocated storage class instance */
|
||||
|
||||
memset(hpriv, 0, sizeof(struct usbhost_hub_s));
|
||||
memset(priv, 0, sizeof(struct usbhost_hub_s));
|
||||
|
||||
/* Initialize class method function pointers */
|
||||
|
||||
hclass->connect = usbhost_connect;
|
||||
hclass->disconnected = usbhost_disconnected;
|
||||
hclass->priv = hpriv;
|
||||
hubclass->connect = usbhost_connect;
|
||||
hubclass->disconnected = usbhost_disconnected;
|
||||
hubclass->priv = priv;
|
||||
|
||||
/* The initial reference count is 1... One reference is held by the driver */
|
||||
|
||||
hpriv->crefs = 1;
|
||||
priv->crefs = 1;
|
||||
|
||||
/* Initialize semaphores (this works okay in the interrupt context) */
|
||||
|
||||
sem_init(&hpriv->exclsem, 0, 1);
|
||||
sem_init(&priv->exclsem, 0, 1);
|
||||
|
||||
/* Initialize interrupt end-point */
|
||||
|
||||
hpriv->intxfer.ep = NULL;
|
||||
priv->intxfer.ep = NULL;
|
||||
|
||||
/* Initialize transaction translator */
|
||||
|
||||
hpriv->tt.class = NULL;
|
||||
priv->tt.class = NULL;
|
||||
|
||||
/* Initialize child class pointers */
|
||||
|
||||
for (child = 0; child < USBHUB_MAX_PORTS; child++)
|
||||
{
|
||||
hpriv->childclass[child] = NULL;
|
||||
priv->childclass[child] = NULL;
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
@ -1181,21 +1179,21 @@ static int usbhost_create(FAR struct usbhost_class_s *hclass,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
static int usbhost_connect(FAR struct usbhost_class_s *hubclass,
|
||||
FAR const uint8_t *configdesc, int desclen)
|
||||
{
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
DEBUGASSERT(configdesc != NULL &&
|
||||
desclen >= sizeof(struct usb_cfgdesc_s));
|
||||
|
||||
/* Parse the configuration descriptor to get the endpoints */
|
||||
|
||||
ret = usbhost_cfgdesc(hclass, configdesc, desclen);
|
||||
ret = usbhost_cfgdesc(hubclass, configdesc, desclen);
|
||||
if (ret != OK)
|
||||
{
|
||||
udbg("failed to parse config descriptor\n");
|
||||
@ -1204,7 +1202,7 @@ static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
{
|
||||
/* Allocate buffer for status change (INT) endpoint */
|
||||
|
||||
ret = DRVR_IOALLOC(hclass->drvr, &hpriv->intxfer.buffer, 1);
|
||||
ret = DRVR_IOALLOC(hubclass->drvr, &priv->intxfer.buffer, 1);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
@ -1212,7 +1210,7 @@ static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
|
||||
/* Now read hub descriptor */
|
||||
|
||||
ret = usbhost_hubdesc(hclass);
|
||||
ret = usbhost_hubdesc(hubclass);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
@ -1220,7 +1218,7 @@ static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
|
||||
/* Power on hub (i.e. power on all hub ports) */
|
||||
|
||||
ret = usbhost_hubpwr(hclass, true);
|
||||
ret = usbhost_hubpwr(hubclass, true);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
@ -1228,7 +1226,7 @@ static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
|
||||
/* INT request to periodically check port status */
|
||||
|
||||
ret = usbhost_intxfer(hclass, &hpriv->intxfer,
|
||||
ret = usbhost_intxfer(hubclass, &priv->intxfer,
|
||||
usbhost_callback);
|
||||
}
|
||||
|
||||
@ -1257,20 +1255,20 @@ static int usbhost_connect(FAR struct usbhost_class_s *hclass,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int usbhost_disconnected(struct usbhost_class_s *hclass)
|
||||
static int usbhost_disconnected(struct usbhost_class_s *hubclass)
|
||||
{
|
||||
FAR struct usbhost_hub_s *hpriv;
|
||||
FAR struct usbhost_hub_s *priv;
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(hclass != NULL && hclass->priv != NULL);
|
||||
hpriv = (FAR struct usbhost_hub_s *)hclass->priv;
|
||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||
|
||||
/* Set an indication to any users of the device that the device is no
|
||||
* longer available.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
hpriv->disconnected = true;
|
||||
flags = irqsave();
|
||||
priv->disconnected = true;
|
||||
|
||||
/* Now check the number of references on the class instance. If it is one,
|
||||
* then we can free the class instance now. Otherwise, we will have to
|
||||
@ -1278,19 +1276,19 @@ static int usbhost_disconnected(struct usbhost_class_s *hclass)
|
||||
* block driver.
|
||||
*/
|
||||
|
||||
ullvdbg("crefs: %d\n", hpriv->crefs);
|
||||
if (hpriv->crefs == 1)
|
||||
ullvdbg("crefs: %d\n", priv->crefs);
|
||||
if (priv->crefs == 1)
|
||||
{
|
||||
/* Free buffer for status change (INT) endpoint */
|
||||
|
||||
DRVR_IOFREE(hclass->drvr, hpriv->intxfer.buffer);
|
||||
DRVR_IOFREE(hubclass->drvr, priv->intxfer.buffer);
|
||||
|
||||
/* Power off (for root hub only) */
|
||||
(void)usbhost_hubpwr(hclass, false);
|
||||
(void)usbhost_hubpwr(hubclass, false);
|
||||
|
||||
/* Destroy the class instance */
|
||||
|
||||
usbhost_destroy(hclass);
|
||||
usbhost_destroy(hubclass);
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
@ -1343,22 +1341,22 @@ int usbhost_hubinit(void)
|
||||
|
||||
int usbhost_rh_connect(FAR struct usbhost_driver_s *drvr)
|
||||
{
|
||||
struct usbhost_class_s *hclass = NULL;
|
||||
struct usbhost_class_s *hubclass = NULL;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
memset(g_addrmap, 0, 4*4);
|
||||
|
||||
hclass = usbhost_allocclass(drvr, NULL, drvr->speed, 1);
|
||||
if (hclass != NULL)
|
||||
hubclass = usbhost_allocclass(drvr, NULL, drvr->speed, 1);
|
||||
if (hubclass != NULL)
|
||||
{
|
||||
ret = usbhost_enumerate(hclass);
|
||||
ret = usbhost_enumerate(hubclass);
|
||||
if (ret != OK)
|
||||
{
|
||||
udbg("failed to enumerate root hub\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
drvr->roothub = hclass;
|
||||
drvr->roothub = hubclass;
|
||||
udbg("Total class memory %d+%d\n", sizeof(struct usbhost_class_s),
|
||||
sizeof(struct usbhost_hub_s));
|
||||
}
|
||||
@ -1385,11 +1383,11 @@ int usbhost_rh_connect(FAR struct usbhost_driver_s *drvr)
|
||||
|
||||
int usbhost_rh_disconnect(FAR struct usbhost_driver_s *drvr)
|
||||
{
|
||||
FAR struct usbhost_class_s *hclass = drvr->roothub;
|
||||
FAR struct usbhost_class_s *hubclass = drvr->roothub;
|
||||
|
||||
if (hclass != NULL)
|
||||
if (hubclass != NULL)
|
||||
{
|
||||
CLASS_DISCONNECTED(hclass);
|
||||
CLASS_DISCONNECTED(hubclass);
|
||||
|
||||
drvr->roothub = NULL;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/************************************************************************************
|
||||
* include/nuttx/usb/usbhost.h
|
||||
*
|
||||
* Copyright (C) 2010-2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2010-2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References:
|
||||
@ -52,11 +52,24 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: ROOTHUB
|
||||
*
|
||||
* Description:
|
||||
* Check for root hub
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define ROOTHUB(devclass) ((devclass)->parent == NULL)
|
||||
|
||||
/************************************************************************************
|
||||
* Name: CLASS_CREATE
|
||||
*
|
||||
@ -71,9 +84,9 @@
|
||||
* Input Parameters:
|
||||
* reg - The USB host class registry entry previously obtained from a call to
|
||||
* usbhost_findclass().
|
||||
* drvr - An instance of struct usbhost_driver_s that the class implementation will
|
||||
* "bind" to its state structure and will subsequently use to communicate with
|
||||
* the USB host driver.
|
||||
* devclass - An instance of struct usbhost_driver_s that the class
|
||||
* implementation will "bind" to its state structure and will subsequently
|
||||
* use to communicate with the USB host driver.
|
||||
* id - In the case where the device supports multiple base classes, subclasses, or
|
||||
* protocols, this specifies which to configure for.
|
||||
*
|
||||
@ -81,7 +94,7 @@
|
||||
* On success, this function will return a non-NULL instance of struct
|
||||
* usbhost_class_s that can be used by the USB host driver to communicate with the
|
||||
* USB host class. NULL is returned on failure; this function will fail only if
|
||||
* the drvr input parameter is NULL or if there are insufficient resources to
|
||||
* the devclass input parameter is NULL or if there are insufficient resources to
|
||||
* create another USB host class instance.
|
||||
*
|
||||
* Assumptions:
|
||||
@ -91,23 +104,21 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define CLASS_CREATE(reg, drvr, id) ((reg)->create(drvr, id))
|
||||
#define CLASS_CREATE(reg, devclass, id) ((reg)->create(devclass, id))
|
||||
|
||||
/************************************************************************************
|
||||
* Name: CLASS_CONNECT
|
||||
*
|
||||
* Description:
|
||||
* This macro will call the connect() method of struct usbhost_class_s. This
|
||||
* method is a callback into the usbclass implementation. It is used to provide the
|
||||
* device's configuration descriptor to the usbclass so that the usbclass may initialize
|
||||
* method is a callback into the devclass implementation. It is used to provide the
|
||||
* device's configuration descriptor to the devclass so that the devclass may initialize
|
||||
* properly
|
||||
*
|
||||
* Input Parameters:
|
||||
* usbclass - The USB host class entry previously obtained from a call to create().
|
||||
* devclass - The USB host class entry previously obtained from a call to create().
|
||||
* configdesc - A pointer to a uint8_t buffer container the configuration descripor.
|
||||
* desclen - The length in bytes of the configuration descriptor.
|
||||
* funcaddr - The USB address of the function containing the endpoint that EP0
|
||||
* controls
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
@ -126,8 +137,8 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define CLASS_CONNECT(usbclass,configdesc,desclen,funcaddr) \
|
||||
((usbclass)->connect(usbclass,configdesc,desclen, funcaddr))
|
||||
#define CLASS_CONNECT(devclass,configdesc,desclen) \
|
||||
((devclass)->connect(devclass,configdesc,desclen))
|
||||
|
||||
/************************************************************************************
|
||||
* Name: CLASS_DISCONNECTED
|
||||
@ -138,7 +149,7 @@
|
||||
* class that the USB device has been disconnected.
|
||||
*
|
||||
* Input Parameters:
|
||||
* usbclass - The USB host class entry previously obtained from a call to create().
|
||||
* devclass - The USB host class entry previously obtained from a call to create().
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
@ -149,7 +160,7 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define CLASS_DISCONNECTED(usbclass) ((usbclass)->disconnected(usbclass))
|
||||
#define CLASS_DISCONNECTED(devclass) ((devclass)->disconnected(devclass))
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: CONN_WAIT
|
||||
@ -220,6 +231,7 @@
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* ep0 - The (opaque) EP0 endpoint instance
|
||||
* funcaddr - The USB address of the function containing the endpoint that EP0
|
||||
* controls
|
||||
* mps (maxpacketsize) - The maximum number of bytes that can be sent to or
|
||||
@ -234,7 +246,8 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define DRVR_EP0CONFIGURE(drvr,funcaddr,mps) ((drvr)->ep0configure(drvr,funcaddr,mps))
|
||||
#define DRVR_EP0CONFIGURE(drvr,ep0,funcaddr,mps) \
|
||||
((drvr)->ep0configure(drvr,ep0,funcaddr,mps))
|
||||
|
||||
/************************************************************************************
|
||||
* Name: DRVR_GETDEVINFO
|
||||
@ -438,7 +451,7 @@
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* req - Describes the request to be sent. This request must lie in memory
|
||||
* xfr - 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
|
||||
@ -456,8 +469,8 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define DRVR_CTRLIN(drvr,req,buffer) ((drvr)->ctrlin(drvr,req,buffer))
|
||||
#define DRVR_CTRLOUT(drvr,req,buffer) ((drvr)->ctrlout(drvr,req,buffer))
|
||||
#define DRVR_CTRLIN(drvr,xfer,cmd) ((drvr)->ctrlin(drvr,xfer,cmd))
|
||||
#define DRVR_CTRLOUT(drvr,xfer,cmd) ((drvr)->ctrlout(drvr,xfer,cmd))
|
||||
|
||||
/************************************************************************************
|
||||
* Name: DRVR_TRANSFER
|
||||
@ -495,7 +508,7 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define DRVR_TRANSFER(drvr,ed,buffer,buflen) ((drvr)->transfer(drvr,ed,buffer,buflen))
|
||||
#define DRVR_TRANSFER(drvr,xfer) ((drvr)->transfer(drvr,xfer))
|
||||
|
||||
/************************************************************************************
|
||||
* Name: DRVR_DISCONNECT
|
||||
@ -521,6 +534,34 @@
|
||||
|
||||
#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr))
|
||||
|
||||
/************************************************************************************
|
||||
* Name: DRVR_RHCTRL and DRVR_RHSTATUS
|
||||
*
|
||||
* Description:
|
||||
* Called by hub class to control root hub.
|
||||
*
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* xfer - Describes the request to be sent. This request must lie in memory
|
||||
* created by DRVR_ALLOC.
|
||||
* cmd - 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.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
* returned indicating the nature of the failure
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_UBHOST_HUB
|
||||
# define DRVR_RHCTRL(drvr,xfer,cmd) ((drvr)->rhctrl(drvr,xfer,cmd))
|
||||
# define DRVR_RHSTATUS(drvr,xfer) ((drvr)->rhstatus(drvr,xfer))
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
@ -553,7 +594,7 @@ struct usbhost_registry_s
|
||||
* provide those instances in write-able memory (RAM).
|
||||
*/
|
||||
|
||||
struct usbhost_registry_s *flink;
|
||||
struct usbhost_registry_s *flink;
|
||||
|
||||
/* This is a callback into the class implementation. It is used to (1) create
|
||||
* a new instance of the USB host class state and to (2) bind a USB host driver
|
||||
@ -562,14 +603,14 @@ struct usbhost_registry_s
|
||||
* simultaneously connected (see the CLASS_CREATE() macro above).
|
||||
*/
|
||||
|
||||
FAR struct usbhost_class_s *(*create)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR const struct usbhost_id_s *id);
|
||||
int (*create)(FAR struct usbhost_class_s *devclass,
|
||||
FAR const struct usbhost_id_s *id);
|
||||
|
||||
/* This information uniquely identifies the USB host class implementation that
|
||||
* goes with a specific USB device.
|
||||
*/
|
||||
|
||||
uint8_t nids; /* Number of IDs in the id[] array */
|
||||
uint8_t nids; /* Number of IDs in the id[] array */
|
||||
FAR const struct usbhost_id_s *id; /* An array of ID info. Actual dimension is nids */
|
||||
};
|
||||
|
||||
@ -579,18 +620,49 @@ struct usbhost_registry_s
|
||||
|
||||
struct usbhost_class_s
|
||||
{
|
||||
#ifdef CONFIG_UBHOST_HUB
|
||||
/* Host driver */
|
||||
|
||||
struct usbhost_driver_s *drvr;
|
||||
|
||||
/* USB device address & speed */
|
||||
|
||||
uint8_t addr;
|
||||
uint8_t speed;
|
||||
|
||||
/* Parent class */
|
||||
|
||||
struct usbhost_class_s *parent;
|
||||
|
||||
/* Control endpoint, ep0 */
|
||||
|
||||
usbhost_ep_t ep0;
|
||||
|
||||
/* Transaction translator hub */
|
||||
|
||||
FAR struct usb_hubtt_s *tt;
|
||||
|
||||
/* Transaction translator port */
|
||||
|
||||
uint8_t ttport;
|
||||
|
||||
/* Class specific private data */
|
||||
|
||||
FAR void *priv;
|
||||
#endif
|
||||
|
||||
/* Provides the configuration descriptor to the class. The configuration
|
||||
* descriptor contains critical information needed by the class in order to
|
||||
* initialize properly (such as endpoint selections).
|
||||
*/
|
||||
|
||||
int (*connect)(FAR struct usbhost_class_s *usbclass,
|
||||
int (*connect)(FAR struct usbhost_class_s *devclass,
|
||||
FAR const uint8_t *configdesc,
|
||||
int desclen, uint8_t funcaddr);
|
||||
int desclen);
|
||||
|
||||
/* This method informs the class that the USB device has been disconnected. */
|
||||
|
||||
int (*disconnected)(FAR struct usbhost_class_s *usbclass);
|
||||
int (*disconnected)(FAR struct usbhost_class_s *devclass);
|
||||
};
|
||||
|
||||
/* This structure describes one endpoint. It is used as an input to the
|
||||
@ -600,12 +672,15 @@ struct usbhost_class_s
|
||||
|
||||
struct usbhost_epdesc_s
|
||||
{
|
||||
uint8_t addr; /* Endpoint address */
|
||||
bool in; /* Direction: true->IN */
|
||||
uint8_t funcaddr; /* USB address of function containing endpoint */
|
||||
uint8_t xfrtype; /* Transfer type. See USB_EP_ATTR_XFER_* in usb.h */
|
||||
uint8_t interval; /* Polling interval */
|
||||
uint16_t mxpacketsize; /* Max packetsize */
|
||||
#ifdef CONFIG_UBHOST_HUB
|
||||
FAR struct usbhost_class_s *devclass; /* Class */
|
||||
#endif
|
||||
uint8_t addr; /* Endpoint address */
|
||||
bool in; /* Direction: true->IN */
|
||||
uint8_t funcaddr; /* USB address of function containing endpoint */
|
||||
uint8_t xfrtype; /* Transfer type. See USB_EP_ATTR_XFER_* in usb.h */
|
||||
uint8_t interval; /* Polling interval */
|
||||
uint16_t mxpacketsize; /* Max packetsize */
|
||||
};
|
||||
|
||||
/* This structure provides information about the connected device */
|
||||
@ -616,15 +691,45 @@ struct usbhost_devinfo_s
|
||||
};
|
||||
|
||||
/* This type represents one endpoint configured by the epalloc() method.
|
||||
* The actual form is know only internally to the USB host controller
|
||||
* The actual form is known only internally to the USB host controller
|
||||
* (for example, for an OHCI driver, this would probably be a pointer
|
||||
* to an endpoint descriptor).
|
||||
*/
|
||||
|
||||
typedef FAR void *usbhost_ep_t;
|
||||
|
||||
/* Generic transfer structure */
|
||||
|
||||
struct usbhost_transfer_s
|
||||
{
|
||||
FAR uint8_t *buffer;
|
||||
size_t buflen;
|
||||
size_t len;
|
||||
int status;
|
||||
|
||||
/* Semaphore of synchronized transfers */
|
||||
|
||||
sem_t done;
|
||||
|
||||
/* Device class */
|
||||
|
||||
FAR struct usbhost_class_s *devclass;
|
||||
|
||||
/* Opaque endpoint pointer; can be xHCI specific */
|
||||
|
||||
usbhost_ep_t ep;
|
||||
|
||||
/* Workqueue for callback */
|
||||
|
||||
struct work_s work;
|
||||
|
||||
/* Transfer complete callback */
|
||||
|
||||
void (*callback)(FAR struct usbhost_transfer_s *);
|
||||
};
|
||||
|
||||
/* struct usbhost_connection_s provides as interface between platform-specific
|
||||
* connection monitoring and the USB host driver connectin and enumeration
|
||||
* connection monitoring and the USB host driver connection and enumeration
|
||||
* logic.
|
||||
*/
|
||||
|
||||
@ -653,13 +758,23 @@ struct usbhost_connection_s
|
||||
|
||||
struct usbhost_driver_s
|
||||
{
|
||||
#ifdef CONFIG_UBHOST_HUB
|
||||
/* Root hub */
|
||||
|
||||
FAR struct usbhost_class_s *roothub;
|
||||
|
||||
/* Controller speed, i.e. High/Full/Low */
|
||||
|
||||
uint8_t speed;
|
||||
#endif
|
||||
|
||||
/* Configure endpoint 0. This method is normally used internally by the
|
||||
* enumerate() method but is made available at the interface to support
|
||||
* an external implementation of the enumeration logic.
|
||||
*/
|
||||
|
||||
int (*ep0configure)(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
||||
uint16_t maxpacketsize);
|
||||
int (*ep0configure)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
||||
uint8_t funcaddr, uint16_t maxpacketsize);
|
||||
|
||||
/* Get information about the connected device */
|
||||
|
||||
@ -711,11 +826,11 @@ struct usbhost_driver_s
|
||||
*/
|
||||
|
||||
int (*ctrlin)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR const struct usb_ctrlreq_s *req,
|
||||
FAR uint8_t *buffer);
|
||||
FAR struct usbhost_transfer_s *xfer,
|
||||
FAR const struct usb_ctrlreq_s *cmd);
|
||||
int (*ctrlout)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR const struct usb_ctrlreq_s *req,
|
||||
FAR const uint8_t *buffer);
|
||||
FAR struct usbhost_transfer_s *xfer,
|
||||
FAR const struct usb_ctrlreq_s *cmd);
|
||||
|
||||
/* Process a request to handle a transfer descriptor. This method will
|
||||
* enqueue the transfer request and wait for it to complete. Only one transfer may
|
||||
@ -726,8 +841,8 @@ struct usbhost_driver_s
|
||||
* transfer has completed.
|
||||
*/
|
||||
|
||||
int (*transfer)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
FAR uint8_t *buffer, size_t buflen);
|
||||
int (*transfer)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_transfer_s *xfer);
|
||||
|
||||
/* Called by the class when an error occurs and driver has been disconnected.
|
||||
* The USB host driver should discard the handle to the class instance (it is
|
||||
@ -736,6 +851,16 @@ struct usbhost_driver_s
|
||||
*/
|
||||
|
||||
void (*disconnect)(FAR struct usbhost_driver_s *drvr);
|
||||
|
||||
#ifdef CONFIG_UBHOST_HUB
|
||||
/* Called by hub class to control root hub. */
|
||||
|
||||
int (*rhctrl)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_transfer_s *xfer,
|
||||
FAR const struct usb_ctrlreq_s *cmd);
|
||||
int (*rhstatus)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_transfer_s *xfer);
|
||||
#endif
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
@ -766,7 +891,7 @@ extern "C"
|
||||
* the device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* usbclass - An write-able instance of struct usbhost_registry_s that will be
|
||||
* devclass - An write-able instance of struct usbhost_registry_s that will be
|
||||
* maintained in a registry.
|
||||
*
|
||||
* Returned Values:
|
||||
@ -775,7 +900,7 @@ extern "C"
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int usbhost_registerclass(struct usbhost_registry_s *usbclass);
|
||||
int usbhost_registerclass(struct usbhost_registry_s *devclass);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbhost_findclass
|
||||
@ -799,6 +924,27 @@ int usbhost_registerclass(struct usbhost_registry_s *usbclass);
|
||||
|
||||
const struct usbhost_registry_s *usbhost_findclass(const struct usbhost_id_s *id);
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
/****************************************************************************
|
||||
* Name: usbhost_hubinit
|
||||
*
|
||||
* Description:
|
||||
* Initialize the USB hub class. This function should be called
|
||||
* be platform-specific code in order to initialize and register support
|
||||
* for the USB host storage class.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Values:
|
||||
* On success this function will return zero (OK); A negated errno value
|
||||
* will be returned on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int usbhost_hubinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBHOST_MSC
|
||||
/****************************************************************************
|
||||
* Name: usbhost_storageinit
|
||||
@ -881,14 +1027,52 @@ int usbhost_mouse_init(void);
|
||||
|
||||
int usbhost_wlaninit(void);
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
/****************************************************************************
|
||||
* Name: usbhost_ctrlxfer
|
||||
*
|
||||
* Description:
|
||||
* Free transfer buffer memory.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the class instance.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On failure, an negated errno value
|
||||
* is returned to indicate the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int usbhost_ctrlxfer(FAR struct usbhost_class_s *devclass, uint8_t type,
|
||||
uint8_t req, uint16_t value, uint16_t index,
|
||||
uint16_t len, FAR uint8_t *buffer);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
/****************************************************************************
|
||||
* Name: usbhost_intxfer
|
||||
*
|
||||
* Description:
|
||||
* Free transfer buffer memory.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the class instance.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On failure, an negated errno value
|
||||
* is returned to indicate the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int usbhost_intxfer(FAR struct usbhost_class_s *devclass,
|
||||
FAR struct usbhost_transfer_s *xfer,
|
||||
void (*callback)(FAR struct usbhost_transfer_s *));
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_enumerate
|
||||
*
|
||||
* Description:
|
||||
* This is a share-able implementation of most of the logic required by the
|
||||
* driver enumerate() method. This logic within this method should be common
|
||||
* to all USB host drivers.
|
||||
*
|
||||
* Enumerate the connected device. As part of this enumeration process,
|
||||
* the driver will (1) get the device's configuration descriptor, (2)
|
||||
* extract the class ID info from the configuration descriptor, (3) call
|
||||
@ -899,27 +1083,42 @@ int usbhost_wlaninit(void);
|
||||
* charge of the sequence of operations.
|
||||
*
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* funcaddr - The USB address of the function containing the endpoint that EP0
|
||||
* controls
|
||||
* usbclass - If the class driver for the device is successful located
|
||||
* and bound to the driver, the allocated class instance is returned into
|
||||
* this caller-provided memory location.
|
||||
* devclass - USB class information common across all classes. Whoever calls
|
||||
* enumerate should fill address, speed, driver and parent class
|
||||
* pointer. Enumeration will fill the control endpoint ep0,
|
||||
* transaction translator (if applicable) and private data
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
|
||||
FAR struct usbhost_class_s **usbclass);
|
||||
int usbhost_enumerate(FAR struct usbhost_class_s *devclass);
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_rh_connect
|
||||
*
|
||||
* Description:
|
||||
* Registers USB host root hub
|
||||
*
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
*
|
||||
* Returned Value:
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
int usbhost_rh_connect(FAR struct usbhost_driver_s *drvr);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
Loading…
Reference in New Issue
Block a user