From dfb15d0e4f93a757902b10ec1db6bd4d838db92c Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 1 Nov 2015 20:06:24 +0000 Subject: [PATCH] * DiscImageChef.Decoders/SCSI/MMC/Features.cs: Added code to separate features and the feature header. * DiscImageChef.Devices/Enums.cs: * DiscImageChef.Devices/Device/ScsiCommands.cs: Added SCSI GET CONFIGURATION --- DiscImageChef.Decoders/ChangeLog | 5 ++ DiscImageChef.Decoders/SCSI/MMC/Features.cs | 37 ++++++++++ DiscImageChef.Devices/ChangeLog | 6 ++ DiscImageChef.Devices/Device/ScsiCommands.cs | 75 ++++++++++++++++++-- DiscImageChef.Devices/Enums.cs | 17 +++++ 5 files changed, 136 insertions(+), 4 deletions(-) diff --git a/DiscImageChef.Decoders/ChangeLog b/DiscImageChef.Decoders/ChangeLog index 90f99264..4ea78fc9 100644 --- a/DiscImageChef.Decoders/ChangeLog +++ b/DiscImageChef.Decoders/ChangeLog @@ -1,3 +1,8 @@ +2015-11-01 Natalia Portillo + + * SCSI/MMC/Features.cs: + Added code to separate features and the feature header. + 2015-11-01 Natalia Portillo * SCSI/MMC/Features.cs: diff --git a/DiscImageChef.Decoders/SCSI/MMC/Features.cs b/DiscImageChef.Decoders/SCSI/MMC/Features.cs index 9b6b89ab..c6ec3c04 100644 --- a/DiscImageChef.Decoders/SCSI/MMC/Features.cs +++ b/DiscImageChef.Decoders/SCSI/MMC/Features.cs @@ -5739,6 +5739,43 @@ namespace DiscImageChef.Decoders.SCSI.MMC { return Prettify_0142(Decode_0142(feature)); } + + public struct FeatureDescriptor + { + public ushort Code; + public byte[] Data; + } + + public struct SeparatedFeatures + { + public uint DataLength; + public ushort CurrentProfile; + public FeatureDescriptor[] Descriptors; + } + + public static SeparatedFeatures Separate(byte[] response) + { + SeparatedFeatures dec = new SeparatedFeatures(); + dec.DataLength = (uint)(response[0] << 24 + response[1] << 16 + response[2] << 8 + response[4]); + dec.CurrentProfile = (ushort)(response[6] << 8 + response[7]); + uint offset = 8; + List descLst = new List(); + + while (offset < response.Length) + { + FeatureDescriptor desc = new FeatureDescriptor(); + desc.Code = (ushort)(response[offset + 0] << 8 + response[offset + 1]); + desc.Data = new byte[response[offset + 3] + 4]; + Array.Copy(response, offset + 4, desc.Data, 0, desc.Data.Length + 4); + offset += (uint)(4 + desc.Data.Length); + + descLst.Add(desc); + } + + dec.Descriptors = descLst.ToArray(); + + return dec; + } } } diff --git a/DiscImageChef.Devices/ChangeLog b/DiscImageChef.Devices/ChangeLog index 0cbb5757..c8c70db3 100644 --- a/DiscImageChef.Devices/ChangeLog +++ b/DiscImageChef.Devices/ChangeLog @@ -1,3 +1,9 @@ +2015-11-01 Natalia Portillo + + * Enums.cs: + * Device/ScsiCommands.cs: + Added SCSI GET CONFIGURATION + 2015-11-01 Natalia Portillo * Enums.cs: diff --git a/DiscImageChef.Devices/Device/ScsiCommands.cs b/DiscImageChef.Devices/Device/ScsiCommands.cs index c05337f9..56044eb2 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands.cs @@ -374,7 +374,6 @@ namespace DiscImageChef.Devices /// /// Sends the SCSI PREVENT ALLOW MEDIUM REMOVAL command to prevent medium removal /// - /// true, if allow medium removal was prevented, false otherwise. /// true if the command failed and contains the sense buffer. /// Sense buffer. /// Timeout in seconds. @@ -387,7 +386,6 @@ namespace DiscImageChef.Devices /// /// Sends the SCSI PREVENT ALLOW MEDIUM REMOVAL command to allow medium removal /// - /// true, if allow medium removal was prevented, false otherwise. /// true if the command failed and contains the sense buffer. /// Sense buffer. /// Timeout in seconds. @@ -400,7 +398,6 @@ namespace DiscImageChef.Devices /// /// Sends the SCSI PREVENT ALLOW MEDIUM REMOVAL command /// - /// true, if allow medium removal was prevented, false otherwise. /// true if the command failed and contains the sense buffer. /// Sense buffer. /// Timeout in seconds. @@ -417,7 +414,6 @@ namespace DiscImageChef.Devices /// /// Sends the SCSI PREVENT ALLOW MEDIUM REMOVAL command /// - /// true, if allow medium removal was prevented, false otherwise. /// true if the command failed and contains the sense buffer. /// Sense buffer. /// Timeout in seconds. @@ -440,6 +436,77 @@ namespace DiscImageChef.Devices return sense; } + + /// + /// Sends the SCSI GET CONFIGURATION command for all Features + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI GET CONFIGURATION response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) + { + return GetConfiguration(out buffer, out senseBuffer, 0x0000, MmcGetConfigurationRt.All, timeout, out duration); + } + + /// + /// Sends the SCSI GET CONFIGURATION command for all Features starting with specified one + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI GET CONFIGURATION response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber, uint timeout, out double duration) + { + return GetConfiguration(out buffer, out senseBuffer, startingFeatureNumber, MmcGetConfigurationRt.All, timeout, out duration); + } + + /// + /// Sends the SCSI GET CONFIGURATION command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI GET CONFIGURATION response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// Starting Feature number. + /// Return type, . + public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber, MmcGetConfigurationRt RT, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[10]; + buffer = new byte[8]; + bool sense; + + cdb[0] = (byte)ScsiCommands.GetConfiguration; + cdb[1] = (byte)((byte)RT & 0x03); + cdb[2] = (byte)((startingFeatureNumber & 0xFF00) >> 8); + cdb[3] = (byte)(startingFeatureNumber & 0xFF); + cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[8] = (byte)(buffer.Length & 0xFF); + cdb[9] = 0; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + error = lastError != 0; + + if (sense) + return true; + + ushort confLength = (ushort)(((int)buffer[2] << 8) + buffer[3] + 2); + buffer = new byte[confLength]; + cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[8] = (byte)(buffer.Length & 0xFF); + senseBuffer = new byte[32]; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "GET CONFIGURATION took {0} ms.", duration); + + return sense; + } } } diff --git a/DiscImageChef.Devices/Enums.cs b/DiscImageChef.Devices/Enums.cs index 12f1594a..cc54604c 100644 --- a/DiscImageChef.Devices/Enums.cs +++ b/DiscImageChef.Devices/Enums.cs @@ -2743,5 +2743,22 @@ namespace DiscImageChef.Devices [Obsolete] PreventAll = 0x03 } + + public enum MmcGetConfigurationRt : byte + { + /// + /// Drive shall return the Feature Header and all Feature Descriptors + /// + All = 0x00, + /// + /// Drive shall return the Feature Header and current Feature Descriptors + /// + Current = 0x01, + /// + /// Drive shall return only the Feature Header with the chosen Feature Descriptor + /// + Single = 0x02, + Reserved = 0x03 + } }