diff --git a/ChangeLog b/ChangeLog index 31d8d81d8cb7c3cc6a64cb1d7c642435a6141a37..51b317e0acffb9b508f77db7cfb450bf13733445 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1833,5 +1833,11 @@ * drivers/mtd/ramtron.c, net/net_checksd.c, fs/fs_fdopen.c, and include/nuttx/mii.h: Several structural changes made to get a clean compile under the ez80 ZDS-II - toolchain (no design changes). + toolchain (no design changes). + * drivers/usbhost/usbhost_storage.c: Incorpated bugfixes reported by Sheref H. + Younan: (1) Read capacity logic read largest block, not the number of blocks + and was, therefore, off by one, and (2) Some devices stall of get Max LUN request + if they support only a single LUN. Logic now assumes a single LUN if the get + Max LUN request fails. + diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c index b2a6d85439a777375b4371f9e8d55c1219790170..8f5864b6d8aae4ccc82abf052a7403254711f46a 100644 --- a/drivers/usbhost/usbhost_storage.c +++ b/drivers/usbhost/usbhost_storage.c @@ -669,6 +669,7 @@ static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv) { FAR struct usb_ctrlreq_s *req = (FAR struct usb_ctrlreq_s *)priv->tbuffer; DEBUGASSERT(priv && priv->tbuffer); + int ret; /* Request maximum logical unit number. NOTE: On an IN transaction, The * req and buffer pointers passed to DRVR_CTRLIN may refer to the same @@ -680,7 +681,17 @@ static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv) req->type = USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE; req->req = USBSTRG_REQ_GETMAXLUN; usbhost_putle16(req->len, 1); - return DRVR_CTRLIN(priv->drvr, req, priv->tbuffer); + + ret = DRVR_CTRLIN(priv->drvr, req, priv->tbuffer); + if (ret != OK) + { + /* Devices that do not support multiple LUNs may stall this command. + * On a failure, a single LUN is assumed. + */ + + *(priv->tbuffer) = 0; + } + return OK; } static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv) @@ -788,7 +799,7 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv) /* Save the capacity information */ resp = (FAR struct scsiresp_readcapacity10_s *)priv->tbuffer; - priv->nblocks = usbhost_getbe32(resp->lba); + priv->nblocks = usbhost_getbe32(resp->lba) + 1; priv->blocksize = usbhost_getbe32(resp->blklen); /* Receive the CSW */