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 <npig...@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