You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/06/14 12:05:32 UTC

[incubator-nuttx] 03/04: usbmsc: Add USBMSC_NOT_STALL_BULKEP for RP2040 workaround

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 8d722709cd11901ecdcdcf97097e7a0d8bc2c234
Author: Yuichi Nakamura <y....@gmail.com>
AuthorDate: Sun Jun 13 23:58:22 2021 +0900

    usbmsc: Add USBMSC_NOT_STALL_BULKEP for RP2040 workaround
    
    The new configuration CONFIG_USBMSC_NOT_STALL_BULKEP avoids to go into
    stall state when :
    - Receiving SCSI_CMD_INQUIRY with flags or pagecode != 0
    - Receiving SCSI_CMD_MODESENSE6 and return the result data shorter than
      the requested data size.
    Instead of stall, it just ignores the error condition.
    
    Originally the usb driver goes into the stall under the conditions
    mentioned above to inform to the USB host that the requested SCSI feature
    is not supported, or the result data is shorter than the requested data
    size.
    But, at this moment, RP2040 USB device driver cannot handle entering and
    leaving stall state of the bulk endpoints well.  Once stalls, the host -
    device communication stops and cannot be resumed.
    
    I have investigated to solve the issue and found that the existing
    RP2040 USB device driver implementation, TinyUSB
    (https://github.com/hathach/tinyusb) mass-storage class driver doesn't
    enter the stall state like the treatment of this patch.
    
    So, I introduce this new configuration as the RP2040 workaround.
    In the future, when the RP2040 USB device driver is fixed and can handle
    the bulk endpoint stall correctly, this patch should be reverted.
---
 drivers/usbdev/Kconfig       |  8 ++++++++
 drivers/usbdev/usbmsc_scsi.c | 15 +++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/drivers/usbdev/Kconfig b/drivers/usbdev/Kconfig
index b3a943f..cfcb4e4 100644
--- a/drivers/usbdev/Kconfig
+++ b/drivers/usbdev/Kconfig
@@ -852,6 +852,14 @@ config USBMSC_SCSI_STACKSIZE
 		Stack size used with the SCSI kernel thread.  The default value
 		is not tuned.
 
+config USBMSC_NOT_STALL_BULKEP
+	bool "Not stall USBMSC bulk endpoints for workaround"
+	default n
+	---help---
+		Not stall USBMSC bulk endpoints in some conditions.
+		Because RP2040 usbdev driver cannot handle stalling/resuming bulk
+		endpoints well, this workaround is required.
+
 endif
 
 menuconfig RNDIS
diff --git a/drivers/usbdev/usbmsc_scsi.c b/drivers/usbdev/usbmsc_scsi.c
index b4d1ea1..7cd5bd8 100644
--- a/drivers/usbdev/usbmsc_scsi.c
+++ b/drivers/usbdev/usbmsc_scsi.c
@@ -663,12 +663,14 @@ static inline int usbmsc_cmdinquiry(FAR struct usbmsc_dev_s *priv,
           response->qualtype = SCSIRESP_INQUIRYPQ_NOTCAPABLE |
                                SCSIRESP_INQUIRYPD_UNKNOWN;
         }
+#ifndef CONFIG_USBMSC_NOT_STALL_BULKEP
       else if ((inquiry->flags != 0) || (inquiry->pagecode != 0))
         {
           usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INQUIRYFLAGS), 0);
           priv->lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA;
           ret = -EINVAL;
         }
+#endif
       else
         {
           memset(response, 0, SCSIRESP_INQUIRY_SIZEOF);
@@ -822,7 +824,9 @@ static int inline usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv,
              (FAR struct scsicmd_modesense6_s *)priv->cdb;
   FAR struct scsiresp_modeparameterhdr6_s *mph =
              (FAR struct scsiresp_modeparameterhdr6_s *)buf;
+#ifndef CONFIG_USBMSC_NOT_STALL_BULKEP
   int mdlen;
+#endif
   int ret;
 
   priv->u.alloclen = modesense->alloclen;
@@ -830,6 +834,11 @@ static int inline usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv,
                         USBMSC_FLAGS_DIRDEVICE2HOST);
   if (ret == OK)
     {
+#ifdef CONFIG_USBMSC_NOT_STALL_BULKEP
+      priv->residue = priv->cbwlen = priv->nreqbytes =
+        SCSIRESP_MODEPARAMETERHDR6_SIZEOF;
+#endif
+
       if ((modesense->flags & ~SCSICMD_MODESENSE6_DBD) != 0 ||
            modesense->subpgcode != 0)
         {
@@ -851,6 +860,7 @@ static int inline usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv,
             (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00);
           mph->bdlen = 0; /* Block descriptor length */
 
+#ifndef CONFIG_USBMSC_NOT_STALL_BULKEP
           /* There are no block descriptors, only the following mode page: */
 
           ret = usbmsc_modepage(priv,
@@ -867,6 +877,7 @@ static int inline usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv,
               priv->nreqbytes =
                 mdlen + SCSIRESP_MODEPARAMETERHDR6_SIZEOF;
             }
+#endif
         }
     }
 
@@ -2584,6 +2595,7 @@ static int usbmsc_cmdfinishstate(FAR struct usbmsc_dev_s *priv)
 
           if (priv->residue > 0)
             {
+#ifndef CONFIG_USBMSC_NOT_STALL_BULKEP
               usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDFINISHRESIDUE),
                        (uint16_t)priv->residue);
 
@@ -2602,6 +2614,9 @@ static int usbmsc_cmdfinishstate(FAR struct usbmsc_dev_s *priv)
 #else
               EP_STALL(priv->epbulkin);
 #endif
+#else
+              priv->residue = 0;
+#endif
             }
         }
       break;