forked from nuttx/nuttx-update
USB host: Integrate logic to assign device function address
This commit is contained in:
parent
d6b963a62e
commit
fde0bf650e
11 changed files with 312 additions and 284 deletions
|
@ -53,6 +53,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/ehci.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
#include <nuttx/usb/usbhost_trace.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
|
@ -146,6 +147,11 @@
|
|||
|
||||
#define FRAME_LIST_SIZE 1024
|
||||
|
||||
/* Port numbers */
|
||||
|
||||
#define RHPNDX(rh) ((rh)->hport.hport.port)
|
||||
#define RHPORT(rh) (RHPNDX(rh)+1)
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Types
|
||||
*******************************************************************************/
|
||||
|
@ -228,7 +234,7 @@ struct sam_rhport_s
|
|||
|
||||
/* This is the hub port description understood by class drivers */
|
||||
|
||||
struct usbhost_hubport_s hport;
|
||||
struct usbhost_roothubport_s hport;
|
||||
|
||||
/* The bound device class driver */
|
||||
|
||||
|
@ -1492,7 +1498,7 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport,
|
|||
* and HUB device address to be included here.
|
||||
*/
|
||||
|
||||
rhpndx = rhport->hport.port;
|
||||
rhpndx = RHPNDX(rhport);
|
||||
regval = ((uint32_t)0 << QH_EPCAPS_HUBADDR_SHIFT) |
|
||||
((uint32_t)(rhpndx + 1) << QH_EPCAPS_PORT_SHIFT) |
|
||||
((uint32_t)1 << QH_EPCAPS_MULT_SHIFT);
|
||||
|
@ -1839,7 +1845,7 @@ static ssize_t sam_async_transfer(struct sam_rhport_s *rhport,
|
|||
usbhost_vtrace2(EHCI_VTRACE2_ASYNCXFR, epinfo->epno, buflen);
|
||||
#else
|
||||
uvdbg("RHport%d EP%d: buffer=%p, buflen=%d, req=%p\n",
|
||||
rhport->hport.port+1, epinfo->epno, buffer, buflen, req);
|
||||
RHPORT(rhport), epinfo->epno, buffer, buflen, req);
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(rhport && epinfo);
|
||||
|
@ -2198,7 +2204,7 @@ static ssize_t sam_intr_transfer(struct sam_rhport_s *rhport,
|
|||
usbhost_vtrace2(EHCI_VTRACE2_INTRXFR, epinfo->epno, buflen);
|
||||
#else
|
||||
uvdbg("RHport%d EP%d: buffer=%p, buflen=%d\n",
|
||||
rhport->hport.port+1, epinfo->epno, buffer, buflen);
|
||||
RHPORT(rhport), epinfo->epno, buffer, buflen);
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(rhport && epinfo && buffer && buflen > 0);
|
||||
|
@ -3192,7 +3198,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx)
|
|||
* write a zero to the Port Enable bit."
|
||||
*/
|
||||
|
||||
regaddr = &HCOR->portsc[rhport->hport.port];
|
||||
regaddr = &HCOR->portsc[RHPNDX(rhport)];
|
||||
regval = sam_getreg(regaddr);
|
||||
regval &= ~EHCI_PORTSC_PE;
|
||||
regval |= EHCI_PORTSC_RESET;
|
||||
|
@ -3294,7 +3300,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx)
|
|||
*/
|
||||
|
||||
usbhost_vtrace2(EHCI_VTRACE2_CLASSENUM, rhpndx+1, rhpndx+1);
|
||||
ret = usbhost_enumerate(&g_ehci.rhport[rhpndx].hport, &rhport->class);
|
||||
ret = usbhost_enumerate(&g_ehci.rhport[rhpndx].hport.hport, &rhport->class);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbhost_trace2(EHCI_TRACE2_CLASSENUM_FAILED, rhpndx+1, -ret);
|
||||
|
@ -3670,10 +3676,10 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
|||
/* Terse output only if we are tracing */
|
||||
|
||||
#ifdef CONFIG_USBHOST_TRACE
|
||||
usbhost_vtrace2(EHCI_VTRACE2_CTRLINOUT, rhport->hport.port + 1, req->req);
|
||||
usbhost_vtrace2(EHCI_VTRACE2_CTRLINOUT, RHPORT(rhport), req->req);
|
||||
#else
|
||||
uvdbg("RHPort%d type: %02x req: %02x value: %02x%02x index: %02x%02x len: %04x\n",
|
||||
rhport->hport.port + 1, req->type, req->req, req->value[1], req->value[0],
|
||||
RHPORT(rhport), req->type, req->req, req->value[1], req->value[0],
|
||||
req->index[1], req->index[0], len);
|
||||
#endif
|
||||
|
||||
|
@ -3959,6 +3965,7 @@ static int sam_reset(void)
|
|||
|
||||
FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
|
||||
{
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
#if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
|
@ -4087,13 +4094,18 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
|
|||
|
||||
/* Initialize the public port representation */
|
||||
|
||||
rhport->hport.drvr = &rhport->drvr;
|
||||
hport = &rhport->hport.hport;
|
||||
hport->drvr = &rhport->drvr;
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
rhport->hport.parent = NULL;
|
||||
hport->parent = NULL;
|
||||
#endif
|
||||
rhport->hport.ep0 = &rhport->ep0;
|
||||
rhport->hport.port = i;
|
||||
rhport->hport.speed = USB_SPEED_FULL;
|
||||
hport->ep0 = &rhport->ep0;
|
||||
hport->port = i;
|
||||
hport->speed = USB_SPEED_FULL;
|
||||
|
||||
/* Initialize function address generation logic */
|
||||
|
||||
usbhost_devaddr_initialize(&rhport->hport);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SAMA5_EHCI_PREALLOCATE
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/ohci.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
#include <nuttx/usb/usbhost_trace.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
|
@ -189,6 +190,11 @@
|
|||
|
||||
#define TD_DELAY(n) (uint32_t)((n) << GTD_STATUS_DI_SHIFT)
|
||||
|
||||
/* Port numbers */
|
||||
|
||||
#define RHPNDX(rh) ((rh)->hport.hport.port)
|
||||
#define RHPORT(rh) (RHPNDX(rh)+1)
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Types
|
||||
*******************************************************************************/
|
||||
|
@ -228,7 +234,7 @@ struct sam_rhport_s
|
|||
|
||||
/* This is the hub port description understood by class drivers */
|
||||
|
||||
struct usbhost_hubport_s hport;
|
||||
struct usbhost_roothubport_s hport;
|
||||
|
||||
/* The bound device class driver */
|
||||
|
||||
|
@ -1643,7 +1649,7 @@ static int sam_ctrltd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplist,
|
|||
ret = sam_wdhwait(rhport, edctrl);
|
||||
if (ret != OK)
|
||||
{
|
||||
usbhost_trace1(OHCI_TRACE1_DEVDISCONN, rhport->hport.port + 1);
|
||||
usbhost_trace1(OHCI_TRACE1_DEVDISCONN, RHPORT(rhport));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1707,7 +1713,7 @@ static int sam_ctrltd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplist,
|
|||
}
|
||||
else
|
||||
{
|
||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, rhport->hport.port + 1,
|
||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport),
|
||||
edctrl->tdstatus);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
@ -1797,14 +1803,14 @@ static void sam_rhsc_bottomhalf(void)
|
|||
|
||||
if ((rhportst & OHCI_RHPORTST_LSDA) != 0)
|
||||
{
|
||||
rhport->hport.speed = USB_SPEED_LOW;
|
||||
rhport->hport.hport.speed = USB_SPEED_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
rhport->hport.speed = USB_SPEED_FULL;
|
||||
rhport->hport.hport.speed = USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
usbhost_vtrace1(OHCI_VTRACE1_SPEED, rhport->hport.speed);
|
||||
usbhost_vtrace1(OHCI_VTRACE1_SPEED, rhport->hport.hport.speed);
|
||||
}
|
||||
|
||||
/* Check if we are now disconnected */
|
||||
|
@ -1817,7 +1823,7 @@ static void sam_rhsc_bottomhalf(void)
|
|||
rhpndx + 1, g_ohci.rhswait);
|
||||
|
||||
rhport->connected = false;
|
||||
rhport->hport.speed = USB_SPEED_FULL;
|
||||
rhport->hport.hport.speed = USB_SPEED_FULL;
|
||||
|
||||
/* Are we bound to a class instance? */
|
||||
|
||||
|
@ -2170,7 +2176,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx)
|
|||
{
|
||||
/* No, return an error */
|
||||
|
||||
usbhost_vtrace1(OHCI_VTRACE1_ENUMDISCONN, rhport->hport.port + 1);
|
||||
usbhost_vtrace1(OHCI_VTRACE1_ENUMDISCONN, RHPORT(rhport));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -2181,7 +2187,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx)
|
|||
ret = sam_ep0enqueue(rhport);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbhost_trace2(OHCI_TRACE2_EP0ENQUEUE_FAILED, rhport->hport.port + 1,
|
||||
usbhost_trace2(OHCI_TRACE2_EP0ENQUEUE_FAILED, RHPORT(rhport),
|
||||
-ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2216,7 +2222,7 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx)
|
|||
*/
|
||||
|
||||
usbhost_vtrace2(OHCI_VTRACE2_CLASSENUM, rhpndx+1, rhpndx+1);
|
||||
ret = usbhost_enumerate(&g_ohci.rhport[rhpndx].hport, &rhport->class);
|
||||
ret = usbhost_enumerate(&g_ohci.rhport[rhpndx].hport.hport, &rhport->class);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbhost_trace2(OHCI_TRACE2_CLASSENUM_FAILED, rhpndx+1, -ret);
|
||||
|
@ -2271,7 +2277,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
|||
edctrl->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT |
|
||||
(uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT;
|
||||
|
||||
if (rhport->hport.speed == USB_SPEED_LOW)
|
||||
if (rhport->hport.hport.speed == USB_SPEED_LOW)
|
||||
{
|
||||
edctrl->hw.ctrl |= ED_CONTROL_S;
|
||||
}
|
||||
|
@ -2287,7 +2293,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
|||
sam_givesem(&g_ohci.exclsem);
|
||||
|
||||
usbhost_vtrace2(OHCI_VTRACE2_EP0CONFIGURE,
|
||||
rhport->hport.port + 1, (uint16_t)edctrl->hw.ctrl);
|
||||
RHPORT(rhport), (uint16_t)edctrl->hw.ctrl);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -2394,7 +2400,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
|
|||
|
||||
/* Check for a low-speed device */
|
||||
|
||||
if (rhport->hport.speed == USB_SPEED_LOW)
|
||||
if (rhport->hport.hport.speed == USB_SPEED_LOW)
|
||||
{
|
||||
ed->hw.ctrl |= ED_CONTROL_S;
|
||||
}
|
||||
|
@ -2766,10 +2772,10 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
|||
DEBUGASSERT(rhport != NULL && eplist != NULL && req != NULL);
|
||||
|
||||
#ifdef CONFIG_USBHOST_TRACE
|
||||
usbhost_vtrace2(OHCI_VTRACE2_CTRLIN, rhport->hport.port + 1, req->req);
|
||||
usbhost_vtrace2(OHCI_VTRACE2_CTRLIN, RHPORT(rhport), req->req);
|
||||
#else
|
||||
uvdbg("RHPort%d type: %02x req: %02x value: %02x%02x index: %02x%02x len: %02x%02x\n",
|
||||
rhport->hport.port + 1, req->type, req->req, req->value[1],
|
||||
RHPORT(rhport), req->type, req->req, req->value[1],
|
||||
req->value[0], req->index[1], req->index[0], req->len[1],
|
||||
req->len[0]);
|
||||
#endif
|
||||
|
@ -2815,10 +2821,10 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
|||
DEBUGASSERT(rhport != NULL && eplist != NULL && req != NULL);
|
||||
|
||||
#ifdef CONFIG_USBHOST_TRACE
|
||||
usbhost_vtrace2(OHCI_VTRACE2_CTRLOUT, rhport->hport.port + 1, req->req);
|
||||
usbhost_vtrace2(OHCI_VTRACE2_CTRLOUT, RHPORT(rhport), req->req);
|
||||
#else
|
||||
uvdbg("RHPort%d type: %02x req: %02x value: %02x%02x index: %02x%02x len: %02x%02x\n",
|
||||
rhport->hport.port + 1, req->type, req->req, req->value[1],
|
||||
RHPORT(rhport), req->type, req->req, req->value[1],
|
||||
req->value[0], req->index[1], req->index[0], req->len[1],
|
||||
req->len[0]);
|
||||
#endif
|
||||
|
@ -2929,7 +2935,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
|||
ret = sam_wdhwait(rhport, ed);
|
||||
if (ret != OK)
|
||||
{
|
||||
usbhost_trace1(OHCI_TRACE1_DEVDISCONN, rhport->hport.port + 1);
|
||||
usbhost_trace1(OHCI_TRACE1_DEVDISCONN, RHPORT(rhport));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
@ -3012,7 +3018,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
|||
}
|
||||
else
|
||||
{
|
||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, rhport->hport.port + 1,
|
||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport),
|
||||
ed->tdstatus);
|
||||
ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO;
|
||||
}
|
||||
|
@ -3095,6 +3101,7 @@ static void sam_disconnect(FAR struct usbhost_driver_s *drvr)
|
|||
|
||||
FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
|
||||
{
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
uintptr_t physaddr;
|
||||
uint32_t regval;
|
||||
uint8_t *buffer;
|
||||
|
@ -3218,6 +3225,8 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
|
|||
{
|
||||
struct sam_rhport_s *rhport = &g_ohci.rhport[i];
|
||||
|
||||
/* Initialize the device operations */
|
||||
|
||||
rhport->drvr.ep0configure = sam_ep0configure;
|
||||
rhport->drvr.epalloc = sam_epalloc;
|
||||
rhport->drvr.epfree = sam_epfree;
|
||||
|
@ -3230,13 +3239,20 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
|
|||
rhport->drvr.transfer = sam_transfer;
|
||||
rhport->drvr.disconnect = sam_disconnect;
|
||||
|
||||
rhport->hport.drvr = &rhport->drvr;
|
||||
/* Initialize the public port representation */
|
||||
|
||||
hport = &rhport->hport.hport;
|
||||
hport->drvr = &rhport->drvr;
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
rhport->hport.parent = NULL;
|
||||
hport->parent = NULL;
|
||||
#endif
|
||||
rhport->hport.ep0 = &rhport->ep0;
|
||||
rhport->hport.port = i;
|
||||
rhport->hport.speed = USB_SPEED_FULL;
|
||||
hport->ep0 = &rhport->ep0;
|
||||
hport->port = i;
|
||||
hport->speed = USB_SPEED_FULL;
|
||||
|
||||
/* Initialize function address generation logic */
|
||||
|
||||
usbhost_devaddr_initialize(&rhport->hport);
|
||||
}
|
||||
|
||||
/* Wait 50MS then perform hardware reset */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* drivers/usbhost/usbhost_devaddr.c
|
||||
* Manage USB device addresses
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2015 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -45,6 +45,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -64,11 +65,11 @@
|
|||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void usbhost_takesem(FAR struct usbhost_devaddr_s *hcd)
|
||||
static void usbhost_takesem(FAR struct usbhost_devaddr_s *devgen)
|
||||
{
|
||||
/* Take the semaphore (perhaps waiting) */
|
||||
|
||||
while (sem_wait(&hcd->exclsem) != 0)
|
||||
while (sem_wait(&devgen->exclsem) != 0)
|
||||
{
|
||||
/* The only case that an error should occur here is if the wait was
|
||||
* awakened by a signal.
|
||||
|
@ -78,39 +79,22 @@ static void usbhost_takesem(FAR struct usbhost_devaddr_s *hcd)
|
|||
}
|
||||
}
|
||||
|
||||
#define usbhost_givesem(hcd) sem_post(&hcd->exclsem)
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_hash
|
||||
*
|
||||
* Description:
|
||||
* Create a hash value from a device address.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static inline uint8_t usbhost_devaddr_hash(uint8_t devaddr)
|
||||
{
|
||||
uint8_t ret = devaddr;
|
||||
|
||||
ret ^= (devaddr >> 2);
|
||||
ret ^= (devaddr >> 3);
|
||||
return ret & USBHOST_DEVADDR_HASHMASK;
|
||||
}
|
||||
#define usbhost_givesem(devgen) sem_post(&devgen->exclsem)
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_allocate
|
||||
*
|
||||
* Description:
|
||||
* Allocate a new unique device address for this HCD.
|
||||
* Allocate a new unique device address.
|
||||
*
|
||||
* Assumptions:
|
||||
* Caller hold the exclsem
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static int usbhost_devaddr_allocate(FAR struct usbhost_devaddr_s *hcd)
|
||||
static int usbhost_devaddr_allocate(FAR struct usbhost_devaddr_s *devgen)
|
||||
{
|
||||
uint8_t startaddr = hcd->next;
|
||||
uint8_t startaddr = devgen->next;
|
||||
uint8_t devaddr;
|
||||
int index;
|
||||
int bitno;
|
||||
|
@ -121,25 +105,25 @@ static int usbhost_devaddr_allocate(FAR struct usbhost_devaddr_s *hcd)
|
|||
{
|
||||
/* Try the next device address */
|
||||
|
||||
devaddr = hcd->next;
|
||||
if (hcd->next >= 0x7f)
|
||||
devaddr = devgen->next;
|
||||
if (devgen->next >= 0x7f)
|
||||
{
|
||||
hcd->next = 1;
|
||||
devgen->next = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hcd->next++;
|
||||
devgen->next++;
|
||||
}
|
||||
|
||||
/* Is this address already allocated? */
|
||||
|
||||
index = devaddr >> 5;
|
||||
bitno = devaddr & 0x1f;
|
||||
if ((hcd->alloctab[index] & (1 << bitno)) == 0)
|
||||
if ((devgen->alloctab[index] & (1 << bitno)) == 0)
|
||||
{
|
||||
/* No... allocate it now */
|
||||
|
||||
hcd->alloctab[index] |= (1 << bitno);
|
||||
devgen->alloctab[index] |= (1 << bitno);
|
||||
return (int)devaddr;
|
||||
}
|
||||
|
||||
|
@ -156,6 +140,74 @@ static int usbhost_devaddr_allocate(FAR struct usbhost_devaddr_s *hcd)
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_free
|
||||
*
|
||||
* Description:
|
||||
* De-allocate a device address.
|
||||
*
|
||||
* Assumptions:
|
||||
* Caller hold the exclsem
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void usbhost_devaddr_free(FAR struct usbhost_devaddr_s *devgen,
|
||||
uint8_t devaddr)
|
||||
{
|
||||
int index;
|
||||
int bitno;
|
||||
|
||||
/* Free the address by clearing the associated bit in the alloctab[]; */
|
||||
|
||||
index = devaddr >> 5;
|
||||
bitno = devaddr & 0x1f;
|
||||
|
||||
DEBUGASSERT((devgen->alloctab[index] |= (1 << bitno)) != 0);
|
||||
devgen->alloctab[index] &= ~(1 << bitno);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_roothubport
|
||||
*
|
||||
* Description:
|
||||
* Find and return a reference the root hub port.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static inline FAR struct usbhost_roothubport_s *
|
||||
usbhost_roothubport(FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
while (hport->parent != NULL)
|
||||
{
|
||||
hport = hport->parent;
|
||||
}
|
||||
|
||||
return (FAR struct usbhost_roothubport_s *)hport;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_gen
|
||||
*
|
||||
* Description:
|
||||
* Find root hub port and return a reference to the device function address
|
||||
* data set.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static FAR struct usbhost_devaddr_s *
|
||||
usbhost_devaddr_gen(FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
FAR struct usbhost_roothubport_s *rhport;
|
||||
|
||||
rhport = usbhost_roothubport(hport);
|
||||
if (rhport != NULL)
|
||||
{
|
||||
return &rhport->devgen;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Public Functions
|
||||
*******************************************************************************/
|
||||
|
@ -165,169 +217,113 @@ static int usbhost_devaddr_allocate(FAR struct usbhost_devaddr_s *hcd)
|
|||
*
|
||||
* Description:
|
||||
* Initialize the caller provided struct usbhost_devaddr_s instance in
|
||||
* preparation for the management of device addresses on behalf of an HCD.
|
||||
* preparation for the management of device addresses on behalf of an root
|
||||
* hub port.
|
||||
*
|
||||
* Input Parameters:
|
||||
* rhport - A reference to a roothubport structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
void usbhost_devaddr_initialize(FAR struct usbhost_devaddr_s *hcd)
|
||||
void usbhost_devaddr_initialize(FAR struct usbhost_roothubport_s *rhport)
|
||||
{
|
||||
DEBUGASSERT(hcd);
|
||||
FAR struct usbhost_devaddr_s *devgen;
|
||||
|
||||
memset(hcd, 0, sizeof(struct usbhost_devaddr_s));
|
||||
sem_init(&hcd->exclsem, 0, 1);
|
||||
hcd->next = 1;
|
||||
DEBUGASSERT(rhport);
|
||||
devgen = &rhport->devgen;
|
||||
|
||||
memset(devgen, 0, sizeof(struct usbhost_devaddr_s));
|
||||
sem_init(&devgen->exclsem, 0, 1);
|
||||
devgen->next = 1;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_create
|
||||
*
|
||||
* Description:
|
||||
* Create a new unique device address for this HCD. Bind the void* arg to the
|
||||
* the device address and return the newly allocated device address.
|
||||
* Create a new unique device address for this hub port.
|
||||
*
|
||||
* Input Parameters:
|
||||
* hport - A reference to a hub port structure to which a device has been
|
||||
* newly connected and so is in need of a function address.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value is returned on failure.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
int usbhost_devaddr_create(FAR struct usbhost_devaddr_s *hcd,
|
||||
FAR void *associate)
|
||||
int usbhost_devaddr_create(FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
FAR struct usbhost_devhash_s *hentry;
|
||||
uint8_t hvalue;
|
||||
FAR struct usbhost_devaddr_s *devgen;
|
||||
int devaddr;
|
||||
|
||||
/* Allocate a hash table entry */
|
||||
/* Get the address generation data from the root hub port */
|
||||
|
||||
hentry = (FAR struct usbhost_devhash_s *)kmm_malloc(sizeof(struct usbhost_devhash_s));
|
||||
if (!hentry)
|
||||
{
|
||||
udbg("ERROR: Failed to allocate a hash table entry\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
DEBUGASSERT(hport);
|
||||
devgen = usbhost_devaddr_gen(hport);
|
||||
DEBUGASSERT(devgen);
|
||||
|
||||
/* Get exclusive access to the HCD device address data */
|
||||
/* Get exclusive access to the root hub port device address data */
|
||||
|
||||
usbhost_takesem(hcd);
|
||||
usbhost_takesem(devgen);
|
||||
|
||||
/* Allocate a device address */
|
||||
|
||||
devaddr = usbhost_devaddr_allocate(hcd);
|
||||
devaddr = usbhost_devaddr_allocate(devgen);
|
||||
usbhost_givesem(devgen);
|
||||
|
||||
if (devaddr < 0)
|
||||
{
|
||||
udbg("ERROR: Failed to allocate a device address\n");
|
||||
free(hentry);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialize the hash table entry */
|
||||
|
||||
hentry->devaddr = devaddr;
|
||||
hentry->payload = associate;
|
||||
|
||||
/* Add the new device address to the hash table */
|
||||
|
||||
hvalue = usbhost_devaddr_hash(devaddr);
|
||||
hentry->flink = hcd->hashtab[hvalue];
|
||||
hcd->hashtab[hvalue] = hentry;
|
||||
|
||||
/* Try to re-use the lowest numbered device addresses */
|
||||
|
||||
if (hcd->next > devaddr)
|
||||
{
|
||||
hcd->next = devaddr;
|
||||
}
|
||||
return devaddr;
|
||||
}
|
||||
|
||||
usbhost_givesem(hcd);
|
||||
return devaddr;
|
||||
}
|
||||
/* Set the function address in the hub port structure */
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_find
|
||||
*
|
||||
* Description:
|
||||
* Given a device address, find the void* value that was bound to the device
|
||||
* address by usbhost_devaddr_create() when the device address was allocated.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
FAR void *usbhost_devaddr_find(FAR struct usbhost_devaddr_s *hcd,
|
||||
uint8_t devaddr)
|
||||
{
|
||||
FAR struct usbhost_devhash_s *hentry;
|
||||
uint8_t hvalue;
|
||||
|
||||
/* Get exclusive access to the HCD device address data */
|
||||
|
||||
hvalue = usbhost_devaddr_hash(devaddr);
|
||||
usbhost_takesem(hcd);
|
||||
|
||||
/* Check each entry in the hash table */
|
||||
|
||||
for (hentry = hcd->hashtab[hvalue]; hentry; hentry = hentry->flink)
|
||||
{
|
||||
/* Is this the address we are looking for? */
|
||||
|
||||
if (hentry->devaddr == devaddr)
|
||||
{
|
||||
/* Yes.. return the payload from the hash table entry */
|
||||
|
||||
usbhost_givesem(hcd);
|
||||
return hentry->payload;
|
||||
}
|
||||
}
|
||||
|
||||
/* Didn't find the device address */
|
||||
|
||||
usbhost_givesem(hcd);
|
||||
return NULL;
|
||||
hport->funcaddr = devaddr;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_destroy
|
||||
*
|
||||
* Description:
|
||||
* Release a device address previously allocated by usbhost_devaddr_destroy()
|
||||
* and destroy the association with the void* data.
|
||||
* Release a device address previously assigned to a hub port by
|
||||
* usbhost_devaddr_create().
|
||||
*
|
||||
* Input Parameters:
|
||||
* hport - A reference to a hub port structure from which a device has been
|
||||
* disconnected and so no longer needs the function address.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
void usbhost_devaddr_destroy(FAR struct usbhost_devaddr_s *hcd, uint8_t devaddr)
|
||||
void usbhost_devaddr_destroy(FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
FAR struct usbhost_devhash_s *hentry;
|
||||
FAR struct usbhost_devhash_s *prev;
|
||||
uint8_t hvalue;
|
||||
FAR struct usbhost_devaddr_s *devgen;
|
||||
|
||||
/* Get exclusive access to the HCD device address data */
|
||||
/* Ignore bad device address */
|
||||
|
||||
hvalue = usbhost_devaddr_hash(devaddr);
|
||||
usbhost_takesem(hcd);
|
||||
|
||||
/* Search the hast table for the matching entry */
|
||||
|
||||
for (hentry = hcd->hashtab[hvalue], prev = NULL;
|
||||
hentry;
|
||||
prev = hentry, hentry = hentry->flink)
|
||||
if (hport->funcaddr > 0 && hport->funcaddr < 0x7f)
|
||||
{
|
||||
/* Is this the address we are looking for? */
|
||||
/* Get the address generation data from the root hub port */
|
||||
|
||||
if (hentry->devaddr == devaddr)
|
||||
{
|
||||
/* Yes.. remove the entry from the hash list */
|
||||
DEBUGASSERT(hport);
|
||||
devgen = usbhost_devaddr_gen(hport);
|
||||
DEBUGASSERT(devgen);
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->flink = hentry->flink;
|
||||
}
|
||||
else
|
||||
{
|
||||
hcd->hashtab[hvalue] = hentry->flink;
|
||||
}
|
||||
/* Get exclusive access to the root hub port device address data */
|
||||
|
||||
/* And release the entry */
|
||||
usbhost_takesem(devgen);
|
||||
|
||||
kmm_free(hentry);
|
||||
break;
|
||||
}
|
||||
/* Free the device address */
|
||||
|
||||
usbhost_devaddr_free(devgen, hport->funcaddr);
|
||||
usbhost_givesem(devgen);
|
||||
}
|
||||
|
||||
usbhost_givesem(hcd);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/hub.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -313,7 +314,7 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport,
|
|||
uint8_t maxpacketsize;
|
||||
uint8_t descsize;
|
||||
FAR uint8_t *buffer = NULL;
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(hport != NULL && hport->drvr != NULL);
|
||||
|
||||
|
@ -520,6 +521,15 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport,
|
|||
|
||||
usleep(100*1000);
|
||||
|
||||
/* Assign a function address to the device connected to this port */
|
||||
|
||||
ret = usbhost_devaddr_create(hport);
|
||||
if (ret < 0)
|
||||
{
|
||||
udbg("ERROR: Failed to allocate device address: %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Parse the configuration descriptor and bind to the class instance for the
|
||||
* device. This needs to be the last thing done because the class driver
|
||||
* will begin configuring the device.
|
||||
|
@ -529,6 +539,7 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport,
|
|||
if (ret != OK)
|
||||
{
|
||||
udbg("ERROR: usbhost_classbind returned %d\n", ret);
|
||||
usbhost_devaddr_destroy(hport);
|
||||
}
|
||||
|
||||
errout:
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/hid.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
#ifdef CONFIG_HIDKBD_ENCODED
|
||||
# include <nuttx/streams.h>
|
||||
|
@ -1936,8 +1937,10 @@ static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
|
|||
static int usbhost_disconnected(struct usbhost_class_s *usbclass)
|
||||
{
|
||||
FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)usbclass;
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
|
||||
hport = priv->usbclass.hport;
|
||||
|
||||
/* Set an indication to any users of the keyboard device that the device
|
||||
* is no longer available.
|
||||
|
@ -1986,6 +1989,9 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
|
|||
(void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
|
||||
}
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
usbhost_devaddr_destroy(hport);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/hid.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
#ifdef CONFIG_HIDMOUSE_TSCIF
|
||||
# include <nuttx/input/touchscreen.h>
|
||||
|
@ -2015,9 +2016,11 @@ static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
|
|||
static int usbhost_disconnected(struct usbhost_class_s *usbclass)
|
||||
{
|
||||
FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)usbclass;
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
|
||||
hport = priv->usbclass.hport;
|
||||
|
||||
/* Set an indication to any users of the mouse device that the device
|
||||
* is no longer available.
|
||||
|
@ -2065,6 +2068,9 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
|
|||
(void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
|
||||
}
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
usbhost_devaddr_destroy(hport);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/hub.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
|
||||
|
@ -125,8 +126,6 @@ struct usbhost_hubclass_s
|
|||
|
||||
/* Memory allocation services */
|
||||
|
||||
static inline uint8_t usbhost_allocaddr(void);
|
||||
static inline void usbhost_freeaddr(uint8_t addr);
|
||||
static inline FAR struct usbhost_hubport_s *usbhost_allochub(
|
||||
FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_class_s *hubclass, uint8_t speed,
|
||||
|
@ -192,55 +191,10 @@ static struct usbhost_registry_s g_hub =
|
|||
&g_id /* id[] */
|
||||
};
|
||||
|
||||
/* Each bit indicates if corresponding bit number
|
||||
* is allocated as usb address
|
||||
*/
|
||||
|
||||
static uint32_t g_addrmap[4];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbhost_allocaddr
|
||||
*
|
||||
* Description:
|
||||
* This is just a wrapper to handle the annoying behavior of semaphore
|
||||
* waits that return due to the receipt of a signal.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint8_t usbhost_allocaddr(void)
|
||||
{
|
||||
uint8_t addr;
|
||||
|
||||
for (addr = 0; addr < 128; addr++)
|
||||
{
|
||||
if (!(g_addrmap[addr/32] & (0x1 << (addr % 32))))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (addr + 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbhost_freecaddr
|
||||
*
|
||||
* Description:
|
||||
* This is just a wrapper to handle the annoying behavior of semaphore
|
||||
* waits that return due to the receipt of a signal.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void usbhost_freeaddr(uint8_t addr)
|
||||
{
|
||||
addr--;
|
||||
g_addrmap[addr/32] &= (~(0x1 << (addr % 32)));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbhost_allochub
|
||||
*
|
||||
|
@ -288,7 +242,7 @@ static inline FAR struct usbhost_hubport_s *
|
|||
|
||||
child->drvr = drvr;
|
||||
child->parent = parent;
|
||||
child->funcaddr = usbhost_allocaddr();
|
||||
child->funcaddr = 0;
|
||||
child->speed = speed;
|
||||
|
||||
epdesc.hport = child;
|
||||
|
@ -334,7 +288,8 @@ static inline void usbhost_freehub(FAR struct usbhost_hubport_s *hport)
|
|||
hport->ep0 = NULL;
|
||||
}
|
||||
|
||||
usbhost_freeaddr(hport->funcaddr);
|
||||
usbhost_devaddr_destroy(hport);
|
||||
hport->funcaddr = 0;
|
||||
|
||||
/* Free the hport instance */
|
||||
|
||||
|
|
|
@ -347,11 +347,15 @@ static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
|
|||
static void usbhost_destroy(FAR void *arg)
|
||||
{
|
||||
FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg;
|
||||
FAR struct usbhost_hport_s *hport
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
FAR struct usbhost_driver_s *drvr;
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
|
||||
hport = priv->usbclass.hport;
|
||||
|
||||
DEBUGASSERT(hport->drvr);
|
||||
drvr = hport->drvr;
|
||||
|
||||
uvdbg("crefs: %d\n", priv->crefs);
|
||||
|
||||
/* Unregister the driver */
|
||||
|
@ -364,11 +368,15 @@ static void usbhost_destroy(FAR void *arg)
|
|||
|
||||
/* Free any transfer buffers */
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
usbhost_devaddr_destroy(hport);
|
||||
|
||||
/* Destroy the semaphores */
|
||||
|
||||
/* Disconnect the USB host device */
|
||||
|
||||
DRVR_DISCONNECT(hport->drvr);
|
||||
DRVR_DISCONNECT(drvr);
|
||||
|
||||
/* And free the class instance. Hmmm.. this may execute on the worker
|
||||
* thread and the work structure is part of what is getting freed. That
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/storage.h>
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
/* Don't compile if prerequisites are not met */
|
||||
|
||||
|
@ -1809,9 +1810,11 @@ static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
|
|||
static int usbhost_disconnected(struct usbhost_class_s *usbclass)
|
||||
{
|
||||
FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)usbclass;
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
|
||||
hport = priv->usbclass.hport;
|
||||
|
||||
/* Set an indication to any users of the mass storage device that the device
|
||||
* is no longer available.
|
||||
|
@ -1851,6 +1854,10 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
|
|||
}
|
||||
|
||||
irqrestore(flags);
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
usbhost_devaddr_destroy(hport);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <nuttx/usb/usbhost_devaddr.h>
|
||||
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
|
@ -606,6 +608,8 @@ typedef FAR void *usbhost_ep_t;
|
|||
* root hub is managed by the HCD. This structure describes that state of
|
||||
* that port and provides the linkage to the parent hub in that event that
|
||||
* the port is on an external hub.
|
||||
*
|
||||
* The root hub port can be distinguish because it has parent == NULL.
|
||||
*/
|
||||
|
||||
struct usbhost_hubport_s
|
||||
|
@ -620,6 +624,21 @@ struct usbhost_hubport_s
|
|||
uint8_t speed; /* Device speed */
|
||||
};
|
||||
|
||||
/* The root hub port differs in that it includes a data set that is used to
|
||||
* manage the generation of unique device function addresses on all
|
||||
* downstream ports.
|
||||
*/
|
||||
|
||||
struct usbhost_roothubport_s
|
||||
{
|
||||
/* This structure must appear first so that this structure is cast-
|
||||
* compatible with usbhost_hubport_s.
|
||||
*/
|
||||
|
||||
struct usbhost_hubport_s hport; /* Common hub port definitions */
|
||||
struct usbhost_devaddr_s devgen; /* Address generation data */
|
||||
};
|
||||
|
||||
/* struct usbhost_class_s provides access from the USB host driver to the
|
||||
* USB host class implementation.
|
||||
*/
|
||||
|
@ -695,16 +714,6 @@ typedef CODE void (*usbhost_asynch_t)(FAR void *arg, int result);
|
|||
|
||||
struct usbhost_driver_s
|
||||
{
|
||||
#ifdef CONFIG_USBHOST_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.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* include/nuttx/usb/usbhost_devaddr.h
|
||||
* Manage USB device addresses
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* NOTE: This interface was inspired by the Linux gadget interface by
|
||||
|
@ -49,6 +49,9 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Pre-processor Definitions
|
||||
*******************************************************************************/
|
||||
|
@ -61,22 +64,11 @@
|
|||
* Public Types
|
||||
*******************************************************************************/
|
||||
|
||||
struct usbhost_devhash_s
|
||||
{
|
||||
FAR struct usbhost_devhash_s *flink;
|
||||
FAR void *payload;
|
||||
uint8_t devaddr;
|
||||
};
|
||||
|
||||
struct usbhost_devaddr_s
|
||||
{
|
||||
uint8_t next; /* Next device address */
|
||||
sem_t exclsem; /* Enforces mutulaly exlusive access */
|
||||
sem_t exclsem; /* Enforces mutually exclusive access */
|
||||
uint32_t alloctab[4]; /* Bit allocation table */
|
||||
|
||||
/* Hash table */
|
||||
|
||||
FAR struct usbhost_devhash_s *hashtab[USBHOST_DEVADDR_HASHSIZE];
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -96,51 +88,61 @@ extern "C"
|
|||
* Public Functions
|
||||
*******************************************************************************/
|
||||
|
||||
struct usbhost_hubport_s; /* Forward reference */
|
||||
struct usbhost_roothubport_s; /* Forward reference */
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the caller provided struct usbhost_devaddr_s instance in
|
||||
* preparation for the management of device addresses on behalf of an HCD.
|
||||
* preparation for the management of device addresses on behalf of an root
|
||||
* hub port.
|
||||
*
|
||||
* Input Parameters:
|
||||
* rhport - A reference to a roothubport structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
void usbhost_devaddr_initialize(FAR struct usbhost_devaddr_s *hcd);
|
||||
void usbhost_devaddr_initialize(FAR struct usbhost_roothubport_s *rhport);
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_create
|
||||
*
|
||||
* Description:
|
||||
* Create a new unique device address for this HCD. Bind the void* arg to the
|
||||
* the device address and return the newly allocated device address.
|
||||
* Create a new unique device address for this hub port.
|
||||
*
|
||||
* Input Parameters:
|
||||
* hport - A reference to a hub port structure to which a device has been
|
||||
* newly connected and so is in need of a function address.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value is returned on failure.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
int usbhost_devaddr_create(FAR struct usbhost_devaddr_s *hcd,
|
||||
FAR void *associate);
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_find
|
||||
*
|
||||
* Description:
|
||||
* Given a device address, find the void* value that was bound to the device
|
||||
* address by usbhost_devaddr_create() when the device address was allocated.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
FAR void *usbhost_devaddr_find(FAR struct usbhost_devaddr_s *hcd,
|
||||
uint8_t devaddr);
|
||||
int usbhost_devaddr_create(FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbhost_devaddr_destroy
|
||||
*
|
||||
* Description:
|
||||
* Release a device address previously allocated by usbhost_devaddr_destroy()
|
||||
* and destroy the association with the void* data.
|
||||
* Release a device address previously assigned to a hub port by
|
||||
* usbhost_devaddr_create().
|
||||
*
|
||||
* Input Parameters:
|
||||
* hport - A reference to a hub port structure from which a device has been
|
||||
* disconnected and so no longer needs the function address.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
void usbhost_devaddr_destroy(FAR struct usbhost_devaddr_s *hcd, uint8_t devaddr);
|
||||
void usbhost_devaddr_destroy(FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
|
Loading…
Reference in a new issue