[PATCH v2 19/45] usb: Update the test to cover reading and writing

Simon Glass sjg at chromium.org
Thu Oct 13 14:29:01 CEST 2022


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 at chromium.org>
---

Changes in v2:
- Rebase to master

 drivers/scsi/scsi_emul.c         |  9 ++++++++
 drivers/usb/emul/sandbox_flash.c | 35 ++++++++++++++++++++++++++++----
 include/scsi.h                   | 10 +++++++++
 include/scsi_emul.h              | 16 +++++++++++----
 test/dm/usb.c                    | 19 ++++++++++++++++-
 5 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/scsi_emul.c b/drivers/scsi/scsi_emul.c
index 5ba364bdac7..6b8468f7994 100644
--- a/drivers/scsi/scsi_emul.c
+++ b/drivers/scsi/scsi_emul.c
@@ -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;
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 2589c708d88..6e8cfe1650a 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -4,6 +4,8 @@
  * Written by Simon Glass <sjg at 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)
diff --git a/include/scsi.h b/include/scsi.h
index 94e1d8ccb28..9efefea99bb 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -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
  *
diff --git a/include/scsi_emul.h b/include/scsi_emul.h
index 13c3f860b40..d439f7c00c2 100644
--- a/include/scsi_emul.h
+++ b/include/scsi_emul.h
@@ -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);
diff --git a/test/dm/usb.c b/test/dm/usb.c
index 445b21a560b..7671ef156d8 100644
--- a/test/dm/usb.c
+++ b/test/dm/usb.c
@@ -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;
-- 
2.38.0.rc1.362.ged0d419d3c-goog



More information about the U-Boot mailing list