@@ -45,6 +45,16 @@ struct usb_msd_csw {
uint8_t status;
};
+struct usb_msd_cbw {
+ uint32_t sig;
+ uint32_t tag;
+ uint32_t data_len;
+ uint8_t flags;
+ uint8_t lun;
+ uint8_t cmd_len;
+ uint8_t cmd[16];
+};
+
typedef struct {
USBDevice dev;
enum USBMSDMode mode;
@@ -52,6 +62,7 @@ typedef struct {
uint8_t *scsi_buf;
uint32_t data_len;
uint32_t residue;
+ struct usb_msd_cbw cbw;
struct usb_msd_csw csw;
SCSIRequest *req;
SCSIBus bus;
@@ -63,16 +74,6 @@ typedef struct {
USBPacket *packet;
} MSDState;
-struct usb_msd_cbw {
- uint32_t sig;
- uint32_t tag;
- uint32_t data_len;
- uint8_t flags;
- uint8_t lun;
- uint8_t cmd_len;
- uint8_t cmd[16];
-};
-
enum {
STR_MANUFACTURER = 1,
STR_PRODUCT,
@@ -188,6 +189,26 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
}
}
+static int usb_msd_recv_command(MSDState *s, USBPacket *p)
+{
+ if (p->iov.size != 31) {
+ fprintf(stderr, "usb-msd: Bad CBW size");
+ return -1;
+ }
+
+ usb_packet_copy(p, &s->cbw, 31);
+ s->cbw.sig = le32_to_cpu(s->cbw.sig);
+ s->cbw.tag = le32_to_cpu(s->cbw.tag);
+ s->cbw.data_len = le32_to_cpu(s->cbw.data_len);
+
+ if (s->cbw.sig != 0x43425355) {
+ fprintf(stderr, "usb-msd: Bad signature %08x\n",
+ s->cbw.sig);
+ return -1;
+ }
+ return 0;
+}
+
static void usb_msd_send_status(MSDState *s, USBPacket *p)
{
int len;
@@ -197,7 +218,12 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
assert(s->csw.sig == 0x53425355);
len = MIN(sizeof(s->csw), p->iov.size);
+
+ s->csw.sig = cpu_to_le32(s->csw.sig);
+ s->csw.tag = cpu_to_le32(s->csw.tag);
+ s->csw.residue = cpu_to_le32(s->csw.residue);
usb_packet_copy(p, &s->csw, len);
+
memset(&s->csw, 0, sizeof(s->csw));
}
@@ -231,8 +257,8 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
s->residue = s->data_len;
- s->csw.sig = cpu_to_le32(0x53425355);
- s->csw.tag = cpu_to_le32(req->tag);
+ s->csw.sig = 0x53425355;
+ s->csw.tag = req->tag;
s->csw.residue = s->residue;
s->csw.status = status != 0;
@@ -338,9 +364,7 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
{
MSDState *s = (MSDState *)dev;
- uint32_t tag;
int ret = 0;
- struct usb_msd_cbw cbw;
uint8_t devep = p->ep->nr;
switch (p->pid) {
@@ -350,35 +374,27 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
switch (s->mode) {
case USB_MSDM_CBW:
- if (p->iov.size != 31) {
- fprintf(stderr, "usb-msd: Bad CBW size");
- goto fail;
- }
- usb_packet_copy(p, &cbw, 31);
- if (le32_to_cpu(cbw.sig) != 0x43425355) {
- fprintf(stderr, "usb-msd: Bad signature %08x\n",
- le32_to_cpu(cbw.sig));
+ if (usb_msd_recv_command(s, p) != 0) {
goto fail;
}
- DPRINTF("Command on LUN %d\n", cbw.lun);
- if (cbw.lun != 0) {
- fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
+ DPRINTF("Command on LUN %d\n", s->cbw.lun);
+ if (s->cbw.lun != 0) {
+ fprintf(stderr, "usb-msd: Bad LUN %d\n", s->cbw.lun);
goto fail;
}
- tag = le32_to_cpu(cbw.tag);
- s->data_len = le32_to_cpu(cbw.data_len);
+ s->data_len = s->cbw.data_len;
if (s->data_len == 0) {
s->mode = USB_MSDM_CSW;
- } else if (cbw.flags & 0x80) {
+ } else if (s->cbw.flags & 0x80) {
s->mode = USB_MSDM_DATAIN;
} else {
s->mode = USB_MSDM_DATAOUT;
}
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
- tag, cbw.flags, cbw.cmd_len, s->data_len);
+ tag, s->cbw.flags, s->cbw.cmd_len, s->data_len);
s->residue = 0;
s->scsi_len = 0;
- s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
+ s->req = scsi_req_new(s->scsi_dev, s->cbw.tag, 0, s->cbw.cmd, NULL);
scsi_req_enqueue(s->req);
if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
scsi_req_continue(s->req);