USB hub: First steps to make interfaces backward compatible
This commit is contained in:
parent
8c1c365ae7
commit
a6d9f0622c
@ -40,12 +40,16 @@ ifeq ($(CONFIG_USBHOST),y)
|
|||||||
# Include built-in USB host driver logic
|
# Include built-in USB host driver logic
|
||||||
|
|
||||||
CSRCS += usbhost_registry.c usbhost_registerclass.c usbhost_findclass.c
|
CSRCS += usbhost_registry.c usbhost_registerclass.c usbhost_findclass.c
|
||||||
CSRCS += usbhost_enumerate.c usbhost_storage.c usbhost_devaddr.c
|
CSRCS += usbhost_enumerate.c usbhost_devaddr.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_USBHOST_HUB),y)
|
ifeq ($(CONFIG_USBHOST_HUB),y)
|
||||||
CSRCS += usbhost_hub.c
|
CSRCS += usbhost_hub.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USBHOST_MSC),y)
|
||||||
|
CSRCS += usbhost_storage.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USBHOST_HIDKBD),y)
|
ifeq ($(CONFIG_USBHOST_HIDKBD),y)
|
||||||
CSRCS += usbhost_hidkbd.c
|
CSRCS += usbhost_hidkbd.c
|
||||||
endif
|
endif
|
||||||
|
@ -67,8 +67,6 @@
|
|||||||
static inline uint16_t usbhost_getle16(const uint8_t *val);
|
static inline uint16_t usbhost_getle16(const uint8_t *val);
|
||||||
static void usbhost_putle16(uint8_t *dest, uint16_t val);
|
static void usbhost_putle16(uint8_t *dest, uint16_t val);
|
||||||
|
|
||||||
static void usbhost_callback(FAR struct usbhost_transfer_s *xfer);
|
|
||||||
|
|
||||||
static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc,
|
static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc,
|
||||||
FAR struct usbhost_id_s *id);
|
FAR struct usbhost_id_s *id);
|
||||||
static inline int usbhost_configdesc(const uint8_t *configdesc, int desclen,
|
static inline int usbhost_configdesc(const uint8_t *configdesc, int desclen,
|
||||||
@ -116,19 +114,6 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val)
|
|||||||
dest[1] = val >> 8;
|
dest[1] = val >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: usbhost_callback
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
static void usbhost_callback(FAR struct usbhost_transfer_s *xfer)
|
|
||||||
{
|
|
||||||
sem_post(&xfer->done);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Name: usbhost_devdesc
|
* Name: usbhost_devdesc
|
||||||
*
|
*
|
||||||
@ -173,8 +158,8 @@ static inline int usbhost_devdesc(FAR const struct usb_devdesc_s *devdesc,
|
|||||||
static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen,
|
static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen,
|
||||||
struct usbhost_id_s *id)
|
struct usbhost_id_s *id)
|
||||||
{
|
{
|
||||||
struct usb_cfgdesc_s *cfgdesc;
|
FAR struct usb_cfgdesc_s *cfgdesc;
|
||||||
struct usb_ifdesc_s *ifdesc;
|
FAR struct usb_ifdesc_s *ifdesc;
|
||||||
int remaining;
|
int remaining;
|
||||||
|
|
||||||
DEBUGASSERT(configdesc != NULL && cfglen >= USB_SIZEOF_CFGDESC);
|
DEBUGASSERT(configdesc != NULL && cfglen >= USB_SIZEOF_CFGDESC);
|
||||||
@ -392,7 +377,7 @@ int usbhost_enumerate(FAR struct usbhost_class_s *devclass)
|
|||||||
usbhost_putle16(ctrlreq->index, 0);
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
usbhost_putle16(ctrlreq->len, descsize);
|
usbhost_putle16(ctrlreq->len, descsize);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(devclass, ctrlreq, buffer);
|
ret = DRVR_CTRLIN(devclass->drvr, ctrlreq, buffer);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to get device descriptor, length=%d: %d\n",
|
udbg("ERROR: Failed to get device descriptor, length=%d: %d\n",
|
||||||
@ -417,7 +402,7 @@ int usbhost_enumerate(FAR struct usbhost_class_s *devclass)
|
|||||||
usbhost_putle16(ctrlreq->index, 0);
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
usbhost_putle16(ctrlreq->len, 0);
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(devclass, ctrlreq, NULL);
|
ret = DRVR_CTRLOUT(devclass->drvr, ctrlreq, NULL);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to set address: %d\n");
|
udbg("ERROR: Failed to set address: %d\n");
|
||||||
@ -441,7 +426,7 @@ int usbhost_enumerate(FAR struct usbhost_class_s *devclass)
|
|||||||
usbhost_putle16(ctrlreq->index, 0);
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
usbhost_putle16(ctrlreq->len, USB_SIZEOF_DEVDESC);
|
usbhost_putle16(ctrlreq->len, USB_SIZEOF_DEVDESC);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(devclass, ctrlreq, buffer);
|
ret = DRVR_CTRLIN(devclass->drvr, ctrlreq, buffer);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to get device descriptor, length=%d: %d\n",
|
udbg("ERROR: Failed to get device descriptor, length=%d: %d\n",
|
||||||
@ -469,7 +454,7 @@ int usbhost_enumerate(FAR struct usbhost_class_s *devclass)
|
|||||||
usbhost_putle16(ctrlreq->index, 0);
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
usbhost_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC);
|
usbhost_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(devclass, ctrlreq, buffer);
|
ret = DRVR_CTRLIN(devclass->drvr, ctrlreq, buffer);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to get configuration descriptor, length=%d: %d\n",
|
udbg("ERROR: Failed to get configuration descriptor, length=%d: %d\n",
|
||||||
@ -492,7 +477,7 @@ int usbhost_enumerate(FAR struct usbhost_class_s *devclass)
|
|||||||
usbhost_putle16(ctrlreq->index, 0);
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
usbhost_putle16(ctrlreq->len, cfglen);
|
usbhost_putle16(ctrlreq->len, cfglen);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(devclass, ctrlreq, buffer);
|
ret = DRVR_CTRLIN(devclass->drvr, ctrlreq, buffer);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to get configuration descriptor, length=%d: %d\n",
|
udbg("ERROR: Failed to get configuration descriptor, length=%d: %d\n",
|
||||||
@ -508,7 +493,7 @@ int usbhost_enumerate(FAR struct usbhost_class_s *devclass)
|
|||||||
usbhost_putle16(ctrlreq->index, 0);
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
usbhost_putle16(ctrlreq->len, 0);
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(devclass, ctrlreq, NULL);
|
ret = DRVR_CTRLOUT(devclass->drvr, ctrlreq, NULL);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to set configuration: %d\n", ret);
|
udbg("ERROR: Failed to set configuration: %d\n", ret);
|
||||||
@ -562,78 +547,3 @@ errout:
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: usbhost_ctrlxfer
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Free transfer buffer memory.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* devclass - A reference to the class instance.
|
|
||||||
* ctrlreq - Describes the control request transfer
|
|
||||||
* buffer - Data accompanying the control transfer
|
|
||||||
*
|
|
||||||
* Returned Values:
|
|
||||||
* On sucess, 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,
|
|
||||||
FAR struct usb_ctrlreq_s *ctrlreq,
|
|
||||||
FAR uint8_t *buffer)
|
|
||||||
{
|
|
||||||
struct usbhost_transfer_s xfer;
|
|
||||||
struct timespec timeout;
|
|
||||||
uint16_t len;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
len = usbhost_getle16(ctrlreq->len);
|
|
||||||
xfer.buffer = buffer;
|
|
||||||
xfer.buflen = len;
|
|
||||||
xfer.len = len;
|
|
||||||
xfer.status = -EIO;
|
|
||||||
xfer.devclass = devclass;
|
|
||||||
xfer.ep = devclass->ep0;
|
|
||||||
xfer.callback = usbhost_callback;
|
|
||||||
|
|
||||||
sem_init(&xfer.done, 0, 0);
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_HUB
|
|
||||||
if (ROOTHUB(devclass))
|
|
||||||
{
|
|
||||||
ret = DRVR_RHCTRL(devclass->drvr, &xfer, ctrlreq);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if ((ctrlreq->type & USB_REQ_DIR_IN) != 0)
|
|
||||||
{
|
|
||||||
ret = DRVR_CTRLIN(devclass->drvr, &xfer, ctrlreq);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = DRVR_CTRLOUT(devclass->drvr, &xfer, ctrlreq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != OK)
|
|
||||||
{
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout.tv_sec = 5;
|
|
||||||
timeout.tv_nsec = 1000*1000;
|
|
||||||
|
|
||||||
ret = sem_timedwait(&xfer.done, &timeout);
|
|
||||||
if (ret == OK)
|
|
||||||
{
|
|
||||||
ret = xfer.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
sem_destroy(&xfer.done);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||||
* Author: Kaushal Parikh <kaushal@dspworks.in>
|
* Author: Kaushal Parikh <kaushal@dspworks.in>
|
||||||
|
* Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -92,21 +93,23 @@
|
|||||||
|
|
||||||
struct usbhost_hub_s
|
struct usbhost_hub_s
|
||||||
{
|
{
|
||||||
volatile bool disconnected; /* TRUE: Device has been disconnected */
|
FAR struct usb_ctrlreq_s *ctrlreq; /* Allocated control request */
|
||||||
|
FAR uint8_t *buffer; /* Allocated buffer */
|
||||||
uint8_t ifno; /* Interface number */
|
uint8_t ifno; /* Interface number */
|
||||||
|
uint8_t nports; /* Number of ports */
|
||||||
|
uint8_t lpsm; /* Logical power switching mode */
|
||||||
|
uint8_t ocmode; /* Over current protection mode */
|
||||||
|
uint8_t ctrlcurrent; /* Control current */
|
||||||
|
volatile bool disconnected; /* TRUE: Device has been disconnected */
|
||||||
|
bool compounddev; /* Hub is part of compound device */
|
||||||
|
bool indicator; /* Port indicator */
|
||||||
|
|
||||||
|
uint16_t pwrondelay; /* Power on wait time in ms */
|
||||||
int16_t crefs; /* Reference count on the driver instance */
|
int16_t crefs; /* Reference count on the driver instance */
|
||||||
sem_t exclsem; /* Used to maintain mutual exclusive access */
|
sem_t exclsem; /* Used to maintain mutual exclusive access */
|
||||||
|
|
||||||
uint8_t nports; /* Number of ports */
|
|
||||||
uint8_t lpsm; /* Logical power switching mode */
|
|
||||||
bool compounddev; /* Hub is part of compound device */
|
|
||||||
uint8_t ocmode; /* Over current protection mode */
|
|
||||||
bool indicator; /* Port indicator */
|
|
||||||
uint16_t pwrondelay; /* Power on wait time in ms */
|
|
||||||
uint8_t ctrlcurrent; /* Control current */
|
|
||||||
|
|
||||||
struct usb_hubtt_s tt; /* Transaction translator */
|
struct usb_hubtt_s tt; /* Transaction translator */
|
||||||
struct usbhost_transfer_s intxfer; /* Interrupt IN endpoint */
|
usbhost_ep_t intin; /* Interrupt IN endpoint */
|
||||||
|
|
||||||
struct usbhost_class_s *childclass[USBHUB_MAX_PORTS];
|
struct usbhost_class_s *childclass[USBHUB_MAX_PORTS];
|
||||||
/* Pointer to child devices */
|
/* Pointer to child devices */
|
||||||
@ -116,11 +119,6 @@ struct usbhost_hub_s
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Semaphores */
|
|
||||||
|
|
||||||
static void usbhost_takesem(sem_t *sem);
|
|
||||||
#define usbhost_givesem(s) sem_post(s);
|
|
||||||
|
|
||||||
/* Memory allocation services */
|
/* Memory allocation services */
|
||||||
|
|
||||||
static inline uint8_t usbhost_allocaddr(void);
|
static inline uint8_t usbhost_allocaddr(void);
|
||||||
@ -198,29 +196,6 @@ static uint32_t g_addrmap[4];
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: usbhost_takesem
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This is just a wrapper to handle the annoying behavior of semaphore
|
|
||||||
* waits that return due to the receipt of a signal.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void usbhost_takesem(sem_t *sem)
|
|
||||||
{
|
|
||||||
/* Take the semaphore (perhaps waiting) */
|
|
||||||
|
|
||||||
while (sem_wait(sem) != 0)
|
|
||||||
{
|
|
||||||
/* The only case that an error should occr here is if the wait was
|
|
||||||
* awakened by a signal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ASSERT(errno == EINTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: usbhost_allocaddr
|
* Name: usbhost_allocaddr
|
||||||
*
|
*
|
||||||
@ -291,12 +266,12 @@ static inline FAR struct usbhost_class_s *
|
|||||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||||
|
|
||||||
/* We are not executing from an interrupt handler so we can just call
|
/* We are not executing from an interrupt handler so we can just call
|
||||||
* kmalloc() to get memory for the class instance.
|
* kmm_malloc() to get memory for the class instance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(!up_interrupt_context());
|
DEBUGASSERT(!up_interrupt_context());
|
||||||
devclass = (FAR struct usbhost_class_s *)
|
devclass = (FAR struct usbhost_class_s *)
|
||||||
kmalloc(sizeof(struct usbhost_class_s));
|
kmm_malloc(sizeof(struct usbhost_class_s));
|
||||||
|
|
||||||
uvdbg("Allocated: %p\n", devclass);
|
uvdbg("Allocated: %p\n", devclass);
|
||||||
|
|
||||||
@ -313,20 +288,20 @@ static inline FAR struct usbhost_class_s *
|
|||||||
devclass->priv = NULL;
|
devclass->priv = NULL;
|
||||||
|
|
||||||
devclass->tt = NULL;
|
devclass->tt = NULL;
|
||||||
devclass->ttport = 0;
|
devclass->rhport = 0;
|
||||||
|
|
||||||
if (!ROOTHUB(devclass))
|
if (!ROOTHUB(devclass))
|
||||||
{
|
{
|
||||||
if (hubclass->tt != NULL)
|
if (hubclass->tt != NULL)
|
||||||
{
|
{
|
||||||
devclass->tt = hubclass->tt;
|
devclass->tt = hubclass->tt;
|
||||||
devclass->ttport = hubclass->ttport;
|
devclass->rhport = hubclass->rhport;
|
||||||
}
|
}
|
||||||
else if ((devclass->speed != USB_SPEED_HIGH) &&
|
else if ((devclass->speed != USB_SPEED_HIGH) &&
|
||||||
(hubclass->speed == USB_SPEED_HIGH))
|
(hubclass->speed == USB_SPEED_HIGH))
|
||||||
{
|
{
|
||||||
devclass->tt = &priv->tt;
|
devclass->tt = &priv->tt;
|
||||||
devclass->ttport = port;
|
devclass->rhport = port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +355,7 @@ static inline void usbhost_freeclass(FAR struct usbhost_class_s *devclass)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uvdbg("Freeing: %p\n", devclass);
|
uvdbg("Freeing: %p\n", devclass);
|
||||||
kfree(devclass);
|
kmm_free(devclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -412,9 +387,9 @@ static void usbhost_destroy(FAR void *arg)
|
|||||||
{
|
{
|
||||||
uvdbg("crefs: %d\n", priv->crefs);
|
uvdbg("crefs: %d\n", priv->crefs);
|
||||||
|
|
||||||
if (priv->intxfer.ep)
|
if (priv->intin)
|
||||||
{
|
{
|
||||||
DRVR_EPFREE(hubclass->drvr, priv->intxfer.ep);
|
DRVR_EPFREE(hubclass->drvr, priv->intin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy the semaphores */
|
/* Destroy the semaphores */
|
||||||
@ -431,9 +406,9 @@ static void usbhost_destroy(FAR void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear priv class */
|
/* Free private class */
|
||||||
|
|
||||||
kfree(hubclass->priv);
|
kmm_free(hubclass->priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
usbhost_freeclass(hubclass);
|
usbhost_freeclass(hubclass);
|
||||||
@ -609,11 +584,11 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hubclass,
|
|||||||
|
|
||||||
/* We are good... Allocate the endpoints */
|
/* We are good... Allocate the endpoints */
|
||||||
|
|
||||||
ret = DRVR_EPALLOC(hubclass->drvr, &intindesc, &priv->intxfer.ep);
|
ret = DRVR_EPALLOC(hubclass->drvr, &intindesc, &priv->intin);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to allocate Interrupt IN endpoint: %d\n", ret);
|
udbg("ERROR: Failed to allocate Interrupt IN endpoint: %d\n", ret);
|
||||||
(void)DRVR_EPFREE(hubclass->drvr, priv->intxfer.ep);
|
(void)DRVR_EPFREE(hubclass->drvr, priv->intin);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,6 +620,7 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hubclass,
|
|||||||
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hubclass)
|
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hubclass)
|
||||||
{
|
{
|
||||||
FAR struct usbhost_hub_s *priv;
|
FAR struct usbhost_hub_s *priv;
|
||||||
|
FAR struct usb_ctrlreq_s *ctrlreq;
|
||||||
struct usb_hubdesc_s hubdesc;
|
struct usb_hubdesc_s hubdesc;
|
||||||
uint16_t hubchar;
|
uint16_t hubchar;
|
||||||
int ret;
|
int ret;
|
||||||
@ -652,9 +628,18 @@ static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hubclass)
|
|||||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(hubclass, (USB_REQ_DIR_IN | USBHUB_REQ_TYPE_HUB),
|
/* Get the hub descriptor */
|
||||||
USB_REQ_GETDESCRIPTOR, USB_DESC_TYPE_HUB,
|
|
||||||
0, USB_SIZEOF_HUBDESC, (uint8_t *)&hubdesc);
|
ctrlreq = priv->ctrlreq;
|
||||||
|
DEBUGASSERT(ctrlreq);
|
||||||
|
|
||||||
|
ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_HUB;
|
||||||
|
ctrlreq->req = USB_REQ_GETDESCRIPTOR;
|
||||||
|
usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_HUB << 8));
|
||||||
|
usbhost_putle16(ctrlreq->index, 0);
|
||||||
|
usbhost_putle16(ctrlreq->len, USB_SIZEOF_HUBDESC);
|
||||||
|
|
||||||
|
ret = DRVR_CTRLIN(hubclass->drvr, ctrlreq, (FAR uint8_t *)&hubdesc);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to read hub descriptor: %d\n", ret);
|
udbg("ERROR: Failed to read hub descriptor: %d\n", ret);
|
||||||
@ -699,6 +684,7 @@ 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 inline int usbhost_hubpwr(FAR struct usbhost_class_s *hubclass, bool on)
|
||||||
{
|
{
|
||||||
FAR struct usbhost_hub_s *priv;
|
FAR struct usbhost_hub_s *priv;
|
||||||
|
FAR struct usb_ctrlreq_s *ctrlreq;
|
||||||
|
|
||||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||||
@ -717,11 +703,20 @@ static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hubclass, bool on)
|
|||||||
req = USB_REQ_CLEARFEATURE;
|
req = USB_REQ_CLEARFEATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set port power */
|
||||||
|
|
||||||
|
ctrlreq = priv->ctrlreq;
|
||||||
|
DEBUGASSERT(ctrlreq);
|
||||||
|
|
||||||
for (port = 1; port <= priv->nports; port++)
|
for (port = 1; port <= priv->nports; port++)
|
||||||
{
|
{
|
||||||
ret = usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
ctrlreq->type = USBHUB_REQ_TYPE_PORT;
|
||||||
req, USBHUB_PORT_FEAT_POWER,
|
ctrlreq->req = req;
|
||||||
port, 0, NULL);
|
usbhost_putle16(ctrlreq->value, (USBHUB_PORT_FEAT_POWER << 8));
|
||||||
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
|
ret = DRVR_CTRLOUT(hubclass->drvr, ctrlreq, NULL);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to power %d port %d: %d\n", on, port, ret);
|
udbg("ERROR: Failed to power %d port %d: %d\n", on, port, ret);
|
||||||
@ -737,7 +732,7 @@ static inline int usbhost_hubpwr(FAR struct usbhost_class_s *hubclass, bool on)
|
|||||||
* Name: usbhost_intxfer
|
* Name: usbhost_intxfer
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Free transfer buffer memory.
|
* Set-up to receive a callback when an interrupt packet is received.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* devclass - A reference to the class instance.
|
* devclass - A reference to the class instance.
|
||||||
@ -774,10 +769,7 @@ static int usbhost_intxfer(FAR struct usbhost_class_s *devclass,
|
|||||||
* Name: usbhost_hubevent
|
* Name: usbhost_hubevent
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This function implements the connect() method of struct
|
* Handle a hub event.
|
||||||
* usbhost_class_s. This method is a callback into the class
|
|
||||||
* implementation. It is used to provide the device's configuration
|
|
||||||
* descriptor to the class so that the class may initialize properly
|
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* xfer - The USB host class instance.
|
* xfer - The USB host class instance.
|
||||||
@ -795,6 +787,7 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
{
|
{
|
||||||
FAR struct usbhost_class_s *hubclass;
|
FAR struct usbhost_class_s *hubclass;
|
||||||
FAR struct usbhost_hub_s *priv;
|
FAR struct usbhost_hub_s *priv;
|
||||||
|
FAR struct usb_ctrlreq_s *ctrlreq;
|
||||||
struct usb_portstatus_s portstatus;
|
struct usb_portstatus_s portstatus;
|
||||||
uint16_t status;
|
uint16_t status;
|
||||||
uint16_t change;
|
uint16_t change;
|
||||||
@ -810,7 +803,10 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||||
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||||
|
|
||||||
statusmap = xfer->buffer[0];
|
ctrlreq = priv->ctrlreq;
|
||||||
|
DEBUGASSERT(ctrlreq);
|
||||||
|
|
||||||
|
statusmap = priv->buffer[0];
|
||||||
|
|
||||||
for (port = 1; port <= priv->nports; port++)
|
for (port = 1; port <= priv->nports; port++)
|
||||||
{
|
{
|
||||||
@ -827,10 +823,13 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
|
|
||||||
/* Read hub port status */
|
/* Read hub port status */
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(hubclass,
|
ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT;
|
||||||
(USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT),
|
ctrlreq->req = USB_REQ_GETSTATUS;
|
||||||
USB_REQ_GETSTATUS, 0, port,
|
usbhost_putle16(ctrlreq->value, 0);
|
||||||
USB_SIZEOF_PORTSTS, (uint8_t *)&portstatus);
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, USB_SIZEOF_PORTSTS);
|
||||||
|
|
||||||
|
ret = DRVR_CTRLIN(hubclass->drvr, ctrlreq, (FAR uint8_t *)&portstatus);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to read port %d status: %d\n", port, ret);
|
udbg("ERROR: Failed to read port %d status: %d\n", port, ret);
|
||||||
@ -848,9 +847,13 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
{
|
{
|
||||||
if (change & mask)
|
if (change & mask)
|
||||||
{
|
{
|
||||||
ret = usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
ctrlreq->type = USBHUB_REQ_TYPE_PORT;
|
||||||
USB_REQ_CLEARFEATURE, feat,
|
ctrlreq->req = USB_REQ_CLEARFEATURE;
|
||||||
port, 0, NULL);
|
usbhost_putle16(ctrlreq->value, (feat << 8));
|
||||||
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
|
ret = DRVR_CTRLOUT(hubclass->drvr, ctrlreq, NULL);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to clear port %d change mask %x: %d\n",
|
udbg("ERROR: Failed to clear port %d change mask %x: %d\n",
|
||||||
@ -880,14 +883,17 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
|
|
||||||
while (debouncetime < 1500)
|
while (debouncetime < 1500)
|
||||||
{
|
{
|
||||||
ret = usbhost_ctrlxfer(hubclass,
|
ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT;
|
||||||
(USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT),
|
ctrlreq->req = USB_REQ_GETSTATUS;
|
||||||
USB_REQ_GETSTATUS, 0, port,
|
usbhost_putle16(ctrlreq->value, 0);
|
||||||
USB_SIZEOF_PORTSTS, (uint8_t *)&portstatus);
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
if (ret != OK)
|
usbhost_putle16(ctrlreq->len, USB_SIZEOF_PORTSTS);
|
||||||
{
|
|
||||||
break;
|
ret = DRVR_CTRLIN(hubclass->drvr, ctrlreq, (FAR uint8_t *)&portstatus);
|
||||||
}
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
status = usbhost_getle16(portstatus.status);
|
status = usbhost_getle16(portstatus.status);
|
||||||
change = usbhost_getle16(portstatus.change);
|
change = usbhost_getle16(portstatus.change);
|
||||||
@ -909,9 +915,13 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
|
|
||||||
if (change & USBHUB_PORT_STAT_CCONNECTION)
|
if (change & USBHUB_PORT_STAT_CCONNECTION)
|
||||||
{
|
{
|
||||||
(void)usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
ctrlreq->type = USBHUB_REQ_TYPE_PORT;
|
||||||
USB_REQ_CLEARFEATURE, USBHUB_PORT_FEAT_CCONNECTION,
|
ctrlreq->req = USB_REQ_CLEARFEATURE;
|
||||||
port, 0, NULL);
|
usbhost_putle16(ctrlreq->value, (USBHUB_PORT_FEAT_CCONNECTION << 8));
|
||||||
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
|
(void)DRVR_CTRLOUT(hubclass->drvr, ctrlreq, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
debouncetime += 25;
|
debouncetime += 25;
|
||||||
@ -927,10 +937,14 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
if (status & USBHUB_PORT_STAT_CONNECTION)
|
if (status & USBHUB_PORT_STAT_CONNECTION)
|
||||||
{
|
{
|
||||||
/* Connect */
|
/* Connect */
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
ctrlreq->type = USBHUB_REQ_TYPE_PORT;
|
||||||
USB_REQ_SETFEATURE,
|
ctrlreq->req = USB_REQ_SETFEATURE;
|
||||||
USBHUB_PORT_FEAT_RESET, port, 0, NULL);
|
usbhost_putle16(ctrlreq->value, (USBHUB_PORT_FEAT_RESET << 8));
|
||||||
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
|
ret = DRVR_CTRLOUT(hubclass->drvr, ctrlreq, NULL);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: ailed to reset port %d: %d\n", port, ret);
|
udbg("ERROR: ailed to reset port %d: %d\n", port, ret);
|
||||||
@ -939,10 +953,13 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
|
|
||||||
up_mdelay(100);
|
up_mdelay(100);
|
||||||
|
|
||||||
ret = usbhost_ctrlxfer(hubclass,
|
ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT;
|
||||||
(USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT),
|
ctrlreq->req = USB_REQ_GETSTATUS;
|
||||||
USB_REQ_GETSTATUS, 0, port,
|
usbhost_putle16(ctrlreq->value, 0);
|
||||||
USB_SIZEOF_PORTSTS, (uint8_t *)&portstatus);
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, USB_SIZEOF_PORTSTS);
|
||||||
|
|
||||||
|
ret = DRVR_CTRLIN(hubclass->drvr, ctrlreq, (FAR uint8_t *)&portstatus);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
udbg("ERROR: Failed to reset port %d: %d\n", port, ret);
|
udbg("ERROR: Failed to reset port %d: %d\n", port, ret);
|
||||||
@ -962,10 +979,13 @@ static void usbhost_hubevent(FAR struct usbhost_transfer_s *xfer)
|
|||||||
|
|
||||||
if (change & USBHUB_PORT_STAT_CRESET)
|
if (change & USBHUB_PORT_STAT_CRESET)
|
||||||
{
|
{
|
||||||
(void)usbhost_ctrlxfer(hubclass, USBHUB_REQ_TYPE_PORT,
|
ctrlreq->type = USBHUB_REQ_TYPE_PORT;
|
||||||
USB_REQ_CLEARFEATURE,
|
ctrlreq->req = USB_REQ_CLEARFEATURE;
|
||||||
USBHUB_PORT_FEAT_CRESET,
|
usbhost_putle16(ctrlreq->value, (USBHUB_PORT_FEAT_CRESET << 8));
|
||||||
port, 0, NULL);
|
usbhost_putle16(ctrlreq->index, port);
|
||||||
|
usbhost_putle16(ctrlreq->len, 0);
|
||||||
|
|
||||||
|
(void)DRVR_CTRLOUT(hubclass->drvr, ctrlreq, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & USBHUB_PORT_STAT_HIGH_SPEED)
|
if (status & USBHUB_PORT_STAT_HIGH_SPEED)
|
||||||
@ -1078,7 +1098,7 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val)
|
|||||||
* Name: usbhost_callback
|
* Name: usbhost_callback
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Put a (possibly unaligned) 16-bit little endian value.
|
* Handle end of transfer callback.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* dest - A pointer to the first byte to save the little endian value.
|
* dest - A pointer to the first byte to save the little endian value.
|
||||||
@ -1091,9 +1111,18 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val)
|
|||||||
|
|
||||||
static void usbhost_callback(FAR struct usbhost_transfer_s *xfer)
|
static void usbhost_callback(FAR struct usbhost_transfer_s *xfer)
|
||||||
{
|
{
|
||||||
|
FAR struct usbhost_class_s *hubclass;
|
||||||
|
FAR struct usbhost_hub_s *priv;
|
||||||
|
|
||||||
|
DEBUGASSERT(xfer != NULL && xfer->devclass != NULL);
|
||||||
|
hubclass = (FAR struct usbhost_class_s *)xfer->devclass;
|
||||||
|
|
||||||
|
DEBUGASSERT(hubclass != NULL && hubclass->priv != NULL);
|
||||||
|
priv = (FAR struct usbhost_hub_s *)hubclass->priv;
|
||||||
|
|
||||||
if (xfer->status != OK)
|
if (xfer->status != OK)
|
||||||
{
|
{
|
||||||
xfer->buffer[0] = 0;
|
priv->buffer[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)work_queue(HPWORK, &xfer->work, (worker_t)usbhost_hubevent, xfer, 0);
|
(void)work_queue(HPWORK, &xfer->work, (worker_t)usbhost_hubevent, xfer, 0);
|
||||||
@ -1133,52 +1162,65 @@ static void usbhost_callback(FAR struct usbhost_transfer_s *xfer)
|
|||||||
static int usbhost_create(FAR struct usbhost_class_s *hubclass,
|
static int usbhost_create(FAR struct usbhost_class_s *hubclass,
|
||||||
FAR const struct usbhost_id_s *id)
|
FAR const struct usbhost_id_s *id)
|
||||||
{
|
{
|
||||||
struct usbhost_hub_s *priv;
|
FAR struct usbhost_hub_s *priv;
|
||||||
|
size_t maxlen;
|
||||||
int child;
|
int child;
|
||||||
int ret = -ENOMEM;
|
int ret;
|
||||||
|
|
||||||
/* Allocate a USB host class instance */
|
/* Allocate a USB host class instance */
|
||||||
|
|
||||||
priv = kmalloc(sizeof(struct usbhost_hub_s));
|
priv = kmm_zalloc(sizeof(struct usbhost_hub_s));
|
||||||
|
if (priv == NULL)
|
||||||
if (priv != NULL)
|
|
||||||
{
|
{
|
||||||
/* Initialize the allocated storage class instance */
|
return -ENOMEM;
|
||||||
|
|
||||||
memset(priv, 0, sizeof(struct usbhost_hub_s));
|
|
||||||
|
|
||||||
/* Initialize class method function pointers */
|
|
||||||
|
|
||||||
hubclass->connect = usbhost_connect;
|
|
||||||
hubclass->disconnected = usbhost_disconnected;
|
|
||||||
hubclass->priv = priv;
|
|
||||||
|
|
||||||
/* The initial reference count is 1... One reference is held by the driver */
|
|
||||||
|
|
||||||
priv->crefs = 1;
|
|
||||||
|
|
||||||
/* Initialize semaphores (this works okay in the interrupt context) */
|
|
||||||
|
|
||||||
sem_init(&priv->exclsem, 0, 1);
|
|
||||||
|
|
||||||
/* Initialize interrupt end-point */
|
|
||||||
|
|
||||||
priv->intxfer.ep = NULL;
|
|
||||||
|
|
||||||
/* Initialize transaction translator */
|
|
||||||
|
|
||||||
priv->tt.class = NULL;
|
|
||||||
|
|
||||||
/* Initialize child class pointers */
|
|
||||||
|
|
||||||
for (child = 0; child < USBHUB_MAX_PORTS; child++)
|
|
||||||
{
|
|
||||||
priv->childclass[child] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for control requests */
|
||||||
|
|
||||||
|
ret = DRVR_ALLOC(hubclass->drvr, (FAR uint8_t **)&priv->ctrlreq, &maxlen);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
udbg("DRVR_ALLOC failed: %d\n", ret);
|
||||||
|
goto errout_with_hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffer for status change (INT) endpoint */
|
||||||
|
|
||||||
|
ret = DRVR_IOALLOC(hubclass->drvr, &priv->buffer, 1);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
udbg("DRVR_ALLOC failed: %d\n", ret);
|
||||||
|
goto errout_with_ctrlreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize class method function pointers */
|
||||||
|
|
||||||
|
hubclass->connect = usbhost_connect;
|
||||||
|
hubclass->disconnected = usbhost_disconnected;
|
||||||
|
hubclass->priv = priv;
|
||||||
|
|
||||||
|
/* The initial reference count is 1... One reference is held by the driver */
|
||||||
|
|
||||||
|
priv->crefs = 1;
|
||||||
|
|
||||||
|
/* Initialize semaphores (this works okay in the interrupt context) */
|
||||||
|
|
||||||
|
sem_init(&priv->exclsem, 0, 1);
|
||||||
|
|
||||||
|
/* Initialize child class pointers */
|
||||||
|
|
||||||
|
for (child = 0; child < USBHUB_MAX_PORTS; child++)
|
||||||
|
{
|
||||||
|
priv->childclass[child] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
errout_with_ctrlreq:
|
||||||
|
kmm_free(priv->ctrlreq);
|
||||||
|
|
||||||
|
errout_with_hub:
|
||||||
|
kmm_free(priv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1239,15 +1281,7 @@ static int usbhost_connect(FAR struct usbhost_class_s *hubclass,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Allocate buffer for status change (INT) endpoint */
|
/* Read the hub descriptor */
|
||||||
|
|
||||||
ret = DRVR_IOALLOC(hubclass->drvr, &priv->intxfer.buffer, 1);
|
|
||||||
if (ret != OK)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now read hub descriptor */
|
|
||||||
|
|
||||||
ret = usbhost_hubdesc(hubclass);
|
ret = usbhost_hubdesc(hubclass);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
@ -1265,8 +1299,7 @@ static int usbhost_connect(FAR struct usbhost_class_s *hubclass,
|
|||||||
|
|
||||||
/* INT request to periodically check port status */
|
/* INT request to periodically check port status */
|
||||||
|
|
||||||
ret = usbhost_intxfer(hubclass, &priv->intxfer,
|
ret = usbhost_intxfer(hubclass, &priv->ctrlreq, usbhost_callback);
|
||||||
usbhost_callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1320,7 +1353,7 @@ static int usbhost_disconnected(struct usbhost_class_s *hubclass)
|
|||||||
{
|
{
|
||||||
/* Free buffer for status change (INT) endpoint */
|
/* Free buffer for status change (INT) endpoint */
|
||||||
|
|
||||||
DRVR_IOFREE(hubclass->drvr, priv->intxfer.buffer);
|
DRVR_IOFREE(hubclass->drvr, priv->buffer);
|
||||||
|
|
||||||
/* Power off (for root hub only) */
|
/* Power off (for root hub only) */
|
||||||
(void)usbhost_hubpwr(hubclass, false);
|
(void)usbhost_hubpwr(hubclass, false);
|
||||||
|
@ -52,9 +52,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <semaphore.h>
|
|
||||||
|
|
||||||
#include <nuttx/wqueue.h>
|
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
@ -451,7 +448,7 @@
|
|||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||||
* the class create() method.
|
* the class create() method.
|
||||||
* xfr - Describes the request to be sent. This request must lie in memory
|
* req - Describes the request to be sent. This request must lie in memory
|
||||||
* created by DRVR_ALLOC.
|
* created by DRVR_ALLOC.
|
||||||
* buffer - A buffer used for sending the request and for returning any
|
* buffer - A buffer used for sending the request and for returning any
|
||||||
* responses. This buffer must be large enough to hold the length value
|
* responses. This buffer must be large enough to hold the length value
|
||||||
@ -469,8 +466,8 @@
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#define DRVR_CTRLIN(drvr,xfer,cmd) ((drvr)->ctrlin(drvr,xfer,cmd))
|
#define DRVR_CTRLIN(drvr,req,buffer) ((drvr)->ctrlin(drvr,req,buffer))
|
||||||
#define DRVR_CTRLOUT(drvr,xfer,cmd) ((drvr)->ctrlout(drvr,xfer,cmd))
|
#define DRVR_CTRLOUT(drvr,req,buffer) ((drvr)->ctrlout(drvr,req,buffer))
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: DRVR_TRANSFER
|
* Name: DRVR_TRANSFER
|
||||||
@ -535,7 +532,7 @@
|
|||||||
#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr))
|
#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr))
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: DRVR_RHCTRL and DRVR_RHSTATUS
|
* Name: DRVR_RHSTATUS
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Called by hub class to control root hub.
|
* Called by hub class to control root hub.
|
||||||
@ -558,7 +555,6 @@
|
|||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_HUB
|
#ifdef CONFIG_USBHOST_HUB
|
||||||
# define DRVR_RHCTRL(drvr,xfer,cmd) ((drvr)->rhctrl(drvr,xfer,cmd))
|
|
||||||
# define DRVR_RHSTATUS(drvr,xfer) ((drvr)->rhstatus(drvr,xfer))
|
# define DRVR_RHSTATUS(drvr,xfer) ((drvr)->rhstatus(drvr,xfer))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -630,34 +626,14 @@ typedef FAR void *usbhost_ep_t;
|
|||||||
struct usbhost_class_s
|
struct usbhost_class_s
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USBHOST_HUB
|
#ifdef CONFIG_USBHOST_HUB
|
||||||
/* Common host driver */
|
FAR struct usbhost_driver_s *drvr; /* Common host driver */
|
||||||
|
FAR struct usbhost_class_s *parent; /* Parent class */
|
||||||
FAR struct usbhost_driver_s *drvr;
|
usbhost_ep_t ep0; /* Control endpoint, ep0 */
|
||||||
|
FAR struct usb_hubtt_s *tt; /* Transaction translator hub */
|
||||||
/* Parent class */
|
FAR void *priv; /* Class specific private data */
|
||||||
|
uint8_t addr; /* Device function address */
|
||||||
FAR struct usbhost_class_s *parent;
|
uint8_t speed; /* Device speed */
|
||||||
|
uint8_t rhport; /* Root hub port index */
|
||||||
/* Control endpoint, ep0 */
|
|
||||||
|
|
||||||
usbhost_ep_t ep0;
|
|
||||||
|
|
||||||
/* Transaction translator hub */
|
|
||||||
|
|
||||||
FAR struct usb_hubtt_s *tt;
|
|
||||||
|
|
||||||
/* Class specific private data */
|
|
||||||
|
|
||||||
FAR void *priv;
|
|
||||||
|
|
||||||
/* USB device address & speed */
|
|
||||||
|
|
||||||
uint8_t addr;
|
|
||||||
uint8_t speed;
|
|
||||||
|
|
||||||
/* Transaction translator port */
|
|
||||||
|
|
||||||
uint8_t ttport;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Provides the configuration descriptor to the class. The configuration
|
/* Provides the configuration descriptor to the class. The configuration
|
||||||
@ -698,34 +674,18 @@ struct usbhost_devinfo_s
|
|||||||
{
|
{
|
||||||
uint8_t speed:2; /* Device speed: 0=low, 1=full, 2=high */
|
uint8_t speed:2; /* Device speed: 0=low, 1=full, 2=high */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Generic transfer structure */
|
/* Generic transfer structure */
|
||||||
|
|
||||||
struct usbhost_transfer_s
|
struct usbhost_transfer_s
|
||||||
{
|
{
|
||||||
FAR uint8_t *buffer;
|
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
size_t len;
|
size_t len;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* Semaphore of synchronized transfers */
|
|
||||||
|
|
||||||
sem_t done;
|
|
||||||
|
|
||||||
/* Device class */
|
/* Device class */
|
||||||
|
|
||||||
FAR struct usbhost_class_s *devclass;
|
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
|
/* struct usbhost_connection_s provides as interface between platform-specific
|
||||||
@ -826,11 +786,11 @@ struct usbhost_driver_s
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int (*ctrlin)(FAR struct usbhost_driver_s *drvr,
|
int (*ctrlin)(FAR struct usbhost_driver_s *drvr,
|
||||||
FAR struct usbhost_transfer_s *xfer,
|
FAR const struct usb_ctrlreq_s *req,
|
||||||
FAR const struct usb_ctrlreq_s *cmd);
|
FAR uint8_t *buffer);
|
||||||
int (*ctrlout)(FAR struct usbhost_driver_s *drvr,
|
int (*ctrlout)(FAR struct usbhost_driver_s *drvr,
|
||||||
FAR struct usbhost_transfer_s *xfer,
|
FAR const struct usb_ctrlreq_s *req,
|
||||||
FAR const struct usb_ctrlreq_s *cmd);
|
FAR const uint8_t *buffer);
|
||||||
|
|
||||||
/* Process a request to handle a transfer descriptor. This method will
|
/* 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
|
* enqueue the transfer request and wait for it to complete. Only one transfer may
|
||||||
@ -855,9 +815,6 @@ struct usbhost_driver_s
|
|||||||
#ifdef CONFIG_USBHOST_HUB
|
#ifdef CONFIG_USBHOST_HUB
|
||||||
/* Called by hub class to control root 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,
|
int (*rhstatus)(FAR struct usbhost_driver_s *drvr,
|
||||||
FAR struct usbhost_transfer_s *xfer);
|
FAR struct usbhost_transfer_s *xfer);
|
||||||
#endif
|
#endif
|
||||||
@ -1058,27 +1015,6 @@ int usbhost_wlaninit(void);
|
|||||||
|
|
||||||
int usbhost_enumerate(FAR struct usbhost_class_s *devclass);
|
int usbhost_enumerate(FAR struct usbhost_class_s *devclass);
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: usbhost_ctrlxfer
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Free transfer buffer memory.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* devclass - A reference to the class instance.
|
|
||||||
* ctrlreq - Describes the control request transfer
|
|
||||||
* buffer - Data accompanying the control transfer
|
|
||||||
*
|
|
||||||
* 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,
|
|
||||||
FAR struct usb_ctrlreq_s *ctrlreq,
|
|
||||||
FAR uint8_t *buffer);
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_HUB
|
#ifdef CONFIG_USBHOST_HUB
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Name: usbhost_rh_connect
|
* Name: usbhost_rh_connect
|
||||||
|
Loading…
Reference in New Issue
Block a user