9
0
Fork 0

Add td allocation logic

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3190 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2010-12-17 02:19:04 +00:00
parent 5f0d8d26ad
commit 96619c64f1
2 changed files with 289 additions and 15 deletions

View File

@ -139,6 +139,8 @@ struct usbhost_state_s
sem_t exclsem; /* Used to maintain mutual exclusive access */
sem_t waitsem; /* Used to wait for transfer completion events */
struct work_s work; /* For interacting with the worker thread */
FAR uint8_t *tdbuffer; /* The allocated transfer descriptor buffer */
size_t tdbuflen; /* Size of the allocated transfer buffer */
struct usbhost_epdesc_s bulkin; /* Bulk IN endpoint */
struct usbhost_epdesc_s bulkout; /* Bulk OUT endpoint */
};
@ -168,9 +170,17 @@ static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *dev
static void usbhost_destroy(FAR void *arg);
static void usbhost_work(FAR struct usbhost_state_s *priv, worker_t worker);
/* Data helpers */
/* (Little Endian) Data helpers */
static inline uint16_t usbhost_getint16(const uint8_t *val);
static inline uint16_t usbhost_getle16(const uint8_t *val);
static inline void usbhost_putle16(uint8_t *dest, uint16_t val);
static void usbhost_putle32(uint8_t *dest, uint32_t val);
/* Transfer descriptor memory management */
static int usbhost_tdalloc(FAR struct usbhost_state_s *priv);
static int usbhost_tdfree(FAR struct usbhost_state_s *priv);
static FAR struct usbstrg_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv);
/* struct usbhost_registry_s methods */
@ -439,7 +449,7 @@ static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *dev
* host class instance.
*
* Input Parameters:
* arg - A reference to the class instance to be freed.
* arg - A reference to the class instance to be destroyed.
*
* Returned Values:
* None
@ -483,7 +493,7 @@ static void usbhost_destroy(FAR void *arg)
* longer be executed.
*
* Input Parameters:
* arg - A reference to the class instance to be freed.
* arg - A reference to the class instance.
*
* Returned Values:
* None
@ -587,7 +597,7 @@ static void usbhost_statemachine(FAR void *arg)
* just execute the work now.
*
* Input Parameters:
* priv - A reference to the class instance to be freed.
* priv - A reference to the class instance.
* worker - A reference to the worker function to be executed
*
* Returned Values:
@ -616,7 +626,7 @@ static void usbhost_work(FAR struct usbhost_state_s *priv, worker_t worker)
}
/****************************************************************************
* Name: usbhost_getint16
* Name: usbhost_getle16
*
* Description:
* Get a (possibly unaligned) 16-bit little endian value.
@ -629,11 +639,147 @@ static void usbhost_work(FAR struct usbhost_state_s *priv, worker_t worker)
*
****************************************************************************/
static inline uint16_t usbhost_getint16(const uint8_t *val)
static inline uint16_t usbhost_getle16(const uint8_t *val)
{
return (uint16_t)val[1] << 8 | (uint16_t)val[0];
}
/****************************************************************************
* Name: usbhost_putle16
*
* Description:
* Put a (possibly unaligned) 16-bit little endian value.
*
* Input Parameters:
* dest - A pointer to the first byte to save the little endian value.
* val - The 16-bit value to be saved.
*
* Returned Values:
* None
*
****************************************************************************/
static void usbhost_putle16(uint8_t *dest, uint16_t val)
{
dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
dest[1] = val >> 8;
}
/****************************************************************************
* Name: usbhost_putle32
*
* Description:
* Put a (possibly unaligned) 32-bit little endian value.
*
* Input Parameters:
* dest - A pointer to the first byte to save the little endian value.
* val - The 32-bit value to be saved.
*
* Returned Values:
* None
*
****************************************************************************/
static void usbhost_putle32(uint8_t *dest, uint32_t val)
{
/* Little endian means LS halfwrd first in byte stream */
usbhost_putle16(dest, (uint16_t)(val & 0xffff));
usbhost_putle16(dest+2, (uint16_t)(val >> 16));
}
/****************************************************************************
* Name: usbhost_tdalloc
*
* Description:
* Allocate transfer descriptor memory.
*
* Input Parameters:
* priv - A reference to the class instance.
*
* Returned Values:
* On sucess, zero (OK) is returned. On failure, an negated errno value
* is returned to indicate the nature of the failure.
*
****************************************************************************/
static int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
{
int result = OK;
/* Is a descriptor already allocated? */
if (!priv->tdbuffer)
{
result = DRVR_ALLOC(priv->drvr, &priv->tdbuffer, &priv->tdbuflen);
}
return result;
}
/****************************************************************************
* Name: usbhost_tdfree
*
* Description:
* Free transfer descriptor memory.
*
* Input Parameters:
* priv - A reference to the class instance.
*
* Returned Values:
* On sucess, zero (OK) is returned. On failure, an negated errno value
* is returned to indicate the nature of the failure.
*
****************************************************************************/
static int usbhost_tdfree(FAR struct usbhost_state_s *priv)
{
int result = OK;
/* Is a descriptor already allocated? */
if (!priv->tdbuffer)
{
result = DRVR_FREE(priv->drvr, priv->tdbuffer);
priv->tdbuffer = NULL;
priv->tdbuflen = 0;
}
return result;
}
/****************************************************************************
* Name: usbhost_cbwalloc
*
* Description:
* Allocate and initialize a CBW. Upon successful return, the CBW is cleared
* and has the CBW signature in place.
*
* Input Parameters:
* priv - A reference to the class instance.
*
* Returned Values:
* None
*
****************************************************************************/
static FAR struct usbstrg_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv)
{
FAR struct usbstrg_cbw_s *cbw = NULL;
int result;
/* Allocate any special memory that the the driver may have for us */
result = usbhost_tdalloc(priv);
if (result == OK && priv->tdbuflen >= sizeof(struct usbstrg_cbw_s))
{
/* Intialize the CBW sructure */
cbw = (FAR struct usbstrg_cbw_s *)priv->tdbuffer;
memset(cbw, 0, sizeof(struct usbstrg_cbw_s));
usbhost_putle32(cbw->signature, USBSTRG_CBW_SIGNATURE);
}
return cbw;
}
/****************************************************************************
* struct usbhost_registry_s methods
****************************************************************************/
@ -768,7 +914,7 @@ static int usbhost_configdesc(FAR struct usbhost_class_s *class,
* It might be a good check to get the number of interfaces here too.
*/
remaining = (int)usbhost_getint16(cfgdesc->totallen);
remaining = (int)usbhost_getle16(cfgdesc->totallen);
/* Skip to the next entry descriptor */
@ -831,7 +977,7 @@ static int usbhost_configdesc(FAR struct usbhost_class_s *class,
priv->bulkout.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
priv->bulkout.in = false;
priv->bulkout.mxpacketsize = usbhost_getint16(epdesc->mxpacketsize);
priv->bulkout.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
}
else
{
@ -849,7 +995,7 @@ static int usbhost_configdesc(FAR struct usbhost_class_s *class,
priv->bulkin.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
priv->bulkin.in = true;
priv->bulkin.mxpacketsize = usbhost_getint16(epdesc->mxpacketsize);
priv->bulkin.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
}
}
}
@ -1192,6 +1338,7 @@ static int usbhost_geometry(FAR struct inode *inode, struct geometry *geometry)
/* Check if the mass storage device is still connected */
priv = (FAR struct usbhost_state_s *)inode->i_private;
if (!priv->drvr)
{
/* No... the block driver is no longer bound to the class. That means that
@ -1205,7 +1352,6 @@ static int usbhost_geometry(FAR struct inode *inode, struct geometry *geometry)
{
/* Return the geometry of the USB mass storage device */
priv = (FAR struct usbhost_state_s *)inode->i_private;
usbhost_takesem(&priv->exclsem);
DEBUGASSERT(priv->state == USBSTRG_STATE_READY);

View File

@ -49,6 +49,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
@ -166,6 +167,119 @@
#define CLASS_DISCONNECTED(class) ((class)->disconnected(class))
/************************************************************************************
* Name: DRVR_ENUMERATE
*
* Description:
* Enumerate the connected device. This function will enqueue the
* enumeration process. 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 usbhost_findclass()
* to find the class that supports this device, (4) call the create()
* method on the struct usbhost_registry_s interface to get a class
* instance, and finally (5) call the configdesc() method of the struct
* usbhost_class_s interface. After that, the class is in 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.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* This function will *not* be called from an interrupt handler.
*
************************************************************************************/
#define DRVR_ENUMERATE(drvr) ((drvr)->enumerate(drvr))
/************************************************************************************
* Name: DRVR_TRANSFER
*
* Description:
* Enqueue a request to handle a transfer descriptor. This method will
* enqueue the transfer request and return immediately. The transfer will
* be performed asynchronously. When the transfer completes, the USB host
* driver will call he complete() method of the struct usbhost_class_s
* interface. Only one transfer may be queued; this function cannot be
* again until the class complete() method has been called.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ed - The IN or OUT endpoint descriptor for the device endpoint on which to
* perform the transfer.
* buffer - A buffer containing the data to be sent (OUT endpoint) or received
* (IN endpoint).
* buflen - The length of the data to be sent or received.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* This function will *not* be called from an interrupt handler.
*
************************************************************************************/
#define DRVR_TRANSFER(drvr,ed,buffer,buflen) ((drvr)->transfer(drvr,ed,buffer,buflen))
/************************************************************************************
* Name: DRVR_ALLOC
*
* Description:
* Some hardware supports special memory in which transfer descriptors can
* be accessed more efficiently. This method provides a mechanism to allocate
* the transfer descriptor memory. If the underlying hardware does not support
* such "special" memory, this functions may simply map to malloc.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* buffer - The address of a memory location provided by the caller in which to
* return the allocated buffer memory address.
* maxlen - The address of a memory location provided by the caller in which to
* return the maximum size of the allocated buffer memory.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* This function will *not* be called from an interrupt handler.
*
************************************************************************************/
#define DRVR_ALLOC(drvr,buffer,maxlen) ((drvr)->alloc(drvr,buffer,maxlen))
/************************************************************************************
* Name: DRVR_FREE
*
* Description:
* Some hardware supports special memory in which transfer descriptors can
* be accessed more efficiently. This method provides a mechanism to free that
* transfer descriptor memory. If the underlying hardware does not support
* such "special" memory, this functions may simply map to free().
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* buffer - The address of the allocated buffer memory to be freed.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* This function will *not* be called from an interrupt handler.
*
************************************************************************************/
#define DRVR_FREE(drvr,buffer) ((drvr)->free(drvr,buffer))
/************************************************************************************
* Public Types
************************************************************************************/
@ -260,16 +374,30 @@ struct usbhost_driver_s
* sequence of operations.
*/
int (*enumerate)(FAR struct usbhost_driver_s *drvr, FAR struct usbhost_epdesc_s *ed);
int (*enumerate)(FAR struct usbhost_driver_s *drvr);
/* Enqueue a request to process a transfer descriptor. This method will
/* Enqueue a request to handle a transfer descriptor. This method will
* enqueue the transfer request and return immediately. The transfer will
* be performed asynchronously. When the transfer completes, the USB host
* driver will call he complete() method of the struct usbhost_class_s
* interface.
* interface. Only one transfer may be queued; this function cannot be
* again until the class complete() method has been called.
*/
int (*transfer)(FAR struct usbhost_driver_s *drvr, FAR struct usbhost_epdesc_s *ed);
int (*transfer)(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_epdesc_s *ed,
FAR uint8_t *buffer, size_t buflen);
/* Some hardware supports special memory in which transfer descriptors can
* be accessed more efficiently. The following methods provide a mechanism
* to allocate and free the transfer descriptor memory. If the underlying
* hardware does not support such "special" memory, these functions may
* simply map to malloc and free.
*/
int (*alloc)(FAR struct usbhost_driver_s *drvr,
FAR uint8_t **buffer, FAR size_t *maxlen);
int (*free)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
/* Receive control information */