From 4566137cb8f4a2a5f240e9b93eb6a52e369b5d11 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 20 Dec 2010 16:51:15 +0000 Subject: [PATCH] minor git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3200 42af7a65-404d-4744-a932-0658087f49c3 --- arch/arm/src/lpc17xx/lpc17_usbhost.c | 123 ++++++++++++++++++++++----- drivers/usbhost/usbhost_storage.c | 117 +------------------------ include/nuttx/usb/usbhost.h | 101 ++++++++-------------- 3 files changed, 142 insertions(+), 199 deletions(-) diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c index 8fb4d1df39..c2cb49f574 100755 --- a/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,11 @@ struct lpc17_usbhost_s /* The bound device class driver */ struct usbhost_class_s *class; + + /* Driver status */ + + uint8_t tdstatus; /* TD control status bits from last Writeback Done Head event */ + sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */ }; /* Host Controller Communication Area */ @@ -194,6 +200,16 @@ static void lpc17_putreg(uint32_t val, uint32_t addr); # define lpc17_putreg(val,addr) putreg32(val,addr) #endif +/* Semaphores ******************************************************************/ + +static void lpc17_takesem(sem_t *sem); +#define lpc17_givesem(s) sem_post(s); + +/* Byte stream access helper functions *****************************************/ + +static inline uint16_t lpc17_getle16(const uint8_t *val); +static void lpc17_putle16(uint8_t *dest, uint16_t val); + /* Descriptor helper functions *************************************************/ static struct lpc17_hced_s *lpc17_edalloc(struct lpc17_usbhost_s *priv); @@ -220,8 +236,12 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr); static int lpc17_alloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer, FAR size_t *maxlen); static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); -static int lpc17_control(FAR struct usbhost_driver_s *drvr, - const struct usb_ctrlreq_s *req, FAR uint8_t *buffer); +static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer); +static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer); static int lpc17_transfer(FAR struct usbhost_driver_s *drvr, FAR struct usbhost_epdesc_s *ed, FAR uint8_t *buffer, size_t buflen); @@ -249,7 +269,8 @@ static struct lpc17_usbhost_s g_usbhost = .enumerate = lpc17_enumerate, .alloc = lpc17_alloc, .free = lpc17_free, - .control = lpc17_control, + .ctrlin = lpc17_ctrlin, + .ctrlout = lpc17_ctrlout, .transfer = lpc17_transfer, .disconnect = lpc17_disconnect, }, @@ -390,6 +411,56 @@ static void lpc17_putreg(uint32_t val, uint32_t addr) } #endif +/**************************************************************************** + * Name: lpc17_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 lpc17_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: lpc17_getle16 + * + * Description: + * Get a (possibly unaligned) 16-bit little endian value. + * + ****************************************************************************/ + +static inline uint16_t lpc17_getle16(const uint8_t *val) +{ + return (uint16_t)val[1] << 8 | (uint16_t)val[0]; +} + +/**************************************************************************** + * Name: lpc17_putle16 + * + * Description: + * Put a (possibly unaligned) 16-bit little endian value. + * + ****************************************************************************/ + +static void lpc17_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: lpc17_edalloc * @@ -698,15 +769,16 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) } /************************************************************************************ - * Name: lpc17_control + * Name: lpc17_ctrlin and lpc17_ctrlout * * Description: - * Enqueue a request on the control endpoint. This method will enqueue - * the request and return immediately. The transfer will be performed - * asynchronously. When the transfer completes, the USB host driver will - * call the complete() method of the struct usbhost_class_s interface. - * Only one transfer may be queued; Neither this method nor the transfer() - * method can be called again until the class complete() method has been called. + * Process a IN or OUT request on the control endpoint. These methods + * will enqueue the request and return immediately. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. * * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to @@ -727,8 +799,17 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * ************************************************************************************/ -static int lpc17_control(FAR struct usbhost_driver_s *drvr, - const struct usb_ctrlreq_s *req, FAR uint8_t *buffer) +static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer) +{ +# warning "Not Implemented" + return -ENOSYS; +} + +static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer) { # warning "Not Implemented" return -ENOSYS; @@ -738,13 +819,13 @@ static int lpc17_control(FAR struct usbhost_driver_s *drvr, * Name: lpc17_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 the complete() method of the struct usbhost_class_s - * interface. Only one transfer may be queued; Neither this method nor the - * control method can be called again until the class complete() method has - * been called. + * Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and return immediately. Only one transfer may be + * queued; Neither this method nor the ctrlin or ctrlout methods can be called + * again until this function returns. + * + * This is a blocking method; this functions will not return until the + * transfer has completed. * * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to @@ -857,6 +938,10 @@ void up_usbhostinitialize(void) usbtrace(TRACE_DEVINIT, 0); + /* Initialize the state data structure */ + + sem_init(&priv->wdhsem, 0, 0); + /* Enable power by setting PCUSB in the PCONP register */ flags = irqsave(); diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c index 2193caf1f0..149a8a7aff 100644 --- a/drivers/usbhost/usbhost_storage.c +++ b/drivers/usbhost/usbhost_storage.c @@ -124,7 +124,6 @@ struct usbhost_state_s uint16_t blocksize; /* Block size of USB mass storage device */ uint32_t nblocks; /* Number of blocks on the USB mass storage device */ 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 */ @@ -203,8 +202,6 @@ static struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr, static int usbhost_configdesc(FAR struct usbhost_class_s *class, FAR const uint8_t *configdesc, int desclen); -static int usbhost_complete(FAR struct usbhost_class_s *class, - FAR const uint8_t *response, int resplen); static int usbhost_disconnected(FAR struct usbhost_class_s *class); /* struct block_operations methods */ @@ -596,13 +593,7 @@ static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv) req.req = USBSTRG_REQ_GETMAXLUN; usbhost_putle16(req.len, 1); - result = DRVR_CONTROL(priv->drvr, &req, priv->tdbuffer); - if (result == OK) - { - /* Wait for the control operation to complete */ - - usbhost_takesem(&priv->waitsem); - } + result = DRVR_CTRLIN(priv->drvr, &req, priv->tdbuffer); } return result; } @@ -624,18 +615,10 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv) (uint8_t*)cbw, USBSTRG_CBW_SIZEOF); if (result == OK) { - /* Wait for the CBW OUT operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the CSW */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, USBSTRG_CSW_SIZEOF); - - /* Wait for the CSW IN operation to complete */ - - usbhost_takesem(&priv->waitsem); } } return result; @@ -658,30 +641,16 @@ static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv) (uint8_t*)cbw, USBSTRG_CBW_SIZEOF); if (result == OK) { - /* Wait for the CBW OUT operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the sense data response */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF); if (result == OK) { - /* Wait for the CBW IN response operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the CSW */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, USBSTRG_CSW_SIZEOF); - if (result == OK) - { - /* Wait for the CSW IN operation to complete */ - - usbhost_takesem(&priv->waitsem); - } } } } @@ -706,20 +675,12 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv) (uint8_t*)cbw, USBSTRG_CBW_SIZEOF); if (result == OK) { - /* Wait for the CBW OUT operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the read capacity CBW IN response */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, SCSIRESP_READCAPACITY10_SIZEOF); if (result == OK) { - /* Wait for the CBW IN response operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Save the capacity information */ resp = (FAR struct scsiresp_readcapacity10_s *)priv->tdbuffer; @@ -730,12 +691,6 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv) result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, USBSTRG_CSW_SIZEOF); - if (result == OK) - { - /* Wait for the CSW IN operation to complete */ - - usbhost_takesem(&priv->waitsem); - } } } } @@ -760,20 +715,12 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv) (uint8_t*)cbw, USBSTRG_CBW_SIZEOF); if (result == OK) { - /* Wait for the CBW OUT operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the CBW IN response */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, SCSIRESP_INQUIRY_SIZEOF); if (result == OK) { - /* Wait for the CBW IN response operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* TODO: If USB debug is enabled, dump the response data here */ resp = (FAR struct scsiresp_inquiry_s *)priv->tdbuffer; @@ -782,10 +729,6 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv) result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, priv->tdbuffer, USBSTRG_CSW_SIZEOF); - - /* Wait for the CSW IN operation to complete */ - - usbhost_takesem(&priv->waitsem); } } } @@ -831,7 +774,6 @@ static void usbhost_destroy(FAR void *arg) /* Destroy the semaphores */ sem_destroy(&priv->exclsem); - sem_destroy(&priv->waitsem); /* And free the class instance. Hmmm.. this may execute on the worker * thread and the work structure is part of what is getting freed. @@ -1308,7 +1250,6 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d /* Initialize class method function pointers */ priv->class.configdesc = usbhost_configdesc; - priv->class.complete = usbhost_complete; priv->class.disconnected = usbhost_disconnected; /* The initial reference count is 1... One reference is held by the driver */ @@ -1318,7 +1259,6 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d /* Initialize semphores (this works okay in the interrupt context) */ sem_init(&priv->exclsem, 0, 1); - sem_init(&priv->waitsem, 0, 0); /* Bind the driver to the storage class instance */ @@ -1509,45 +1449,6 @@ static int usbhost_configdesc(FAR struct usbhost_class_s *class, return OK; } -/**************************************************************************** - * Name: usbhost_complete - * - * Description: - * This function implements the complete() method of struct - * usbhost_class_s. In the interface with the USB host drivers, the class - * will queue USB IN/OUT transactions. The enqueuing function will return - * and the transactions will be performed asynchrounously. When the - * transaction completes, the USB host driver will call this function in - * order to inform the class that the transaction has completed and to - * provide any response data. - * - * Input Parameters: - * class - The USB host class entry previously obtained from a call to - * create(). - * response - Response data buffer - * resplen - Number of bytes of data in the response data buffer. - * - * 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 may be called from an interrupt handler. - * - ****************************************************************************/ - -static int usbhost_complete(FAR struct usbhost_class_s *class, - FAR const uint8_t *response, int resplen) -{ - FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class; - DEBUGASSERT(priv != NULL && priv->waitsem.semcount <= 0); - - /* Wake up the application thread waiting for the transfer completion event */ - - usbhost_givesem(&priv->waitsem); - return OK; -} - /**************************************************************************** * Name: usbhost_disconnected * @@ -1743,20 +1644,12 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer, (uint8_t*)cbw, USBSTRG_CBW_SIZEOF); if (result == OK) { - /* Wait for the CBW OUT operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the user data */ #warning "For lpc17xx, I think this buffer needs to lie in BANK1" result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, buffer, priv->blocksize * nsectors); if (result == OK) { - /* Wait for the data in operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the CSW */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, @@ -1843,20 +1736,12 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe (uint8_t*)cbw, USBSTRG_CBW_SIZEOF); if (result == OK) { - /* Wait for the CBW OUT operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Send the user data */ #warning "For lpc17xx, I think this buffer needs to lie in BANK1" result = DRVR_TRANSFER(priv->drvr, &priv->bulkout, (uint8_t*)buffer, priv->blocksize * nsectors); if (result == OK) { - /* Wait for the data in operation to complete */ - - usbhost_takesem(&priv->waitsem); - /* Receive the CSW */ result = DRVR_TRANSFER(priv->drvr, &priv->bulkin, diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h index 2035299c28..687dd884b9 100644 --- a/include/nuttx/usb/usbhost.h +++ b/include/nuttx/usb/usbhost.h @@ -118,33 +118,6 @@ #define CLASS_CONFIGDESC(class,configdesc,desclen) ((class)->configdesc(class,configdesc,desclen)) -/************************************************************************************ - * Name: CLASS_COMPLETE - * - * Description: - * This macro will call the complete() method of struct usbhost_class_s. In the - * interface with the USB host drivers, the class will queue USB IN/OUT - * transactions. The enqueuing function will return and the transactions will be - * performed asynchrounously. When the transaction completes, the USB host driver - * will call this function in order to inform the class that the transaction has - * completed and to provide any response data. - * - * Input Parameters: - * class - The USB host class entry previously obtained from a call to create(). - * response - Response data buffer - * resplen - Number of bytes of data in the response data buffer. - * - * 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 may be called from an interrupt handler. - * - ************************************************************************************/ - -#define CLASS_COMPLETE(class,response,resplen) (class)->complete(class,response,resplen)) - /************************************************************************************ * Name: CLASS_DISCONNECTED * @@ -250,15 +223,16 @@ #define DRVR_FREE(drvr,buffer) ((drvr)->free(drvr,buffer)) /************************************************************************************ - * Name: DRVR_CONTROL + * Name: DRVR_CTRLIN and DRVR_CTRLOUT * * Description: - * Enqueue a request on the control endpoint. This method will enqueue - * the request and return immediately. The transfer will be performed - * asynchronously. When the transfer completes, the USB host driver will - * call the complete() method of the struct usbhost_class_s interface. - * Only one transfer may be queued; Neither this method nor the transfer() - * method can be called again until the class complete() method has been called. + * Process a IN or OUT request on the control endpoint. These methods + * will enqueue the request and return immediately. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. * * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to @@ -279,19 +253,20 @@ * ************************************************************************************/ -#define DRVR_CONTROL(drvr,req,buffer) ((drvr)->control(drvr,req,buffer)) +#define DRVR_CTRLIN(drvr,req,buffer) ((drvr)->ctrlin(drvr,req,buffer)) +#define DRVR_CTRLOUT(drvr,req,buffer) ((drvr)->ctrlout(drvr,req,buffer)) /************************************************************************************ * 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 the complete() method of the struct usbhost_class_s - * interface. Only one transfer may be queued; Neither this method nor the - * control method can be called again until the class complete() method has - * been called. + * Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and return immediately. Only one transfer may be + * queued; Neither this method nor the ctrlin or ctrlout methods can be called + * again until this function returns. + * + * This is a blocking method; this functions will not return until the + * transfer has completed. * * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to @@ -402,12 +377,6 @@ struct usbhost_class_s int (*configdesc)(FAR struct usbhost_class_s *class, FAR const uint8_t *configdesc, int desclen); - /* This method must be called by the USB host driver whenever a transfer - * completes. - */ - - int (*complete)(FAR struct usbhost_class_s *class, FAR const uint8_t *response, int resplen); - /* This method informs the class that the USB device has been disconnected. */ int (*disconnected)(FAR struct usbhost_class_s *class); @@ -444,25 +413,29 @@ struct usbhost_driver_s FAR uint8_t **buffer, FAR size_t *maxlen); int (*free)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); - /* Enqueue a request on the control endpoint. This method will enqueue - * the request and return immediately. The transfer will be performed - * asynchronously. When the transfer completes, the USB host driver will - * call the complete() method of the struct usbhost_class_s interface. - * Only one transfer may be queued; Neither this method nor the transfer() - * method can be called again until the class complete() method has been called. + /* Process a IN or OUT request on the control endpoint. These methods + * will enqueue the request and return immediately. Only one transfer may be + * queued; Neither these methods nor the transfer() method can be called again + * until the control transfer functions returns. + * + * These are blocking methods; these functions will not return until the + * control transfer has completed. */ - int (*control)(FAR struct usbhost_driver_s *drvr, - const struct usb_ctrlreq_s *req, - FAR uint8_t *buffer); + int (*ctrlin)(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR uint8_t *buffer); + int (*ctrlout)(FAR struct usbhost_driver_s *drvr, + FAR const struct usb_ctrlreq_s *req, + FAR const uint8_t *buffer); - /* 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 the complete() method of the struct usbhost_class_s - * interface. Only one transfer may be queued; Neither this method nor the - * control method can be called again until the class complete() method has - * been called. + /* Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and return immediately. Only one transfer may be + * queued; Neither this method nor the ctrlin or ctrlout methods can be called + * again until this function returns. + * + * This is a blocking method; this functions will not return until the + * transfer has completed. */ int (*transfer)(FAR struct usbhost_driver_s *drvr,