From 751c2f468fdeba8b7bfc86639644349a96946123 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 5 Oct 2015 20:27:44 +0100 Subject: [PATCH] Move decoders to a separate library. --- BD.cs | 836 ++++++ CD.cs | 1603 ++++++++++++ ChangeLog | 12 + DVD.cs | 1083 ++++++++ DiscImageChef.Decoders.csproj | 52 + Floppy.cs | 808 ++++++ MMC.cs | 1121 ++++++++ Properties/AssemblyInfo.cs | 27 + SCSI.cs | 4582 +++++++++++++++++++++++++++++++++ 9 files changed, 10124 insertions(+) create mode 100644 BD.cs create mode 100644 CD.cs create mode 100644 ChangeLog create mode 100644 DVD.cs create mode 100644 DiscImageChef.Decoders.csproj create mode 100644 Floppy.cs create mode 100644 MMC.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 SCSI.cs 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 + } +} +