usb-msc: support WRITE commands
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 16 Nov 2011 12:02:47 +0000 (13:02 +0100)
committerKevin O'Connor <kevin@koconnor.net>
Fri, 18 Nov 2011 02:20:30 +0000 (21:20 -0500)
Writes only require building the CDB and some care with the direction
in the USB packet.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
src/blockcmd.c
src/blockcmd.h
src/usb-msc.c

index c12772909042d8910865301f3644ad87ae4b8b8b..f5e2ce3f70518ba85bd504e2bb23486bd9056fdd 100644 (file)
@@ -91,3 +91,15 @@ cdb_read(struct disk_op_s *op)
     cmd.count = htons(op->count);
     return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
 }
+
+// Write sectors.
+int
+cdb_write(struct disk_op_s *op)
+{
+    struct cdb_rwdata_10 cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_WRITE_10;
+    cmd.lba = htonl(op->lba);
+    cmd.count = htons(op->count);
+    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
+}
index 49921b05d86fdfc2006da4a45b55f2608bc61332..84ab65988af26183df9acdf51724b3ea7afb6251 100644 (file)
@@ -75,5 +75,6 @@ int cdb_test_unit_ready(struct disk_op_s *op);
 int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data);
 int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
 int cdb_read(struct disk_op_s *op);
+int cdb_write(struct disk_op_s *op);
 
 #endif // blockcmd.h
index 37644814960b0bc71a953634e824813d3a6a6e98..068e18cee86c742d2780047c5cef4fb2bf943309 100644 (file)
@@ -73,13 +73,13 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
     u32 bytes = blocksize * op->count;
     struct cbw_s cbw;
     memset(&cbw, 0, sizeof(cbw));
+    memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE);
     cbw.dCBWSignature = CBW_SIGNATURE;
     cbw.dCBWTag = 999; // XXX
     cbw.dCBWDataTransferLength = bytes;
-    cbw.bmCBWFlags = USB_DIR_IN; // XXX
+    cbw.bmCBWFlags = (cbw.CBWCB[0] == CDB_CMD_WRITE_10) ? USB_DIR_OUT : USB_DIR_IN;
     cbw.bCBWLUN = 0; // XXX
     cbw.bCBWCBLength = USB_CDB_SIZE;
-    memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE);
 
     // Transfer cbw to device.
     int ret = usb_msc_send(udrive_g, USB_DIR_OUT
@@ -87,9 +87,9 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
     if (ret)
         goto fail;
 
-    // Transfer data from device.
+    // Transfer data to/from device.
     if (bytes) {
-        ret = usb_msc_send(udrive_g, USB_DIR_IN, op->buf_fl, bytes);
+        ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes);
         if (ret)
             goto fail;
     }
@@ -131,9 +131,9 @@ process_usb_op(struct disk_op_s *op)
     switch (op->command) {
     case CMD_READ:
         return cdb_read(op);
-    case CMD_FORMAT:
     case CMD_WRITE:
-        return DISK_RET_EWRITEPROTECT;
+        return cdb_write(op);
+    case CMD_FORMAT:
     case CMD_RESET:
     case CMD_ISREADY:
     case CMD_VERIFY: