This is not really required for the state machine but it improves
the symmetry of zero-data packets with data packets, and helps with
assertions and reasoning about traces.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
include/hw/usb/msd.h | 1 +
hw/usb/dev-storage.c | 10 +++++++---
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h
index af12a16c35f..6d741e44160 100644
--- a/include/hw/usb/msd.h
+++ b/include/hw/usb/msd.h
@@ -14,6 +14,7 @@ typedef enum USBMSDCBWState {
USB_MSD_CBW_NONE, /* Ready, waiting for CBW packet. */
USB_MSD_CBW_DATAOUT, /* Expecting DATA-OUT (to device) packet */
USB_MSD_CBW_DATAIN, /* Expecting DATA-IN (from device) packet */
+ USB_MSD_CBW_NODATA, /* No data, CSW but also a SCSI completion */
USB_MSD_CBW_CSW /* No more data, expecting CSW packet. */
} USBMSDCBWState;
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 5b773a22e60..a2544d2659f 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -318,9 +318,12 @@ void usb_msd_command_complete(SCSIRequest *req, size_t resid)
scsi_req_unref(req);
s->req = NULL;
+ g_assert(s->cbw_state == USB_MSD_CBW_DATAIN ||
+ s->cbw_state == USB_MSD_CBW_DATAOUT ||
+ s->cbw_state == USB_MSD_CBW_NODATA);
+
if (p) {
- g_assert(s->cbw_state == USB_MSD_CBW_DATAIN ||
- s->cbw_state == USB_MSD_CBW_DATAOUT);
+ g_assert(s->cbw_state != USB_MSD_CBW_NODATA);
if (s->data_len) {
int len = (p->iov.size - p->actual_length);
usb_packet_skip(p, len);
@@ -500,7 +503,7 @@ static void usb_msd_handle_data_out(USBDevice *dev, USBPacket *p)
tag = le32_to_cpu(cbw.tag);
s->data_len = le32_to_cpu(cbw.data_len);
if (s->data_len == 0) {
- s->cbw_state = USB_MSD_CBW_CSW;
+ s->cbw_state = USB_MSD_CBW_NODATA;
} else if (cbw.flags & 0x80) {
s->cbw_state = USB_MSD_CBW_DATAIN;
} else {
@@ -565,6 +568,7 @@ static void usb_msd_handle_data_in(USBDevice *dev, USBPacket *p)
int len;
switch (s->cbw_state) {
+ case USB_MSD_CBW_NODATA:
case USB_MSD_CBW_DATAOUT:
if (!check_valid_csw(p)) {
goto fail;
--
2.47.1