diff --git a/DiscImageChef.Devices/ChangeLog b/DiscImageChef.Devices/ChangeLog index 04d797239..cd2b43705 100644 --- a/DiscImageChef.Devices/ChangeLog +++ b/DiscImageChef.Devices/ChangeLog @@ -1,3 +1,9 @@ +2017-05-23 Natalia Portillo + + * Enums.cs: + * DiscImageChef.Devices.csproj: + * Kreon.cs: Added Kreon commands. + 2017-05-19 Natalia Portillo * Enums.cs: diff --git a/DiscImageChef.Devices/Device/ScsiCommands/Kreon.cs b/DiscImageChef.Devices/Device/ScsiCommands/Kreon.cs new file mode 100644 index 000000000..818f212d5 --- /dev/null +++ b/DiscImageChef.Devices/Device/ScsiCommands/Kreon.cs @@ -0,0 +1,248 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : Adaptec.cs +// Author(s) : Natalia Portillo +// +// Component : Adaptec vendor commands. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains vendor commands for Adaptec ACB-4000A and +// ACB-4070 ST-506 to SCSI controllers. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2017 Natalia Portillo +// ****************************************************************************/ + +using System; +using DiscImageChef.Console; + +namespace DiscImageChef.Devices +{ + public partial class Device + { + /// + /// Sets the drive to the xtreme unlocked state + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + public bool KreonDeprecatedUnlock(out byte[] senseBuffer, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[6]; + byte[] buffer = new byte[0]; + bool sense; + + cdb[0] = (byte)ScsiCommands.Kreon_Command; + cdb[1] = 0x08; + cdb[2] = 0x01; + cdb[3] = 0x01; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "KREON DEPRECATED UNLOCK took {0} ms.", duration); + + return sense; + } + + /// + /// Sets the drive to the locked state. + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + public bool KreonLock(out byte[] senseBuffer, uint timeout, out double duration) + { + return KreonSetLockState(out senseBuffer, KreonLockStates.Locked, timeout, out duration); + } + + /// + /// Sets the drive to the xtreme unlocked state + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + public bool KreonUnlockXtreme(out byte[] senseBuffer, uint timeout, out double duration) + { + return KreonSetLockState(out senseBuffer, KreonLockStates.Xtreme, timeout, out duration); + } + + /// + /// Sets the drive to the wxripper unlocked state + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + public bool KreonUnlockWxripper(out byte[] senseBuffer, uint timeout, out double duration) + { + return KreonSetLockState(out senseBuffer, KreonLockStates.Wxripper, timeout, out duration); + } + + /// + /// Sets the drive to the specified lock state + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + /// Lock state + public bool KreonSetLockState(out byte[] senseBuffer, KreonLockStates state, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[6]; + byte[] buffer = new byte[0]; + bool sense; + + cdb[0] = (byte)ScsiCommands.Kreon_Command; + cdb[1] = 0x08; + cdb[2] = 0x01; + cdb[3] = 0x11; + cdb[4] = (byte)state; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "KREON SET LOCK STATE took {0} ms.", duration); + + return sense; + } + + /// + /// Gets a list of supported features + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + /// Features supported by drive. + public bool KreonGetFeatureList(out byte[] senseBuffer, out KreonFeatures features, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[6]; + byte[] buffer = new byte[26]; + bool sense; + features = 0; + + cdb[0] = (byte)ScsiCommands.Kreon_Command; + cdb[1] = 0x08; + cdb[2] = 0x01; + cdb[3] = 0x01; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "KREON GET FEATURE LIST took {0} ms.", duration); + + if(sense) + return sense; + + if(buffer[0] != 0xA5 || buffer[1] != 0x5A || buffer[2] != 0x5A || buffer[3] == 0xA5) + return true; + + for(int i = 4; i < 26; i += 4) + { + ushort feature = BitConverter.ToUInt16(buffer, i); + + if(feature == 0x0000) + break; + + switch(feature) + { + case 0x0001: + features |= KreonFeatures.XtremeUnlock360; + break; + case 0x0101: + features |= KreonFeatures.WxripperUnlock360; + break; + case 0x2001: + features |= KreonFeatures.DecryptSS360; + break; + case 0x2101: + features |= KreonFeatures.ChallengeResponse360; + break; + case 0x0002: + features |= KreonFeatures.XtremeUnlock; + break; + case 0x0102: + features |= KreonFeatures.WxripperUnlock; + break; + case 0x2002: + features |= KreonFeatures.DecryptSS; + break; + case 0x2102: + features |= KreonFeatures.ChallengeResponse; + break; + case 0x00F0: + features |= KreonFeatures.Lock; + break; + case 0x01F0: + features |= KreonFeatures.ErrorSkipping; + break; + } + } + + return false; + } + + /// + /// Gets the SS sector. + /// + /// true if the command failed and contains the sense buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + /// The SS sector. + public bool KreonExtractSS(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) + { + buffer = new byte[2048]; + byte[] cdb = new byte[12]; + senseBuffer = new byte[32]; + bool sense; + + cdb[0] = (byte)ScsiCommands.Kreon_SS_Command; + cdb[1] = 0x00; + cdb[2] = 0xFF; + cdb[3] = 0x02; + cdb[4] = 0xFD; + cdb[5] = 0xFF; + cdb[6] = 0xFE; + cdb[7] = 0x00; + cdb[8] = 0x08; + cdb[9] = 0x00; + // TODO: Documentation puts this as xx but doesn't say what is the meaning. + cdb[10] = 0x00; + cdb[11] = 0xC0; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "KREON EXTRACT SS took {0} ms.", duration); + + return sense; + } + } +} + diff --git a/DiscImageChef.Devices/DiscImageChef.Devices.csproj b/DiscImageChef.Devices/DiscImageChef.Devices.csproj index 37bae6608..a76851341 100644 --- a/DiscImageChef.Devices/DiscImageChef.Devices.csproj +++ b/DiscImageChef.Devices/DiscImageChef.Devices.csproj @@ -79,6 +79,7 @@ + diff --git a/DiscImageChef.Devices/Enums.cs b/DiscImageChef.Devices/Enums.cs index 2299131ea..c1156e659 100644 --- a/DiscImageChef.Devices/Enums.cs +++ b/DiscImageChef.Devices/Enums.cs @@ -2678,6 +2678,17 @@ namespace DiscImageChef.Devices /// Plasmon_Shred = 0xEE, #endregion Plasmon vendor commands + + #region Kreon vendor commands + /// + /// Most Kreon commands start with this + /// + Kreon_Command = 0xFF, + /// + /// Kreon extract Security Sectors command start with this + /// + Kreon_SS_Command = 0xAD + #endregion Kreon vendor commands } #endregion SCSI Commands @@ -3805,5 +3816,57 @@ namespace DiscImageChef.Devices ResponseSPI_R5 = ResponseSPI_S1 | ResponseSPI_S2, ResponseSPI_R7 = ResponseSPI_S1 | ResponseSPI_B4 } + + [Flags] + public enum KreonFeatures + { + /// + /// Drive can set the xtreme unlock state with Xbox 360 discs + /// + XtremeUnlock360, + /// + /// Drive can set the wxripper unlock state with Xbox 360 discs + /// + WxripperUnlock360, + /// + /// Drive can read and decrypt the SS from Xbox 360 discs + /// + DecryptSS360, + /// + /// Drive has full challenge response capabilities with Xbox 360 discs + /// + ChallengeResponse360, + /// + /// Drive can set the xtreme unlock state with Xbox discs + /// + XtremeUnlock, + /// + /// Drive can set the wxripper unlock state with Xbox discs + /// + WxripperUnlock, + /// + /// Drive can read and decrypt the SS from Xbox discs + /// + DecryptSS, + /// + /// Drive has full challenge response capabilities with Xbox discs + /// + ChallengeResponse, + /// + /// Drive supports the locked state + /// + Lock, + /// + /// Drive supports skipping read errors + /// + ErrorSkipping + } + + public enum KreonLockStates : byte + { + Locked = 0, + Xtreme = 1, + Wxripper = 2 + } }