usb: Update the test to cover reading and writing
authorSimon Glass <sjg@chromium.org>
Fri, 21 Oct 2022 00:22:55 +0000 (18:22 -0600)
committerTom Rini <trini@konsulko.com>
Mon, 31 Oct 2022 15:02:44 +0000 (11:02 -0400)
Add test coverage for blk_write() as well.

The blk_erase() is not tested for now as the USB stor interface does not
support erase.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/scsi/scsi_emul.c
drivers/usb/emul/sandbox_flash.c
include/scsi.h
include/scsi_emul.h
test/dm/usb.c

index 5ba364b..6b8468f 100644 (file)
@@ -62,6 +62,15 @@ int sb_scsi_emul_command(struct scsi_emul_info *info,
                ret = SCSI_EMUL_DO_READ;
                break;
        }
+       case SCSI_WRITE10: {
+               const struct scsi_write10_req *write_req = (void *)req;
+
+               info->seek_block = be32_to_cpu(write_req->lba);
+               info->write_len = be16_to_cpu(write_req->xfer_len);
+               info->buff_used = info->write_len * info->block_size;
+               ret = SCSI_EMUL_DO_WRITE;
+               break;
+       }
        default:
                debug("Command not supported: %x\n", req->cmd[0]);
                ret = -EPROTONOSUPPORT;
index 2589c70..6e8cfe1 100644 (file)
@@ -4,6 +4,8 @@
  * Written by Simon Glass <sjg@chromium.org>
  */
 
+#define LOG_CATEGORY   UCLASS_USB
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -190,7 +192,8 @@ static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff,
        ret = sb_scsi_emul_command(info, req, len);
        if (!ret) {
                setup_response(priv);
-       } else if (ret == SCSI_EMUL_DO_READ && priv->fd != -1) {
+       } else if ((ret == SCSI_EMUL_DO_READ || ret == SCSI_EMUL_DO_WRITE) &&
+                  priv->fd != -1) {
                os_lseek(priv->fd, info->seek_block * info->block_size,
                         OS_SEEK_SET);
                setup_response(priv);
@@ -217,6 +220,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
                case SCSIPH_START:
                        info->alloc_len = 0;
                        info->read_len = 0;
+                       info->write_len = 0;
                        if (priv->error || len != UMASS_BBB_CBW_SIZE ||
                            cbw->dCBWSignature != CBWSIGNATURE)
                                goto err;
@@ -230,8 +234,31 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
                        return handle_ufi_command(priv, cbw->CBWCDB,
                                                  cbw->bCDBLength);
                case SCSIPH_DATA:
-                       debug("data out\n");
-                       break;
+                       log_debug("data out, len=%x, info->write_len=%x\n", len,
+                                 info->write_len);
+                       info->transfer_len = cbw->dCBWDataTransferLength;
+                       priv->tag = cbw->dCBWTag;
+                       if (!info->write_len)
+                               return 0;
+                       if (priv->fd != -1) {
+                               ulong bytes_written;
+
+                               bytes_written = os_write(priv->fd, buff, len);
+                               log_debug("bytes_written=%lx", bytes_written);
+                               if (bytes_written != len)
+                                       return -EIO;
+                               info->write_len -= len / info->block_size;
+                               if (!info->write_len)
+                                       info->phase = SCSIPH_STATUS;
+                       } else {
+                               if (info->alloc_len && len > info->alloc_len)
+                                       len = info->alloc_len;
+                               if (len > SANDBOX_FLASH_BUF_SIZE)
+                                       len = SANDBOX_FLASH_BUF_SIZE;
+                               memcpy(info->buff, buff, len);
+                               info->phase = SCSIPH_STATUS;
+                       }
+                       return len;
                default:
                        break;
                }
@@ -310,7 +337,7 @@ static int sandbox_flash_probe(struct udevice *dev)
        struct scsi_emul_info *info = &priv->eminfo;
        int ret;
 
-       priv->fd = os_open(plat->pathname, OS_O_RDONLY);
+       priv->fd = os_open(plat->pathname, OS_O_RDWR);
        if (priv->fd != -1) {
                ret = os_get_filesize(plat->pathname, &info->file_size);
                if (ret)
index 94e1d8c..9efefea 100644 (file)
@@ -255,6 +255,16 @@ struct __packed scsi_read10_req {
        u8 spare2[3];
 };
 
+/** struct scsi_write10_req - data for the write10 command */
+struct __packed scsi_write10_req {
+       u8 cmd;
+       u8 lun_flags;
+       u32 lba;
+       u8 spare;
+       u16 xfer_len;
+       u8 spare2[3];
+};
+
 /**
  * struct scsi_plat - stores information about SCSI controller
  *
index 13c3f86..d439f7c 100644 (file)
@@ -41,13 +41,20 @@ struct scsi_emul_info {
        enum scsi_cmd_phase phase;
        int buff_used;
        int read_len;
+       int write_len;
        uint seek_pos;
        int alloc_len;
        uint transfer_len;
 };
 
-/* Indicates that a read is being started */
-#define SCSI_EMUL_DO_READ      1
+/**
+ * Return value from sb_scsi_emul_command() indicates that a read or write is
+ * being started
+ */
+enum {
+       SCSI_EMUL_DO_READ       = 1,
+       SCSI_EMUL_DO_WRITE      = 2,
+};
 
 /**
  * sb_scsi_emul_command() - Process a SCSI command
@@ -61,8 +68,9 @@ struct scsi_emul_info {
  * @info: Emulation information
  * @req: Request to process
  * @len: Length of request in bytes
- * @return SCSI_EMUL_DO_READ if a read has started, 0 if some other operation
- *     has started, -ve if there was an error
+ * @return SCSI_EMUL_DO_READ if a read has started, SCSI_EMUL_DO_WRITE if a
+ *     write has started, 0 if some other operation has started, -ve if there
+ *     was an error
  */
 int sb_scsi_emul_command(struct scsi_emul_info *info,
                         const struct scsi_cmd *req, int len);
index 445b21a..7671ef1 100644 (file)
@@ -61,7 +61,24 @@ static int dm_test_usb_flash(struct unit_test_state *uts)
        ut_asserteq(512, dev_desc->blksz);
        memset(cmp, '\0', sizeof(cmp));
        ut_asserteq(2, blk_read(blk, 0, 2, cmp));
-       ut_assertok(strcmp(cmp, "this is a test"));
+       ut_asserteq_str("this is a test", cmp);
+
+       strcpy(cmp, "another test");
+       ut_asserteq(1, blk_write(blk, 1, 1, cmp));
+
+       memset(cmp, '\0', sizeof(cmp));
+       ut_asserteq(2, blk_read(blk, 0, 2, cmp));
+       ut_asserteq_str("this is a test", cmp);
+       ut_asserteq_str("another test", cmp + 512);
+
+       memset(cmp, '\0', sizeof(cmp));
+       ut_asserteq(1, blk_write(blk, 1, 1, cmp));
+
+       memset(cmp, '\0', sizeof(cmp));
+       ut_asserteq(2, blk_read(blk, 0, 2, cmp));
+       ut_asserteq_str("this is a test", cmp);
+       ut_asserteq_str("", cmp + 512);
+
        ut_assertok(usb_stop());
 
        return 0;