commit 751c2f468fdeba8b7bfc86639644349a96946123 Author: Natalia Portillo Date: Mon Oct 5 20:27:44 2015 +0100 Move decoders to a separate library. diff --git a/BD.cs b/BD.cs new file mode 100644 index 0000000..d3b9e5a --- /dev/null +++ b/BD.cs @@ -0,0 +1,836 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : BD.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Decoders. + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Decodes Blu-ray structures. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Text; +using System.Collections.Generic; + +namespace DiscImageChef.Decoders +{ + /// + /// Information from the following standards: + /// ANSI X3.304-1997 + /// T10/1048-D revision 9.0 + /// T10/1048-D revision 10a + /// T10/1228-D revision 7.0c + /// T10/1228-D revision 11a + /// T10/1363-D revision 10g + /// T10/1545-D revision 1d + /// T10/1545-D revision 5 + /// T10/1545-D revision 5a + /// T10/1675-D revision 2c + /// T10/1675-D revision 4 + /// T10/1836-D revision 2g + /// + public static class BD + { + #region Private constants + const string DiscTypeBDROM = "BDO"; + const string DiscTypeBDRE = "BDW"; + const string DiscTypeBDR = "BDR"; + + /// + /// Disc Definition Structure Identifier "DS" + /// + const UInt16 DDSIdentifier = 0x4453; + /// + /// Disc Information Unit Identifier "DI" + /// + const UInt16 DIUIdentifier = 0x4449; + #endregion Private constants + + #region Public methods + public static DiscInformation? DecodeDiscInformation(byte[] DIResponse) + { + if (DIResponse == null) + return null; + + if (DIResponse.Length != 4100) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (BD Disc Information): Found incorrect Blu-ray Disc Information size ({0} bytes)", DIResponse.Length); + + return null; + } + + DiscInformation decoded = new DiscInformation(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0); + decoded.Reserved1 = DIResponse[2]; + decoded.Reserved2 = DIResponse[3]; + + int offset = 4; + List units = new List(); + + while (true) + { + if (offset >= 100) + break; + + DiscInformationUnits unit = new DiscInformationUnits(); + unit.Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset); + + if (unit.Signature != DIUIdentifier) + break; + + unit.Format = DIResponse[2 + offset]; + unit.UnitsPerBlock = DIResponse[3 + offset]; + unit.Legacy = DIResponse[4 + offset]; + unit.Sequence = DIResponse[5 + offset]; + unit.Length = DIResponse[6 + offset]; + unit.Reserved = DIResponse[7 + offset]; + unit.DiscTypeIdentifier = new byte[3]; + Array.Copy(DIResponse, 8 + offset, unit.DiscTypeIdentifier, 0, 3); + unit.DiscSizeClassVersion = DIResponse[11 + offset]; + switch (Encoding.ASCII.GetString(unit.DiscTypeIdentifier)) + { + case DiscTypeBDROM: + { + unit.FormatDependentContents = new byte[52]; + Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 52); + break; + } + case DiscTypeBDRE: + case DiscTypeBDR: + { + unit.FormatDependentContents = new byte[88]; + Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 88); + unit.ManufacturerID = new byte[6]; + Array.Copy(DIResponse, 100 + offset, unit.ManufacturerID, 0, 6); + unit.MediaTypeID = new byte[3]; + Array.Copy(DIResponse, 106 + offset, unit.MediaTypeID, 0, 3); + unit.TimeStamp = BigEndianBitConverter.ToUInt16(DIResponse, 109 + offset); + unit.ProductRevisionNumber = DIResponse[111 + offset]; + break; + } + default: + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (BD Disc Information): Found unknown disc type identifier \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)); + break; + } + } + + units.Add(unit); + + offset += unit.Length; + } + + if (units.Count > 0) + { + decoded.Units = new DiscInformationUnits[units.Count]; + for (int i = 0; i < units.Count; i++) + decoded.Units[i] = units[i]; + } + + return decoded; + } + + public static string PrettifyDiscInformation(DiscInformation? DIResponse) + { + if (DIResponse == null) + return null; + + DiscInformation response = DIResponse.Value; + + StringBuilder sb = new StringBuilder(); + + foreach (DiscInformationUnits unit in response.Units) + { + sb.AppendFormat("DI Unit Sequence: {0}", unit.Sequence).AppendLine(); + sb.AppendFormat("DI Unit Format: 0x{0:X2}", unit.Format).AppendLine(); + sb.AppendFormat("There are {0} per block", unit.UnitsPerBlock).AppendLine(); + if (Encoding.ASCII.GetString(unit.DiscTypeIdentifier) != DiscTypeBDROM) + sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine(); + sb.AppendFormat("DI Unit is {0} bytes", unit.Length).AppendLine(); + sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)).AppendLine(); + sb.AppendFormat("Disc size/class/version: {0}", unit.DiscSizeClassVersion).AppendLine(); + if (Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR || + Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) + { + sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)).AppendLine(); + sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)).AppendLine(); + sb.AppendFormat("Disc timestamp: 0x{0:X2}", unit.TimeStamp).AppendLine(); + sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine(); + } + + sb.AppendFormat("Blu-ray DI Unit format dependent contents as hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(unit.FormatDependentContents, 80)); + } + + return sb.ToString(); + } + + public static string PrettifyDiscInformation(byte[] DIResponse) + { + DiscInformation? decoded = DecodeDiscInformation(DIResponse); + return PrettifyDiscInformation(decoded); + } + + public static BurstCuttingArea? DecodeBurstCuttingArea(byte[] BCAResponse) + { + if (BCAResponse == null) + return null; + + if (BCAResponse.Length != 68) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (BD BCA): Found incorrect Blu-ray BCA size ({0} bytes)", BCAResponse.Length); + + return null; + } + + BurstCuttingArea decoded = new BurstCuttingArea(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(BCAResponse, 0); + decoded.Reserved1 = BCAResponse[2]; + decoded.Reserved2 = BCAResponse[3]; + decoded.BCA = new byte[64]; + Array.Copy(BCAResponse, 4, decoded.BCA, 0, 64); + + return decoded; + } + + public static string PrettifyBurstCuttingArea(BurstCuttingArea? BCAResponse) + { + if (BCAResponse == null) + return null; + + BurstCuttingArea response = BCAResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (BD BCA): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (BD BCA): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + } + sb.AppendFormat("Blu-ray Burst Cutting Area in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.BCA, 80)); + + return sb.ToString(); + } + + public static string PrettifyBurstCuttingArea(byte[] BCAResponse) + { + BurstCuttingArea? decoded = DecodeBurstCuttingArea(BCAResponse); + return PrettifyBurstCuttingArea(decoded); + } + + public static DiscDefinitionStructure? DecodeDDS(byte[] DDSResponse) + { + if (DDSResponse == null) + return null; + + DiscDefinitionStructure decoded = new DiscDefinitionStructure(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(DDSResponse, 0); + decoded.Reserved1 = DDSResponse[2]; + decoded.Reserved2 = DDSResponse[3]; + decoded.Signature = BigEndianBitConverter.ToUInt16(DDSResponse, 4); + if (decoded.Signature != DDSIdentifier) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (BD DDS): Found incorrect DDS signature (0x{0:X4})", decoded.Signature); + + return null; + + } + decoded.Format = DDSResponse[6]; + decoded.Reserved3 = DDSResponse[7]; + decoded.UpdateCount = BigEndianBitConverter.ToUInt32(DDSResponse, 8); + decoded.Reserved4 = BigEndianBitConverter.ToUInt64(DDSResponse, 12); + decoded.DriveAreaPSN = BigEndianBitConverter.ToUInt32(DDSResponse, 20); + decoded.Reserved5 = BigEndianBitConverter.ToUInt32(DDSResponse, 24); + decoded.DefectListPSN = BigEndianBitConverter.ToUInt32(DDSResponse, 28); + decoded.Reserved6 = BigEndianBitConverter.ToUInt32(DDSResponse, 32); + decoded.PSNofLSNZero = BigEndianBitConverter.ToUInt32(DDSResponse, 36); + decoded.LastUserAreaLSN = BigEndianBitConverter.ToUInt32(DDSResponse, 40); + decoded.ISA0 = BigEndianBitConverter.ToUInt32(DDSResponse, 44); + decoded.OSA = BigEndianBitConverter.ToUInt32(DDSResponse, 48); + decoded.ISA1 = BigEndianBitConverter.ToUInt32(DDSResponse, 52); + decoded.SpareAreaFullFlags = DDSResponse[56]; + decoded.Reserved7 = DDSResponse[57]; + decoded.DiscTypeSpecificField1 = DDSResponse[58]; + decoded.Reserved8 = DDSResponse[59]; + decoded.DiscTypeSpecificField2 = BigEndianBitConverter.ToUInt32(DDSResponse, 60); + decoded.Reserved9 = BigEndianBitConverter.ToUInt32(DDSResponse, 64); + decoded.StatusBits = new byte[32]; + Array.Copy(DDSResponse, 68, decoded.StatusBits, 0, 32); + decoded.DiscTypeSpecificData = new byte[DDSResponse.Length - 100]; + Array.Copy(DDSResponse, 100, decoded.DiscTypeSpecificData, 0, DDSResponse.Length - 100); + + return decoded; + } + + public static string PrettifyDDS(DiscDefinitionStructure? DDSResponse) + { + if (DDSResponse == null) + return null; + + DiscDefinitionStructure response = DDSResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine(); + sb.AppendFormat("DEBUG (BD Disc Definition Structure): Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine(); + } + + sb.AppendFormat("DDS Format: 0x{0:X2}", response.Format).AppendLine(); + sb.AppendFormat("DDS has ben updated {0} times", response.UpdateCount).AppendLine(); + sb.AppendFormat("First PSN of Drive Area: 0x{0:X8}", response.DriveAreaPSN).AppendLine(); + sb.AppendFormat("First PSN of Defect List: 0x{0:X8}", response.DefectListPSN).AppendLine(); + sb.AppendFormat("PSN of User Data Area's LSN 0: 0x{0:X8}", response.PSNofLSNZero).AppendLine(); + sb.AppendFormat("Last User Data Area's LSN 0: 0x{0:X8}", response.LastUserAreaLSN).AppendLine(); + sb.AppendFormat("ISA0 size: {0}", response.ISA0).AppendLine(); + sb.AppendFormat("OSA size: {0}", response.OSA).AppendLine(); + sb.AppendFormat("ISA1 size: {0}", response.ISA1).AppendLine(); + sb.AppendFormat("Spare Area Full Flags: 0x{0:X2}", response.SpareAreaFullFlags).AppendLine(); + sb.AppendFormat("Disc Type Specific Field 1: 0x{0:X2}", response.DiscTypeSpecificField1).AppendLine(); + sb.AppendFormat("Disc Type Specific Field 2: 0x{0:X8}", response.DiscTypeSpecificField2).AppendLine(); + sb.AppendFormat("Blu-ray DDS Status Bits in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.StatusBits, 80)); + sb.AppendFormat("Blu-ray DDS Disc Type Specific Data in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DiscTypeSpecificData, 80)); + + return sb.ToString(); + } + + public static string PrettifyDDS(byte[] DDSResponse) + { + DiscDefinitionStructure? decoded = DecodeDDS(DDSResponse); + return PrettifyDDS(decoded); + } + + public static CartridgeStatus? DecodeCartridgeStatus(byte[] CSResponse) + { + if (CSResponse == null) + return null; + + if (CSResponse.Length != 8) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (BD Cartridge Status): Found incorrect Blu-ray Spare Area Information size ({0} bytes)", CSResponse.Length); + + return null; + } + + CartridgeStatus decoded = new CartridgeStatus(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CSResponse, 0); + decoded.Reserved1 = CSResponse[2]; + decoded.Reserved2 = CSResponse[3]; + decoded.Cartridge = Convert.ToBoolean(CSResponse[4] & 0x80); + decoded.OUT = Convert.ToBoolean(CSResponse[4]&0x40); + decoded.Reserved3 = (byte)((CSResponse[4] & 0x38) >> 3); + decoded.OUT = Convert.ToBoolean(CSResponse[4]&0x04); + decoded.Reserved4 = (byte)(CSResponse[4] & 0x03); + decoded.Reserved5 = CSResponse[5]; + decoded.Reserved6 = CSResponse[6]; + decoded.Reserved7 = CSResponse[7]; + + return decoded; + } + + public static string PrettifyCartridgeStatus(CartridgeStatus? CSResponse) + { + if (CSResponse == null) + return null; + + CartridgeStatus response = CSResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine(); + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); + sb.AppendFormat("DEBUG (BD Cartridge Status): Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine(); + } + + if (response.Cartridge) + { + sb.AppendLine("Media is inserted in a cartridge"); + if (response.OUT) + sb.AppendLine("Media has been taken out, or inserted in, the cartridge"); + if (response.CWP) + sb.AppendLine("Media is write protected"); + } + else + { + sb.AppendLine("Media is not in a cartridge"); + //if (MainClass.isDebug) + { + if (response.OUT) + sb.AppendLine("Media has out bit marked, shouldn't"); + if (response.CWP) + sb.AppendLine("Media has write protection bit marked, shouldn't"); + } + } + return sb.ToString(); + } + + public static string PrettifyCartridgeStatus(byte[] CSResponse) + { + CartridgeStatus? decoded = DecodeCartridgeStatus(CSResponse); + return PrettifyCartridgeStatus(decoded); + } + + public static SpareAreaInformation? DecodeCDTOC(byte[] SAIResponse) + { + if (SAIResponse == null) + return null; + + if (SAIResponse.Length != 16) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (BD Spare Area Information): Found incorrect Blu-ray Spare Area Information size ({0} bytes)", SAIResponse.Length); + + return null; + } + + SpareAreaInformation decoded = new SpareAreaInformation(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(SAIResponse, 0); + decoded.Reserved1 = SAIResponse[2]; + decoded.Reserved2 = SAIResponse[3]; + decoded.Reserved3 = BigEndianBitConverter.ToUInt32(SAIResponse, 4); + decoded.FreeSpareBlocks = BigEndianBitConverter.ToUInt32(SAIResponse, 8); + decoded.AllocatedSpareBlocks = BigEndianBitConverter.ToUInt32(SAIResponse, 12); + + return decoded; + } + + public static string PrettifySpareAreaInformation(SpareAreaInformation? SAIResponse) + { + if (SAIResponse == null) + return null; + + SpareAreaInformation response = SAIResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (BD Spare Area Information): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (BD Spare Area Information): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + sb.AppendFormat("DEBUG (BD Spare Area Information): Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); + } + sb.AppendFormat("{0} free spare blocks", response.FreeSpareBlocks).AppendLine(); + sb.AppendFormat("{0} allocated spare blocks", response.AllocatedSpareBlocks).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifySpareAreaInformation(byte[] SAIResponse) + { + SpareAreaInformation? decoded = DecodeCDTOC(SAIResponse); + return PrettifySpareAreaInformation(decoded); + } + #endregion Public methods + + #region Public structures + public struct DiscInformation + { + /// + /// Bytes 0 to 1 + /// Always 4098 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 to 4099 + /// Disc information units + /// + public DiscInformationUnits[] Units; + } + + public struct DiscInformationUnits + { + /// + /// Byte 0 + /// "DI" + /// + public UInt16 Signature; + /// + /// Byte 2 + /// Disc information format + /// + public byte Format; + /// + /// Byte 3 + /// Number of DI units per block + /// + public byte UnitsPerBlock; + /// + /// Byte 4 + /// Reserved for BD-ROM, legacy information for BD-R/-RE + /// + public byte Legacy; + /// + /// Byte 5 + /// Sequence number for this DI unit + /// + public byte Sequence; + /// + /// Byte 6 + /// Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE + /// + public byte Length; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved; + /// + /// Bytes 8 to 10 + /// Disc type identifier + /// + public byte[] DiscTypeIdentifier; + /// + /// Byte 11 + /// Disc size/class/version + /// + public byte DiscSizeClassVersion; + /// + /// Bytes 12 to 63 for BD-ROM, bytes 12 to 99 for BD-R/-RE + /// Format dependent contents, disclosed in private blu-ray specifications + /// + public byte[] FormatDependentContents; + /// + /// Bytes 100 to 105, BD-R/-RE only + /// Manufacturer ID + /// + public byte[] ManufacturerID; + /// + /// Bytes 106 to 108, BD-R/-RE only + /// Media type ID + /// + public byte[] MediaTypeID; + /// + /// Bytes 109 to 110, BD-R/-RE only + /// Timestamp + /// + public UInt16 TimeStamp; + /// + /// Byte 111 + /// Product revision number + /// + public byte ProductRevisionNumber; + } + + public struct BurstCuttingArea + { + /// + /// Bytes 0 to 1 + /// Always 66 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 to 67 + /// BCA data + /// + public byte[] BCA; + } + + public struct DiscDefinitionStructure + { + /// + /// Bytes 0 to 1 + /// Data Length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 5 + /// "DS" + /// + public UInt16 Signature; + /// + /// Byte 6 + /// DDS format + /// + public byte Format; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved3; + /// + /// Bytes 8 to 11 + /// DDS update count + /// + public UInt32 UpdateCount; + /// + /// Bytes 12 to 19 + /// Reserved + /// + public UInt64 Reserved4; + /// + /// Bytes 20 to 23 + /// First PSN of Drive Area + /// + public UInt32 DriveAreaPSN; + /// + /// Bytes 24 to 27 + /// Reserved + /// + public UInt32 Reserved5; + /// + /// Bytes 28 to 31 + /// First PSN of Defect List + /// + public UInt32 DefectListPSN; + /// + /// Bytes 32 to 35 + /// Reserved + /// + public UInt32 Reserved6; + /// + /// Bytes 36 to 39 + /// PSN of LSN 0 of user data area + /// + public UInt32 PSNofLSNZero; + /// + /// Bytes 40 to 43 + /// Last LSN of user data area + /// + public UInt32 LastUserAreaLSN; + /// + /// Bytes 44 to 47 + /// ISA0 size + /// + public UInt32 ISA0; + /// + /// Bytes 48 to 51 + /// OSA size + /// + public UInt32 OSA; + /// + /// Bytes 52 to 55 + /// ISA1 size + /// + public UInt32 ISA1; + /// + /// Byte 56 + /// Spare Area full flags + /// + public byte SpareAreaFullFlags; + /// + /// Byte 57 + /// Reserved + /// + public byte Reserved7; + /// + /// Byte 58 + /// Disc type specific field + /// + public byte DiscTypeSpecificField1; + /// + /// Byte 59 + /// Reserved + /// + public byte Reserved8; + /// + /// Byte 60 to 63 + /// Disc type specific field + /// + public UInt32 DiscTypeSpecificField2; + /// + /// Byte 64 to 67 + /// Reserved + /// + public UInt32 Reserved9; + /// + /// Bytes 68 to 99 + /// Status bits of INFO1/2 and PAC1/2 on L0 and L1 + /// + public byte[] StatusBits; + /// + /// Bytes 100 to end + /// Disc type specific data + /// + public byte[] DiscTypeSpecificData; + } + + public struct CartridgeStatus + { + /// + /// Bytes 0 to 1 + /// Always 6 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bit 7 + /// Medium is inserted in a cartridge + /// + public bool Cartridge; + /// + /// Byte 4, bit 6 + /// Medium taken out / put in a cartridge + /// + public bool OUT; + /// + /// Byte 4, bits 5 to 3 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 4, bit 2 + /// Cartridge sets write protection + /// + public bool CWP; + /// + /// Byte 4, bits 1 to 0 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved6; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved7; + } + + public struct SpareAreaInformation + { + /// + /// Bytes 0 to 1 + /// Always 14 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 7 + /// Reserved + /// + public UInt32 Reserved3; + /// + /// Bytes 8 to 11 + /// Free spare blocks + /// + public UInt32 FreeSpareBlocks; + /// + /// Bytes 12 to 15 + /// Allocated spare blocks + /// + public UInt32 AllocatedSpareBlocks; + } + #endregion Public structures + } +} + diff --git a/CD.cs b/CD.cs new file mode 100644 index 0000000..8a432a6 --- /dev/null +++ b/CD.cs @@ -0,0 +1,1603 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : CD.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Decoders. + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Decodes CD and DDCD structures. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Text; + +namespace DiscImageChef.Decoders +{ + /// + /// Information from the following standards: + /// ANSI X3.304-1997 + /// T10/1048-D revision 9.0 + /// T10/1048-D revision 10a + /// T10/1228-D revision 7.0c + /// T10/1228-D revision 11a + /// T10/1363-D revision 10g + /// T10/1545-D revision 1d + /// T10/1545-D revision 5 + /// T10/1545-D revision 5a + /// T10/1675-D revision 2c + /// T10/1675-D revision 4 + /// T10/1836-D revision 2g + /// + public static class CD + { + #region Enumerations + + public enum TOC_ADR : byte + { + /// + /// Q Sub-channel mode information not supplied + /// + NoInformation = 0x00, + /// + /// Q Sub-channel encodes current position data + /// + CurrentPosition = 0x01, + /// + /// Q Sub-channel encodes the media catalog number + /// + MediaCatalogNumber = 0x02, + /// + /// Q Sub-channel encodes the ISRC + /// + ISRC = 0x03 + } + + public enum TOC_CONTROL : byte + { + /// + /// Stereo audio, no pre-emphasis + /// + TwoChanNoPreEmph = 0x00, + /// + /// Stereo audio with pre-emphasis + /// + TwoChanPreEmph = 0x01, + /// + /// If mask applied, track can be copied + /// + CopyPermissionMask = 0x02, + /// + /// Data track, recorded uninterrumpted + /// + DataTrack = 0x04, + /// + /// Data track, recorded incrementally + /// + DataTrackIncremental = 0x05, + /// + /// Quadraphonic audio, no pre-emphasis + /// + FourChanNoPreEmph = 0x08, + /// + /// Quadraphonic audio with pre-emphasis + /// + FourChanPreEmph = 0x09, + /// + /// Reserved mask + /// + ReservedMask = 0x0C + } + + public enum CDTextPackTypeIndicator : byte + { + /// + /// Title of the track (or album if track == 0) + /// + Title = 0x80, + /// + /// Performer + /// + Performer = 0x81, + /// + /// Songwriter + /// + Songwriter = 0x82, + /// + /// Composer + /// + Composer = 0x83, + /// + /// Arranger + /// + Arranger = 0x84, + /// + /// Message from the content provider or artist + /// + Message = 0x85, + /// + /// Disc identification information + /// + DiscIdentification = 0x86, + /// + /// Genre identification + /// + GenreIdentification = 0x87, + /// + /// Table of content information + /// + TOCInformation = 0x88, + /// + /// Second table of content information + /// + SecondTOCInformation = 0x89, + /// + /// Reserved + /// + Reserved1 = 0x8A, + /// + /// Reserved + /// + Reserved2 = 0x8B, + /// + /// Reserved + /// + Reserved3 = 0x8C, + /// + /// Reserved for content provider only + /// + ReservedForContentProvider = 0x8D, + /// + /// UPC of album or ISRC of track + /// + UPCorISRC = 0x8E, + /// + /// Size information of the block + /// + BlockSizeInformation = 0x8F + } + + #endregion Enumerations + + #region Public methods + + public static CDTOC? DecodeCDTOC(byte[] CDTOCResponse) + { + if (CDTOCResponse == null) + return null; + + CDTOC decoded = new CDTOC(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDTOCResponse, 0); + decoded.FirstTrack = CDTOCResponse[2]; + decoded.LastTrack = CDTOCResponse[3]; + decoded.TrackDescriptors = new CDTOCTrackDataDescriptor[(decoded.DataLength - 2) / 8]; + + if (decoded.DataLength + 2 != CDTOCResponse.Length) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (CDTOC Decoder): Expected CDTOC size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDTOCResponse.Length); + return null; + } + + for (int i = 0; i < ((decoded.DataLength - 2) / 8); i++) + { + decoded.TrackDescriptors[i].Reserved1 = CDTOCResponse[0 + i * 8 + 4]; + decoded.TrackDescriptors[i].ADR = (byte)((CDTOCResponse[1 + i * 8 + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].CONTROL = (byte)(CDTOCResponse[1 + i * 8 + 4] & 0x0F); + decoded.TrackDescriptors[i].TrackNumber = CDTOCResponse[2 + i * 8 + 4]; + decoded.TrackDescriptors[i].Reserved2 = CDTOCResponse[3 + i * 8 + 4]; + decoded.TrackDescriptors[i].TrackStartAddress = BigEndianBitConverter.ToUInt32(CDTOCResponse, 4 + i * 8 + 4); + } + + return decoded; + } + + public static string PrettifyCDTOC(CDTOC? CDTOCResponse) + { + if (CDTOCResponse == null) + return null; + + CDTOC response = CDTOCResponse.Value; + + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat("First track number in first complete session: {0}", response.FirstTrack).AppendLine(); + sb.AppendFormat("Last track number in last complete session: {0}", response.LastTrack).AppendLine(); + foreach (CDTOCTrackDataDescriptor descriptor in response.TrackDescriptors) + { + sb.AppendFormat("Track number: {0}", descriptor.TrackNumber); + sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress, + (descriptor.TrackStartAddress & 0x0000FF00) >> 8, + (descriptor.TrackStartAddress & 0x00FF0000) >> 16, + (descriptor.TrackStartAddress & 0xFF000000) >> 24); + + switch ((TOC_ADR)descriptor.ADR) + { + case TOC_ADR.NoInformation: + sb.AppendLine("Q subchannel mode not given"); + break; + case TOC_ADR.CurrentPosition: + sb.AppendLine("Q subchannel stores current position"); + break; + case TOC_ADR.ISRC: + sb.AppendLine("Q subchannel stores ISRC"); + break; + case TOC_ADR.MediaCatalogNumber: + sb.AppendLine("Q subchannel stores media catalog number"); + break; + } + + if((descriptor.CONTROL & (byte)TOC_CONTROL.ReservedMask) == (byte)TOC_CONTROL.ReservedMask) + sb.AppendFormat("Reserved flags 0x{0:X2} set", descriptor.CONTROL).AppendLine(); + else + { + switch ((TOC_CONTROL)(descriptor.CONTROL & 0x0D)) + { + case TOC_CONTROL.TwoChanNoPreEmph: + sb.AppendLine("Stereo audio track with no pre-emphasis"); + break; + case TOC_CONTROL.TwoChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; + case TOC_CONTROL.FourChanNoPreEmph: + sb.AppendLine("Quadraphonic audio track with no pre-emphasis"); + break; + case TOC_CONTROL.FourChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; + case TOC_CONTROL.DataTrack: + sb.AppendLine("Data track, recorded uninterrupted"); + break; + case TOC_CONTROL.DataTrackIncremental: + sb.AppendLine("Data track, recorded incrementally"); + break; + } + + if ((descriptor.CONTROL & (byte)TOC_CONTROL.CopyPermissionMask) == (byte)TOC_CONTROL.CopyPermissionMask) + sb.AppendLine("Digital copy of track is permitted"); + else + sb.AppendLine("Digital copy of track is prohibited"); + + //if (MainClass.isDebug) + { + sb.AppendFormat("Reserved1: {0:X2}", descriptor.Reserved1).AppendLine(); + sb.AppendFormat("Reserved2: {0:X2}", descriptor.Reserved2).AppendLine(); + } + + sb.AppendLine(); + } + } + + return sb.ToString(); + } + + public static string PrettifyCDTOC(byte[] CDTOCResponse) + { + CDTOC? decoded = DecodeCDTOC(CDTOCResponse); + return PrettifyCDTOC(decoded); + } + + public static CDSessionInfo? DecodeCDSessionInfo(byte[] CDSessionInfoResponse) + { + if (CDSessionInfoResponse == null) + return null; + + CDSessionInfo decoded = new CDSessionInfo(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDSessionInfoResponse, 0); + decoded.FirstCompleteSession = CDSessionInfoResponse[2]; + decoded.LastCompleteSession = CDSessionInfoResponse[3]; + decoded.TrackDescriptors = new CDSessionInfoTrackDataDescriptor[(decoded.DataLength - 2) / 8]; + + if (decoded.DataLength + 2 != CDSessionInfoResponse.Length) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (CDSessionInfo Decoder): Expected CDSessionInfo size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDSessionInfoResponse.Length); + return null; + } + + for (int i = 0; i < ((decoded.DataLength - 2) / 8); i++) + { + decoded.TrackDescriptors[i].Reserved1 = CDSessionInfoResponse[0 + i * 8 + 4]; + decoded.TrackDescriptors[i].ADR = (byte)((CDSessionInfoResponse[1 + i * 8 + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].CONTROL = (byte)(CDSessionInfoResponse[1 + i * 8 + 4] & 0x0F); + decoded.TrackDescriptors[i].TrackNumber = CDSessionInfoResponse[2 + i * 8 + 4]; + decoded.TrackDescriptors[i].Reserved2 = CDSessionInfoResponse[3 + i * 8 + 4]; + decoded.TrackDescriptors[i].TrackStartAddress = BigEndianBitConverter.ToUInt32(CDSessionInfoResponse, 4 + i * 8 + 4); + } + + return decoded; + } + + public static string PrettifyCDSessionInfo(CDSessionInfo? CDSessionInfoResponse) + { + if (CDSessionInfoResponse == null) + return null; + + CDSessionInfo response = CDSessionInfoResponse.Value; + + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine(); + sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); + foreach (CDSessionInfoTrackDataDescriptor descriptor in response.TrackDescriptors) + { + sb.AppendFormat("First track number in last complete session: {0}", descriptor.TrackNumber); + sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress, + (descriptor.TrackStartAddress & 0x0000FF00) >> 8, + (descriptor.TrackStartAddress & 0x00FF0000) >> 16, + (descriptor.TrackStartAddress & 0xFF000000) >> 24); + + switch ((TOC_ADR)descriptor.ADR) + { + case TOC_ADR.NoInformation: + sb.AppendLine("Q subchannel mode not given"); + break; + case TOC_ADR.CurrentPosition: + sb.AppendLine("Q subchannel stores current position"); + break; + case TOC_ADR.ISRC: + sb.AppendLine("Q subchannel stores ISRC"); + break; + case TOC_ADR.MediaCatalogNumber: + sb.AppendLine("Q subchannel stores media catalog number"); + break; + } + + if((descriptor.CONTROL & (byte)TOC_CONTROL.ReservedMask) == (byte)TOC_CONTROL.ReservedMask) + sb.AppendFormat("Reserved flags 0x{0:X2} set", descriptor.CONTROL).AppendLine(); + else + { + switch ((TOC_CONTROL)(descriptor.CONTROL & 0x0D)) + { + case TOC_CONTROL.TwoChanNoPreEmph: + sb.AppendLine("Stereo audio track with no pre-emphasis"); + break; + case TOC_CONTROL.TwoChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; + case TOC_CONTROL.FourChanNoPreEmph: + sb.AppendLine("Quadraphonic audio track with no pre-emphasis"); + break; + case TOC_CONTROL.FourChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; + case TOC_CONTROL.DataTrack: + sb.AppendLine("Data track, recorded uninterrupted"); + break; + case TOC_CONTROL.DataTrackIncremental: + sb.AppendLine("Data track, recorded incrementally"); + break; + } + + if ((descriptor.CONTROL & (byte)TOC_CONTROL.CopyPermissionMask) == (byte)TOC_CONTROL.CopyPermissionMask) + sb.AppendLine("Digital copy of track is permitted"); + else + sb.AppendLine("Digital copy of track is prohibited"); + + //if (MainClass.isDebug) + { + sb.AppendFormat("Reserved1: {0:X2}", descriptor.Reserved1).AppendLine(); + sb.AppendFormat("Reserved2: {0:X2}", descriptor.Reserved2).AppendLine(); + } + + sb.AppendLine(); + } + } + + return sb.ToString(); + } + + public static string PrettifyCDSessionInfo(byte[] CDSessionInfoResponse) + { + CDSessionInfo? decoded = DecodeCDSessionInfo(CDSessionInfoResponse); + return PrettifyCDSessionInfo(decoded); + } + + public static CDFullTOC? DecodeCDFullTOC(byte[] CDFullTOCResponse) + { + if (CDFullTOCResponse == null) + return null; + + CDFullTOC decoded = new CDFullTOC(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDFullTOCResponse, 0); + decoded.FirstCompleteSession = CDFullTOCResponse[2]; + decoded.LastCompleteSession = CDFullTOCResponse[3]; + decoded.TrackDescriptors = new CDFullTOCInfoTrackDataDescriptor[(decoded.DataLength - 2) / 11]; + + if (decoded.DataLength + 2 != CDFullTOCResponse.Length) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (CDFullTOC Decoder): Expected CDFullTOC size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDFullTOCResponse.Length); + return null; + } + + for (int i = 0; i < ((decoded.DataLength - 2) / 11); i++) + { + decoded.TrackDescriptors[i].SessionNumber = CDFullTOCResponse[0 + i * 11 + 4]; + decoded.TrackDescriptors[i].ADR = (byte)((CDFullTOCResponse[1 + i * 11 + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].CONTROL = (byte)(CDFullTOCResponse[1 + i * 11 + 4] & 0x0F); + decoded.TrackDescriptors[i].TNO = CDFullTOCResponse[2 + i * 11 + 4]; + decoded.TrackDescriptors[i].POINT = CDFullTOCResponse[3 + i * 11 + 4]; + decoded.TrackDescriptors[i].Min = CDFullTOCResponse[4 + i * 11 + 4]; + decoded.TrackDescriptors[i].Sec = CDFullTOCResponse[5 + i * 11 + 4]; + decoded.TrackDescriptors[i].Frame = CDFullTOCResponse[6 + i * 11 + 4]; + decoded.TrackDescriptors[i].Zero = CDFullTOCResponse[7 + i * 11 + 4]; + decoded.TrackDescriptors[i].HOUR = (byte)((CDFullTOCResponse[7 + i * 11 + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].PHOUR = (byte)(CDFullTOCResponse[7 + i * 11 + 4] & 0x0F); + decoded.TrackDescriptors[i].PMIN = CDFullTOCResponse[8 + i * 11 + 4]; + decoded.TrackDescriptors[i].PSEC = CDFullTOCResponse[9 + i * 11 + 4]; + decoded.TrackDescriptors[i].PFRAME = CDFullTOCResponse[10 + i * 11 + 4]; + } + + return decoded; + } + + public static string PrettifyCDFullTOC(CDFullTOC? CDFullTOCResponse) + { + if (CDFullTOCResponse == null) + return null; + + CDFullTOC response = CDFullTOCResponse.Value; + + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine(); + sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); + foreach (CDFullTOCInfoTrackDataDescriptor descriptor in response.TrackDescriptors) + { + if ((descriptor.CONTROL != 4 && descriptor.CONTROL != 6) || + (descriptor.ADR != 1 && descriptor.ADR != 5) || + descriptor.TNO != 0) + { + sb.AppendLine("Unknown TOC entry format, printing values as-is"); + sb.AppendFormat("SessionNumber = {0}", descriptor.SessionNumber).AppendLine(); + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + else + { + sb.AppendFormat("Session {0}", descriptor.SessionNumber).AppendLine(); + switch (descriptor.ADR) + { + case 1: + { + switch (descriptor.POINT) + { + case 0xA0: + { + sb.AppendFormat("First track number: {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("Disc type: {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("Absolute time: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + case 0xA1: + { + sb.AppendFormat("Last track number: {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("Absolute time: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + case 0xA2: + { + sb.AppendFormat("Lead-out start position: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); + sb.AppendFormat("Absolute time: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + case 0xF0: + { + sb.AppendFormat("Book type: 0x{0:X2}", descriptor.PMIN); + sb.AppendFormat("Material type: 0x{0:X2}", descriptor.PSEC); + sb.AppendFormat("Moment of inertia: 0x{0:X2}", descriptor.PFRAME); + sb.AppendFormat("Absolute time: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + default: + { + if (descriptor.POINT >= 0x01 && descriptor.POINT <= 0x63) + { + sb.AppendFormat("Track start position for track {3}: {4:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.POINT, descriptor.PHOUR).AppendLine(); + sb.AppendFormat("Absolute time: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + } + else + { + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + break; + } + } + break; + } + case 5: + { + switch (descriptor.POINT) + { + case 0xB0: + { + sb.AppendFormat("Start of next possible program in the recordable area of the disc: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + sb.AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); + break; + } + case 0xB1: + { + sb.AppendFormat("Number of skip interval pointers: {0:X2}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("Number of skip track pointers: {0:X2}", descriptor.PSEC).AppendLine(); + break; + } + case 0xB2: + case 0xB3: + case 0xB4: + { + sb.AppendFormat("Skip track {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.Zero).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.PFRAME).AppendLine(); + break; + } + case 0xC0: + { + sb.AppendFormat("Optimum recording power: 0x{0:X2}", descriptor.Min).AppendLine(); + sb.AppendFormat("Start time of the first Lead-in area in the disc: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); + break; + } + case 0xC1: + { + sb.AppendFormat("Copy of information of A1 from ATIP found"); + //if (MainClass.isDebug) + { + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("Zero = {0}", descriptor.Zero).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + break; + } + case 0xCF: + { + sb.AppendFormat("Start position of outer part lead-in area: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); + sb.AppendFormat("Stop position of inner part lead-out area: {3:X2}:{0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + default: + { + if (descriptor.POINT >= 0x01 && descriptor.POINT <= 0x40) + { + sb.AppendFormat("Start time for interval that should be skipped: {0:X2}:{1:X2}:{2:X2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).AppendLine(); + sb.AppendFormat("Ending time for interval that should be skipped: {0:X2}:{1:X2}:{2:X2}", descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); + } + else + { + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + break; + } + } + break; + } + } + } + } + + return sb.ToString(); + } + + public static string PrettifyCDFullTOC(byte[] CDFullTOCResponse) + { + CDFullTOC? decoded = DecodeCDFullTOC(CDFullTOCResponse); + return PrettifyCDFullTOC(decoded); + } + + public static CDPMA? DecodeCDPMA(byte[] CDPMAResponse) + { + if (CDPMAResponse == null) + return null; + + CDPMA decoded = new CDPMA(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDPMAResponse, 0); + decoded.Reserved1 = CDPMAResponse[2]; + decoded.Reserved2 = CDPMAResponse[3]; + decoded.PMADescriptors = new CDPMADescriptors[(decoded.DataLength - 2) / 11]; + + if (decoded.DataLength + 2 != CDPMAResponse.Length) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (CDPMA Decoder): Expected CDPMA size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDPMAResponse.Length); + return null; + } + + for (int i = 0; i < ((decoded.DataLength - 2) / 11); i++) + { + decoded.PMADescriptors[i].Reserved = CDPMAResponse[0 + i * 11 + 4]; + decoded.PMADescriptors[i].ADR = (byte)((CDPMAResponse[1 + i * 11 + 4] & 0xF0) >> 4); + decoded.PMADescriptors[i].CONTROL = (byte)(CDPMAResponse[1 + i * 11 + 4] & 0x0F); + decoded.PMADescriptors[i].TNO = CDPMAResponse[2 + i * 11 + 4]; + decoded.PMADescriptors[i].POINT = CDPMAResponse[3 + i * 11 + 4]; + decoded.PMADescriptors[i].Min = CDPMAResponse[4 + i * 11 + 4]; + decoded.PMADescriptors[i].Sec = CDPMAResponse[5 + i * 11 + 4]; + decoded.PMADescriptors[i].Frame = CDPMAResponse[6 + i * 11 + 4]; + decoded.PMADescriptors[i].HOUR = (byte)((CDPMAResponse[7 + i * 11 + 4] & 0xF0) >> 4); + decoded.PMADescriptors[i].PHOUR = (byte)(CDPMAResponse[7 + i * 11 + 4] & 0x0F); + decoded.PMADescriptors[i].PMIN = CDPMAResponse[8 + i * 11 + 4]; + decoded.PMADescriptors[i].PSEC = CDPMAResponse[9 + i * 11 + 4]; + decoded.PMADescriptors[i].PFRAME = CDPMAResponse[10 + i * 11 + 4]; + } + + return decoded; + } + + public static string PrettifyCDPMA(CDPMA? CDPMAResponse) + { + if (CDPMAResponse == null) + return null; + + CDPMA response = CDPMAResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("Reserved1: 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("Reserved2: 0x{0:X2}", response.Reserved2).AppendLine(); + } + foreach (CDPMADescriptors descriptor in response.PMADescriptors) + { + //if (MainClass.isDebug) + sb.AppendFormat("Reserved1: 0x{0:X2}", descriptor.Reserved).AppendLine(); + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyCDPMA(byte[] CDPMAResponse) + { + CDPMA? decoded = DecodeCDPMA(CDPMAResponse); + return PrettifyCDPMA(decoded); + } + + public static CDATIP? DecodeCDATIP(byte[] CDATIPResponse) + { + if (CDATIPResponse == null) + return null; + + CDATIP decoded = new CDATIP(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + if (CDATIPResponse.Length != 32) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (CDATIP Decoder): Expected CDATIP size (32 bytes) is not received size ({0} bytes), not decoding", CDATIPResponse.Length); + return null; + } + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDATIPResponse, 0); + decoded.Reserved1 = CDATIPResponse[2]; + decoded.Reserved2 = CDATIPResponse[3]; + decoded.ITWP = (byte)((CDATIPResponse[4] & 0xF0) >> 4); + decoded.DDCD = Convert.ToBoolean(CDATIPResponse[4] & 0x08); + decoded.ReferenceSpeed = (byte)(CDATIPResponse[4] & 0x07); + decoded.AlwaysZero = Convert.ToBoolean(CDATIPResponse[5] & 0x80); + decoded.URU = Convert.ToBoolean(CDATIPResponse[5] & 0x40); + decoded.Reserved3 = (byte)(CDATIPResponse[5] & 0x3F); + + decoded.AlwaysOne = Convert.ToBoolean(CDATIPResponse[6] & 0x80); + decoded.DiscType = Convert.ToBoolean(CDATIPResponse[6] & 0x40); + decoded.DiscSubType = (byte)((CDATIPResponse[6] & 0x38) >> 3); + decoded.A1Valid = Convert.ToBoolean(CDATIPResponse[6] & 0x04); + decoded.A2Valid = Convert.ToBoolean(CDATIPResponse[6] & 0x02); + decoded.A3Valid = Convert.ToBoolean(CDATIPResponse[6] & 0x01); + + decoded.Reserved4 = CDATIPResponse[7]; + decoded.LeadInStartMin = CDATIPResponse[8]; + decoded.LeadInStartSec = CDATIPResponse[9]; + decoded.LeadInStartFrame = CDATIPResponse[10]; + decoded.Reserved5 = CDATIPResponse[11]; + decoded.LeadOutStartMin = CDATIPResponse[12]; + decoded.LeadOutStartSec = CDATIPResponse[13]; + decoded.LeadOutStartFrame = CDATIPResponse[14]; + decoded.Reserved6 = CDATIPResponse[15]; + + decoded.A1Values = new byte[3]; + decoded.A2Values = new byte[3]; + decoded.A3Values = new byte[3]; + decoded.S4Values = new byte[3]; + + Array.Copy(CDATIPResponse, 16, decoded.A1Values, 0, 3); + Array.Copy(CDATIPResponse, 20, decoded.A1Values, 0, 3); + Array.Copy(CDATIPResponse, 24, decoded.A1Values, 0, 3); + Array.Copy(CDATIPResponse, 28, decoded.A1Values, 0, 3); + + decoded.Reserved7 = CDATIPResponse[19]; + decoded.Reserved8 = CDATIPResponse[23]; + decoded.Reserved9 = CDATIPResponse[27]; + decoded.Reserved10 = CDATIPResponse[31]; + + return decoded; + } + + public static string PrettifyCDATIP(CDATIP? CDATIPResponse) + { + if (CDATIPResponse == null) + return null; + + CDATIP response = CDATIPResponse.Value; + + StringBuilder sb = new StringBuilder(); + + if (response.DDCD) + { + sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP).AppendLine(); + if (response.DiscType) + sb.AppendLine("Disc is DDCD-RW"); + else + sb.AppendLine("Disc is DDCD-R"); + switch (response.ReferenceSpeed) + { + case 2: + sb.AppendLine("Reference speed is 4x"); + break; + case 3: + sb.AppendLine("Reference speed is 8x"); + break; + default: + sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine(); + break; + } + sb.AppendFormat("ATIP Start time of Lead-in: 0x{0:X6}", (response.LeadInStartMin << 16) + (response.LeadInStartSec << 8) + response.LeadInStartFrame).AppendLine(); + sb.AppendFormat("ATIP Last possible start time of Lead-out: 0x{0:X6}", (response.LeadOutStartMin << 16) + (response.LeadOutStartSec << 8) + response.LeadOutStartFrame).AppendLine(); + sb.AppendFormat("S4 value: 0x{0:X6}", (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]).AppendLine(); + } + else + { + sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP & 0x07).AppendLine(); + if (response.DiscType) + { + switch (response.DiscSubType) + { + case 0: + sb.AppendLine("Disc is CD-RW"); + break; + case 1: + sb.AppendLine("Disc is High-Speed CD-RW"); + break; + default: + sb.AppendFormat("Unknown CD-RW disc subtype: {0}", response.DiscSubType).AppendLine(); + break; + } + switch (response.ReferenceSpeed) + { + case 1: + sb.AppendLine("Reference speed is 2x"); + break; + default: + sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine(); + break; + } + } + else + { + sb.AppendLine("Disc is CD-R"); + switch (response.DiscSubType) + { + default: + sb.AppendFormat("Unknown CD-R disc subtype: {0}", response.DiscSubType).AppendLine(); + break; + } + } + + if (response.URU) + sb.AppendLine("Disc use is unrestricted"); + else + sb.AppendLine("Disc use is restricted"); + + sb.AppendFormat("ATIP Start time of Lead-in: {0:X2}:{1:X2}:{2:X2}", response.LeadInStartMin, response.LeadInStartSec, response.LeadInStartFrame).AppendLine(); + sb.AppendFormat("ATIP Last possible start time of Lead-out: {0:X2}:{1:X2}:{2:X2}", response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame).AppendLine(); + if(response.A1Valid) + sb.AppendFormat("A1 value: 0x{0:X6}", (response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2]).AppendLine(); + if(response.A2Valid) + sb.AppendFormat("A2 value: 0x{0:X6}", (response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2]).AppendLine(); + if(response.A3Valid) + sb.AppendFormat("A3 value: 0x{0:X6}", (response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2]).AppendLine(); + sb.AppendFormat("S4 value: 0x{0:X6}", (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]).AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyCDATIP(byte[] CDATIPResponse) + { + CDATIP? decoded = DecodeCDATIP(CDATIPResponse); + return PrettifyCDATIP(decoded); + } + + public static CDTextLeadIn? DecodeCDTextLeadIn(byte[] CDTextResponse) + { + if (CDTextResponse == null) + return null; + + CDTextLeadIn decoded = new CDTextLeadIn(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDTextResponse, 0); + decoded.Reserved1 = CDTextResponse[2]; + decoded.Reserved2 = CDTextResponse[3]; + decoded.DataPacks = new CDTextPack[(decoded.DataLength - 2) / 18]; + + if (decoded.DataLength + 2 != CDTextResponse.Length) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (CD-TEXT Decoder): Expected CD-TEXT size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDTextResponse.Length); + return null; + } + + for (int i = 0; i < ((decoded.DataLength - 2) / 18); i++) + { + decoded.DataPacks[i].HeaderID1 = CDTextResponse[0 + i * 18 + 4]; + decoded.DataPacks[i].HeaderID2 = CDTextResponse[1 + i * 18 + 4]; + decoded.DataPacks[i].HeaderID3 = CDTextResponse[2 + i * 18 + 4]; + decoded.DataPacks[i].DBCC = Convert.ToBoolean(CDTextResponse[3 + i * 8 + 4] & 0x80); + decoded.DataPacks[i].BlockNumber = (byte)((CDTextResponse[3 + i * 8 + 4] & 0x70) >> 4); + decoded.DataPacks[i].CharacterPosition = (byte)(CDTextResponse[3 + i * 8 + 4] & 0x0F); + decoded.DataPacks[i].TextDataField = new byte[12]; + Array.Copy(CDTextResponse, 4, decoded.DataPacks[i].TextDataField, 0, 12); + decoded.DataPacks[i].CRC = BigEndianBitConverter.ToUInt16(CDTextResponse, 16 + i * 8 + 4); + } + + return decoded; + } + + public static string PrettifyCDTextLeadIn(CDTextLeadIn? CDTextResponse) + { + if (CDTextResponse == null) + return null; + + CDTextLeadIn response = CDTextResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("Reserved1: 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("Reserved2: 0x{0:X2}", response.Reserved2).AppendLine(); + } + foreach (CDTextPack descriptor in response.DataPacks) + { + if ((descriptor.HeaderID1 & 0x80) != 0x80) + sb.AppendFormat("Incorrect CD-Text pack type {0}, not decoding", descriptor.HeaderID1).AppendLine(); + else + { + switch (descriptor.HeaderID1) + { + case 0x80: + { + sb.Append("CD-Text pack contains title for "); + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x81: + { + sb.Append("CD-Text pack contains performer for "); + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x82: + { + sb.Append("CD-Text pack contains songwriter for "); + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x83: + { + sb.Append("CD-Text pack contains composer for "); + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x84: + { + sb.Append("CD-Text pack contains arranger for "); + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x85: + { + sb.Append("CD-Text pack contains content provider's message for "); + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x86: + { + sb.AppendLine("CD-Text pack contains disc identification information"); + break; + } + case 0x87: + { + sb.AppendLine("CD-Text pack contains genre identification information"); + break; + } + case 0x88: + { + sb.AppendLine("CD-Text pack contains table of contents information"); + break; + } + case 0x89: + { + sb.AppendLine("CD-Text pack contains second table of contents information"); + break; + } + case 0x8A: + case 0x8B: + case 0x8C: + { + sb.AppendLine("CD-Text pack contains reserved data"); + break; + } + case 0x8D: + { + sb.AppendLine("CD-Text pack contains data reserved for content provider only"); + break; + } + case 0x8E: + { + if (descriptor.HeaderID2 == 0x00) + sb.AppendLine("CD-Text pack contains UPC"); + else + sb.AppendFormat("CD-Text pack contains ISRC for track {0}", descriptor.HeaderID2).AppendLine(); + break; + } + case 0x8F: + { + sb.AppendLine("CD-Text pack contains size block information"); + break; + } + } + + switch (descriptor.HeaderID1) + { + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x8E: + { + if (descriptor.DBCC) + sb.AppendLine("Double Byte Character Code is used"); + sb.AppendFormat("Block number {0}", descriptor.BlockNumber).AppendLine(); + sb.AppendFormat("Character position {0}", descriptor.CharacterPosition).AppendLine(); + sb.AppendFormat("Text field: \"{0}\"", StringHandlers.CToString(descriptor.TextDataField)).AppendLine(); + break; + } + default: + { + sb.AppendFormat("Binary contents: {0}", PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28)).AppendLine(); + break; + } + } + + sb.AppendFormat("CRC: 0x{0:X4}", descriptor.CRC).AppendLine(); + } + } + + return sb.ToString(); + } + + public static string PrettifyCDTextLeadIn(byte[] CDTextResponse) + { + CDTextLeadIn? decoded = DecodeCDTextLeadIn(CDTextResponse); + return PrettifyCDTextLeadIn(decoded); + } + + #endregion Public methods + + #region Public structures + + public struct CDTOC + { + /// + /// Total size of returned TOC minus this field + /// + public UInt16 DataLength; + /// + /// First track number in hex + /// + public byte FirstTrack; + /// + /// Last track number in hex + /// + public byte LastTrack; + /// + /// Track descriptors + /// + public CDTOCTrackDataDescriptor[] TrackDescriptors; + } + + public struct CDTOCTrackDataDescriptor + { + /// + /// Byte 0 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 1, bits 7 to 4 + /// Type of information in Q subchannel of block where this TOC entry was found + /// + public byte ADR; + /// + /// Byte 1, bits 3 to 0 + /// Track attributes + /// + public byte CONTROL; + /// + /// Byte 2 + /// Track number + /// + public byte TrackNumber; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 7 + /// The track start address in LBA or in MSF + /// + public UInt32 TrackStartAddress; + } + + public struct CDSessionInfo + { + /// + /// Total size of returned session information minus this field + /// + public UInt16 DataLength; + /// + /// First track number in hex + /// + public byte FirstCompleteSession; + /// + /// Last track number in hex + /// + public byte LastCompleteSession; + /// + /// Track descriptors + /// + public CDSessionInfoTrackDataDescriptor[] TrackDescriptors; + } + + public struct CDSessionInfoTrackDataDescriptor + { + /// + /// Byte 0 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 1, bits 7 to 4 + /// Type of information in Q subchannel of block where this TOC entry was found + /// + public byte ADR; + /// + /// Byte 1, bits 3 to 0 + /// Track attributes + /// + public byte CONTROL; + /// + /// Byte 2 + /// First track number in last complete session + /// + public byte TrackNumber; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 7 + /// First track number in last complete session start address in LBA or in MSF + /// + public UInt32 TrackStartAddress; + } + + public struct CDFullTOC + { + /// + /// Total size of returned session information minus this field + /// + public UInt16 DataLength; + /// + /// First complete session number in hex + /// + public byte FirstCompleteSession; + /// + /// Last complete session number in hex + /// + public byte LastCompleteSession; + /// + /// Track descriptors + /// + public CDFullTOCInfoTrackDataDescriptor[] TrackDescriptors; + } + + public struct CDFullTOCInfoTrackDataDescriptor + { + /// + /// Byte 0 + /// Session number in hex + /// + public byte SessionNumber; + /// + /// Byte 1, bits 7 to 4 + /// Type of information in Q subchannel of block where this TOC entry was found + /// + public byte ADR; + /// + /// Byte 1, bits 3 to 0 + /// Track attributes + /// + public byte CONTROL; + /// + /// Byte 2 + /// + public byte TNO; + /// + /// Byte 3 + /// + public byte POINT; + /// + /// Byte 4 + /// + public byte Min; + /// + /// Byte 5 + /// + public byte Sec; + /// + /// Byte 6 + /// + public byte Frame; + /// + /// Byte 7, CD only + /// + public byte Zero; + /// + /// Byte 7, bits 7 to 4, DDCD only + /// + public byte HOUR; + /// + /// Byte 7, bits 3 to 0, DDCD only + /// + public byte PHOUR; + /// + /// Byte 8 + /// + public byte PMIN; + /// + /// Byte 9 + /// + public byte PSEC; + /// + /// Byte 10 + /// + public byte PFRAME; + } + + public struct CDPMA + { + /// + /// Total size of returned session information minus this field + /// + public UInt16 DataLength; + /// + /// Reserved + /// + public byte Reserved1; + /// + /// Reserved + /// + public byte Reserved2; + /// + /// Track descriptors + /// + public CDPMADescriptors[] PMADescriptors; + } + + public struct CDPMADescriptors + { + /// + /// Byte 0 + /// Reserved + /// + public byte Reserved; + /// + /// Byte 1, bits 7 to 4 + /// Type of information in Q subchannel of block where this TOC entry was found + /// + public byte ADR; + /// + /// Byte 1, bits 3 to 0 + /// Track attributes + /// + public byte CONTROL; + /// + /// Byte 2 + /// + public byte TNO; + /// + /// Byte 3 + /// + public byte POINT; + /// + /// Byte 4 + /// + public byte Min; + /// + /// Byte 5 + /// + public byte Sec; + /// + /// Byte 6 + /// + public byte Frame; + /// + /// Byte 7, bits 7 to 4 + /// + public byte HOUR; + /// + /// Byte 7, bits 3 to 0 + /// + public byte PHOUR; + /// + /// Byte 8 + /// + public byte PMIN; + /// + /// Byte 9 + /// + public byte PSEC; + /// + /// Byte 10 + /// + public byte PFRAME; + } + + public struct CDATIP + { + /// + /// Bytes 1 to 0 + /// Total size of returned session information minus this field + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bits 7 to 4 + /// Indicative target writing power + /// + public byte ITWP; + /// + /// Byte 4, bit 3 + /// Set if DDCD + /// + public bool DDCD; + /// + /// Byte 4, bits 2 to 0 + /// Reference speed + /// + public byte ReferenceSpeed; + /// + /// Byte 5, bit 7 + /// Always unset + /// + public bool AlwaysZero; + /// + /// Byte 5, bit 6 + /// Unrestricted media + /// + public bool URU; + /// + /// Byte 5, bits 5 to 0 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 6, bit 7 + /// Always set + /// + public bool AlwaysOne; + /// + /// Byte 6, bit 6 + /// Set if rewritable (CD-RW or DDCD-RW) + /// + public bool DiscType; + /// + /// Byte 6, bits 5 to 3 + /// Disc subtype + /// + public byte DiscSubType; + /// + /// Byte 6, bit 2 + /// A1 values are valid + /// + public bool A1Valid; + /// + /// Byte 6, bit 1 + /// A2 values are valid + /// + public bool A2Valid; + /// + /// Byte 6, bit 0 + /// A3 values are valid + /// + public bool A3Valid; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 8 + /// ATIP Start time of Lead-In (Minute) + /// + public byte LeadInStartMin; + /// + /// Byte 9 + /// ATIP Start time of Lead-In (Second) + /// + public byte LeadInStartSec; + /// + /// Byte 10 + /// ATIP Start time of Lead-In (Frame) + /// + public byte LeadInStartFrame; + /// + /// Byte 11 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 12 + /// ATIP Last possible start time of Lead-Out (Minute) + /// + public byte LeadOutStartMin; + /// + /// Byte 13 + /// ATIP Last possible start time of Lead-Out (Second) + /// + public byte LeadOutStartSec; + /// + /// Byte 14 + /// ATIP Last possible start time of Lead-Out (Frame) + /// + public byte LeadOutStartFrame; + /// + /// Byte 15 + /// Reserved + /// + public byte Reserved6; + /// + /// Bytes 16 to 18 + /// A1 values + /// + public byte[] A1Values; + /// + /// Byte 19 + /// Reserved + /// + public byte Reserved7; + /// + /// Bytes 20 to 22 + /// A2 values + /// + public byte[] A2Values; + /// + /// Byte 23 + /// Reserved + /// + public byte Reserved8; + /// + /// Bytes 24 to 26 + /// A3 values + /// + public byte[] A3Values; + /// + /// Byte 27 + /// Reserved + /// + public byte Reserved9; + /// + /// Bytes 28 to 30 + /// S4 values + /// + public byte[] S4Values; + /// + /// Byte 31 + /// Reserved + /// + public byte Reserved10; + } + + public struct CDTextLeadIn + { + /// + /// Total size of returned CD-Text information minus this field + /// + public UInt16 DataLength; + /// + /// Reserved + /// + public byte Reserved1; + /// + /// Reserved + /// + public byte Reserved2; + /// + /// CD-Text data packs + /// + public CDTextPack[] DataPacks; + } + + public struct CDTextPack + { + /// + /// Byte 0 + /// Pack ID1 (Pack Type) + /// + public byte HeaderID1; + /// + /// Byte 1 + /// Pack ID2 (Track number) + /// + public byte HeaderID2; + /// + /// Byte 2 + /// Pack ID3 + /// + public byte HeaderID3; + /// + /// Byte 3, bit 7 + /// Double Byte Character Code + /// + public bool DBCC; + /// + /// Byte 3, bits 6 to 4 + /// Block number + /// + public byte BlockNumber; + /// + /// Byte 3, bits 3 to 0 + /// Character position + /// + public byte CharacterPosition; + /// + /// Bytes 4 to 15 + /// Text data + /// + public byte[] TextDataField; + /// + /// Bytes 16 to 17 + /// CRC16 + /// + public UInt16 CRC; + } + + #endregion Public structures + } +} + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..95be0c1 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,12 @@ +2015-10-05 Natalia Portillo + + * CD.cs: + * BD.cs: + * MMC.cs: + * DVD.cs: + * SCSI.cs: + * Floppy.cs: + * Properties/AssemblyInfo.cs: + * DiscImageChef.Decoders.csproj: + Move decoders to a separate library. + diff --git a/DVD.cs b/DVD.cs new file mode 100644 index 0000000..ce265e6 --- /dev/null +++ b/DVD.cs @@ -0,0 +1,1083 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : BD.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Decoders. + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Decodes DVD structures. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Text; + +namespace DiscImageChef.Decoders +{ + /// + /// Information from the following standards: + /// ANSI X3.304-1997 + /// T10/1048-D revision 9.0 + /// T10/1048-D revision 10a + /// T10/1228-D revision 7.0c + /// T10/1228-D revision 11a + /// T10/1363-D revision 10g + /// T10/1545-D revision 1d + /// T10/1545-D revision 5 + /// T10/1545-D revision 5a + /// T10/1675-D revision 2c + /// T10/1675-D revision 4 + /// T10/1836-D revision 2g + /// ECMA 365 + /// + public static class DVD + { + #region Public enumerations + public enum DiskCategory : byte + { + DVDROM = 0x00, + DVDRAM = 0x01, + DVDR = 0x02, + DVDRW = 0x03, + HDDVDROM = 0x04, + HDDVDRAM = 0x05, + HDDVDR = 0x06, + Reserved1 = 0x07, + UMD = 0x08, + DVDPRW = 0x09, + DVDPR = 0x0A, + Reserved2 = 0x0B, + Reserved3 = 0x0C, + DVDPRWDL = 0x0D, + DVDPRDL = 0x0E, + Reserved4 = 0x0F + } + + public enum MaximumRateField : byte + { + /// + /// 2.52 Mbps + /// + TwoMbps = 0x00, + /// + /// 5.04 Mbps + /// + FiveMbps = 0x01, + /// + /// 10.08 Mbps + /// + TenMbps = 0x02, + /// + /// 20.16 Mbps + /// + TwentyMbps = 0x03, + /// + /// 30.24 Mbps + /// + ThirtyMbps = 0x04, + Unspecified = 0x0F + } + + public enum LayerTypeFieldMask : byte + { + Embossed = 0x01, + Recordable = 0x02, + Rewritable = 0x04, + Reserved = 0x08 + } + + public enum LinearDensityField : byte + { + /// + /// 0.267 μm/bit + /// + TwoSix = 0x00, + /// + /// 0.293 μm/bit + /// + TwoNine = 0x01, + /// + /// 0.409 to 0.435 μm/bit + /// + FourZero = 0x02, + /// + /// 0.280 to 0.291 μm/bit + /// + TwoEight = 0x04, + /// + /// 0.153 μm/bit + /// + OneFive = 0x05, + /// + /// 0.130 to 0.140 μm/bit + /// + OneThree = 0x06, + /// + /// 0.353 μm/bit + /// + ThreeFive = 0x08, + } + + public enum TrackDensityField : byte + { + /// + /// 0.74 μm/track + /// + Seven = 0x00, + /// + /// 0.80 μm/track + /// + Eight = 0x01, + /// + /// 0.615 μm/track + /// + Six = 0x02, + /// + /// 0.40 μm/track + /// + Four = 0x03, + /// + /// 0.34 μm/track + /// + Three = 0x04 + } + + public enum CopyrightType : byte + { + /// + /// There is no copy protection + /// + NoProtection = 0x00, + /// + /// Copy protection is CSS/CPPM + /// + CSS = 0x01, + /// + /// Copy protection is CPRM + /// + CPRM = 0x02, + /// + /// Copy protection is AACS + /// + AACS = 0x10 + } + + public enum WPDiscTypes : byte + { + /// + /// Should not write without a cartridge + /// + DoNotWrite = 0x00, + /// + /// Can write without a cartridge + /// + CanWrite = 0x01, + Reserved1 = 0x02, + Reserved2 = 0x03 + } + #endregion + + #region Public structures + public struct PhysicalFormatInformation + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bits 7 to 4 + /// Disk category field + /// + public byte DiskCategory; + /// + /// Byte 4, bits 3 to 0 + /// Media version + /// + public byte PartVersion; + /// + /// Byte 5, bits 7 to 4 + /// 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values + /// + public byte DiscSize; + /// + /// Byte 5, bits 3 to 0 + /// Maximum data rate + /// + public byte MaximumRate; + /// + /// Byte 6, bit 7 + /// Reserved + /// + public bool Reserved3; + /// + /// Byte 6, bits 6 to 5 + /// Number of layers + /// + public byte Layers; + /// + /// Byte 6, bit 4 + /// Track path + /// + public bool TrackPath; + /// + /// Byte 6, bits 3 to 0 + /// Layer type + /// + public byte LayerType; + /// + /// Byte 7, bits 7 to 4 + /// Linear density field + /// + public byte LinearDensity; + /// + /// Byte 7, bits 3 to 0 + /// Track density field + /// + public byte TrackDensity; + /// + /// Bytes 8 to 11 + /// PSN where Data Area starts + /// + public UInt32 DataAreaStartPSN; + /// + /// Bytes 12 to 15 + /// PSN where Data Area ends + /// + public UInt32 DataAreaEndPSN; + /// + /// Bytes 16 to 19 + /// PSN where Data Area ends in Layer 0 + /// + public UInt32 Layer0EndPSN; + /// + /// Byte 20, bit 7 + /// True if BCA exists. GC/Wii discs do not have this bit set, but there is a BCA, making it unreadable in normal DVD drives + /// + public bool BCA; + /// + /// Byte 20, bits 6 to 0 + /// Reserved + /// + public byte Reserved4; + /// + /// Bytes 21 to 22 + /// UMD only, media attribute, application-defined, part of media specific in rest of discs + /// + public UInt16 MediaAttribute; + /// + /// Bytes 21 to 2051, set to zeroes in UMD (at least according to ECMA). + /// Media specific + /// + public byte[] MediaSpecific; + } + + public struct LeadInCopyright + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 + /// Copy protection system type + /// + public byte CopyrightType; + /// + /// Byte 5 + /// Bitmask of regions where this disc is playable + /// + public byte RegionInformation; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved4; + } + + public struct DiscKey + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 2052 + /// Disc key for CSS, Album Identifier for CPPM + /// + public byte[] Key; + } + + public struct BurstCuttingArea + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// Burst cutting area contents, 12 to 188 bytes + /// + public byte[] BCA; + } + + public struct DiscManufacturingInformation + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 2052 + /// Disc Manufacturing Information + /// + public byte[] DMI; + } + + public struct DiscMediaIdentifier + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// Disc Media Identifier for CPRM + /// + public byte[] MediaIdentifier; + } + + public struct DiscMediaKeyBlock + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// Disc Media Key Block for CPRM + /// + public byte[] MediaKeyBlock; + } + + public struct DiscDefinitionStructure + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 2052 + /// DVD-RAM / HD DVD-RAM disc definition structure + /// + public byte[] DDS; + } + + public struct MediumStatus + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bit 7 + /// Medium is in a cartridge + /// + public bool Cartridge; + /// + /// Byte 4, bit 6 + /// Medium has been taken out/inserted in a cartridge + /// + public bool OUT; + /// + /// Byte 4, bits 5 to 4 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 4, bit 3 + /// Media is write protected by reason stablished in RAMSWI + /// + public bool MSWI; + /// + /// Byte 4, bit 2 + /// Media is write protected by cartridge + /// + public bool CWP; + /// + /// Byte 4, bit 1 + /// Media is persistently write protected + /// + public bool PWP; + /// + /// Byte 4, bit 0 + /// Reserved + /// + public bool Reserved4; + /// + /// Byte 5 + /// Writable status depending on cartridge + /// + public byte DiscType; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 7 + /// Reason of specific write protection, only defined 0x01 as "bare disc wp", and 0xFF as unspecified. Rest reserved. + /// + public byte RAMSWI; + } + + public struct SpareAreaInformation + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 7 + /// Data length + /// + public UInt32 UnusedPrimaryBlocks; + /// + /// Bytes 8 to 11 + /// Data length + /// + public UInt32 UnusedSupplementaryBlocks; + /// + /// Bytes 12 to 15 + /// Data length + /// + public UInt32 AllocatedSupplementaryBlocks; + } + + public struct LastBorderOutRMD + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// RMD in last recorded Border-out + /// + public byte[] RMD; + } + + public struct PreRecordedInformation + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// Pre-recorded Information in Lead-in for writable media + /// + public byte[] PRI; + } + + public struct UniqueDiscIdentifier + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved4; + /// + /// Bytes 6 to 7 + /// Random number + /// + public UInt16 RandomNumber; + /// + /// Byte 8 to 11 + /// Year + /// + public UInt32 Year; + /// + /// Byte 12 to 13 + /// Month + /// + public UInt16 Month; + /// + /// Byte 14 to 15 + /// Day + /// + public UInt16 Day; + /// + /// Byte 16 to 17 + /// Hour + /// + public UInt16 Hour; + /// + /// Byte 18 to 19 + /// Minute + /// + public UInt16 Minute; + /// + /// Byte 20 to 21 + /// Second + /// + public UInt16 Second; + } + + public struct PhysicalFormatInformationForWritables + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bits 7 to 4 + /// Disk category field + /// + public byte DiskCategory; + /// + /// Byte 4, bits 3 to 0 + /// Media version + /// + public byte PartVersion; + /// + /// Byte 5, bits 7 to 4 + /// 120mm if 0, 80mm if 1 + /// + public byte DiscSize; + /// + /// Byte 5, bits 3 to 0 + /// Maximum data rate + /// + public byte MaximumRate; + /// + /// Byte 6, bit 7 + /// Reserved + /// + public bool Reserved3; + /// + /// Byte 6, bits 6 to 5 + /// Number of layers + /// + public byte Layers; + /// + /// Byte 6, bit 4 + /// Track path + /// + public bool TrackPath; + /// + /// Byte 6, bits 3 to 0 + /// Layer type + /// + public byte LayerType; + /// + /// Byte 7, bits 7 to 4 + /// Linear density field + /// + public byte LinearDensity; + /// + /// Byte 7, bits 3 to 0 + /// Track density field + /// + public byte TrackDensity; + /// + /// Bytes 8 to 11 + /// PSN where Data Area starts + /// + public UInt32 DataAreaStartPSN; + /// + /// Bytes 12 to 15 + /// PSN where Data Area ends + /// + public UInt32 DataAreaEndPSN; + /// + /// Bytes 16 to 19 + /// PSN where Data Area ends in Layer 0 + /// + public UInt32 Layer0EndPSN; + /// + /// Byte 20, bit 7 + /// True if BCA exists + /// + public bool BCA; + /// + /// Byte 20, bits 6 to 0 + /// Reserved + /// + public byte Reserved4; + /// + /// Bytes 21 to 2051 + /// Media specific, content defined in each specification + /// + public byte[] MediaSpecific; + } + + public struct ADIPInformation + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 259 + /// ADIP, defined in DVD standards + /// + public byte[] ADIP; + } + + public struct HDLeadInCopyright + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 2052 + /// HD DVD Lead-In Copyright Information + /// + public byte[] CopyrightInformation; + } + + public struct HDMediumStatus + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bits 7 to 1 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 4, bit 0 + /// Test Zone has been extended + /// + public bool ExtendedTestZone; + /// + /// Byte 5 + /// Number of remaining RMDs in RDZ + /// + public byte RemainingRMDs; + /// + /// Bytes 6 to 7 + /// Number of remaining RMDs in current RMZ + /// + public UInt16 CurrentRemainingRMDs; + } + + public struct LayerCapacity + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bit 7 + /// If set, L0 capacity is immutable + /// + public bool InitStatus; + /// + /// Byte 4, bits 6 to 0 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved6; + /// + /// Byte 8 to 11 + /// L0 Data Area Capacity + /// + public UInt32 Capacity; + } + + public struct MiddleZoneStartAddress + { + /// + /// Bytes 0 to 1 + /// Data length = 10 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bit 7 + /// If set, L0 shifter middle area is immutable + /// + public bool InitStatus; + /// + /// Byte 4, bits 6 to 0 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved6; + /// + /// Byte 8 to 11 + /// Start LBA of Shifted Middle Area on L0 + /// + public UInt32 ShiftedMiddleAreaStartAddress; + } + + public struct JumpIntervalSize + { + /// + /// Bytes 0 to 1 + /// Data length = 10 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved6; + /// + /// Byte 8 to 11 + /// Jump Interval size for the Regular Interval Layer Jump + /// + public UInt32 Size; + } + + public struct ManualLayerJumpAddress + { + /// + /// Bytes 0 to 1 + /// Data length = 10 + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved6; + /// + /// Byte 8 to 11 + /// LBA for the manual layer jump + /// + public UInt32 LBA; + } + #endregion Public structures + } +} + diff --git a/DiscImageChef.Decoders.csproj b/DiscImageChef.Decoders.csproj new file mode 100644 index 0000000..cad6d95 --- /dev/null +++ b/DiscImageChef.Decoders.csproj @@ -0,0 +1,52 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {0BEB3088-B634-4289-AE17-CDF2D25D00D5} + Library + DiscImageChef.Decoders + DiscImageChef.Decoders + 2.2 + v3.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + + + + + + + + + + + + + {F8BDF57B-1571-4CD0-84B3-B422088D359A} + DiscImageChef.Helpers + + + \ No newline at end of file diff --git a/Floppy.cs b/Floppy.cs new file mode 100644 index 0000000..017b0c8 --- /dev/null +++ b/Floppy.cs @@ -0,0 +1,808 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : BD.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Decoders. + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Decodes DVD structures. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Runtime.InteropServices; + +namespace DiscImageChef.Decoders +{ + // Information from: + // National Semiconductor PC87332VLJ datasheet + // SMsC FDC37C78 datasheet + // Intel 82078 datasheet + // Intel 82077AA datasheet + // Toshiba TC8566AF datasheet + // Fujitsu MB8876A datasheet + // Inside Macintosh, Volume II, ISBN 0-201-17732-3 + // ECMA-147 + // ECMA-100 + public static class Floppy + { + #region Public enumerations + + /// + /// In-sector code for sector size + /// + public enum IBMSectorSizeCode : byte + { + /// + /// 128 bytes/sector + /// + EighthKilo = 0, + /// + /// 256 bytes/sector + /// + QuarterKilo = 1, + /// + /// 512 bytes/sector + /// + HalfKilo = 2, + /// + /// 1024 bytes/sector + /// + Kilo = 3, + /// + /// 2048 bytes/sector + /// + TwiceKilo = 4, + /// + /// 4096 bytes/sector + /// + FriceKilo = 5, + /// + /// 8192 bytes/sector + /// + TwiceFriceKilo = 6, + /// + /// 16384 bytes/sector + /// + FricelyFriceKilo = 7 + } + + public enum IBMIdType : byte + { + IndexMark = 0xFC, + AddressMark = 0xFE, + DataMark = 0xFB, + DeletedDataMark = 0xF8 + } + + public enum AppleEncodedFormat : byte + { + /// + /// Disk is an Apple II 3.5" disk + /// + AppleII = 0x96, + /// + /// Disk is an Apple Lisa 3.5" disk + /// + Lisa = 0x97, + /// + /// Disk is an Apple Macintosh single-sided 3.5" disk + /// + MacSingleSide = 0x9A, + /// + /// Disk is an Apple Macintosh double-sided 3.5" disk + /// + MacDoubleSide = 0xD9 + } + + #endregion Public enumerations + + #region Public structures + + #region IBM System 3740 floppy + + /// + /// Track format for IBM System 3740 floppy + /// + public struct IBMFMTrack + { + /// + /// Start of track + /// + public IBMFMTrackPreamble trackStart; + /// + /// Track sectors + /// + public IBMFMSector[] sectors; + /// + /// Undefined size + /// + public byte[] gap; + } + + /// + /// Start of IBM PC FM floppy track + /// + public struct IBMFMTrackPreamble + { + /// + /// Gap from index pulse, 80 bytes set to 0xFF + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] + public byte[] gap; + /// + /// 6 bytes set to 0x00 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] zero; + /// + /// Set to + /// + public IBMIdType type; + /// + /// Gap until first sector, 26 bytes to 0xFF + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] + public byte[] gap1; + } + + /// + /// Raw demodulated format for IBM System 3740 floppies + /// + public struct IBMFMSector + { + /// + /// Sector address mark + /// + public IBMFMSectorAddressMark addressMark; + /// + /// 11 bytes set to 0xFF + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] + public byte[] innerGap; + /// + /// Sector data block + /// + public IBMFMSectorAddressMark dataBlock; + /// + /// Variable bytes set to 0xFF + /// + public byte[] outerGap; + } + + /// + /// Sector address mark for IBM System 3740 floppies, contains sync word + /// + public struct IBMFMSectorAddressMark + { + /// + /// 6 bytes set to 0 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] zero; + /// + /// Set to + /// + public IBMIdType type; + /// + /// Track number + /// + public byte track; + /// + /// Side number + /// + public byte side; + /// + /// Sector number + /// + public byte sector; + /// + /// + /// + public IBMSectorSizeCode sectorSize; + /// + /// CRC16 from to end of + /// + public UInt16 crc; + } + + /// + /// Sector data block for IBM System 3740 floppies + /// + public struct IBMFMSectorDataBlock + { + /// + /// 12 bytes set to 0 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// + /// Set to or to + /// + public IBMIdType type; + /// + /// User data + /// + public byte[] data; + /// + /// CRC16 from to end of + /// + public UInt16 crc; + } + + #endregion IBM System 3740 floppy + + #region IBM System 34 floppy + + /// + /// Track format for IBM System 34 floppy + /// Used by IBM PC, Apple Macintosh (high-density only), and a lot others + /// + public struct IBMMFMTrack + { + /// + /// Start of track + /// + public IBMMFMTrackPreamble trackStart; + /// + /// Track sectors + /// + public IBMMFMSector[] sectors; + /// + /// Undefined size + /// + public byte[] gap; + } + + /// + /// Start of IBM PC MFM floppy track + /// Used by IBM PC, Apple Macintosh (high-density only), and a lot others + /// + public struct IBMMFMTrackPreamble + { + /// + /// Gap from index pulse, 80 bytes set to 0x4E + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + public byte[] gap; + /// + /// 12 bytes set to 0x00 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// + /// 3 bytes set to 0xC2 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] ctwo; + /// + /// Set to + /// + public IBMIdType type; + /// + /// Gap until first sector, 50 bytes to 0x4E + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] + public byte[] gap1; + } + + /// + /// Raw demodulated format for IBM System 34 floppies + /// + public struct IBMMFMSector + { + /// + /// Sector address mark + /// + public IBMMFMSectorAddressMark addressMark; + /// + /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] + public byte[] innerGap; + /// + /// Sector data block + /// + public IBMMFMSectorAddressMark dataBlock; + /// + /// Variable bytes set to 0x4E, ECMA defines 54 + /// + public byte[] outerGap; + } + + /// + /// Sector address mark for IBM System 34 floppies, contains sync word + /// + public struct IBMMFMSectorAddressMark + { + /// + /// 12 bytes set to 0 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// + /// 3 bytes set to 0xA1 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// + /// Set to + /// + public IBMIdType type; + /// + /// Track number + /// + public byte track; + /// + /// Side number + /// + public byte side; + /// + /// Sector number + /// + public byte sector; + /// + /// + /// + public IBMSectorSizeCode sectorSize; + /// + /// CRC16 from to end of + /// + public UInt16 crc; + } + + /// + /// Sector data block for IBM System 34 floppies + /// + public struct IBMMFMSectorDataBlock + { + /// + /// 12 bytes set to 0 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// + /// 3 bytes set to 0xA1 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// + /// Set to or to + /// + public IBMIdType type; + /// + /// User data + /// + public byte[] data; + /// + /// CRC16 from to end of + /// + public UInt16 crc; + } + + #endregion IBM System 34 floppy + + #region Perpendicular MFM floppy + + /// + /// Perpendicular floppy track + /// + public struct PerpendicularFloppyTrack + { + /// + /// Start of track + /// + public IBMMFMTrackPreamble trackStart; + /// + /// Track sectors + /// + public PerpendicularFloppySector[] sectors; + /// + /// Undefined size + /// + public byte[] gap; + } + + /// + /// Raw demodulated format for perpendicular floppies + /// + public struct PerpendicularFloppySector + { + /// + /// Sector address mark + /// + public IBMMFMSectorAddressMark addressMark; + /// + /// 41 bytes set to 0x4E + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 41)] + public byte[] innerGap; + /// + /// Sector data block + /// + public IBMMFMSectorDataBlock dataBlock; + /// + /// Variable-sized inter-sector gap, ECMA defines 83 bytes + /// + public byte[] outerGap; + } + + #endregion Perpendicular MFM floppy + + #region ISO floppy + + /// + /// ISO floppy track, also used by Atari ST and others + /// + public struct ISOFloppyTrack + { + /// + /// Start of track, 32 bytes set to 0x4E + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] innerGap; + /// + /// Track sectors + /// + public IBMMFMSector[] sectors; + /// + /// Undefined size + /// + public byte[] gap; + } + + #endregion ISO floppy + + #region Apple ][ GCR floppy + + /// + /// GCR-encoded Apple ][ GCR floppy track + /// + public struct AppleOldGCRRawSectorRawTrack + { + /// + /// Track preamble, set to self-sync 0xFF, between 40 and 95 bytes + /// + public byte[] gap; + public AppleOldGCRRawSector[] sectors; + } + + /// + /// GCR-encoded Apple ][ GCR floppy sector + /// + public struct AppleOldGCRRawSector + { + /// + /// Address field + /// + public AppleOldGCRRawAddressField addressField; + /// + /// Track preamble, set to self-sync 0xFF, between 5 and 10 bytes + /// + public byte[] innerGap; + /// + /// Data field + /// + public AppleOldGCRRawDataField dataField; + /// + /// Track preamble, set to self-sync 0xFF, between 14 and 24 bytes + /// + public byte[] gap; + } + + /// + /// GCR-encoded Apple ][ GCR floppy sector address field + /// + public struct AppleOldGCRRawAddressField + { + /// + /// Always 0xD5, 0xAA, 0x96 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// + /// Volume number encoded as: + /// volume[0] = (decodedVolume >> 1) | 0xAA + /// volume[1] = decodedVolume | 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] volume; + /// + /// Track number encoded as: + /// track[0] = (decodedTrack >> 1) | 0xAA + /// track[1] = decodedTrack | 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] track; + /// + /// Sector number encoded as: + /// sector[0] = (decodedSector >> 1) | 0xAA + /// sector[1] = decodedSector | 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] sector; + /// + /// decodedChecksum = decodedVolume ^ decodedTrack ^ decodedSector + /// checksum[0] = (decodedChecksum >> 1) | 0xAA + /// checksum[1] = decodedChecksum | 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] checksum; + /// + /// Always 0xDE, 0xAA, 0xEB + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] epilogue; + } + + /// + /// GCR-encoded Apple ][ GCR floppy sector data field + /// + public struct AppleOldGCRRawDataField + { + /// + /// Always 0xD5, 0xAA, 0xAD + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// + /// Encoded data bytes. + /// 410 bytes for 5to3 (aka DOS 3.2) format + /// 342 bytes for 6to2 (aka DOS 3.3) format + /// + public byte[] data; + public byte checksum; + /// + /// Always 0xDE, 0xAA, 0xEB + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] epilogue; + } + + #endregion Apple ][ GCR floppy + + #region Apple Sony GCR floppy + + /// + /// GCR-encoded Apple Sony GCR floppy track + /// + public struct AppleSonyGCRRawSectorRawTrack + { + /// + /// Track preamble, set to self-sync 0xFF, 36 bytes + /// + public byte[] gap; + public AppleOldGCRRawSector[] sectors; + } + + /// + /// GCR-encoded Apple Sony GCR floppy sector + /// + public struct AppleSonyGCRRawSector + { + /// + /// Address field + /// + public AppleSonyGCRRawAddressField addressField; + /// + /// Track preamble, set to self-sync 0xFF, 6 bytes + /// + public byte[] innerGap; + /// + /// Data field + /// + public AppleSonyGCRRawDataField dataField; + /// + /// Track preamble, set to self-sync 0xFF, unknown size + /// + public byte[] gap; + } + + /// + /// GCR-encoded Apple Sony GCR floppy sector address field + /// + public struct AppleSonyGCRRawAddressField + { + /// + /// Always 0xD5, 0xAA, 0x96 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// + /// Encoded (decodedTrack & 0x3F) + /// + public byte track; + /// + /// Encoded sector number + /// + public byte sector; + /// + /// Encoded side number + /// + public byte side; + /// + /// Disk format + /// + public AppleEncodedFormat format; + /// + /// Checksum + /// + public byte checksum; + /// + /// Always 0xDE, 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] epilogue; + } + + /// + /// GCR-encoded Apple ][ GCR floppy sector data field + /// + public struct AppleSonyGCRRawDataField + { + /// + /// Always 0xD5, 0xAA, 0xAD + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// + /// Spare, usually + /// + public byte spare; + /// + /// Encoded data bytes. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 698)] + public byte[] data; + /// + /// Checksum + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] checksum; + /// + /// Always 0xDE, 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] epilogue; + } + + #endregion Apple Sony GCR floppy + + #region Commodore GCR decoded + + /// + /// Decoded Commodore GCR sector header + /// + public struct CommodoreSectorHeader + { + /// + /// Always 0x08 + /// + public byte id; + /// + /// XOR of following fields + /// + public byte checksum; + /// + /// Sector number + /// + public byte sector; + /// + /// Track number + /// + public byte track; + /// + /// Format ID, unknown meaning + /// + public UInt16 format; + /// + /// Filled with 0x0F + /// + public UInt16 fill; + } + + /// + /// Decoded Commodore GCR sector data + /// + public struct CommodoreSectorData + { + /// + /// Always 0x07 + /// + public byte id; + /// + /// User data + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public byte data; + /// + /// XOR of + /// + public byte checksum; + /// + /// Filled with 0x0F + /// + public UInt16 fill; + } + + #endregion Commodore GCR decoded + + #region Commodore Amiga + + public struct CommodoreAmigaSector + { + /// + /// Set to 0x00 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] zero; + /// + /// Set to 0xA1 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] sync; + /// + /// Set to 0xFF + /// + public byte amiga; + /// + /// Track number + /// + public byte track; + /// + /// Sector number + /// + public byte sector; + /// + /// Remaining sectors til end of writing + /// + public byte remaining; + /// + /// OS dependent tag + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] label; + /// + /// Checksum from to + /// + public UInt32 headerChecksum; + /// + /// Checksum from + /// + public UInt32 dataChecksum; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] + public byte[] data; + } + + #endregion Commodore Amiga + + #endregion Public structures + } +} + diff --git a/MMC.cs b/MMC.cs new file mode 100644 index 0000000..61323d5 --- /dev/null +++ b/MMC.cs @@ -0,0 +1,1121 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : MMC.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Decoders. + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Decodes common structures to DVD, HD DVD and BD. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Text; + +namespace DiscImageChef.Decoders +{ + /// + /// Information from the following standards: + /// ANSI X3.304-1997 + /// T10/1048-D revision 9.0 + /// T10/1048-D revision 10a + /// T10/1228-D revision 7.0c + /// T10/1228-D revision 11a + /// T10/1363-D revision 10g + /// T10/1545-D revision 1d + /// T10/1545-D revision 5 + /// T10/1545-D revision 5a + /// T10/1675-D revision 2c + /// T10/1675-D revision 4 + /// T10/1836-D revision 2g + /// + public static class MMC + { + #region Public enumerations + public enum FormatLayerTypeCodes : ushort + { + CDLayer = 0x0008, + DVDLayer = 0x0010, + BDLayer = 0x0040, + HDDVDLayer = 0x0050 + } + + public enum SessionStatusCodes : byte + { + Empty = 0x00, + Incomplete = 0x01, + ReservedOrDamaged = 0x02, + Complete = 0x03 + } + + public enum DiscStatusCodes : byte + { + Empty = 0x00, + Incomplete = 0x01, + Finalized = 0x02, + Others = 0x03 + } + + public enum BGFormatStatusCodes : byte + { + NoFormattable = 0x00, + IncompleteBackgroundFormat = 0x01, + BackgroundFormatInProgress = 0x02, + FormatComplete = 0x03 + } + + public enum DiscTypeCodes : byte + { + /// + /// Also valid for CD-DA, DVD and BD + /// + CDROM = 0x00, + CDi = 0x10, + CDROMXA = 0x20, + Undefined = 0xFF + } + #endregion + + #region Public methods + public static AACSVolumeIdentifier? DecodeAACSVolumeIdentifier(byte[] AACSVIResponse) + { + if (AACSVIResponse == null) + return null; + + AACSVolumeIdentifier decoded = new AACSVolumeIdentifier(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.VolumeIdentifier = new byte[AACSVIResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSVIResponse, 0); + decoded.Reserved1 = AACSVIResponse[2]; + decoded.Reserved2 = AACSVIResponse[3]; + Array.Copy(AACSVIResponse, 4, decoded.VolumeIdentifier, 0, AACSVIResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSVolumeIdentifier(AACSVolumeIdentifier? AACSVIResponse) + { + if (AACSVIResponse == null) + return null; + + AACSVolumeIdentifier response = AACSVIResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (AACS Volume Identifier): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (AACS Volume Identifier): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + } + sb.AppendFormat("AACS Volume Identifier in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VolumeIdentifier, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSVolumeIdentifier(byte[] AACSVIResponse) + { + AACSVolumeIdentifier? decoded = DecodeAACSVolumeIdentifier(AACSVIResponse); + return PrettifyAACSVolumeIdentifier(decoded); + } + + public static AACSMediaSerialNumber? DecodeAACSMediaSerialNumber(byte[] AACSMSNResponse) + { + if (AACSMSNResponse == null) + return null; + + AACSMediaSerialNumber decoded = new AACSMediaSerialNumber(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.MediaSerialNumber = new byte[AACSMSNResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSMSNResponse, 0); + decoded.Reserved1 = AACSMSNResponse[2]; + decoded.Reserved2 = AACSMSNResponse[3]; + Array.Copy(AACSMSNResponse, 4, decoded.MediaSerialNumber, 0, AACSMSNResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSMediaSerialNumber(AACSMediaSerialNumber? AACSMSNResponse) + { + if (AACSMSNResponse == null) + return null; + + AACSMediaSerialNumber response = AACSMSNResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (AACS Media Serial Number): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (AACS Media Serial Number): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + } + sb.AppendFormat("AACS Media Serial Number in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaSerialNumber, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSMediaSerialNumber(byte[] AACSMSNResponse) + { + AACSMediaSerialNumber? decoded = DecodeAACSMediaSerialNumber(AACSMSNResponse); + return PrettifyAACSMediaSerialNumber(decoded); + } + + public static AACSMediaIdentifier? DecodeAACSMediaIdentifier(byte[] AACSMIResponse) + { + if (AACSMIResponse == null) + return null; + + AACSMediaIdentifier decoded = new AACSMediaIdentifier(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.MediaIdentifier = new byte[AACSMIResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSMIResponse, 0); + decoded.Reserved1 = AACSMIResponse[2]; + decoded.Reserved2 = AACSMIResponse[3]; + Array.Copy(AACSMIResponse, 4, decoded.MediaIdentifier, 0, AACSMIResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSMediaIdentifier(AACSMediaIdentifier? AACSMIResponse) + { + if (AACSMIResponse == null) + return null; + + AACSMediaIdentifier response = AACSMIResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (AACS Media Identifier): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (AACS Media Identifier): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + } + sb.AppendFormat("AACS Media Identifier in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaIdentifier, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSMediaIdentifier(byte[] AACSMIResponse) + { + AACSMediaIdentifier? decoded = DecodeAACSMediaIdentifier(AACSMIResponse); + return PrettifyAACSMediaIdentifier(decoded); + } + + public static AACSMediaKeyBlock? DecodeAACSMediaKeyBlock(byte[] AACSMKBResponse) + { + if (AACSMKBResponse == null) + return null; + + AACSMediaKeyBlock decoded = new AACSMediaKeyBlock(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.MediaKeyBlockPacks = new byte[AACSMKBResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSMKBResponse, 0); + decoded.Reserved = AACSMKBResponse[2]; + decoded.TotalPacks = AACSMKBResponse[3]; + Array.Copy(AACSMKBResponse, 4, decoded.MediaKeyBlockPacks, 0, AACSMKBResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSMediaKeyBlock(AACSMediaKeyBlock? AACSMKBResponse) + { + if (AACSMKBResponse == null) + return null; + + AACSMediaKeyBlock response = AACSMKBResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (AACS Media Key Block): Reserved = 0x{0:X2}", response.Reserved).AppendLine(); + } + sb.AppendFormat("Total number of media key blocks available to transfer {0}", response.TotalPacks).AppendLine(); + sb.AppendFormat("AACS Media Key Blocks in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaKeyBlockPacks, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSMediaKeyBlock(byte[] AACSMKBResponse) + { + AACSMediaKeyBlock? decoded = DecodeAACSMediaKeyBlock(AACSMKBResponse); + return PrettifyAACSMediaKeyBlock(decoded); + } + + public static AACSDataKeys? DecodeAACSDataKeys(byte[] AACSDKResponse) + { + if (AACSDKResponse == null) + return null; + + AACSDataKeys decoded = new AACSDataKeys(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataKeys = new byte[AACSDKResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSDKResponse, 0); + decoded.Reserved1 = AACSDKResponse[2]; + decoded.Reserved2 = AACSDKResponse[3]; + Array.Copy(AACSDKResponse, 4, decoded.DataKeys, 0, AACSDKResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSDataKeys(AACSDataKeys? AACSDKResponse) + { + if (AACSDKResponse == null) + return null; + + AACSDataKeys response = AACSDKResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (AACS Data Keys): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (AACS Data Keys): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + } + sb.AppendFormat("AACS Data Keys in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DataKeys, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSDataKeys(byte[] AACSDKResponse) + { + AACSDataKeys? decoded = DecodeAACSDataKeys(AACSDKResponse); + return PrettifyAACSDataKeys(decoded); + } + + public static AACSLBAExtentsResponse? DecodeAACSLBAExtents(byte[] AACSLBAExtsResponse) + { + if (AACSLBAExtsResponse == null) + return null; + + AACSLBAExtentsResponse decoded = new AACSLBAExtentsResponse(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSLBAExtsResponse, 0); + decoded.Reserved = AACSLBAExtsResponse[2]; + decoded.MaxLBAExtents = AACSLBAExtsResponse[3]; + + if ((AACSLBAExtsResponse.Length - 4) % 16 != 0) + return decoded; + + decoded.Extents = new AACSLBAExtent[(AACSLBAExtsResponse.Length - 4) / 16]; + + for (int i = 0; i < (AACSLBAExtsResponse.Length - 4) / 16; i++) + { + decoded.Extents[i].Reserved = new byte[8]; + Array.Copy(AACSLBAExtsResponse, 0 + i * 16 + 4, decoded.Extents[i].Reserved, 0, 8); + decoded.Extents[i].StartLBA = BigEndianBitConverter.ToUInt32(AACSLBAExtsResponse, 8 + i * 16 + 4); + decoded.Extents[i].LBACount = BigEndianBitConverter.ToUInt32(AACSLBAExtsResponse, 12 + i * 16 + 4); + } + + return decoded; + } + + public static string PrettifyAACSLBAExtents(AACSLBAExtentsResponse? AACSLBAExtsResponse) + { + if (AACSLBAExtsResponse == null) + return null; + + AACSLBAExtentsResponse response = AACSLBAExtsResponse.Value; + + StringBuilder sb = new StringBuilder(); + + if (response.MaxLBAExtents == 0) + { + if (response.DataLength > 2) + sb.AppendLine("Drive can store 256 LBA Extents"); + else + sb.AppendLine("Drive cannot store LBA Extents"); + } + else + sb.AppendFormat("Drive can store {0} LBA Extents", response.MaxLBAExtents).AppendLine(); + + for (int i = 0; i < response.Extents.Length; i++) + sb.AppendFormat("LBA Extent {0} starts at LBA {1} and goes for {2} sectors", i, response.Extents[i].StartLBA, response.Extents[i].LBACount); + + return sb.ToString(); + } + + public static string PrettifyAACSLBAExtents(byte[] AACSLBAExtsResponse) + { + AACSLBAExtentsResponse? decoded = DecodeAACSLBAExtents(AACSLBAExtsResponse); + return PrettifyAACSLBAExtents(decoded); + } + + public static CPRMMediaKeyBlock? DecodeCPRMMediaKeyBlock(byte[] CPRMMKBResponse) + { + if (CPRMMKBResponse == null) + return null; + + CPRMMediaKeyBlock decoded = new CPRMMediaKeyBlock(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.MKBPackData = new byte[CPRMMKBResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CPRMMKBResponse, 0); + decoded.Reserved = CPRMMKBResponse[2]; + decoded.TotalPacks = CPRMMKBResponse[3]; + Array.Copy(CPRMMKBResponse, 4, decoded.MKBPackData, 0, CPRMMKBResponse.Length - 4); + + return decoded; + } + + public static string PrettifyCPRMMediaKeyBlock(CPRMMediaKeyBlock? CPRMMKBResponse) + { + if (CPRMMKBResponse == null) + return null; + + CPRMMediaKeyBlock response = CPRMMKBResponse.Value; + + StringBuilder sb = new StringBuilder(); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (CPRM Media Key Block): Reserved1 = 0x{0:X2}", response.Reserved).AppendLine(); + } + sb.AppendFormat("Total number of CPRM Media Key Blocks available to transfer: {0}", response.TotalPacks).AppendLine(); + sb.AppendFormat("CPRM Media Key Blocks in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MKBPackData, 80)); + + return sb.ToString(); + } + + public static string PrettifyCPRMMediaKeyBlock(byte[] CPRMMKBResponse) + { + CPRMMediaKeyBlock? decoded = DecodeCPRMMediaKeyBlock(CPRMMKBResponse); + return PrettifyCPRMMediaKeyBlock(decoded); + } + + public static RecognizedFormatLayers? DecodeFormatLayers(byte[] FormatLayersResponse) + { + if (FormatLayersResponse == null) + return null; + + if (FormatLayersResponse.Length < 8) + return null; + + RecognizedFormatLayers decoded = new RecognizedFormatLayers(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(FormatLayersResponse, 0); + decoded.Reserved1 = FormatLayersResponse[2]; + decoded.Reserved2 = FormatLayersResponse[3]; + decoded.NumberOfLayers = FormatLayersResponse[4]; + decoded.Reserved3 = (byte)((FormatLayersResponse[5] & 0xC0) >> 6); + decoded.DefaultFormatLayer = (byte)((FormatLayersResponse[5] & 0x30) >> 4); + decoded.Reserved4 = (byte)((FormatLayersResponse[5] & 0x0C) >> 2); + decoded.OnlineFormatLayer = (byte)(FormatLayersResponse[5] & 0x03); + + decoded.FormatLayers = new UInt16[(FormatLayersResponse.Length - 6) / 2]; + + for (int i = 0; i < (FormatLayersResponse.Length - 6) / 2; i++) + { + decoded.FormatLayers[i] = BigEndianBitConverter.ToUInt16(FormatLayersResponse, i * 2 + 6); + } + + return decoded; + } + + public static string PrettifyFormatLayers(RecognizedFormatLayers? FormatLayersResponse) + { + if (FormatLayersResponse == null) + return null; + + RecognizedFormatLayers response = FormatLayersResponse.Value; + + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat("{0} format layers recognized", response.NumberOfLayers); + + for (int i = 0; i < response.FormatLayers.Length; i++) + { + switch (response.FormatLayers[i]) + { + case (UInt16)FormatLayerTypeCodes.BDLayer: + { + sb.AppendFormat("Layer {0} is of type Blu-ray", i).AppendLine(); + if (response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + if (response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; + } + case (UInt16)FormatLayerTypeCodes.CDLayer: + { + sb.AppendFormat("Layer {0} is of type CD", i).AppendLine(); + if (response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + if (response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; + } + case (UInt16)FormatLayerTypeCodes.DVDLayer: + { + sb.AppendFormat("Layer {0} is of type DVD", i).AppendLine(); + if (response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + if (response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; + } + case (UInt16)FormatLayerTypeCodes.HDDVDLayer: + { + sb.AppendFormat("Layer {0} is of type HD DVD", i).AppendLine(); + if (response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + if (response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; + } + default: + { + sb.AppendFormat("Layer {0} is of unknown type 0x{1:X4}", i, response.FormatLayers[i]).AppendLine(); + if (response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + if (response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; + } + } + } + + return sb.ToString(); + } + + public static string PrettifyFormatLayers(byte[] FormatLayersResponse) + { + RecognizedFormatLayers? decoded = DecodeFormatLayers(FormatLayersResponse); + return PrettifyFormatLayers(decoded); + } + + public static WriteProtectionStatus? DecodeWriteProtectionStatus(byte[] WPSResponse) + { + if (WPSResponse == null) + return null; + + WriteProtectionStatus decoded = new WriteProtectionStatus(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(WPSResponse, 0); + decoded.Reserved1 = WPSResponse[2]; + decoded.Reserved2 = WPSResponse[3]; + decoded.Reserved3 = (byte)((WPSResponse[4] & 0xF0) >> 4); + decoded.MSWI = Convert.ToBoolean(WPSResponse[4] & 0x08); + decoded.CWP = Convert.ToBoolean(WPSResponse[4] & 0x04); + decoded.PWP = Convert.ToBoolean(WPSResponse[4] & 0x02); + decoded.SWPP = Convert.ToBoolean(WPSResponse[4] & 0x01); + decoded.Reserved4 = WPSResponse[5]; + decoded.Reserved5 = WPSResponse[6]; + decoded.Reserved6 = WPSResponse[7]; + + return decoded; + } + + public static string PrettifyWriteProtectionStatus(WriteProtectionStatus? WPSResponse) + { + if (WPSResponse == null) + return null; + + WriteProtectionStatus response = WPSResponse.Value; + + StringBuilder sb = new StringBuilder(); + + if (response.MSWI) + sb.AppendLine("Writing inhibited by media specific reason"); + if (response.CWP) + sb.AppendLine("Cartridge sets write protection"); + if (response.PWP) + sb.AppendLine("Media surface sets write protection"); + if (response.SWPP) + sb.AppendLine("Software write protection is set until power down"); + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (Write Protection Status): Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (Write Protection Status): Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + sb.AppendFormat("DEBUG (Write Protection Status): Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); + sb.AppendFormat("DEBUG (Write Protection Status): Reserved4 = 0x{0:X2}", response.Reserved4).AppendLine(); + sb.AppendFormat("DEBUG (Write Protection Status): Reserved5 = 0x{0:X2}", response.Reserved5).AppendLine(); + sb.AppendFormat("DEBUG (Write Protection Status): Reserved6 = 0x{0:X2}", response.Reserved6).AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyWriteProtectionStatus(byte[] WPSResponse) + { + WriteProtectionStatus? decoded = DecodeWriteProtectionStatus(WPSResponse); + return PrettifyWriteProtectionStatus(decoded); + } + #endregion Public methods + + #region Public structures + public struct AACSVolumeIdentifier + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// AACS volume identifier data + /// + public byte[] VolumeIdentifier; + } + + public struct AACSMediaSerialNumber + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// AACS media serial number + /// + public byte[] MediaSerialNumber; + } + + public struct AACSMediaIdentifier + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// AACS media identifier data + /// + public byte[] MediaIdentifier; + } + + public struct AACSMediaKeyBlock + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved; + /// + /// Byte 3 + /// Number of MKB packs available to transfer + /// + public byte TotalPacks; + /// + /// Bytes 4 to end + /// AACS media key block packs + /// + public byte[] MediaKeyBlockPacks; + } + + public struct AACSDataKeys + { + /// + /// Bytes 0 to 1 + /// Data length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to end + /// AACS data keys + /// + public byte[] DataKeys; + } + + public struct AACSLBAExtentsResponse + { + /// + /// Bytes 0 to 1 + /// Data Length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved; + /// + /// Byte 3 + /// Number of LBA extents the drive can store. + /// if(MaxLBAExtents == 0 && DataLength > 2), 256 extents can be stored + /// + public byte MaxLBAExtents; + /// + /// Bytes 4 to end + /// LBA Extents + /// + public AACSLBAExtent[] Extents; + } + + public struct AACSLBAExtent + { + /// + /// Bytes 0 to 7 + /// Reserved + /// + public byte[] Reserved; + /// + /// Bytes 8 to 11 + /// Start LBA of extent + /// + public UInt32 StartLBA; + /// + /// Bytes 12 to 15 + /// Extent length + /// + public UInt32 LBACount; + } + + public struct CPRMMediaKeyBlock + { + /// + /// Bytes 0 to 1 + /// Data Length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved; + /// + /// Byte 3 + /// Number of MKB packs available to transfer + /// + public byte TotalPacks; + /// + /// Byte 4 + /// MKB Packs + /// + public byte[] MKBPackData; + } + + public struct RecognizedFormatLayers + { + /// + /// Bytes 0 to 1 + /// Data Length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4 + /// Number of format layers in hybrid disc identified by drive + /// + public byte NumberOfLayers; + /// + /// Byte 5, bits 7 to 6 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 5, bits 5 to 4 + /// Layer no. used when disc is inserted + /// + public byte DefaultFormatLayer; + /// + /// Byte 5, bits 3 to 2 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 5, bits 1 to 0 + /// Layer no. currently in use + /// + public byte OnlineFormatLayer; + /// + /// Bytes 6 to end + /// Recognized format layers + /// + public UInt16[] FormatLayers; + } + + public struct WriteProtectionStatus + { + /// + /// Bytes 0 to 1 + /// Data Length + /// + public UInt16 DataLength; + /// + /// Byte 2 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Byte 4, bits 7 to 4 + /// Reserved + /// + public byte Reserved3; + /// + /// Byte 4, bit 3 + /// Writing inhibited by media specific reason + /// + public bool MSWI; + /// + /// Byte 4, bit 2 + /// Cartridge sets write protection + /// + public bool CWP; + /// + /// Byte 4, bit 1 + /// Media surface sets write protection + /// + public bool PWP; + /// + /// Byte 4, bit 0 + /// Software write protection until power down + /// + public bool SWPP; + /// + /// Byte 5 + /// Reserved + /// + public byte Reserved4; + /// + /// Byte 6 + /// Reserved + /// + public byte Reserved5; + /// + /// Byte 7 + /// Reserved + /// + public byte Reserved6; + } + + public struct DiscInformation + { + /// + /// Bytes 0 to 1 + /// 32 + OPCTablesNumber*8 + /// + public UInt16 DataLength; + /// + /// Byte 2, bits 7 to 5 + /// 000b + /// + public byte DataType; + /// + /// Byte 2, bit 4 + /// If set, disc is erasable + /// + public bool Erasable; + /// + /// Byte 2, bits 3 to 2 + /// Status of last session + /// + public byte LastSessionStatus; + /// + /// Byte 2, bits 1 to 0 + /// Status of disc + /// + public byte DiscStatus; + /// + /// Byte 3 + /// Number of logical track that contains LBA 0 + /// + public byte FirstTrackNumber; + /// + /// Byte 9 (MSB) and byte 4 (LSB) + /// Number of sessions + /// + public byte Sessions; + /// + /// Byte 10 (MSB) and byte 5 (LSB) + /// Number of first track in last session + /// + public byte FirstTrackLastSession; + /// + /// Byte 11 (MSB) and byte 6 (LSB) + /// Number of last track in last session + /// + public byte LastTrackLastSession; + /// + /// Byte 7, bit 7 + /// If set, DiscIdentification is valid + /// + public bool DID_V; + /// + /// Byte 7, bit 6 + /// If set, DiscBarcode is valid + /// + public bool DBC_V; + /// + /// Byte 7, bit 5 + /// If set, disc is unrestricted + /// + public bool URU; + /// + /// Byte 7, bit 4 + /// If set DiscApplicationCode is valid + /// + public bool DAC_V; + /// + /// Byte 7, bit 3 + /// Reserved + /// + public bool Reserved; + /// + /// Byte 7, bit 2 + /// Copy of dirty bit from MRW status + /// + public bool Dbit; + /// + /// Byte 7, bits 1 to 0 + /// Background format status + /// + public byte BGFormatStatus; + /// + /// Byte 8 + /// Disc type code + /// + public byte DiscType; + /// + /// Bytes 12 to 15 + /// Disc identification number from PMA + /// + public UInt32 DiscIdentification; + /// + /// Bytes 16 to 19 + /// Last Session Lead-in Start Address (MSF for CD, LBA for others) + /// + public UInt32 LastSessionLeadInStartLBA; + /// + /// Bytes 20 to 23 + /// Last Possible Lead-out Start Address (MSF for CD, LBA for others) + /// + public UInt32 LastPossibleLeadOutStartLBA; + /// + /// Bytes 24 to 31 + /// Disc barcode + /// + public UInt64 DiscBarcode; + /// + /// Byte 32 + /// Disc application code + /// + public byte DiscApplicationCode; + /// + /// Byte 33 + /// How many OPC tables are + /// + public byte OPCTablesNumber; + /// + /// Bytes 34 to end + /// OPC tables (8 bytes each) + /// + public OPCTable[] OPCTables; + } + + public struct OPCTable + { + /// + /// Bytes 0 to 1 + /// kilobytes/sec this OPC table applies to + /// + public UInt16 Speed; + /// + /// Bytes 2 to 7 + /// OPC values + /// + public byte[] OPCValues; + } + + public struct TrackInformation + { + /// + /// Bytes 0 to 1 + /// Data length, always 10 + /// + public UInt16 DataLength; + /// + /// Byte 2, bits 7 to 5 + /// 001b + /// + public byte DataType; + /// + /// Byte 2, bits 4 to 0 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 5 + /// Maximum possible number of tracks on the disc + /// + public UInt16 MaxTracks; + /// + /// Bytes 6 to 7 + /// Number of assigned tracks on the disc + /// + public UInt16 AssignedTracks; + /// + /// Bytes 8 to 9 + /// Maximum possible number of appendable tracks on the disc + /// + public UInt16 MaxAppendable; + /// + /// Bytes 10 to 11 + /// Current number of appendable tracks on the disc + /// + public UInt16 CurrentAppendable; + } + + public struct OPWInformation + { + /// + /// Bytes 0 to 1 + /// Data length, always 14 + /// + public UInt16 DataLength; + /// + /// Byte 2, bits 7 to 5 + /// 010b + /// + public byte DataType; + /// + /// Byte 2, bits 4 to 0 + /// Reserved + /// + public byte Reserved1; + /// + /// Byte 3 + /// Reserved + /// + public byte Reserved2; + /// + /// Bytes 4 to 5 + /// Remaining POW Replacements + /// + public UInt32 RemainingReplacements; + /// + /// Bytes 6 to 7 + /// Remaining POW Reallocation Map Entries + /// + public UInt32 RemainingReallocationEntries; + /// + /// Bytes 8 to 9 + /// Number of Remaining POW Updates + /// + public UInt32 RemainingUpdates; + } + #endregion Public structures + } +} + diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4dbc185 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("DiscImageChef.Decoders")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Claunia.com")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("© Claunia.com")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/SCSI.cs b/SCSI.cs new file mode 100644 index 0000000..a331baa --- /dev/null +++ b/SCSI.cs @@ -0,0 +1,4582 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : SCSI.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Decoders. + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Decodes SCSI structures. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Text; + +namespace DiscImageChef.Decoders +{ + /// + /// Information from the following standards: + /// T10/995-D revision 10 + /// T10/1236-D revision 20 + /// T10/1416-D revision 23 + /// + public static class SCSI + { + #region Enumerations + + enum SCSIPeripheralQualifiers : byte + { + /// + /// Peripheral qualifier: Device is connected and supported + /// + SCSIPQSupported = 0x00, + /// + /// Peripheral qualifier: Device is supported but not connected + /// + SCSIPQUnconnected = 0x01, + /// + /// Peripheral qualifier: Reserved value + /// + SCSIPQReserved = 0x02, + /// + /// Peripheral qualifier: Device is connected but unsupported + /// + SCSIPQUnsupported = 0x03, + /// + /// Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07 + /// + SCSIPQVendorMask = 0x04 + } + + enum SCSIPeripheralDeviceTypes : byte + { + /// + /// Direct-access device + /// + SCSIPDTDirectAccess = 0x00, + /// + /// Sequential-access device + /// + SCSIPDTSequentialAccess = 0x01, + /// + /// Printer device + /// + SCSIPDTPrinterDevice = 0x02, + /// + /// Processor device + /// + SCSIPDTProcessorDevice = 0x03, + /// + /// Write-once device + /// + SCSIPDTWriteOnceDevice = 0x04, + /// + /// CD-ROM/DVD/etc device + /// + SCSIPDTMultiMediaDevice = 0x05, + /// + /// Scanner device + /// + SCSIPDTScannerDevice = 0x06, + /// + /// Optical memory device + /// + SCSIPDTOpticalDevice = 0x07, + /// + /// Medium change device + /// + SCSIPDTMediumChangerDevice = 0x08, + /// + /// Communications device + /// + SCSIPDTCommsDevice = 0x09, + /// + /// Graphics arts pre-press device (defined in ASC IT8) + /// + SCSIPDTPrePressDevice1 = 0x0A, + /// + /// Graphics arts pre-press device (defined in ASC IT8) + /// + SCSIPDTPrePressDevice2 = 0x0B, + /// + /// Array controller device + /// + SCSIPDTArrayControllerDevice = 0x0C, + /// + /// Enclosure services device + /// + SCSIPDTEnclosureServiceDevice = 0x0D, + /// + /// Simplified direct-access device + /// + SCSIPDTSimplifiedDevice = 0x0E, + /// + /// Optical card reader/writer device + /// + SCSIPDTOCRWDevice = 0x0F, + /// + /// Bridging Expanders + /// + SCSIPDTBridgingExpander = 0x10, + /// + /// Object-based Storage Device + /// + SCSIPDTObjectDevice = 0x11, + /// + /// Automation/Drive Interface + /// + SCSIPDTADCDevice = 0x12, + /// + /// Well known logical unit + /// + SCSIPDTWellKnownDevice = 0x1E, + /// + /// Unknown or no device type + /// + SCSIPDTUnknownDevice = 0x1F + } + + enum SCSIANSIVersions : byte + { + /// + /// Device does not claim conformance to any ANSI version + /// + SCSIANSINoVersion = 0x00, + /// + /// Device complies with an obsolete ANSI standard + /// + SCSIANSIObsolete = 0x01, + /// + /// Device complies with ANSI X3.131:1994 + /// + SCSIANSI1994Version = 0x02, + /// + /// Device complies with ANSI X3.301:1997 + /// + SCSIANSI1997Version = 0x03, + /// + /// Device complies with ANSI X3.351:2001 + /// + SCSIANSI2001Version = 0x04, + /// + /// Device complies with SPC3, T10, 2005. + /// + SCSIANSI2005Version = 0x05 + } + + enum SCSIECMAVersions : byte + { + /// + /// Device does not claim conformance to any ECMA version + /// + SCSIECMANoVersion = 0x00, + /// + /// Device complies with an obsolete ECMA standard + /// + SCSIECMAObsolete = 0x01 + } + + enum SCSIISOVersions : byte + { + /// + /// Device does not claim conformance to any ISO/IEC version + /// + SCSIISONoVersion = 0x00, + /// + /// Device complies with ISO/IEC 9316:1995 + /// + SCSIISO1995Version = 0x02 + } + + enum SCSISPIClocking : byte + { + /// + /// Supports only ST + /// + SCSIClockingST = 0x00, + /// + /// Supports only DT + /// + SCSIClockingDT = 0x01, + /// + /// Reserved value + /// + SCSIClockingReserved = 0x02, + /// + /// Supports ST and DT + /// + SCSIClockingSTandDT = 0x03, + } + + enum SCSIVersionDescriptorStandardMask : ushort + { + NoStandard = 0x0000, + SAM = 0x0020, + SAM2 = 0x0040, + SAM3 = 0x0060, + SAM4 = 0x0080, + SPC = 0x0120, + MMC = 0x0140, + SCC = 0x0160, + SBC = 0x0180, + SMC = 0x01A0, + SES = 0x01C0, + SCC2 = 0x01E0, + SSC = 0x0200, + RBC = 0x0220, + MMC2 = 0x0240, + SPC2 = 0x0260, + OCRW = 0x0280, + MMC3 = 0x02A0, + RMC = 0x02C0, + SMC2 = 0x02E0, + SPC3 = 0x0300, + SBC2 = 0x0320, + OSD = 0x0340, + SSC2 = 0x0360, + BCC = 0x0380, + MMC4 = 0x03A0, + ADC = 0x03C0, + SES2 = 0x03E0, + SSC3 = 0x0400, + MMC5 = 0x0420, + OSD2 = 0x0440, + SPC4 = 0x0460, + SMC3 = 0x0480, + ADC2 = 0x04A0, + SSA_TL2 = 0x0820, + SSA_TL1 = 0x0840, + SSA_S3P = 0x0860, + SSA_S2P = 0x0880, + SIP = 0x08A0, + FCP = 0x08C0, + SBP2 = 0x08E0, + FCP2 = 0x0900, + SST = 0x0920, + SRP = 0x0940, + iSCSI = 0x0960, + SBP3 = 0x0980, + ADP = 0x09C0, + ADT = 0x09E0, + FCP3 = 0x0A00, + ADT2 = 0x0A20, + SPI = 0x0AA0, + Fast20 = 0xAC0, + SPI2 = 0x0AE0, + SPI3 = 0x0B00, + EPI = 0x0B20, + SPI4 = 0x0B40, + SPI5 = 0x0B60, + SAS = 0x0BE0, + SAS11 = 0x0C00, + FC_PH = 0x0D20, + FC_AL = 0x0D40, + FC_AL2 = 0x0D60, + FC_PH3 = 0x0D80, + FC_FS = 0x0DA0, + FC_PI = 0x0DC0, + FC_PI2 = 0x0DE0, + FC_FS2 = 0x0E00, + FC_LS = 0x0E20, + FC_SP = 0x0E40, + FC_DA = 0x12E0, + FC_Tape = 0x1300, + FC_FLA = 0x1320, + FC_PLDA = 0x1340, + SSA_PH2 = 0x1360, + SSA_PH3 = 0x1380, + IEEE1394 = 0x14A0, + IEEE1394a = 0x14C0, + IEEE1394b = 0x14E0, + ATA_ATAPI6 = 0x15E0, + ATA_ATAPI7 = 0x1600, + ATA_ATAPI8 = 0x1620, + USB = 0x1720, + SAT = 0x1EA0 + } + + enum SCSIVersionDescriptorSAMMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0994 revision 18 + /// + T10_0994_r18 = 0x001B, + /// + /// ANSI X3.270:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorSAM2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1157-D revision 23 + /// + T10_1157_r23 = 0x0014, + /// + /// T10/1157-D revision 24 + /// + T10_1157_r24 = 0x0015, + /// + /// ANSI INCITS 366-2003 + /// + ANSI_2003 = 0x001C + } + + enum SCSIVersionDescriptorSAM3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1561-D revision 7 + /// + T10_1561_r07 = 0x0002, + /// + /// T10/1561-D revision 13 + /// + T10_1561_r13 = 0x0015, + /// + /// T10/1157-D revision 14 + /// + T10_1561_r14 = 0x0016, + /// + /// ANSI INCITS 402-2005 + /// + ANSI_2005 = 0x0017 + } + + enum SCSIVersionDescriptorSPCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0995 revision 11a + /// + T10_0995_r11a = 0x001B, + /// + /// ANSI X3.301:1997 + /// + ANSI_1997 = 0x001C + } + + enum SCSIVersionDescriptorMMCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1048 revision 10a + /// + T10_1048_r10a = 0x001B, + /// + /// ANSI X3.304:1997 + /// + ANSI_1997 = 0x001C + } + + enum SCSIVersionDescriptorSCCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1047 revision 06c + /// + T10_1048_r06c = 0x001B, + /// + /// ANSI X3.276:1997 + /// + ANSI_1997 = 0x001C + } + + enum SCSIVersionDescriptorSBCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0996 revision 08c + /// + T10_0996_r08c = 0x001B, + /// + /// ANSI NCITS.306:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorSMCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0999 revision 10a + /// + T10_0999_r10a = 0x001B, + /// + /// ANSI NCITS.314:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorSESMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1212 revision 08b + /// + T10_1212_r08b = 0x001B, + /// + /// ANSI NCITS.305:1998 + /// + ANSI_1998 = 0x001C, + /// + /// T10/1212 revision 08b with ANSI NCITS.305/AM1:2000 + /// + T10_1212_r08b_2000 = 0x001D, + /// + /// ANSI NCITS.305:1998 with ANSI NCITS.305/AM1:2000 + /// + ANSI_1998_2000 = 0x001E + } + + enum SCSIVersionDescriptorSCC2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1125 revision 04 + /// + T10_1125_r04 = 0x001B, + /// + /// ANSI NCITS.318:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorSSCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0997 revision 17 + /// + T10_0997_r17 = 0x0001, + /// + /// T10/0997 revision 22 + /// + T10_0997_r22 = 0x0007, + /// + /// ANSI NCITS.335:2000 + /// + ANSI_2000 = 0x001C + } + + enum SCSIVersionDescriptorRBCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1240 revision 10a + /// + T10_1240_r10a = 0x0018, + /// + /// ANSI NCITS.330:2000 + /// + ANSI_2000 = 0x001C + } + + enum SCSIVersionDescriptorMMC2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1228 revision 11 + /// + T10_1228_r11 = 0x0015, + /// + /// T10/1228 revision 11a + /// + T10_1228_r11a = 0x001B, + /// + /// ANSI NCITS.333:2000 + /// + ANSI_2000 = 0x001C + } + + enum SCSIVersionDescriptorSPC2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1236 revision 12 + /// + T10_1236_r12 = 0x0007, + /// + /// T10/1236 revision 18 + /// + T10_1236_r18 = 0x0009, + /// + /// T10/1236 revision 19 + /// + T10_1236_r19 = 0x0015, + /// + /// T10/1236 revision 20 + /// + T10_1236_r20 = 0x0016, + /// + /// ANSI INCITS 351-2001 + /// + ANSI_2001 = 0x0017, + } + + enum SCSIVersionDescriptorOCRWMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ISO/IEC 14776-381 + /// + ISO14776_381 = 0x001E + } + + enum SCSIVersionDescriptorMMC3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1363-D revision 9 + /// + T10_1363_r09 = 0x0015, + /// + /// T10/1363-D revision 10g + /// + T10_1363_r10g = 0x0016, + /// + /// ANSI INCITS 360-2002 + /// + ANSI_2001 = 0x0018 + } + + enum SCSIVersionDescriptorSMC2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1383-D revision 5 + /// + T10_1383_r05 = 0x0015, + /// + /// T10/1383-D revision 6 + /// + T10_1383_r06 = 0x001C, + /// + /// T10/1363-D revision 7 + /// + T10_1383_r07 = 0x001D, + /// + /// ANSI INCITS 382-2004 + /// + ANSI_2004 = 0x001E + } + + enum SCSIVersionDescriptorSPC3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1416-D revision 7 + /// + T10_1416_r07 = 0x0001, + /// + /// T10/1416-D revision 21 + /// + T10_1416_r21 = 0x0007, + /// + /// T10/1416-D revision 22 + /// + T10_1416_r22 = 0x000F + } + + enum SCSIVersionDescriptorSBC2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1383 revision 5 + /// + T10_1383_r05 = 0x0002, + /// + /// T10/1383 revision 6 + /// + T10_1383_r06 = 0x0004, + /// + /// T10/1383 revision 7 + /// + T10_1383_r07 = 0x001B, + /// + /// ANSI INCITS 405-2005 + /// + ANSI_2005 = 0x001D + } + + enum SCSIVersionDescriptorOSDMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1355 revision 0 + /// + T10_1355_r0 = 0x0001, + /// + /// T10/1355 revision 7a + /// + T10_1355_r7a = 0x0002, + /// + /// T10/1355 revision 8 + /// + T10_1355_r8 = 0x0003, + /// + /// T10/1355 revision 9 + /// + T10_1355_r9 = 0x0004, + /// + /// T10/1355 revision 10 + /// + T10_1355_r10 = 0x0015, + /// + /// ANSI INCITS 400-2004 + /// + ANSI_2004 = 0x0016 + } + + enum SCSIVersionDescriptorSSC2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1434-D revision 7 + /// + T10_1434_r07 = 0x0014, + /// + /// T10/1434-D revision 9 + /// + T10_1434_r09 = 0x0015, + /// + /// ANSI INCITS 380-2003 + /// + ANSI_2003 = 0x001D + } + + enum SCSIVersionDescriptorMMC4Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1545-D revision 5 + /// + T10_1545_r5 = 0x0010, + /// + /// T10/1545-D revision 3 + /// + T10_1545_r3 = 0x001D, + /// + /// T10/1545-D revision 3d + /// + T10_1545_r3d = 0x001E, + /// + /// ANSI INCITS 401-2005 + /// + ANSI_2005 = 0x001F + } + + enum SCSIVersionDescriptorADCMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1558-D revision 6 + /// + T10_1558_r6 = 0x0015, + /// + /// T10/1558-D revision 7 + /// + T10_1558_r7 = 0x0016, + /// + /// ANSI INCITS 403-2005 + /// + ANSI_2005 = 0x0017 + } + + enum SCSIVersionDescriptorSSA_TL2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10.1/1147 revision 05b + /// + T10_1147_r05b = 0x001B, + /// + /// ANSI NCITS.308:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorSSA_TL1Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10.1/0989 revision 10b + /// + T10_0989_r10b = 0x001B, + /// + /// ANSI X3.295:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorSSA_S3PMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10.1/1051 revision 05b + /// + T10_1051_r05b = 0x001B, + /// + /// ANSI NCITS.309:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorSSA_S2PMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10.1/1121 revision 07b + /// + T10_1121_r07b = 0x001B, + /// + /// ANSI X3.294:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorSIPMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0856 revision 10 + /// + T10_0856_r10 = 0x001B, + /// + /// ANSI X3.292:1997 + /// + ANSI_1997 = 0x001C + } + + enum SCSIVersionDescriptorFCPMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0993 revision 12 + /// + T10_0993_r12 = 0x001B, + /// + /// ANSI X3.269:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorSBP2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1155 revision 04 + /// + T10_1155_r04 = 0x001B, + /// + /// ANSI NCITS.325:1999 + /// + ANSI_1999 = 0x001C + } + + enum SCSIVersionDescriptorFCP2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1144-D revision 4 + /// + T10_1144_r4 = 0x0001, + /// + /// T10/1144-D revision 7 + /// + T10_1144_r7 = 0x0015, + /// + /// T10/1144-D revision 7a + /// + T10_1144_r7a = 0x0016, + /// + /// ANSI INCITS 350-2003 + /// + ANSI_2003 = 0x0017, + /// + /// T10/1144-D revision 8 + /// + T10_1144_r8 = 0x0018 + } + + enum SCSIVersionDescriptorSSTMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1380-D revision 8b + /// + T10_1380_r8b = 0x0015 + } + + enum SCSIVersionDescriptorSRPMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1415-D revision 10 + /// + T10_1415_r10 = 0x0014, + /// + /// T10/1415-D revision 16a + /// + T10_1415_r16a = 0x0015, + /// + /// ANSI INCITS 365-2002 + /// + ANSI_2003 = 0x001C + } + + enum SCSIVersionDescriptorSBP3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1467-D revision 1f + /// + T10_1467_r1f = 0x0002, + /// + /// T10/1467-D revision 3 + /// + T10_1467_r3 = 0x0014, + /// + /// T10/1467-D revision 4 + /// + T10_1467_r4 = 0x001A, + /// + /// T10/1467-D revision 5 + /// + T10_1467_r5 = 0x001B, + /// + /// ANSI INCITS 375-2004 + /// + ANSI_2004 = 0x001C + } + + enum SCSIVersionDescriptorADTMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1557-D revision 11 + /// + T10_1557_r11 = 0x0019, + /// + /// T10/1557-D revision 14 + /// + T10_1557_r14 = 0x001A, + /// + /// ANSI INCITS 406-2005 + /// + ANSI_2005 = 0x001D + } + + enum SCSIVersionDescriptorFCP3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1560-D revision 4 + /// + T10_1560_r4 = 0x000F + } + + enum SCSIVersionDescriptorSPIMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/0855 revision 15a + /// + T10_0855_r15a = 0x0019, + /// + /// ANSI X3.253:1995 + /// + ANSI_1995 = 0x001A, + /// + /// T10/0855 revision 15a with SPI Amnd revision 3a + /// + T10_0855_r15a_Amnd_3a = 0x001B, + /// + /// ANSI X3.253:1995 with SPI Amnd ANSI X3.253/AM1:1998 + /// + ANSI_1995_1998 = 0x001C + } + + enum SCSIVersionDescriptorFast20Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1071 revision 06 + /// + T10_1071_r06 = 0x001B, + /// + /// ANSI X3.277:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorSPI2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1142 revision 20b + /// + T10_1142_r20b = 0x001B, + /// + /// ANSI X3.302:1999 + /// + ANSI_1999 = 0x001C + } + + enum SCSIVersionDescriptorSPI3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1302-D revision 10 + /// + T10_1302D_r10 = 0x0018, + /// + /// T10/1302-D revision 13a + /// + T10_1302D_r13a = 0x0019, + /// + /// T10/1302-D revision 14 + /// + T10_1302D_r14 = 0x001A, + /// + /// ANSI NCITS.336:2000 + /// + ANSI_2000 = 0x001C + } + + enum SCSIVersionDescriptorEPIMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1134 revision 16 + /// + T10_1134_r16 = 0x001B, + /// + /// ANSI NCITS TR-23:1999 + /// + ANSI_1999 = 0x001C + } + + enum SCSIVersionDescriptorSPI4Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1365-D revision 7 + /// + T10_1365_r7 = 0x0014, + /// + /// T10/1365-D revision 9 + /// + T10_1365_r9 = 0x0015, + /// + /// ANSI INCITS 362-2002 + /// + ANSI_2002 = 0x0016, + /// + /// T10/1365-D revision 10 + /// + T10_1365_r10 = 0x0019 + } + + enum SCSIVersionDescriptorSPI5Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1525-D revision 3 + /// + T10_1525_r3 = 0x0019, + /// + /// T10/1525-D revision 5 + /// + T10_1525_r5 = 0x001A, + /// + /// T10/1525-D revision 6 + /// + T10_1525_r6 = 0x001B, + /// + /// ANSI INCITS 367-2003 + /// + ANSI_2003 = 0x001C + } + + enum SCSIVersionDescriptorSASMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1562-D revision 01 + /// + T10_1562_r01 = 0x0001, + /// + /// T10/1562-D revision 03 + /// + T10_1562_r03 = 0x0015, + /// + /// T10/1562-D revision 04 + /// + T10_1562_r04 = 0x001A, + /// + /// T10/1562-D revision 04 + /// + T10_1562_r04bis = 0x001B, + /// + /// T10/1562-D revision 05 + /// + T10_1562_r05 = 0x001C, + /// + /// ANSI INCITS 376-2003 + /// + ANSI_2003 = 0x001D + } + + enum SCSIVersionDescriptorSAS11Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10/1601-D revision 9 + /// + T10_1601_r9 = 0x0007, + /// + /// T10/1601-D revision 10 + /// + T10_1601_r10 = 0x000F + } + + enum SCSIVersionDescriptorFCPHMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ANSI X3.230:1994 + /// + ANSI_1994 = 0x001B, + /// + /// ANSI X3.230:1994 with Amnd 1 ANSI X3.230/AM1:1996 + /// + ANSI_1994_1996 = 0x001C + } + + enum SCSIVersionDescriptorFCALMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ANSI X3.272:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorFCAL2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1133 revision 7.0 + /// + T11_1133_r70 = 0x0001, + /// + /// ANSI NCITS.332:1999 + /// + ANSI_1999 = 0x001C, + /// + /// ANSI INCITS 332-1999 with Amnd 1 AM1-2002 + /// + ANSI_1999_2002 = 0x001D + } + + enum SCSIVersionDescriptorFCPH3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ANSI X3.303-1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorFCFSMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1331 revision 1.2 + /// + T11_1331_r12 = 0x0017, + /// + /// T11/1331 revision 1.7 + /// + T11_1331_r17 = 0x0018, + /// + /// ANSI INCITS 373-2003 + /// + ANSI_2003 = 0x001C + } + + enum SCSIVersionDescriptorFCPIMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ANSI INCITS 352-2002 + /// + ANSI_2002 = 0x001C + } + + enum SCSIVersionDescriptorFCPI2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1506-D revision 5.0 + /// + T11_1506_r50 = 0x0002 + } + + enum SCSIVersionDescriptorFCSPMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1570-D revision 1.6 + /// + T11_1570_r16 = 0x0002 + } + + enum SCSIVersionDescriptorFCDAMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1513-DT revision 3.1 + /// + T11_1513_r31 = 0x0002 + } + + enum SCSIVersionDescriptorFCTapeMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1315 revision 1.16 + /// + T11_1315_r116 = 0x0001, + /// + /// T11/1315 revision 1.17 + /// + T11_1315_r117 = 0x001B, + /// + /// ANSI NCITS TR-24:1999 + /// + ANSI_1999 = 0x001C + } + + enum SCSIVersionDescriptorFCFLAMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1235 revision 7 + /// + T11_1235_r7 = 0x001B, + /// + /// ANSI NCITS TR-20:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorFCPLDAMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T11/1162 revision 2.1 + /// + T11_1162_r21 = 0x001B, + /// + /// ANSI NCITS TR-19:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorSSAPH2Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10.1/1145 revision 09c + /// + T10_1145_r09c = 0x001B, + /// + /// ANSI X3.293:1996 + /// + ANSI_1996 = 0x001C + } + + enum SCSIVersionDescriptorSSAPH3Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T10.1/1146 revision 05b + /// + T10_1146_r05b = 0x001B, + /// + /// ANSI NCITS.307:1998 + /// + ANSI_1998 = 0x001C + } + + enum SCSIVersionDescriptorIEEE1394Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ANSI IEEE 1394:1995 + /// + ANSI_1995 = 0x001D + } + + enum SCSIVersionDescriptorATA6Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// ANSI INCITS 361-2002 + /// + ANSI_2002 = 0x001D + } + + enum SCSIVersionDescriptorATA7Mask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// T13/1532-D revision 3 + /// + T13_1532_r3 = 0x0002, + /// + /// ANSI INCITS 397-2005 + /// + ANSI_2005 = 0x001C + } + + enum SCSIVersionDescriptorATA8Mask : ushort + { + /// + /// ATA8-AAM Architecture Model (no version claimed) + /// + ATA8_AAM = 0x0000, + /// + /// ATA8-PT Parallel Transport (no version claimed) + /// + ATA8_PT = 0x0001, + /// + /// ATA8-AST Serial Transport (no version claimed) + /// + ATA8_AST = 0x0002, + /// + /// ATA8-ACS ATA/ATAPI Command Set (no version claimed) + /// + ATA8_ACS = 0x0003 + } + + enum SCSIVersionDescriptorUSBMask : ushort + { + /// + /// No revision of the standard is claimed + /// + NoVersion = 0x0000, + /// + /// Universal Serial Bus Specification, Revision 1.1 + /// + USB11 = 0x0008, + /// + /// Universal Serial Bus Specification, Revision 2.0 + /// + USB20 = 0x0009, + /// + /// USB Mass Storage Class Bulk-Only Transport, Revision 1.0 + /// + USB_MSC_BULK = 0x0010 + } + + enum SCSITGPSValues : byte + { + /// + /// Assymetrical access not supported + /// + NotSupported = 0x00, + /// + /// Only implicit assymetrical access is supported + /// + OnlyImplicit = 0x01, + /// + /// Only explicit assymetrical access is supported + /// + OnlyExplicit = 0x02, + /// + /// Both implicit and explicit assymetrical access are supported + /// + Both = 0x03 + } + + #endregion Enumerations + + #region Private methods + + static string PrettifySCSIVendorString(string SCSIVendorString) + { + switch (SCSIVendorString) + { + case "3M": + return "3M Company"; + case "ACL": + return "Automated Cartridge Librarys, Inc."; + case "ADAPTEC": + return "Adaptec"; + case "ADSI": + return "Adaptive Data Systems, Inc. (a Western Digital subsidiary)"; + case "ADTX": + return "ADTX Co., Ltd."; + case "AERONICS": + return "Aeronics, Inc."; + case "AGFA": + return "AGFA"; + case "AMCODYNE": + return "Amcodyne"; + case "ANAMATIC": + return "Anamartic Limited (England)"; + case "ANCOT": + return "ANCOT Corp."; + case "ANRITSU": + return "Anritsu Corporation"; + case "APPLE": + return "Apple Computer, Inc."; + case "ARCHIVE": + return "Archive"; + case "ASACA": + return "ASACA Corp."; + case "ASPEN": + return "Aspen Peripherals"; + case "AST": + return "AST Research"; + case "ASTK": + return "Alcatel STK A/S"; + case "AT&T": + return "AT&T"; + case "ATARI": + return "Atari Corporation"; + case "ATG CYG": + return "ATG Cygnet Inc."; + case "ATTO": + return "ATTO Technology Inc."; + case "ATX": + return "Alphatronix"; + case "AVR": + return "Advanced Vision Research"; + case "BALLARD": + return "Ballard Synergy Corp."; + case "BERGSWD": + return "Berg Software Design"; + case "BEZIER": + return "Bezier Systems, Inc."; + case "BULL": + return "Bull Peripherals Corp."; + case "BUSLOGIC": + return "BusLogic Inc."; + case "BiT": + return "BiT Microsystems"; + case "BoxHill": + return "Box Hill Systems Corporation"; + case "CALIPER": + return "Caliper (California Peripheral Corp.)"; + case "CAST": + return "Advanced Storage Tech"; + case "CDC": + return "Control Data or MPI"; + case "CDP": + return "Columbia Data Products"; + case "CHEROKEE": + return "Cherokee Data Systems"; + case "CHINON": + return "Chinon"; + case "CIE&YED": + return "YE Data, C.Itoh Electric Corp."; + case "CIPHER": + return "Cipher Data Products"; + case "CIRRUSL": + return "Cirrus Logic Inc."; + case "CMD": + return "CMD Technology Inc."; + case "CNGR SFW": + return "Congruent Software, Inc."; + case "COGITO": + return "Cogito"; + case "COMPAQ": + return "Compaq Computer Corporation"; + case "COMPORT": + return "Comport Corp."; + case "COMPSIG": + return "Computer Signal Corporation"; + case "CONNER": + return "Conner Peripherals"; + case "CORE": + return "Core International, Inc."; + case "CPU TECH": + return "CPU Technology, Inc."; + case "CREO": + return "Creo Products Inc."; + case "CROSFLD": + return "Crosfield Electronics"; + case "CSM, INC": + return "Computer SM, Inc."; + case "CalComp": + return "CalComp, A Lockheed Company"; + case "Ciprico": + return "Ciprico, Inc."; + case "DATABOOK": + return "Databook, Inc."; + case "DATACOPY": + return "Datacopy Corp."; + case "DATAPT": + return "Datapoint Corp."; + case "DEC": + return "Digital Equipment"; + case "DELPHI": + return "Delphi Data Div. of Sparks Industries, Inc."; + case "DENON": + return "Denon/Nippon Columbia"; + case "DenOptix": + return "DenOptix, Inc."; + case "DEST": + return "DEST Corp."; + case "DGC": + return "Data General Corp."; + case "DIGIDATA": + return "Digi-Data Corporation"; + case "DILOG": + return "Distributed Logic Corp."; + case "DISC": + return "Document Imaging Systems Corp."; + case "DPT": + return "Distributed Processing Technology"; + case "DSI": + return "Data Spectrum, Inc."; + case "DSM": + return "Deterner Steuerungs- und Maschinenbau GmbH & Co."; + case "DTC QUME": + return "Data Technology Qume"; + case "DXIMAGIN": + return "DX Imaging"; + case "Digital": + return "Digital Equipment Corporation"; + case "ECMA": + return "European Computer Manufacturers Association"; + case "Elms": + return "Elms Systems Corporation"; + case "EMC": + return "EMC Corp."; + case "EMULEX": + return "Emulex"; + case "EPSON": + return "Epson"; + case "Eris/RSI": + return "RSI Systems, Inc."; + case "EXABYTE": + return "Exabyte Corp."; + case "FILENET": + return "FileNet Corp."; + case "FRAMDRV": + return "FRAMEDRIVE Corp."; + case "FUJI": + return "Fuji Electric Co., Ltd. (Japan)"; + case "FUJITSU": + return "Fujitsu"; + case "FUNAI": + return "Funai Electric Co., Ltd."; + case "FUTURED": + return "Future Domain Corp."; + case "GIGATAPE": + return "GIGATAPE GmbH"; + case "GIGATRND": + return "GigaTrend Incorporated"; + case "GOULD": + return "Gould"; + case "Gen_Dyn": + return "General Dynamics"; + case "Goidelic": + return "Goidelic Precision, Inc."; + case "HITACHI": + return "Hitachi America Ltd or Nissei Sangyo America Ltd"; + case "HONEYWEL": + return "Honeywell Inc."; + case "HP": + return "Hewlett Packard"; + case "i-cubed": + return "i-cubed ltd."; + case "IBM": + return "International Business Machines"; + case "ICL": + return "ICL"; + case "IDE": + return "International Data Engineering, Inc."; + case "IGR": + return "Intergraph Corp."; + case "IMPLTD": + return "Integrated Micro Products Ltd."; + case "IMPRIMIS": + return "Imprimis Technology Inc."; + case "INSITE": + return "Insite Peripherals"; + case "INTEL": + return "INTEL Corporation"; + case "IOC": + return "I/O Concepts, Inc."; + case "IOMEGA": + return "Iomega"; + case "ISi": + return "Information Storage inc."; + case "ISO": + return "International Standards Organization"; + case "ITC": + return "International Tapetronics Corporation"; + case "JPC Inc.": + return "JPC Inc."; + case "JVC": + return "JVC Information Products Co."; + case "KENNEDY": + return "Kennedy Company"; + case "KENWOOD": + return "KENWOOD Corporation"; + case "KODAK": + return "Eastman Kodak"; + case "KONAN": + return "Konan"; + case "KONICA": + return "Konica Japan"; + case "LAPINE": + return "Lapine Technology"; + case "LASERDRV": + return "LaserDrive Limited"; + case "LASERGR": + return "Lasergraphics, Inc."; + case "LION": + return "Lion Optics Corporation"; + case "LMS": + return "Laser Magnetic Storage International Company"; + case "MATSHITA": + return "Matsushita"; + case "MAXSTRAT": + return "Maximum Strategy, Inc."; + case "MAXTOR": + return "Maxtor Corp."; + case "MDI": + return "Micro Design International, Inc."; + case "MEADE": + return "Meade Instruments Corporation"; + case "MELA": + return "Mitsubishi Electronics America"; + case "MELCO": + return "Mitsubishi Electric (Japan)"; + case "MEMREL": + return "Memrel Corporation"; + case "MEMTECH": + return "MemTech Technology"; + case "MERIDATA": + return "Oy Meridata Finland Ltd."; + case "METRUM": + return "Metrum, Inc."; + case "MICROBTX": + return "Microbotics Inc."; + case "MICROP": + return "Micropolis"; + case "MICROTEK": + return "Microtek Storage Corp"; + case "MINSCRIB": + return "Miniscribe"; + case "MITSUMI": + return "Mitsumi Electric Co., Ltd."; + case "MOTOROLA": + return "Motorola"; + case "MST": + return "Morning Star Technologies, Inc."; + case "MTNGATE": + return "MountainGate Data Systems"; + case "MaxOptix": + return "Maxoptix Corp."; + case "Minitech": + return "Minitech (UK) Limited"; + case "Minolta": + return "Minolta Corporation"; + case "NAI": + return "North Atlantic Industries"; + case "NAKAMICH": + return "Nakamichi Corporation"; + case "NCL": + return "NCL America"; + case "NCR": + return "NCR Corporation"; + case "NEC": + return "NEC"; + case "NISCA": + return "NISCA Inc."; + case "NKK": + return "NKK Corp."; + case "NRC": + return "Nakamichi Corporation"; + case "NSM": + return "NSM Jukebox GmbH"; + case "NT": + return "Northern Telecom"; + case "NatInst": + return "National Instruments"; + case "NatSemi": + return "National Semiconductor Corp."; + case "OAI": + return "Optical Access International"; + case "OCE": + return "Oce Graphics"; + case "OKI": + return "OKI Electric Industry Co.,Ltd (Japan)"; + case "OMI": + return "Optical Media International"; + case "OMNIS": + return "OMNIS Company (FRANCE)"; + case "OPTIMEM": + return "Cipher/Optimem"; + case "OPTOTECH": + return "Optotech"; + case "ORCA": + return "Orca Technology"; + case "OSI": + return "Optical Storage International"; + case "OTL": + return "OTL Engineering"; + case "PASCOsci": + return "Pasco Scientific"; + case "PERTEC": + return "Pertec Peripherals Corporation"; + case "PFTI": + return "Performance Technology Inc."; + case "PFU": + return "PFU Limited"; + case "PIONEER": + return "Pioneer Electronic Corp."; + case "PLASMON": + return "Plasmon Data"; + case "PRAIRIE": + return "PrairieTek"; + case "PREPRESS": + return "PrePRESS Solutions"; + case "PRESOFT": + return "PreSoft Architects"; + case "PRESTON": + return "Preston Scientific"; + case "PRIAM": + return "Priam"; + case "PRIMAGFX": + return "Primagraphics Ltd"; + case "PTI": + return "Peripheral Technology Inc."; + case "QIC": + return "Quarter-Inch Cartridge Drive Standards, Inc."; + case "QUALSTAR": + return "Qualstar"; + case "QUANTUM": + return "Quantum Corp."; + case "QUANTEL": + return "Quantel Ltd."; + case "R-BYTE": + return "R-Byte, Inc."; + case "RACALREC": + return "Racal Recorders"; + case "RADSTONE": + return "Radstone Technology"; + case "RGI": + return "Raster Graphics, Inc."; + case "RICOH": + return "Ricoh"; + case "RODIME": + return "Rodime"; + case "RTI": + return "Reference Technology"; + case "SAMSUNG": + return "Samsung Electronics Co., Ltd."; + case "SANKYO": + return "Sankyo Seiki"; + case "SANYO": + return "SANYO Electric Co., Ltd."; + case "SCREEN": + return "Dainippon Screen Mfg. Co., Ltd."; + case "SEAGATE": + return "Seagate"; + case "SEQUOIA": + return "Sequoia Advanced Technologies, Inc."; + case "SIEMENS": + return "Siemens"; + case "SII": + return "Seiko Instruments Inc."; + case "SMS": + return "Scientific Micro Systems/OMTI"; + case "SNYSIDE": + return "Sunnyside Computing Inc."; + case "SONIC": + return "Sonic Solutions"; + case "SONY": + return "Sony Corporation Japan"; + case "SPECIAL": + return "Special Computing Co."; + case "SPECTRA": + return "Spectra Logic, a Division of Western Automation Labs, Inc."; + case "SPERRY": + return "Sperry (now Unisys Corp.)"; + case "STK": + return "Storage Technology Corporation"; + case "StrmLgc": + return "StreamLogic Corp."; + case "SUMITOMO": + return "Sumitomo Electric Industries, Ltd."; + case "SUN": + return "Sun Microsystems, Inc."; + case "SYMBIOS": + return "Symbios Logic Inc."; + case "SYSGEN": + return "Sysgen"; + case "Shinko": + return "Shinko Electric Co., Ltd."; + case "SyQuest": + return "SyQuest Technology, Inc."; + case "T-MITTON": + return "Transmitton England"; + case "TALARIS": + return "Talaris Systems, Inc."; + case "TALLGRAS": + return "Tallgrass Technologies"; + case "TANDBERG": + return "Tandberg Data A/S"; + case "TANDON": + return "Tandon"; + case "TEAC": + return "TEAC Japan"; + case "TECOLOTE": + return "Tecolote Designs"; + case "TEGRA": + return "Tegra Varityper"; + case "TENTIME": + return "Laura Technologies, Inc."; + case "TI-DSG": + return "Texas Instruments"; + case "TOSHIBA": + return "Toshiba Japan"; + case "Tek": + return "Tektronix"; + case "ULTRA": + return "UltraStor Corporation"; + case "UNISYS": + return "Unisys"; + case "USCORE": + return "Underscore, Inc."; + case "USDC": + return "US Design Corp."; + case "VERBATIM": + return "Verbatim Corporation"; + case "VEXCEL": + return "VEXCEL IMAGING GmbH"; + case "VICOMSL1": + return "Vicom Systems, Inc."; + case "VRC": + return "Vermont Research Corp."; + case "WANGTEK": + return "Wangtek"; + case "WDIGTL": + return "Western Digital"; + case "WEARNES": + return "Wearnes Technology Corporation"; + case "WangDAT": + return "WangDAT"; + case "X3": + return "Accredited Standards Committee X3, Information Technology"; + case "XEBEC": + return "Xebec Corporation"; + case "Acuid": + return "Acuid Corporation Ltd."; + case "AcuLab": + return "AcuLab, Inc. (Tulsa, OK)"; + case "ADIC": + return "Advanced Digital Information Corporation"; + case "ADVA": + return "ADVA Optical Networking AG"; + case "Ancor": + return "Ancor Communications, Inc."; + case "ANDATACO": + return "Andataco (now nStor)"; + case "ARK": + return "ARK Research Corporation"; + case "ARTECON": + return "Artecon Inc. (Obs. - now Dot Hill)"; + case "ASC": + return "Advanced Storage Concepts, Inc."; + case "BHTi": + return "Breece Hill Technologies"; + case "BITMICRO": + return "BiT Microsystems, Inc."; + case "BNCHMARK": + return "Benchmark Tape Systems Corporation"; + case "BREA": + return "BREA Technologies, Inc."; + case "BROCADE": + return "Brocade Communications Systems, Incorporated"; + case "CenData": + return "Central Data Corporation"; + case "Cereva": + return "Cereva Networks Inc."; + case "CISCO": + return "Cisco Systems, Inc."; + case "CNSi": + return "Chaparral Network Storage, Inc."; + case "COMPTEX": + return "Comptex Pty Limited"; + case "CPL": + return "Cross Products Ltd"; + case "CROSSRDS": + return "Crossroads Systems, Inc."; + case "Data Com": + return "Data Com Information Systems Pty. Ltd."; + case "DataCore": + return "DataCore Software Corporation"; + case "DDN": + return "DataDirect Networks, Inc."; + case "DEI": + return "Digital Engineering, Inc."; + case "DELL": + return "Dell Computer Corporation"; + case "DigiIntl": + return "Digi International"; + case "DotHill": + return "Dot Hill Systems Corp."; + case "ECCS": + return "ECCS, Inc."; + case "EMASS": + return "EMASS, Inc."; + case "EMTEC": + return "EMTEC Magnetics"; + case "EuroLogc": + return "Eurologic Systems Limited"; + case "FFEILTD": + return "FujiFilm Electonic Imaging Ltd"; + case "FUJIFILM": + return "Fuji Photo Film, Co., Ltd."; + case "G&D": + return "Giesecke & Devrient GmbH"; + case "GENSIG": + return "General Signal Networks"; + case "Global": + return "Global Memory Test Consortium"; + case "GoldStar": + return "LG Electronics Inc."; + case "HAGIWARA": + return "Hagiwara Sys-Com Co., Ltd."; + case "ICP": + return "ICP vortex Computersysteme GmbH"; + case "IMATION": + return "Imation"; + case "Indigita": + return "Indigita Corporation"; + case "INITIO": + return "Initio Corporation"; + case "IVIVITY": + return "iVivity, Inc."; + case "Kyocera": + return "Kyocera Corporation"; + case "LG": + return "LG Electronics Inc."; + case "LGE": + return "LG Electronics Inc."; + case "LSI": + return "LSI Logic Corp."; + case "LSILOGIC": + return "LSI Logic Storage Systems, Inc."; + case "LTO-CVE": + return "Linear Tape - Open, Compliance Verification Entity"; + case "MAXELL": + return "Hitachi Maxell, Ltd."; + case "McDATA": + return "McDATA Corporation"; + case "MEII": + return "Mountain Engineering II, Inc."; + case "MOSAID": + return "Mosaid Technologies Inc."; + case "MPM": + return "Mitsubishi Paper Mills, Ltd."; + case "NCITS": + return "National Committee for Information Technology Standards"; + case "NEXSAN": + return "Nexsan Technologies, Ltd."; + case "NISHAN": + return "Nishan Systems Inc."; + case "NSD": + return "Nippon Systems Development Co.,Ltd."; + case "nStor": + return "nStor Technologies, Inc."; + case "NUCONNEX": + return "NuConnex"; + case "NUSPEED": + return "NuSpeed, Inc."; + case "ORANGE": + return "Orange Micro, Inc."; + case "PATHLGHT": + return "Pathlight Technology, Inc."; + case "PICO": + return "Packard Instrument Company"; + case "PROCOM": + return "Procom Technology"; + case "RHAPSODY": + return "Rhapsody Networks, Inc."; + case "RHS": + return "Racal-Heim Systems GmbH"; + case "SAN": + return "Storage Area Networks, Ltd."; + case "SCInc.": + return "Storage Concepts, Inc."; + case "SDI": + return "Storage Dimensions, Inc."; + case "SDS": + return "Solid Data Systems"; + case "SPD": + return "Storage Products Distribution, Inc."; + case "Sterling": + return "Sterling Diagnostic Imaging, Inc."; + case "STOR": + return "StorageNetworks, Inc."; + case "STORAPP": + return "StorageApps, Inc."; + case "STORM": + return "Storm Technology, Inc."; + case "TDK": + return "TDK Corporation"; + case "TMS": + return "Texas Memory Systems, Inc."; + case "TRIPACE": + return "Tripace"; + case "VDS": + return "Victor Data Systems Co., Ltd."; + case "VIXEL": + return "Vixel Corporation"; + case "WSC0001": + return "Wisecom, Inc."; + case "Mendocin": + return "Mendocino Software"; + case "0B4C": + return "MOOSIK Ltd."; + case "2AI": + return "2AI (Automatisme et Avenir Informatique)"; + case "3PARdata": + return "3PARdata, Inc."; + case "A-Max": + return "A-Max Technology Co., Ltd"; + case "Acer": + return "Acer, Inc."; + case "AIPTEK": + return "AIPTEK International Inc."; + case "AMCC": + return "Applied Micro Circuits Corporation"; + case "Amphenol": + return "Amphenol"; + case "andiamo": + return "Andiamo Systems, Inc."; + case "ANTONIO": + return "Antonio Precise Products Manufactory Ltd."; + case "ARIO": + return "Ario Data Networks, Inc."; + case "ARISTOS": + return "Aristos Logic Corp."; + case "ATA": + return "SCSI / ATA Translator Software (Organization Not Specified)"; + case "ATL": + return "Quantum|ATL Products"; + case "AVC": + return "AVC Technology Ltd"; + case "Barco": + return "Barco"; + case "BAROMTEC": + return "Barom Technologies Co., Ltd."; + case "BDT": + return "Buero- und Datentechnik GmbH & Co.KG"; + case "BENQ": + return "BENQ Corporation."; + case "BIR": + return "Bio-Imaging Research, Inc."; + case "BlueArc": + return "BlueArc Corporation"; + case "Broadcom": + return "Broadcom Corporation"; + case "CAMBEX": + return "Cambex Corporation"; + case "CAMEOSYS": + return "Cameo Systems Inc."; + case "CANDERA": + return "Candera Inc."; + case "CAPTION": + return "CAPTION BANK"; + case "CATALYST": + return "Catalyst Enterprises"; + case "CERTANCE": + return "Certance"; + case "CLOVERLF": + return "Cloverleaf Communications, Inc"; + case "CMTechno": + return "CMTech"; + case "CNT": + return "Computer Network Technology"; + case "COBY": + return "Coby Electronics Corporation, USA"; + case "COMPELNT": + return "Compellent Technologies, Inc."; + case "COPANSYS": + return "COPAN SYSTEMS INC"; + case "COWON": + return "COWON SYSTEMS, Inc."; + case "CSCOVRTS": + return "Cisco - Veritas"; + case "CYBERNET": + return "Cybernetics"; + case "Cygnal": + return "Dekimo"; + case "DALSEMI": + return "Dallas Semiconductor"; + case "DANGER": + return "Danger Inc."; + case "DAT-MG": + return "DAT Manufacturers Group"; + case "DNS": + return "Data and Network Security"; + case "DP": + return "Dell, Inc."; + case "DSC": + return "DigitalStream Corporation"; + case "elipsan": + return "Elipsan UK Ltd."; + case "ENERGY-B": + return "Energybeam Corporation"; + case "ENGENIO": + return "Engenio Information Technologies, Inc."; + case "EQLOGIC": + return "EqualLogic"; + case "evolve": + return "Evolution Technologies, Inc"; + case "EXATEL": + return "Exatelecom Co., Ltd."; + case "EXAVIO": + return "Exavio, Inc."; + case "FALCON": + return "FalconStor, Inc."; + case "Fibxn": + return "Fiberxon, Inc."; + case "FID": + return "First International Digital, Inc."; + case "FREECION": + return "Nable Communications, Inc."; + case "Gadzoox": + return "Gadzoox Networks, Inc."; + case "GDI": + return "Generic Distribution International"; + case "Generic": + return "Generic Technology Co., Ltd."; + case "HAPP3": + return "Inventec Multimedia and Telecom co., ltd"; + case "Heydays": + return "Mazo Technology Co., Ltd."; + case "HI-TECH": + return "HI-TECH Software Pty. Ltd."; + case "HPQ": + return "Hewlett Packard"; + case "HYUNWON": + return "HYUNWON inc"; + case "IET": + return "ISCSI ENTERPRISE TARGET"; + case "IFT": + return "Infortrend Technology, Inc."; + case "INCIPNT": + return "Incipient Technologies Inc."; + case "INCITS": + return "InterNational Committee for Information Technology"; + case "INRANGE": + return "INRANGE Technologies Corporation"; + case "integrix": + return "Integrix, Inc."; + case "iqstor": + return "iQstor Networks, Inc."; + case "IVMMLTD": + return "InnoVISION Multimedia Ltd."; + case "JETWAY": + return "Jetway Information Co., Ltd"; + case "KASHYA": + return "Kashya, Inc."; + case "KSCOM": + return "KSCOM Co. Ltd.,"; + case "KUDELSKI": + return "Nagravision SA - Kudelski Group"; + case "LEFTHAND": + return "LeftHand Networks"; + case "Lexar": + return "Lexar Media, Inc."; + case "LUXPRO": + return "Luxpro Corporation"; + case "Malakite": + return "Malachite Technologies (New VID is: Sandial)"; + case "MaXXan": + return "MaXXan Systems, Inc."; + case "MAYCOM": + return "maycom Co., Ltd."; + case "MBEAT": + return "K-WON C&C Co.,Ltd"; + case "MCC": + return "Measurement Computing Corporation"; + case "MHTL": + return "Matsunichi Hi-Tech Limited"; + case "MICROLIT": + return "Microlite Corporation"; + case "MKM": + return "Mitsubishi Kagaku Media Co., LTD."; + case "MP-400": + return "Daiwa Manufacturing Limited"; + case "MPEYE": + return "Touchstone Technology Co., Ltd"; + case "MPMan": + return "MPMan.com, Inc."; + case "MSFT": + return "Microsoft Corporation"; + case "MSI": + return "Micro-Star International Corp."; + case "MTI": + return "MTI Technology Corporation"; + case "MXI": + return "Memory Experts International"; + case "nac": + return "nac Image Technology Inc."; + case "NAGRA": + return "Nagravision SA - Kudelski Group"; + case "Neartek": + return "Neartek, Inc."; + case "NETAPP": + return "Network Appliance"; + case "Netcom": + return "Netcom Storage"; + case "NHR": + return "NH Research, Inc."; + case "NVIDIA": + return "NVIDIA Corporation"; + case "Olidata": + return "Olidata S.p.A."; + case "OMNIFI": + return "Rockford Corporation - Omnifi Media"; + case "Packard": + return "Parkard Bell"; + case "PARALAN": + return "Paralan Corporation"; + case "PerStor": + return "Perstor"; + case "PHILIPS": + return "Philips Electronics"; + case "Pillar": + return "Pillar Data Systems"; + case "PIVOT3": + return "Pivot3, Inc."; + case "PROSTOR": + return "ProStor Systems, Inc."; + case "PTICO": + return "Pacific Technology International"; + case "QLogic": + return "QLogic Corporation"; + case "Realm": + return "Realm Systems"; + case "Revivio": + return "Revivio, Inc."; + case "SANRAD": + return "SANRAD Inc."; + case "SC.Net": + return "StorageConnections.Net"; + case "SCIENTEK": + return "SCIENTEK CORP"; + case "SEAC": + return "SeaChange International, Inc."; + case "SEAGRAND": + return "SEAGRAND In Japan"; + case "SigmaTel": + return "SigmaTel, Inc."; + case "SLI": + return "Sierra Logic, Inc."; + case "SoniqCas": + return "SoniqCast"; + case "STONEFLY": + return "StoneFly Networks, Inc."; + case "STORCOMP": + return "Storage Computer Corporation"; + case "SUNCORP": + return "SunCorporation"; + case "suntx": + return "Suntx System Co., Ltd"; + case "SYMANTEC": + return "Symantec Corporation"; + case "T11": + return "INCITS Technical Committee T11"; + case "TANDEM": + return "Tandem (now HP)"; + case "TGEGROUP": + return "TGE Group Co.,LTD."; + case "Tite": + return "Tite Technology Limited"; + case "TOLISGRP": + return "The TOLIS Group"; + case "TROIKA": + return "Troika Networks, Inc."; + case "TRULY": + return "TRULY Electronics MFG. LTD."; + case "UDIGITAL": + return "United Digital Limited"; + case "VERITAS": + return "VERITAS Software Corporation"; + case "VicomSys": + return "Vicom Systems, Inc."; + case "VIDEXINC": + return "Videx, Inc."; + case "VITESSE": + return "Vitesse Semiconductor Corporation"; + case "VMAX": + return "VMAX Technologies Corp."; + case "Vobis": + return "Vobis Microcomputer AG"; + case "Waitec": + return "Waitec NV"; + case "Wasabi": + return "Wasabi Systems"; + case "WAVECOM": + return "Wavecom"; + case "WD": + return "Western Digital Technologies Inc."; + case "WDC": + return "Western Digital Technologies inc."; + case "Xerox": + return "Xerox Corporation"; + case "XIOtech": + return "XIOtech Corporation"; + case "XIRANET": + return "Xiranet Communications GmbH"; + case "XYRATEX": + return "Xyratex"; + case "YINHE": + return "NUDT Computer Co."; + case "YIXUN": + return "Yixun Electronic Co.,Ltd."; + case "YOTTA": + return "YottaYotta, Inc."; + case "Zarva": + return "Zarva Digital Technology Co., Ltd."; + case "ZETTA": + return "Zetta Systems, Inc."; + default: + return SCSIVendorString; + } + } + + #endregion Private methods + + #region Public methods + + public static SCSIInquiry? DecodeSCSIInquiry(byte[] SCSIInquiryResponse) + { + if (SCSIInquiryResponse == null) + return null; + + if (SCSIInquiryResponse.Length < 36) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (SCSI INQUIRY Decoder): INQUIRY response is less than minimum of 36 bytes, decoded data can be incorrect, proceeding anyway."); + //else + return null; + } + + if (SCSIInquiryResponse.Length != SCSIInquiryResponse[4] + 4) + { + //if (MainClass.isDebug) + Console.WriteLine("DEBUG (SCSI INQUIRY Decoder): INQUIRY response length ({0} bytes) is different than specified in length field ({1} bytes), decoded data can be incorrect, proceeding anyway.", SCSIInquiryResponse.Length, SCSIInquiryResponse[4] + 4); + //else + return null; + } + + SCSIInquiry decoded = new SCSIInquiry(); + + if (SCSIInquiryResponse.Length >= 1) + { + decoded.PeripheralQualifier = (byte)((SCSIInquiryResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (byte)(SCSIInquiryResponse[0] & 0x1F); + } + if (SCSIInquiryResponse.Length >= 2) + { + decoded.RMB = Convert.ToBoolean((SCSIInquiryResponse[1] & 0x80)); + decoded.Reserved1 = (byte)(SCSIInquiryResponse[1] & 0x7F); + } + if (SCSIInquiryResponse.Length >= 3) + { + decoded.ISOVersion = (byte)((SCSIInquiryResponse[2] & 0xC0) >> 6); + decoded.ECMAVersion = (byte)((SCSIInquiryResponse[2] & 0x38) >> 3); + decoded.ANSIVersion = (byte)(SCSIInquiryResponse[2] & 0x07); + } + if (SCSIInquiryResponse.Length >= 4) + { + decoded.AERC = Convert.ToBoolean((SCSIInquiryResponse[3] & 0x80)); + decoded.TrmTsk = Convert.ToBoolean((SCSIInquiryResponse[3] & 0x40)); + decoded.NormACA = Convert.ToBoolean((SCSIInquiryResponse[3] & 0x20)); + decoded.HiSup = Convert.ToBoolean((SCSIInquiryResponse[3] & 0x10)); + decoded.ResponseDataFormat = (byte)(SCSIInquiryResponse[3] & 0x07); + } + if (SCSIInquiryResponse.Length >= 5) + decoded.AdditionalLength = SCSIInquiryResponse[4]; + if (SCSIInquiryResponse.Length >= 6) + { + decoded.SCCS = Convert.ToBoolean((SCSIInquiryResponse[5] & 0x80)); + decoded.ACC = Convert.ToBoolean((SCSIInquiryResponse[5] & 0x40)); + decoded.TPGS = (byte)((SCSIInquiryResponse[5] & 0x30) >> 4); + decoded.ThreePC = Convert.ToBoolean((SCSIInquiryResponse[5] & 0x08)); + decoded.Reserved2 = (byte)((SCSIInquiryResponse[5] & 0x06) >> 1); + decoded.Protect = Convert.ToBoolean((SCSIInquiryResponse[5] & 0x01)); + } + if (SCSIInquiryResponse.Length >= 7) + { + decoded.BQue = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x80)); + decoded.EncServ = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x40)); + decoded.VS1 = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x20)); + decoded.MultiP = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x10)); + decoded.MChngr = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x08)); + decoded.ACKREQQ = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x04)); + decoded.Addr32 = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x02)); + decoded.Addr16 = Convert.ToBoolean((SCSIInquiryResponse[6] & 0x01)); + } + if (SCSIInquiryResponse.Length >= 8) + { + decoded.RelAddr = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x80)); + decoded.WBus32 = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x40)); + decoded.WBus16 = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x20)); + decoded.Sync = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x10)); + decoded.Linked = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x08)); + decoded.TranDis = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x04)); + decoded.CmdQue = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x02)); + decoded.VS2 = Convert.ToBoolean((SCSIInquiryResponse[7] & 0x01)); + } + if (SCSIInquiryResponse.Length >= 16) + { + decoded.VendorIdentification = new byte[8]; + Array.Copy(SCSIInquiryResponse, 8, decoded.VendorIdentification, 0, 8); + } + if (SCSIInquiryResponse.Length >= 32) + { + decoded.ProductIdentification = new byte[16]; + Array.Copy(SCSIInquiryResponse, 16, decoded.ProductIdentification, 0, 16); + } + if (SCSIInquiryResponse.Length >= 36) + { + decoded.ProductRevisionLevel = new byte[4]; + Array.Copy(SCSIInquiryResponse, 32, decoded.ProductRevisionLevel, 0, 4); + } + if (SCSIInquiryResponse.Length >= 56) + { + decoded.VendorSpecific = new byte[20]; + Array.Copy(SCSIInquiryResponse, 36, decoded.VendorSpecific, 0, 20); + } + if (SCSIInquiryResponse.Length >= 57) + { + decoded.Reserved3 = (byte)((SCSIInquiryResponse[56] & 0xF0) >> 4); + decoded.Clocking = (byte)((SCSIInquiryResponse[56] & 0x0C) >> 2); + decoded.QAS = Convert.ToBoolean((SCSIInquiryResponse[56] & 0x02)); + decoded.IUS = Convert.ToBoolean((SCSIInquiryResponse[56] & 0x01)); + } + if (SCSIInquiryResponse.Length >= 58) + decoded.Reserved4 = SCSIInquiryResponse[57]; + if (SCSIInquiryResponse.Length >= 74) + { + decoded.VersionDescriptors = new ushort[8]; + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + for (int i = 0; i < 8; i++) + { + decoded.VersionDescriptors[i] = BigEndianBitConverter.ToUInt16(SCSIInquiryResponse, 58 + (i * 2)); + } + } + if (SCSIInquiryResponse.Length >= 75 && SCSIInquiryResponse.Length < 96) + { + decoded.Reserved5 = new byte[SCSIInquiryResponse.Length - 74]; + Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, SCSIInquiryResponse.Length - 74); + } + if (SCSIInquiryResponse.Length >= 96) + { + decoded.Reserved5 = new byte[22]; + Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, 22); + } + if (SCSIInquiryResponse.Length > 96) + { + decoded.VendorSpecific2 = new byte[SCSIInquiryResponse.Length - 96]; + Array.Copy(SCSIInquiryResponse, 96, decoded.Reserved5, 0, SCSIInquiryResponse.Length - 96); + } + + return decoded; + } + + public static string PrettifySCSIInquiry(SCSIInquiry? SCSIInquiryResponse) + { + if (SCSIInquiryResponse == null) + return null; + + SCSIInquiry response = SCSIInquiryResponse.Value; + + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat("Device vendor: {0}", PrettifySCSIVendorString(StringHandlers.SpacePaddedToString(response.VendorIdentification))).AppendLine(); + sb.AppendFormat("Device name: {0}", StringHandlers.SpacePaddedToString(response.ProductIdentification)).AppendLine(); + sb.AppendFormat("Device release level: {0}", StringHandlers.SpacePaddedToString(response.ProductRevisionLevel)).AppendLine(); + switch ((SCSIPeripheralQualifiers)response.PeripheralQualifier) + { + case SCSIPeripheralQualifiers.SCSIPQSupported: + sb.AppendLine("Device is connected and supported."); + break; + case SCSIPeripheralQualifiers.SCSIPQUnconnected: + sb.AppendLine("Device is supported but not connected."); + break; + case SCSIPeripheralQualifiers.SCSIPQReserved: + sb.AppendLine("Reserved value set in Peripheral Qualifier field."); + break; + case SCSIPeripheralQualifiers.SCSIPQUnsupported: + sb.AppendLine("Device is connected but unsupported."); + break; + default: + sb.AppendFormat("Vendor value {0} set in Peripheral Qualifier field.", response.PeripheralQualifier).AppendLine(); + break; + } + + switch ((SCSIPeripheralDeviceTypes)response.PeripheralDeviceType) + { + case SCSIPeripheralDeviceTypes.SCSIPDTDirectAccess: //0x00, + sb.AppendLine("Direct-access device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTSequentialAccess: //0x01, + sb.AppendLine("Sequential-access device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTPrinterDevice: //0x02, + sb.AppendLine("Printer device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTProcessorDevice: //0x03, + sb.AppendLine("Processor device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTWriteOnceDevice: //0x04, + sb.AppendLine("Write-once device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTMultiMediaDevice: //0x05, + sb.AppendLine("CD-ROM/DVD/etc device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTScannerDevice: //0x06, + sb.AppendLine("Scanner device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTOpticalDevice: //0x07, + sb.AppendLine("Optical memory device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTMediumChangerDevice: //0x08, + sb.AppendLine("Medium change device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTCommsDevice: //0x09, + sb.AppendLine("Communications device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTPrePressDevice1: //0x0A, + sb.AppendLine("Graphics arts pre-press device (defined in ASC IT8)"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTPrePressDevice2: //0x0B, + sb.AppendLine("Graphics arts pre-press device (defined in ASC IT8)"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTArrayControllerDevice: //0x0C, + sb.AppendLine("Array controller device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTEnclosureServiceDevice: //0x0D, + sb.AppendLine("Enclosure services device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTSimplifiedDevice: //0x0E, + sb.AppendLine("Simplified direct-access device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTOCRWDevice: //0x0F, + sb.AppendLine("Optical card reader/writer device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTBridgingExpander: //0x10, + sb.AppendLine("Bridging Expanders"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTObjectDevice: //0x11, + sb.AppendLine("Object-based Storage Device"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTADCDevice: //0x12, + sb.AppendLine("Automation/Drive Interface"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTWellKnownDevice: //0x1E, + sb.AppendLine("Well known logical unit"); + break; + case SCSIPeripheralDeviceTypes.SCSIPDTUnknownDevice: //0x1F + sb.AppendLine("Unknown or no device type"); + break; + default: + sb.AppendFormat("Unknown device type field value 0x{0:X2}", response.PeripheralDeviceType).AppendLine(); + break; + } + + switch ((SCSIANSIVersions)response.ANSIVersion) + { + case SCSIANSIVersions.SCSIANSINoVersion: + sb.AppendLine("Device does not claim to comply with any SCSI ANSI standard"); + break; + case SCSIANSIVersions.SCSIANSIObsolete: + sb.AppendLine("Device claims to comply with an obsolete SCSI ANSI standard"); + break; + case SCSIANSIVersions.SCSIANSI1994Version: + sb.AppendLine("Device claims to comply with ANSI X3.131:1994"); + break; + case SCSIANSIVersions.SCSIANSI1997Version: + sb.AppendLine("Device claims to comply with ANSI X3.301:1997"); + break; + case SCSIANSIVersions.SCSIANSI2001Version: + sb.AppendLine("Device claims to comply with ANSI X3.351:2001"); + break; + case SCSIANSIVersions.SCSIANSI2005Version: + sb.AppendLine("Device claims to comply with ANSI X3.???:2005"); + break; + default: + sb.AppendFormat("Device claims to comply with unknown SCSI ANSI standard value 0x{0:X2})", response.ANSIVersion).AppendLine(); + break; + } + + switch ((SCSIECMAVersions)response.ECMAVersion) + { + case SCSIECMAVersions.SCSIECMANoVersion: + sb.AppendLine("Device does not claim to comply with any SCSI ECMA standard"); + break; + case SCSIECMAVersions.SCSIECMAObsolete: + sb.AppendLine("Device claims to comply with an obsolete SCSI ECMA standard"); + break; + default: + sb.AppendFormat("Device claims to comply with unknown SCSI ECMA standard value 0x{0:X2})", response.ECMAVersion).AppendLine(); + break; + } + + switch ((SCSIISOVersions)response.ISOVersion) + { + case SCSIISOVersions.SCSIISONoVersion: + sb.AppendLine("Device does not claim to comply with any SCSI ISO/IEC standard"); + break; + case SCSIISOVersions.SCSIISO1995Version: + sb.AppendLine("Device claims to comply with ISO/IEC 9316:1995"); + break; + default: + sb.AppendFormat("Device claims to comply with unknown SCSI ISO/IEC standard value 0x{0:X2})", response.ISOVersion).AppendLine(); + break; + } + + if (response.RMB) + sb.AppendLine("Device is removable"); + if (response.AERC) + sb.AppendLine("Device supports Asynchronous Event Reporting Capability"); + if (response.TrmTsk) + sb.AppendLine("Device supports TERMINATE TASK command"); + if (response.NormACA) + sb.AppendLine("Device supports setting Normal ACA"); + if (response.HiSup) + sb.AppendLine("Device supports LUN hierarchical addressing"); + if (response.SCCS) + sb.AppendLine("Device contains an embedded storage array controller"); + if (response.ACC) + sb.AppendLine("Device contains an Access Control Coordinator"); + if (response.ThreePC) + sb.AppendLine("Device supports third-party copy commands"); + if (response.Protect) + sb.AppendLine("Device supports protection information"); + if (response.BQue) + sb.AppendLine("Device supports basic queueing"); + if (response.EncServ) + sb.AppendLine("Device contains an embedded enclosure services component"); + if (response.MultiP) + sb.AppendLine("Multi-port device"); + if (response.MChngr) + sb.AppendLine("Device contains or is attached to a medium changer"); + if (response.ACKREQQ) + sb.AppendLine("Device supports request and acknowledge handshakes"); + if (response.Addr32) + sb.AppendLine("Device supports 32-bit wide SCSI addresses"); + if (response.Addr16) + sb.AppendLine("Device supports 16-bit wide SCSI addresses"); + if (response.RelAddr) + sb.AppendLine("Device supports relative addressing"); + if (response.WBus32) + sb.AppendLine("Device supports 32-bit wide data transfers"); + if (response.WBus16) + sb.AppendLine("Device supports 16-bit wide data transfers"); + if (response.Sync) + sb.AppendLine("Device supports synchronous data transfer"); + if (response.Linked) + sb.AppendLine("Device supports linked commands"); + if (response.TranDis) + sb.AppendLine("Device supports CONTINUE TASK and TARGET TRANSFER DISABLE commands"); + if (response.QAS) + sb.AppendLine("Device supports Quick Arbitration and Selection"); + if (response.CmdQue) + sb.AppendLine("Device supports TCQ queue"); + if (response.IUS) + sb.AppendLine("Device supports information unit transfers"); + //if (MainClass.isDebug) + { + if (response.VS1) + sb.AppendLine("Vendor specific bit 5 on byte 6 of INQUIRY response is set"); + if (response.VS2) + sb.AppendLine("Vendor specific bit 0 on byte 7 of INQUIRY response is set"); + } + + switch ((SCSITGPSValues)response.TPGS) + { + case SCSITGPSValues.NotSupported: + sb.AppendLine("Device does not support assymetrical access"); + break; + case SCSITGPSValues.OnlyImplicit: + sb.AppendLine("Device only supports implicit assymetrical access"); + break; + case SCSITGPSValues.OnlyExplicit: + sb.AppendLine("Device only supports explicit assymetrical access"); + break; + case SCSITGPSValues.Both: + sb.AppendLine("Device supports implicit and explicit assymetrical access"); + break; + default: + sb.AppendFormat("Unknown value in TPGS field 0x{0:X2}", response.TPGS).AppendLine(); + break; + } + + switch ((SCSISPIClocking)response.Clocking) + { + case SCSISPIClocking.SCSIClockingST: + sb.AppendLine("Device supports only ST clocking"); + break; + case SCSISPIClocking.SCSIClockingDT: + sb.AppendLine("Device supports only DT clocking"); + break; + case SCSISPIClocking.SCSIClockingReserved: + sb.AppendLine("Reserved value 0x02 found in SPI clocking field"); + break; + case SCSISPIClocking.SCSIClockingSTandDT: + sb.AppendLine("Device supports ST and DT clocking"); + break; + default: + sb.AppendFormat("Unknown value in SPI clocking field 0x{0:X2}", response.Clocking).AppendLine(); + break; + } + + foreach (UInt16 VersionDescriptor in response.VersionDescriptors) + { + switch (VersionDescriptor & 0xFFE0) + { + case (int)SCSIVersionDescriptorStandardMask.NoStandard: //0x0000 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device claims no standard"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of no standard", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAM: //0x0020 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSAMMask.NoVersion: + sb.AppendLine("Device complies with standard SAM, no version"); + break; + case (int)SCSIVersionDescriptorSAMMask.T10_0994_r18: + sb.AppendLine("Device complies with T10/0994 revision 18 (SAM)"); + break; + case (int)SCSIVersionDescriptorSAMMask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.270:1996 (SAM)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAM", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAM2: //0x0040 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSAM2Mask.NoVersion: + sb.AppendLine("Device complies with standard SAM-2, no version"); + break; + case (int)SCSIVersionDescriptorSAM2Mask.T10_1157_r23: + sb.AppendLine("Device complies with T10/1157-D revision 23 (SAM-2)"); + break; + case (int)SCSIVersionDescriptorSAM2Mask.T10_1157_r24: + sb.AppendLine("Device complies with T10/1157-D revision 24 (SAM-2)"); + break; + case (int)SCSIVersionDescriptorSAM2Mask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 366-2003 (SAM-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAM-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAM3: //0x0060 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSAM3Mask.NoVersion: + sb.AppendLine("Device complies with standard SAM-3, no version"); + break; + case (int)SCSIVersionDescriptorSAM3Mask.T10_1561_r07: + sb.AppendLine("Device complies with T10/1561-D revision 7 (SAM-3)"); + break; + case (int)SCSIVersionDescriptorSAM3Mask.T10_1561_r13: + sb.AppendLine("Device complies with T10/1561-D revision 13 (SAM-3)"); + break; + case (int)SCSIVersionDescriptorSAM3Mask.T10_1561_r14: + sb.AppendLine("Device complies with T10/1157-D revision 14 (SAM-3)"); + break; + case (int)SCSIVersionDescriptorSAM3Mask.ANSI_2005: + sb.AppendLine("Device complies with ANSI INCITS 402-2005 (SAM-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAM-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAM4: //0x0080 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard SAM-4, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAM-4", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPC: //0x0120 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPCMask.NoVersion: + sb.AppendLine("Device complies with standard SPC, no version"); + break; + case (int)SCSIVersionDescriptorSPCMask.T10_0995_r11a: + sb.AppendLine("Device complies with T10/0995 revision 11a (SPC)"); + break; + case (int)SCSIVersionDescriptorSPCMask.ANSI_1997: + sb.AppendLine("Device complies with ANSI X3.301:1997 (SPC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.MMC: //0x0140 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorMMCMask.NoVersion: + sb.AppendLine("Device complies with standard MMC, no version"); + break; + case (int)SCSIVersionDescriptorMMCMask.T10_1048_r10a: + sb.AppendLine("Device complies with T10/1048 revision 10a (MMC)"); + break; + case (int)SCSIVersionDescriptorMMCMask.ANSI_1997: + sb.AppendLine("Device complies with ANSI X3.304:1997 (MMC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard MMC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SCC: //0x0160 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSCCMask.NoVersion: + sb.AppendLine("Device complies with standard SCC, no version"); + break; + case (int)SCSIVersionDescriptorSCCMask.T10_1048_r06c: + sb.AppendLine("Device complies with T10/1047 revision 06c (SCC)"); + break; + case (int)SCSIVersionDescriptorSCCMask.ANSI_1997: + sb.AppendLine("Device complies with ANSI X3.276:1997 (SCC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SCC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SBC: //0x0180 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSBCMask.NoVersion: + sb.AppendLine("Device complies with standard SBC, no version"); + break; + case (int)SCSIVersionDescriptorSBCMask.T10_0996_r08c: + sb.AppendLine("Device complies with T10/0996 revision 08c (SBC)"); + break; + case (int)SCSIVersionDescriptorSBCMask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.306:1998 (SBC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SBC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SMC: //0x01A0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSMCMask.NoVersion: + sb.AppendLine("Device complies with standard SMC, no version"); + break; + case (int)SCSIVersionDescriptorSMCMask.T10_0999_r10a: + sb.AppendLine("Device complies with T10/0999 revision 10a (SMC)"); + break; + case (int)SCSIVersionDescriptorSMCMask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.314:1998 (SMC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SMC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SES: //0x01C0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSESMask.NoVersion: + sb.AppendLine("Device complies with standard SES, no version"); + break; + case (int)SCSIVersionDescriptorSESMask.T10_1212_r08b: + sb.AppendLine("Device complies with T10/1212 revision 08b (SES)"); + break; + case (int)SCSIVersionDescriptorSESMask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.305:1998 (SES)"); + break; + case (int)SCSIVersionDescriptorSESMask.T10_1212_r08b_2000: + sb.AppendLine("Device complies with T10/1212 revision 08b with ANSI NCITS.305/AM1:2000 (SES)"); + break; + case (int)SCSIVersionDescriptorSESMask.ANSI_1998_2000: + sb.AppendLine("Device complies with ANSI NCITS.305:1998 with ANSI NCITS.305/AM1:2000 (SES)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SES", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SCC2: //0x01E0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSCC2Mask.NoVersion: + sb.AppendLine("Device complies with standard SCC-2, no version"); + break; + case (int)SCSIVersionDescriptorSCC2Mask.T10_1125_r04: + sb.AppendLine("Device complies with T10/1125 revision 04 (SCC-2)"); + break; + case (int)SCSIVersionDescriptorSCC2Mask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.318:1998 (SCC-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SCC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSC: //0x0200 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSCMask.NoVersion: + sb.AppendLine("Device complies with standard SSC, no version"); + break; + case (int)SCSIVersionDescriptorSSCMask.T10_0997_r17: + sb.AppendLine("Device complies with T10/0997 revision 17 (SSC)"); + break; + case (int)SCSIVersionDescriptorSSCMask.T10_0997_r22: + sb.AppendLine("Device complies with T10/0997 revision 22 (SSC)"); + break; + case (int)SCSIVersionDescriptorSSCMask.ANSI_2000: + sb.AppendLine("Device complies with ANSI NCITS.335:2000 (SSC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.RBC: //0x0220 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorRBCMask.NoVersion: + sb.AppendLine("Device complies with standard RBC, no version"); + break; + case (int)SCSIVersionDescriptorRBCMask.T10_1240_r10a: + sb.AppendLine("Device complies with T10/1240 revision 10a (RBC)"); + break; + case (int)SCSIVersionDescriptorRBCMask.ANSI_2000: + sb.AppendLine("Device complies with ANSI NCITS.330:2000 (RBC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard RBC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.MMC2: //0x0240 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorMMC2Mask.NoVersion: + sb.AppendLine("Device complies with standard MMC-2, no version"); + break; + case (int)SCSIVersionDescriptorMMC2Mask.T10_1228_r11: + sb.AppendLine("Device complies with T10/1228 revision 11 (MMC-2)"); + break; + case (int)SCSIVersionDescriptorMMC2Mask.T10_1228_r11a: + sb.AppendLine("Device complies with T10/1228 revision 11a (MMC-2)"); + break; + case (int)SCSIVersionDescriptorMMC2Mask.ANSI_2000: + sb.AppendLine("Device complies with ANSI NCITS.333:2000 (MMC-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard MMC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPC2: //0x0260 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPC2Mask.NoVersion: + sb.AppendLine("Device complies with standard SPC-2, no version"); + break; + case (int)SCSIVersionDescriptorSPC2Mask.T10_1236_r12: + sb.AppendLine("Device complies with T10/1236 revision 12 (SPC-2)"); + break; + case (int)SCSIVersionDescriptorSPC2Mask.T10_1236_r18: + sb.AppendLine("Device complies with T10/1236 revision 18 (SPC-2)"); + break; + case (int)SCSIVersionDescriptorSPC2Mask.T10_1236_r19: + sb.AppendLine("Device complies with T10/1236 revision 19 (SPC-2)"); + break; + case (int)SCSIVersionDescriptorSPC2Mask.T10_1236_r20: + sb.AppendLine("Device complies with T10/1236 revision 20 (SPC-2)"); + break; + case (int)SCSIVersionDescriptorSPC2Mask.ANSI_2001: + sb.AppendLine("Device complies with ANSI INCITS 351-2001 (SPC-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.OCRW: //0x0280 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorOCRWMask.NoVersion: + sb.AppendLine("Device complies with standard OCRW, no version"); + break; + case (int)SCSIVersionDescriptorOCRWMask.ISO14776_381: + sb.AppendLine("Device complies with ISO/IEC 14776-381 (OCRW)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard OCRW", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.MMC3: //0x02A0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorMMC3Mask.NoVersion: + sb.AppendLine("Device complies with standard MMC-3, no version"); + break; + case (int)SCSIVersionDescriptorMMC3Mask.T10_1363_r09: + sb.AppendLine("Device complies with T10/1363-D revision 9 (MMC-3)"); + break; + case (int)SCSIVersionDescriptorMMC3Mask.T10_1363_r10g: + sb.AppendLine("Device complies with T10/1363-D revision 10g (MMC-3)"); + break; + case (int)SCSIVersionDescriptorMMC3Mask.ANSI_2001: + sb.AppendLine("Device complies with ANSI INCITS 360-2002 (MMC-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard MMC-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.RMC: //0x02C0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard "); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SMC2: //0x02E0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSMC2Mask.NoVersion: + sb.AppendLine("Device complies with standard SMC-2, no version"); + break; + case (int)SCSIVersionDescriptorSMC2Mask.T10_1383_r05: + sb.AppendLine("Device complies with T10/1383-D revision 5 (SMC-2)"); + break; + case (int)SCSIVersionDescriptorSMC2Mask.T10_1383_r06: + sb.AppendLine("Device complies with T10/1383-D revision 6 (SMC-2)"); + break; + case (int)SCSIVersionDescriptorSMC2Mask.T10_1383_r07: + sb.AppendLine("Device complies with T10/1383-D revision 7 (SMC-2)"); + break; + case (int)SCSIVersionDescriptorSMC2Mask.ANSI_2004: + sb.AppendLine("Device complies with ANSI_2004 (SMC-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SMC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPC3: //0x0300 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPC3Mask.NoVersion: + sb.AppendLine("Device complies with standard SPC-3, no version"); + break; + case (int)SCSIVersionDescriptorSPC3Mask.T10_1416_r07: + sb.AppendLine("Device complies with T10/1416-D revision 7 (SPC-3)"); + break; + case (int)SCSIVersionDescriptorSPC3Mask.T10_1416_r21: + sb.AppendLine("Device complies with T10/1416-D revision 21 (SPC-3)"); + break; + case (int)SCSIVersionDescriptorSPC3Mask.T10_1416_r22: + sb.AppendLine("Device complies with T10/1416-D revision 22 (SPC-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPC-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SBC2: //0x0320 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSBC2Mask.NoVersion: + sb.AppendLine("Device complies with standard SBC-2, no version"); + break; + case (int)SCSIVersionDescriptorSBC2Mask.T10_1383_r05: + sb.AppendLine("Device complies with T10/1383 revision 5 (SBC-2)"); + break; + case (int)SCSIVersionDescriptorSBC2Mask.T10_1383_r06: + sb.AppendLine("Device complies with T10/1383 revision 6 (SBC-2)"); + break; + case (int)SCSIVersionDescriptorSBC2Mask.T10_1383_r07: + sb.AppendLine("Device complies with T10/1383 revision 7 (SBC-2)"); + break; + case (int)SCSIVersionDescriptorSBC2Mask.ANSI_2005: + sb.AppendLine("Device complies with ANSI INCITS 405-2005 (SBC-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SBC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.OSD: //0x0340 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorOSDMask.NoVersion: + sb.AppendLine("Device complies with standard OSD, no version"); + break; + case (int)SCSIVersionDescriptorOSDMask.T10_1355_r0: + sb.AppendLine("Device complies with T10/1355 revision 0 (OSD)"); + break; + case (int)SCSIVersionDescriptorOSDMask.T10_1355_r7a: + sb.AppendLine("Device complies with T10/1355 revision 7a (OSD)"); + break; + case (int)SCSIVersionDescriptorOSDMask.T10_1355_r8: + sb.AppendLine("Device complies with T10/1355 revision 8 (OSD)"); + break; + case (int)SCSIVersionDescriptorOSDMask.T10_1355_r9: + sb.AppendLine("Device complies with T10/1355 revision 9 (OSD)"); + break; + case (int)SCSIVersionDescriptorOSDMask.T10_1355_r10: + sb.AppendLine("Device complies with T10/1355 revision 10 (OSD)"); + break; + case (int)SCSIVersionDescriptorOSDMask.ANSI_2004: + sb.AppendLine("Device complies with ANSI INCITS 400-2004 (OSD)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard OSD", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSC2: //0x0360 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSC2Mask.NoVersion: + sb.AppendLine("Device complies with standard SSC-2, no version"); + break; + case (int)SCSIVersionDescriptorSSC2Mask.T10_1434_r07: + sb.AppendLine("Device complies with T10/1434-D revision 7 (SSC-2)"); + break; + case (int)SCSIVersionDescriptorSSC2Mask.T10_1434_r09: + sb.AppendLine("Device complies with T10/1434-D revision 9 (SSC-2)"); + break; + case (int)SCSIVersionDescriptorSSC2Mask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 380-2003 (SSC-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.BCC: //0x0380 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard BCC, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard BCC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.MMC4: //0x03A0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorMMC4Mask.NoVersion: + sb.AppendLine("Device complies with standard MMC-4, no version"); + break; + case (int)SCSIVersionDescriptorMMC4Mask.T10_1545_r5: + sb.AppendLine("Device complies with T10/1545-D revision 5 (MMC-4)"); + break; + case (int)SCSIVersionDescriptorMMC4Mask.T10_1545_r3: + sb.AppendLine("Device complies with T10/1545-D revision 3 (MMC-4)"); + break; + case (int)SCSIVersionDescriptorMMC4Mask.T10_1545_r3d: + sb.AppendLine("Device complies with T10/1545-D revision 3d (MMC-4)"); + break; + case (int)SCSIVersionDescriptorMMC4Mask.ANSI_2005: + sb.AppendLine("Device complies with ANSI INCITS 401-2005 (MMC-4)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard MMC-4", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ADC: //0x03C0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorADCMask.NoVersion: + sb.AppendLine("Device complies with standard ADC, no version"); + break; + case (int)SCSIVersionDescriptorADCMask.T10_1558_r6: + sb.AppendLine("Device complies with T10/1558-D revision 6 (ADC)"); + break; + case (int)SCSIVersionDescriptorADCMask.T10_1558_r7: + sb.AppendLine("Device complies with T10/1558-D revision 7 (ADC)"); + break; + case (int)SCSIVersionDescriptorADCMask.ANSI_2005: + sb.AppendLine("Device complies with ANSI INCITS 403-2005 (ADC)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ADC", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SES2: //0x03E0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard SES-2, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SES-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSC3: //0x0400 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard SSC-3, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSC-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.MMC5: //0x0420 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard MMC-5, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard MMC-5", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.OSD2: //0x0440 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard OSD-2, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard OSD-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPC4: //0x0460 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard SPC-4, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPC-4", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SMC3: //0x0480 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard SMC-3, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SMC-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ADC2: //0x04A0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard ADC-2, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ADC-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSA_TL2: //0x0820 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSA_TL2Mask.NoVersion: + sb.AppendLine("Device complies with standard SSA-TL2, no version"); + break; + case (int)SCSIVersionDescriptorSSA_TL2Mask.T10_1147_r05b: + sb.AppendLine("Device complies with T10.1/1147 revision 05b (SSA-TL2)"); + break; + case (int)SCSIVersionDescriptorSSA_TL2Mask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.308:1998 (SSA-TL2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSA-TL2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSA_TL1: //0x0840 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSA_TL1Mask.NoVersion: + sb.AppendLine("Device complies with standard SSA-TL1, no version"); + break; + case (int)SCSIVersionDescriptorSSA_TL1Mask.T10_0989_r10b: + sb.AppendLine("Device complies with T10.1/0989 revision 10b (SSA-TL1)"); + break; + case (int)SCSIVersionDescriptorSSA_TL1Mask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.295:1996 (SSA-TL1)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSA-TL1", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSA_S3P: //0x0860 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSA_S3PMask.NoVersion: + sb.AppendLine("Device complies with standard SSA-S3P, no version"); + break; + case (int)SCSIVersionDescriptorSSA_S3PMask.T10_1051_r05b: + sb.AppendLine("Device complies with T10.1/1051 revision 05b (SSA-S3P)"); + break; + case (int)SCSIVersionDescriptorSSA_S3PMask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.309:1998 (SSA-S3P)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSA-S3P", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSA_S2P: //0x0880 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSA_S2PMask.NoVersion: + sb.AppendLine("Device complies with standard SSA-S2P, no version"); + break; + case (int)SCSIVersionDescriptorSSA_S2PMask.T10_1121_r07b: + sb.AppendLine("Device complies with T10.1/1121 revision 07b (SSA-S2P)"); + break; + case (int)SCSIVersionDescriptorSSA_S2PMask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.294:1996 (SSA-S2P)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSA-S2P", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SIP: //0x08A0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSIPMask.NoVersion: + sb.AppendLine("Device complies with standard SIP, no version"); + break; + case (int)SCSIVersionDescriptorSIPMask.T10_0856_r10: + sb.AppendLine("Device complies with T10/0856 revision 10 (SIP)"); + break; + case (int)SCSIVersionDescriptorSIPMask.ANSI_1997: + sb.AppendLine("Device complies with ANSI X3.292:1997 (SIP)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SIP", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FCP: //0x08C0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCPMask.NoVersion: + sb.AppendLine("Device complies with standard FCP, no version"); + break; + case (int)SCSIVersionDescriptorFCPMask.T10_0993_r12: + sb.AppendLine("Device complies with T10/0993 revision 12 (FCP)"); + break; + case (int)SCSIVersionDescriptorFCPMask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.269:1996 (FCP)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FCP", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SBP2: //0x08E0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSBP2Mask.NoVersion: + sb.AppendLine("Device complies with standard SBP-2, no version"); + break; + case (int)SCSIVersionDescriptorSBP2Mask.T10_1155_r04: + sb.AppendLine("Device complies with T10/1155 revision 04 (SBP-2)"); + break; + case (int)SCSIVersionDescriptorSBP2Mask.ANSI_1999: + sb.AppendLine("Device complies with ANSI NCITS.325:1999 (SBP-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SBP-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FCP2: //0x0900 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCP2Mask.NoVersion: + sb.AppendLine("Device complies with standard FCP-2, no version"); + break; + case (int)SCSIVersionDescriptorFCP2Mask.T10_1144_r4: + sb.AppendLine("Device complies with T10/1144-D revision 4 (FCP-2)"); + break; + case (int)SCSIVersionDescriptorFCP2Mask.T10_1144_r7: + sb.AppendLine("Device complies with T10/1144-D revision 7 (FCP-2)"); + break; + case (int)SCSIVersionDescriptorFCP2Mask.T10_1144_r7a: + sb.AppendLine("Device complies with T10/1144-D revision 7a (FCP-2)"); + break; + case (int)SCSIVersionDescriptorFCP2Mask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 350-2003 (FCP-2)"); + break; + case (int)SCSIVersionDescriptorFCP2Mask.T10_1144_r8: + sb.AppendLine("Device complies with T10/1144-D revision 8 (FCP-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FCP-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SST: //0x0920 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSTMask.NoVersion: + sb.AppendLine("Device complies with standard SST, no version"); + break; + case (int)SCSIVersionDescriptorSSTMask.T10_1380_r8b: + sb.AppendLine("Device complies with T10/1380-D revision 8b (SST)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SST", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SRP: //0x0940 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSRPMask.NoVersion: + sb.AppendLine("Device complies with standard SRP, no version"); + break; + case (int)SCSIVersionDescriptorSRPMask.T10_1415_r10: + sb.AppendLine("Device complies with T10/1415-D revision 10 (SRP)"); + break; + case (int)SCSIVersionDescriptorSRPMask.T10_1415_r16a: + sb.AppendLine("Device complies with T10/1415-D revision 16a (SRP)"); + break; + case (int)SCSIVersionDescriptorSRPMask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 365-2002 (SRP)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SRP", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.iSCSI: //0x0960 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard iSCSI, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard iSCSI", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SBP3: //0x0980 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSBP3Mask.NoVersion: + sb.AppendLine("Device complies with standard SBP-3, no version"); + break; + case (int)SCSIVersionDescriptorSBP3Mask.T10_1467_r1f: + sb.AppendLine("Device complies with T10/1467-D revision 1f (SBP-3)"); + break; + case (int)SCSIVersionDescriptorSBP3Mask.T10_1467_r3: + sb.AppendLine("Device complies with T10/1467-D revision 3 (SBP-3)"); + break; + case (int)SCSIVersionDescriptorSBP3Mask.T10_1467_r4: + sb.AppendLine("Device complies with T10/1467-D revision 4 (SBP-3)"); + break; + case (int)SCSIVersionDescriptorSBP3Mask.T10_1467_r5: + sb.AppendLine("Device complies with T10/1467-D revision 5 (SBP-3)"); + break; + case (int)SCSIVersionDescriptorSBP3Mask.ANSI_2004: + sb.AppendLine("Device complies with ANSI INCITS 375-2004 (SBP-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SBP-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ADP: //0x09C0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard ADP, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ADP", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ADT: //0x09E0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorADTMask.NoVersion: + sb.AppendLine("Device complies with standard ADT, no version"); + break; + case (int)SCSIVersionDescriptorADTMask.T10_1557_r11: + sb.AppendLine("Device complies with T10/1557-D revision 11 (ADT)"); + break; + case (int)SCSIVersionDescriptorADTMask.T10_1557_r14: + sb.AppendLine("Device complies with T10/1557-D revision 14 (ADT)"); + break; + case (int)SCSIVersionDescriptorADTMask.ANSI_2005: + sb.AppendLine("Device complies with ANSI INCITS 406-2005 (ADT)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ADT", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FCP3: //0x0A00 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCP3Mask.NoVersion: + sb.AppendLine("Device complies with standard FCP-3, no version"); + break; + case (int)SCSIVersionDescriptorFCP3Mask.T10_1560_r4: + sb.AppendLine("Device complies with T10/1560-D revision 4 (FCP-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FCP-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ADT2: //0x0A20 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard ADT-2, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ADT-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPI: //0x0AA0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPIMask.NoVersion: + sb.AppendLine("Device complies with standard SPI, no version"); + break; + case (int)SCSIVersionDescriptorSPIMask.T10_0855_r15a: + sb.AppendLine("Device complies with T10/0855 revision 15a (SPI)"); + break; + case (int)SCSIVersionDescriptorSPIMask.ANSI_1995: + sb.AppendLine("Device complies with ANSI X3.253:1995 (SPI)"); + break; + case (int)SCSIVersionDescriptorSPIMask.T10_0855_r15a_Amnd_3a: + sb.AppendLine("Device complies with T10/0855 revision 15a with SPI Amnd revision 3a (SPI)"); + break; + case (int)SCSIVersionDescriptorSPIMask.ANSI_1995_1998: + sb.AppendLine("Device complies with ANSI X3.253:1995 with SPI Amnd ANSI X3.253/AM1:1998 (SPI)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPI", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.Fast20: //0xAC0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFast20Mask.NoVersion: + sb.AppendLine("Device complies with standard Fast-20, no version"); + break; + case (int)SCSIVersionDescriptorFast20Mask.T10_1071_r06: + sb.AppendLine("Device complies with T10/1071 revision 06 (Fast-20)"); + break; + case (int)SCSIVersionDescriptorFast20Mask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.277:1996 (Fast-20)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard Fast-20", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPI2: //0x0AE0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPI2Mask.NoVersion: + sb.AppendLine("Device complies with standard SPI-2, no version"); + break; + case (int)SCSIVersionDescriptorSPI2Mask.T10_1142_r20b: + sb.AppendLine("Device complies with T10/1142 revision 20b (SPI-2)"); + break; + case (int)SCSIVersionDescriptorSPI2Mask.ANSI_1999: + sb.AppendLine("Device complies with ANSI X3.302:1999 (SPI-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPI-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPI3: //0x0B00 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPI3Mask.NoVersion: + sb.AppendLine("Device complies with standard SPI-3, no version"); + break; + case (int)SCSIVersionDescriptorSPI3Mask.T10_1302D_r10: + sb.AppendLine("Device complies with T10/1302-D revision 10 (SPI-3)"); + break; + case (int)SCSIVersionDescriptorSPI3Mask.T10_1302D_r13a: + sb.AppendLine("Device complies with T10/1302-D revision 13a (SPI-3)"); + break; + case (int)SCSIVersionDescriptorSPI3Mask.T10_1302D_r14: + sb.AppendLine("Device complies with T10/1302-D revision 14 (SPI-3)"); + break; + case (int)SCSIVersionDescriptorSPI3Mask.ANSI_2000: + sb.AppendLine("Device complies with ANSI NCITS.336:2000 (SPI-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPI-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.EPI: //0x0B20 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorEPIMask.NoVersion: + sb.AppendLine("Device complies with standard EPI, no version"); + break; + case (int)SCSIVersionDescriptorEPIMask.T10_1134_r16: + sb.AppendLine("Device complies with T10/1134 revision 16 (EPI)"); + break; + case (int)SCSIVersionDescriptorEPIMask.ANSI_1999: + sb.AppendLine("Device complies with ANSI NCITS TR-23:1999 (EPI)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard EPI", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPI4: //0x0B40 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPI4Mask.NoVersion: + sb.AppendLine("Device complies with standard SPI-4, no version"); + break; + case (int)SCSIVersionDescriptorSPI4Mask.T10_1365_r7: + sb.AppendLine("Device complies with T10/1365-D revision 7 (SPI-4)"); + break; + case (int)SCSIVersionDescriptorSPI4Mask.T10_1365_r9: + sb.AppendLine("Device complies with T10/1365-D revision 9 (SPI-4)"); + break; + case (int)SCSIVersionDescriptorSPI4Mask.ANSI_2002: + sb.AppendLine("Device complies with ANSI INCITS 362-2002 (SPI-4)"); + break; + case (int)SCSIVersionDescriptorSPI4Mask.T10_1365_r10: + sb.AppendLine("Device complies with T10/1365-D revision 10 (SPI-4)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPI-4", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SPI5: //0x0B40 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSPI5Mask.NoVersion: + sb.AppendLine("Device complies with standard SPI-5, no version"); + break; + case (int)SCSIVersionDescriptorSPI5Mask.T10_1525_r3: + sb.AppendLine("Device complies with T10/1525-D revision 3 (SPI-5)"); + break; + case (int)SCSIVersionDescriptorSPI5Mask.T10_1525_r5: + sb.AppendLine("Device complies with T10/1525-D revision 5 (SPI-5)"); + break; + case (int)SCSIVersionDescriptorSPI5Mask.T10_1525_r6: + sb.AppendLine("Device complies with T10/1525-D revision 6 (SPI-5)"); + break; + case (int)SCSIVersionDescriptorSPI5Mask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 367-2003 (SPI-5)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SPI-5", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAS: //0x0BE0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSASMask.NoVersion: + sb.AppendLine("Device complies with standard (SAS)"); + break; + case (int)SCSIVersionDescriptorSASMask.T10_1562_r01: + sb.AppendLine("Device complies with T10/1562-D revision 01 (SAS)"); + break; + case (int)SCSIVersionDescriptorSASMask.T10_1562_r03: + sb.AppendLine("Device complies with T10/1562-D revision 03 (SAS)"); + break; + case (int)SCSIVersionDescriptorSASMask.T10_1562_r04: + case (int)SCSIVersionDescriptorSASMask.T10_1562_r04bis: + sb.AppendLine("Device complies with T10/1562-D revision 04 (SAS)"); + break; + case (int)SCSIVersionDescriptorSASMask.T10_1562_r05: + sb.AppendLine("Device complies with T10/1562-D revision 05 (SAS)"); + break; + case (int)SCSIVersionDescriptorSASMask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 376-2003 (SAS)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAS", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAS11: //0x0C00 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSAS11Mask.NoVersion: + sb.AppendLine("Device complies with standard SAS 1.1, no version"); + break; + case (int)SCSIVersionDescriptorSAS11Mask.T10_1601_r9: + sb.AppendLine("Device complies with T10/1601-D revision 9 (SAS 1.1)"); + break; + case (int)SCSIVersionDescriptorSAS11Mask.T10_1601_r10: + sb.AppendLine("Device complies with T10/1601-D revision 10 (SAS 1.1)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAS 1.1", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_PH: //0x0D20 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCPHMask.NoVersion: + sb.AppendLine("Device complies with standard FC-PH, no version"); + break; + case (int)SCSIVersionDescriptorFCPHMask.ANSI_1994: + sb.AppendLine("Device complies with ANSI X3.230:1994 (FC-PH)"); + break; + case (int)SCSIVersionDescriptorFCPHMask.ANSI_1994_1996: + sb.AppendLine("Device complies with ANSI X3.230:1994 with Amnd 1 ANSI X3.230/AM1:1996 (FC-PH)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-PH", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_AL: //0x0D40 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCALMask.NoVersion: + sb.AppendLine("Device complies with standard FC-AL, no version"); + break; + case (int)SCSIVersionDescriptorFCALMask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.272:1996 (FC-AL)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-AL", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_AL2: //0x0D60 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCAL2Mask.NoVersion: + sb.AppendLine("Device complies with standard FC-AL-2, no version"); + break; + case (int)SCSIVersionDescriptorFCAL2Mask.T11_1133_r70: + sb.AppendLine("Device complies with T11/1133 revision 7.0 (FC-AL-2)"); + break; + case (int)SCSIVersionDescriptorFCAL2Mask.ANSI_1999: + sb.AppendLine("Device complies with ANSI NCITS.332:1999 (FC-AL-2)"); + break; + case (int)SCSIVersionDescriptorFCAL2Mask.ANSI_1999_2002: + sb.AppendLine("Device complies with ANSI INCITS 332-1999 with Amnd 1 AM1-2002 (FC-AL-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-AL-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_PH3: //0x0D80 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCPH3Mask.NoVersion: + sb.AppendLine("Device complies with standard FC-PH-3, no version"); + break; + case (int)SCSIVersionDescriptorFCPH3Mask.ANSI_1998: + sb.AppendLine("Device complies with ANSI X3.303-1998 (FC-PH-3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-PH-3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_FS: //0x0DA0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCFSMask.NoVersion: + sb.AppendLine("Device complies with standard FC-FS, no version"); + break; + case (int)SCSIVersionDescriptorFCFSMask.T11_1331_r12: + sb.AppendLine("Device complies with T11/1331 revision 1.2 (FC-FS)"); + break; + case (int)SCSIVersionDescriptorFCFSMask.T11_1331_r17: + sb.AppendLine("Device complies with T11/1331 revision 1.7 (FC-FS)"); + break; + case (int)SCSIVersionDescriptorFCFSMask.ANSI_2003: + sb.AppendLine("Device complies with ANSI INCITS 373-2003 (FC-FS)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-FS", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_PI: //0x0DC0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCPIMask.NoVersion: + sb.AppendLine("Device complies with standard FC-PI, no version"); + break; + case (int)SCSIVersionDescriptorFCPIMask.ANSI_2002: + sb.AppendLine("Device complies with ANSI INCITS 352-2002 (FC-PI)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-PI", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_PI2: //0x0DE0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCPI2Mask.NoVersion: + sb.AppendLine("Device complies with standard FC-PI-2, no version"); + break; + case (int)SCSIVersionDescriptorFCPI2Mask.T11_1506_r50: + sb.AppendLine("Device complies with T11/1506-D revision 5.0 (FC-PI-2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-PI-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_FS2: //0x0E00 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard FC-FS-2, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-FS-2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_LS: //0x0E20 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard FC-LS, no version"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-LS", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_SP: //0x0E40 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCSPMask.NoVersion: + sb.AppendLine("Device complies with standard FC-SP, no version"); + break; + case (int)SCSIVersionDescriptorFCSPMask.T11_1570_r16: + sb.AppendLine("Device complies with T11/1570-D revision 1.6 (FC-SP)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-SP", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_DA: //0x12E0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCDAMask.NoVersion: + sb.AppendLine("Device complies with standard FC-DA, no version"); + break; + case (int)SCSIVersionDescriptorFCDAMask.T11_1513_r31: + sb.AppendLine("Device complies with T11/1513-DT revision 3.1 (FC-DA)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-DA", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_Tape: //0x1300 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCTapeMask.NoVersion: + sb.AppendLine("Device complies with standard FC-Tape, no version"); + break; + case (int)SCSIVersionDescriptorFCTapeMask.T11_1315_r116: + sb.AppendLine("Device complies with T11/1315 revision 1.16 (FC-Tape)"); + break; + case (int)SCSIVersionDescriptorFCTapeMask.T11_1315_r117: + sb.AppendLine("Device complies with T11/1315 revision 1.17 (FC-Tape)"); + break; + case (int)SCSIVersionDescriptorFCTapeMask.ANSI_1999: + sb.AppendLine("Device complies with ANSI NCITS TR-24:1999 (FC-Tape)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-Tape", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_FLA: //0x1320 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCFLAMask.NoVersion: + sb.AppendLine("Device complies with standard FC-FLA, no version"); + break; + case (int)SCSIVersionDescriptorFCFLAMask.T11_1235_r7: + sb.AppendLine("Device complies with T11/1235 revision 7 (FC-FLA)"); + break; + case (int)SCSIVersionDescriptorFCFLAMask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS TR-20:1998 (FC-FLA)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-FLA", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.FC_PLDA: //0x1340 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorFCPLDAMask.NoVersion: + sb.AppendLine("Device complies with standard FC-PLDA, no version"); + break; + case (int)SCSIVersionDescriptorFCPLDAMask.T11_1162_r21: + sb.AppendLine("Device complies with T11/1162 revision 2.1 (FC-PLDA)"); + break; + case (int)SCSIVersionDescriptorFCPLDAMask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS TR-19:1998 (FC-PLDA)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard FC-PLDA", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSA_PH2: //0x1360 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSAPH2Mask.NoVersion: + sb.AppendLine("Device complies with standard SSA-PH2, no version"); + break; + case (int)SCSIVersionDescriptorSSAPH2Mask.T10_1145_r09c: + sb.AppendLine("Device complies with T10.1/1145 revision 09c (SSA-PH2)"); + break; + case (int)SCSIVersionDescriptorSSAPH2Mask.ANSI_1996: + sb.AppendLine("Device complies with ANSI X3.293:1996 (SSA-PH2)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSA-PH2", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SSA_PH3: //0x1380 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorSSAPH3Mask.NoVersion: + sb.AppendLine("Device complies with standard SSA-PH3, no version"); + break; + case (int)SCSIVersionDescriptorSSAPH3Mask.T10_1146_r05b: + sb.AppendLine("Device complies with T10.1/1146 revision 05b (SSA-PH3)"); + break; + case (int)SCSIVersionDescriptorSSAPH3Mask.ANSI_1998: + sb.AppendLine("Device complies with ANSI NCITS.307:1998 (SSA-PH3)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SSA-PH3", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.IEEE1394: //0x14A0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorIEEE1394Mask.NoVersion: + sb.AppendLine("Device complies with standard IEEE-1394, no version"); + break; + case (int)SCSIVersionDescriptorIEEE1394Mask.ANSI_1995: + sb.AppendLine("Device complies with ANSI IEEE 1394:1995"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard IEEE-1394", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.IEEE1394a: //0x14C0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard IEEE-1394a"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard IEEE-1394a", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.IEEE1394b: //0x14E0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard IEEE-1394b"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard IEEE-1394b", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ATA_ATAPI6: //0x15E0 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorATA6Mask.NoVersion: + sb.AppendLine("Device complies with standard ATA/ATAPI-6, no version"); + break; + case (int)SCSIVersionDescriptorATA6Mask.ANSI_2002: + sb.AppendLine("Device complies with ANSI INCITS 361-2002 (ATA/ATAPI-6)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ATA/ATAPI-6)", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ATA_ATAPI7: //0x1600 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorATA7Mask.NoVersion: + sb.AppendLine("Device complies with standard ATA/ATAPI-7, no version"); + break; + case (int)SCSIVersionDescriptorATA7Mask.T13_1532_r3: + sb.AppendLine("Device complies with T13/1532-D revision 3 (ATA/ATAPI-7)"); + break; + case (int)SCSIVersionDescriptorATA7Mask.ANSI_2005: + sb.AppendLine("Device complies with ANSI INCITS 397-2005 (ATA/ATAPI-7)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ATA/ATAPI-7", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.ATA_ATAPI8: //0x1620 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorATA8Mask.ATA8_AAM: + sb.AppendLine("Device complies with standard ATA8-AAM Architecture Model (no version claimed)"); + break; + case (int)SCSIVersionDescriptorATA8Mask.ATA8_PT: + sb.AppendLine("Device complies with standard ATA8-PT Parallel Transport (no version claimed)"); + break; + case (int)SCSIVersionDescriptorATA8Mask.ATA8_AST: + sb.AppendLine("Device complies with standard ATA8-AST Serial Transport (no version claimed)"); + break; + case (int)SCSIVersionDescriptorATA8Mask.ATA8_ACS: + sb.AppendLine("Device complies with standard ATA8-ACS ATA/ATAPI Command Set (no version claimed)"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ATA/ATAPI-8", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.USB: //0x1720 + switch (VersionDescriptor & 0x001F) + { + case (int)SCSIVersionDescriptorUSBMask.NoVersion: + sb.AppendLine("Device complies with Universal Serial Bus specification, no revision claimed"); + break; + case (int)SCSIVersionDescriptorUSBMask.USB11: + sb.AppendLine("Device complies with Universal Serial Bus Specification, Revision 1.1"); + break; + case (int)SCSIVersionDescriptorUSBMask.USB20: + sb.AppendLine("Device complies with Universal Serial Bus Specification, Revision 2.0"); + break; + case (int)SCSIVersionDescriptorUSBMask.USB_MSC_BULK: + sb.AppendLine("Device complies with Universal Serial Bus Mass Storage Class Bulk-Only Transport, Revision 1.0"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard ", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + case (int)SCSIVersionDescriptorStandardMask.SAT: //0x1EA0 + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendLine("Device complies with standard SAT"); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of standard SAT", VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + default: + switch (VersionDescriptor & 0x001F) + { + case 0x00: + sb.AppendFormat("Device complies with unknown standard 0x:{0:X4}", VersionDescriptor & 0x001F).AppendLine(); + break; + default: + sb.AppendFormat("Device claims unknown version 0x{0:X2} of unknown standard 0x:{1:X4}", VersionDescriptor & 0x001F, VersionDescriptor & 0x001F).AppendLine(); + break; + } + break; + } + } + + //if (MainClass.isDebug) + { + sb.AppendFormat("DEBUG (SCSIInquiry Decoder): Reserved byte 1, bits 6 to 0 = 0x{0:X2}", response.Reserved1).AppendLine(); + sb.AppendFormat("DEBUG (SCSIInquiry Decoder): Reserved byte 5, bits 2 to 1 = 0x{0:X2}", response.Reserved2).AppendLine(); + sb.AppendFormat("DEBUG (SCSIInquiry Decoder): Reserved byte 56, bits 7 to 4 = 0x{0:X2}", response.Reserved3).AppendLine(); + sb.AppendFormat("DEBUG (SCSIInquiry Decoder): Reserved byte 57 = 0x{0:X2}", response.Reserved4).AppendLine(); + + if (response.Reserved5 != null) + { + sb.AppendLine("DEBUG (SCSIInquiry Decoder): Reserved bytes 74 to 95"); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.Reserved5, 60)); + sb.AppendLine("============================================================"); + } + + if (response.VendorSpecific != null) + { + sb.AppendLine("DEBUG (SCSIInquiry Decoder): Vendor-specific bytes 36 to 55"); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VendorSpecific, 60)); + sb.AppendLine("============================================================"); + } + + if (response.VendorSpecific2 != null) + { + sb.AppendFormat("DEBUG (SCSIInquiry Decoder): Vendor-specific bytes 96 to {0}", response.AdditionalLength+4).AppendLine(); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VendorSpecific2, 60)); + sb.AppendLine("============================================================"); + } + } + + return sb.ToString(); + } + + public static string PrettifySCSIInquiry(byte[] SCSIInquiryResponse) + { + SCSIInquiry? decoded = DecodeSCSIInquiry(SCSIInquiryResponse); + return PrettifySCSIInquiry(decoded); + } + + #endregion Public methods + + #region Public structures + + // SCSI INQUIRY command response + public struct SCSIInquiry + { + /// + /// Peripheral qualifier + /// Byte 0, bits 7 to 5 + /// + public byte PeripheralQualifier; + /// + /// Peripheral device type + /// Byte 0, bits 4 to 0 + /// + public byte PeripheralDeviceType; + /// + /// Removable device + /// Byte 1, bit 7 + /// + public bool RMB; + /// + /// Reserved + /// Byte 1, bits 6 to 0 + /// + public byte Reserved1; + /// + /// ISO/IEC SCSI Standard Version + /// Byte 2, bits 7 to 6, mask = 0xC0, >> 6 + /// + public byte ISOVersion; + /// + /// ECMA SCSI Standard Version + /// Byte 2, bits 5 to 3, mask = 0x38, >> 3 + /// + public byte ECMAVersion; + /// + /// ANSI SCSI Standard Version + /// Byte 2, bits 2 to 0, mask = 0x07 + /// + public byte ANSIVersion; + /// + /// Asynchronous Event Reporting Capability supported + /// Byte 3, bit 7 + /// + public bool AERC; + /// + /// Device supports TERMINATE TASK command + /// Byte 3, bit 6 + /// + public bool TrmTsk; + /// + /// Supports setting Normal ACA + /// Byte 3, bit 5 + /// + public bool NormACA; + /// + /// Supports LUN hierarchical addressing + /// Byte 3, bit 4 + /// + public bool HiSup; + /// + /// Responde data format + /// Byte 3, bit 3 to 0 + /// + public byte ResponseDataFormat; + /// + /// Lenght of total INQUIRY response minus 4 + /// Byte 4 + /// + public byte AdditionalLength; + /// + /// Device contains an embedded storage array controller + /// Byte 5, bit 7 + /// + public bool SCCS; + /// + /// Device contains an Access Control Coordinator + /// Byte 5, bit 6 + /// + public bool ACC; + /// + /// Supports asymetrical logical unit access + /// Byte 5, bits 5 to 4 + /// + public byte TPGS; + /// + /// Supports third-party copy commands + /// Byte 5, bit 3 + /// + public bool ThreePC; + /// + /// Reserved + /// Byte 5, bits 2 to 1 + /// + public byte Reserved2; + /// + /// Supports protection information + /// Byte 5, bit 0 + /// + public bool Protect; + /// + /// Supports basic queueing + /// Byte 6, bit 7 + /// + public bool BQue; + /// + /// Device contains an embedded enclosure services component + /// Byte 6, bit 6 + /// + public bool EncServ; + /// + /// Vendor-specific + /// Byte 6, bit 5 + /// + public bool VS1; + /// + /// Multi-port device + /// Byte 6, bit 4 + /// + public bool MultiP; + /// + /// Device contains or is attached to a medium changer + /// Byte 6, bit 3 + /// + public bool MChngr; + /// + /// Device supports request and acknowledge handshakes + /// Byte 6, bit 2 + /// + public bool ACKREQQ; + /// + /// Supports 32-bit wide SCSI addresses + /// Byte 6, bit 1 + /// + public bool Addr32; + /// + /// Supports 16-bit wide SCSI addresses + /// Byte 6, bit 0 + /// + public bool Addr16; + /// + /// Device supports relative addressing + /// Byte 7, bit 7 + /// + public bool RelAddr; + /// + /// Supports 32-bit wide data transfers + /// Byte 7, bit 6 + /// + public bool WBus32; + /// + /// Supports 16-bit wide data transfers + /// Byte 7, bit 5 + /// + public bool WBus16; + /// + /// Supports synchronous data transfer + /// Byte 7, bit 4 + /// + public bool Sync; + /// + /// Supports linked commands + /// Byte 7, bit 3 + /// + public bool Linked; + /// + /// Supports CONTINUE TASK and TARGET TRANSFER DISABLE commands + /// Byte 7, bit 2 + /// + public bool TranDis; + /// + /// Supports TCQ queue + /// Byte 7, bit 1 + /// + public bool CmdQue; + /// + /// Vendor-specific + /// Byte 7, bit 0 + /// + public bool VS2; + /// + /// Vendor identification + /// Bytes 8 to 15 + /// + public byte[] VendorIdentification; + /// + /// Product identification + /// Bytes 16 to 31 + /// + public byte[] ProductIdentification; + /// + /// Product revision level + /// Bytes 32 to 35 + /// + public byte[] ProductRevisionLevel; + /// + /// Vendor-specific data + /// Bytes 36 to 55 + /// + public byte[] VendorSpecific; + /// + /// Byte 56, bits 7 to 4 + /// + public byte Reserved3; + /// + /// Supported SPI clocking + /// Byte 56, bits 3 to 2 + /// + public byte Clocking; + /// + /// Device supports Quick Arbitration and Selection + /// Byte 56, bit 1 + /// + public bool QAS; + /// + /// Supports information unit transfers + /// Byte 56, bit 0 + /// + public bool IUS; + /// + /// Reserved + /// Byte 57 + /// + public byte Reserved4; + /// + /// Array of version descriptors + /// Bytes 58 to 73 + /// + public UInt16[] VersionDescriptors; + /// + /// Reserved + /// Bytes 74 to 95 + /// + public byte[] Reserved5; + /// + /// Reserved + /// Bytes 96 to end + /// + public byte[] VendorSpecific2; + } + + #endregion Public structures + } +} +