From 4f0321484b4cd99dc87bb9cbf4130b076eb5df5a Mon Sep 17 00:00:00 2001 From: Jan Seeger Date: Sun, 7 Sep 2014 13:22:24 +0200 Subject: [PATCH 1/3] set device boundaries and blocksize from read format capacities if the command is implemented. --- .../net/alphadev/usbstorage/bbb/BulkBlockDevice.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java b/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java index e11b6f9..a4d2ae1 100644 --- a/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java +++ b/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java @@ -58,8 +58,13 @@ private void setupCapacityPhase() throws IOException { } // determine the last addressable block - mDeviceBoundaries = capacity.getNumberOfBlocks(); - mBlockSize = capacity.getBlockLength(); + if (capacity.getNumberOfBlocks() != 0) { + mDeviceBoundaries = capacity.getNumberOfBlocks(); + } + + if (capacity.getBlockLength() != 0) { + mBlockSize = capacity.getBlockLength(); + } } catch (IllegalArgumentException ex) { // do nothing as the read format capacities command is optional. } From e087156fc1d26b54084134b34882d24d6e125f2a Mon Sep 17 00:00:00 2001 From: Jan Seeger Date: Sun, 7 Sep 2014 13:23:08 +0200 Subject: [PATCH 2/3] implemented read capacity scsi command. add partially read capacity response parser. --- .../scsi/answer/ReadCapacityResponse.java | 8 +++ .../usbstorage/scsi/command/ReadCapacity.java | 55 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java create mode 100644 lib/src/main/java/net/alphadev/usbstorage/scsi/command/ReadCapacity.java diff --git a/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java b/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java new file mode 100644 index 0000000..604abf6 --- /dev/null +++ b/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java @@ -0,0 +1,8 @@ +package net.alphadev.usbstorage.scsi.answer; + +/** + * @author Jan Seeger + */ +public class ReadCapacityResponse { + public static final int LENGTH = 8; +} diff --git a/lib/src/main/java/net/alphadev/usbstorage/scsi/command/ReadCapacity.java b/lib/src/main/java/net/alphadev/usbstorage/scsi/command/ReadCapacity.java new file mode 100644 index 0000000..7818002 --- /dev/null +++ b/lib/src/main/java/net/alphadev/usbstorage/scsi/command/ReadCapacity.java @@ -0,0 +1,55 @@ +package net.alphadev.usbstorage.scsi.command; + +import net.alphadev.usbstorage.bbb.CommandBlockWrapper; +import net.alphadev.usbstorage.scsi.answer.ReadCapacityResponse; + +import static net.alphadev.usbstorage.util.BitStitching.setBytesFromInt; + +/** + * @author Jan Seeger + */ +@SuppressWarnings("unused") +public class ReadCapacity extends ScsiCommand { + public static final byte READ_CAPACITY = 0x25; + + private int mLogicalBlockAddress; + private byte mControl; + + public ReadCapacity() { + super(READ_CAPACITY); + } + + @Override + public CommandBlockWrapper.Direction getDirection() { + return CommandBlockWrapper.Direction.DEVICE_TO_HOST; + } + + @Override + public byte[] asBytes() { + byte[] retval = new byte[10]; + retval[0] = READ_CAPACITY; // opcode + // retval[1] is reserved + setBytesFromInt(mLogicalBlockAddress, retval, 2); + // retval[6-8] is reserved + retval[9] = mControl; + return retval; + } + + + @Override + public int getExpectedAnswerLength() { + return ReadCapacityResponse.LENGTH; + } + + public int getLogicalBlockAddress() { + return mLogicalBlockAddress; + } + + public void setLogicalBlockAddress(int logicalBlockAddress) { + this.mLogicalBlockAddress = logicalBlockAddress; + } + + public void setControl(byte control) { + this.mControl = control; + } +} From d81708bc261ad60851f96967277f793f99d329d2 Mon Sep 17 00:00:00 2001 From: Jan Seeger Date: Sun, 7 Sep 2014 22:53:40 +0200 Subject: [PATCH 3/3] impl capacity response parser. get the capacity response's size for further use. --- .../usbstorage/bbb/BulkBlockDevice.java | 41 ++++++++++++------- .../scsi/answer/ReadCapacityResponse.java | 18 ++++++++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java b/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java index a4d2ae1..e4d1a1f 100644 --- a/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java +++ b/lib/src/main/java/net/alphadev/usbstorage/bbb/BulkBlockDevice.java @@ -1,10 +1,12 @@ package net.alphadev.usbstorage.bbb; import net.alphadev.usbstorage.api.BulkDevice; +import net.alphadev.usbstorage.scsi.answer.ReadCapacityResponse; import net.alphadev.usbstorage.scsi.answer.ReadFormatCapacitiesEntry; import net.alphadev.usbstorage.scsi.answer.ReadFormatCapacitiesHeader; import net.alphadev.usbstorage.scsi.answer.StandardInquiryAnswer; import net.alphadev.usbstorage.scsi.command.Inquiry; +import net.alphadev.usbstorage.scsi.command.ReadCapacity; import net.alphadev.usbstorage.scsi.command.ReadFormatCapacities; import net.alphadev.usbstorage.scsi.command.ScsiCommand; import net.alphadev.usbstorage.scsi.command.TestUnitReady; @@ -30,16 +32,13 @@ public BulkBlockDevice(BulkDevice usbBlockDevice) throws IOException { setupInquiryPhase(); setupCapacityPhase(); - testReady(); + testUnitReady(); } - private void testReady() throws IOException { + private void testUnitReady() throws IOException { send_mass_storage_command(new TestUnitReady()); - CommandStatusWrapper csw = retrieve_mass_storage_answer(); - if (CommandStatusWrapper.Status.COMMAND_PASSED != csw.getStatus()) { - throw new IllegalStateException("device signaled error state!"); - } + checkDeviceStatus(); } private void setupCapacityPhase() throws IOException { @@ -47,10 +46,7 @@ private void setupCapacityPhase() throws IOException { send_mass_storage_command(new ReadFormatCapacities()); byte[] answer = mAbstractBulkDevice.retrieve_data_packet(ReadFormatCapacitiesHeader.LENGTH); ReadFormatCapacitiesHeader capacity = new ReadFormatCapacitiesHeader(answer); - CommandStatusWrapper csw = retrieve_mass_storage_answer(); - if (CommandStatusWrapper.Status.COMMAND_PASSED != csw.getStatus()) { - throw new IllegalStateException("device signaled error state!"); - } + checkDeviceStatus(); for (int i = 0; i < capacity.getCapacityEntryCount(); i++) { byte[] capacityData = mAbstractBulkDevice.retrieve_data_packet(ReadFormatCapacitiesEntry.LENGTH); @@ -68,6 +64,26 @@ private void setupCapacityPhase() throws IOException { } catch (IllegalArgumentException ex) { // do nothing as the read format capacities command is optional. } + + try { + send_mass_storage_command(new ReadCapacity()); + byte[] answer = mAbstractBulkDevice.retrieve_data_packet(ReadCapacityResponse.LENGTH); + ReadCapacityResponse capacity = new ReadCapacityResponse(answer); + + checkDeviceStatus(); + + mDeviceBoundaries = capacity.getNumberOfBlocks(); + mBlockSize = capacity.getBlockSize(); + } catch (IllegalArgumentException e) { + // whaaat! + } + } + + private void checkDeviceStatus() { + CommandStatusWrapper csw = retrieve_mass_storage_answer(); + if (CommandStatusWrapper.Status.COMMAND_PASSED != csw.getStatus()) { + throw new IllegalStateException("device signaled error state!"); + } } private void setupInquiryPhase() throws IOException { @@ -76,10 +92,7 @@ private void setupInquiryPhase() throws IOException { byte[] answer = mAbstractBulkDevice.retrieve_data_packet(StandardInquiryAnswer.LENGTH); new StandardInquiryAnswer(answer); - CommandStatusWrapper csw = retrieve_mass_storage_answer(); - if (CommandStatusWrapper.Status.COMMAND_PASSED != csw.getStatus()) { - throw new IllegalStateException("device signaled error state!"); - } + checkDeviceStatus(); } private CommandStatusWrapper retrieve_mass_storage_answer() { diff --git a/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java b/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java index 604abf6..46603ba 100644 --- a/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java +++ b/lib/src/main/java/net/alphadev/usbstorage/scsi/answer/ReadCapacityResponse.java @@ -1,8 +1,26 @@ package net.alphadev.usbstorage.scsi.answer; +import static net.alphadev.usbstorage.util.BitStitching.convertToInt; + /** * @author Jan Seeger */ public class ReadCapacityResponse { public static final int LENGTH = 8; + + private int mBlockSize; + private int mNumberOfBlocks; + + public ReadCapacityResponse(byte[] answer) { + mNumberOfBlocks = convertToInt(answer, 0); + mBlockSize = convertToInt(answer, 4); + } + + public int getBlockSize() { + return mBlockSize; + } + + public int getNumberOfBlocks() { + return mNumberOfBlocks; + } }