From ec5f9b60447b3b17b1748f1cc651de873763b7e9 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 13 Oct 2016 04:55:00 +0100 Subject: [PATCH] Added SCSI EVPD page 83h. --- DiscImageChef.Decoders/ChangeLog | 4 + DiscImageChef.Decoders/SCSI/EVPD.cs | 199 +++++++++++++++++++++++++++ DiscImageChef/ChangeLog | 5 + DiscImageChef/Commands/DeviceInfo.cs | 38 ++--- 4 files changed, 220 insertions(+), 26 deletions(-) diff --git a/DiscImageChef.Decoders/ChangeLog b/DiscImageChef.Decoders/ChangeLog index 4bd0a88b..3719ea8b 100644 --- a/DiscImageChef.Decoders/ChangeLog +++ b/DiscImageChef.Decoders/ChangeLog @@ -1,3 +1,7 @@ +2016-10-13 Natalia Portillo + + * EVPD.cs: Added SCSI EVPD page 83h. + 2016-10-13 Natalia Portillo * EVPD.cs: Implemented SCSI EVPD 82h diff --git a/DiscImageChef.Decoders/SCSI/EVPD.cs b/DiscImageChef.Decoders/SCSI/EVPD.cs index b0a9618f..e68b825e 100644 --- a/DiscImageChef.Decoders/SCSI/EVPD.cs +++ b/DiscImageChef.Decoders/SCSI/EVPD.cs @@ -31,6 +31,8 @@ // ****************************************************************************/ using System; +using System.Collections.Generic; +using System.Text; namespace DiscImageChef.Decoders.SCSI { @@ -127,6 +129,203 @@ namespace DiscImageChef.Decoders.SCSI return StringHandlers.CToString(ascii); } + + #region EVPD Page 0x83: Device identification page + + public enum IdentificationCodeSet : byte + { + /// + /// Identifier is binary + /// + Binary = 1, + /// + /// Identifier is pure ASCII + /// + ASCII = 2 + } + + public enum IdentificationTypes : byte + { + /// + /// No assignment authority was used and there is no guarantee the identifier is unique + /// + NoAuthority = 0, + /// + /// Concatenates vendor and product identifier from INQUIRY plus unit serial number from page 80h + /// + Inquiry = 1, + /// + /// Identifier is a 64-bit IEEE EUI-64 + /// + EUI = 2, + /// + /// Identifier is a 64-bit FC-PH Name_Identifier + /// + FCPH = 3 + } + + public struct IdentificatonDescriptor + { + /// + /// Defines how the identifier is stored + /// + public IdentificationCodeSet CodeSet; + /// + /// Defines the type of the identifier + /// + public IdentificationTypes Type; + /// + /// Length of the identifier + /// + public byte Length; + /// + /// Identifier as an ASCII string if applicable + /// + public string ASCII; + /// + /// Binary identifier + /// + public byte[] Binary; + } + + /// + /// Device identification page + /// Page code 0x83 + /// + public struct Page_83 + { + /// + /// The peripheral qualifier. + /// + public PeripheralQualifiers PeripheralQualifier; + /// + /// The type of the peripheral device. + /// + public PeripheralDeviceTypes PeripheralDeviceType; + /// + /// The page code. + /// + public byte PageCode; + /// + /// The length of the page. + /// + public byte PageLength; + /// + /// The descriptors. + /// + public IdentificatonDescriptor[] Descriptors; + } + + public static Page_83? DecodePage_83(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0x83) + return null; + + if(pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 6) + return null; + + Page_83 decoded = new Page_83(); + + decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); + decoded.PageLength = (byte)(pageResponse[3] + 4); + + int position = 4; + List descriptors = new List(); + + while(position < pageResponse.Length) + { + IdentificatonDescriptor descriptor = new IdentificatonDescriptor(); + descriptor.CodeSet = (IdentificationCodeSet)(pageResponse[position] & 0x0F); + descriptor.Type = (IdentificationTypes)(pageResponse[position + 1] & 0x0F); + descriptor.Length = pageResponse[position + 3]; + descriptor.Binary = new byte[descriptor.Length]; + Array.Copy(pageResponse, position + 4, descriptor.Binary, 0, descriptor.Length); + if(descriptor.CodeSet == IdentificationCodeSet.ASCII) + descriptor.ASCII = StringHandlers.CToString(descriptor.Binary); + else + descriptor.ASCII = ""; + + position += 4 + descriptor.Length; + } + + return decoded; + } + + public static string PrettifyPage_83(byte[] pageResponse) + { + return PrettifyPage_83(DecodePage_83(pageResponse)); + } + + public static string PrettifyPage_83(Page_83? modePage) + { + if(!modePage.HasValue) + return null; + + Page_83 page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Device identification page:"); + + if(page.Descriptors.Length == 0) + { + sb.AppendLine("\tThere are no identifiers"); + return sb.ToString(); + } + + foreach(IdentificatonDescriptor descriptor in page.Descriptors) + { + switch(descriptor.Type) + { + case IdentificationTypes.NoAuthority: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII) + sb.AppendFormat("Vendor descriptor contains: {0}", descriptor.ASCII).AppendLine(); + else if(descriptor.CodeSet == IdentificationCodeSet.Binary) + sb.AppendFormat("Vendor descriptor contains binary data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + else + sb.AppendFormat("Vendor descriptor contains unknown kind {1} of data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.CodeSet).AppendLine(); + break; + case IdentificationTypes.Inquiry: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII) + sb.AppendFormat("Inquiry descriptor contains: {0}", descriptor.ASCII).AppendLine(); + else if(descriptor.CodeSet == IdentificationCodeSet.Binary) + sb.AppendFormat("Inquiry descriptor contains binary data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + else + sb.AppendFormat("Inquiry descriptor contains unknown kind {1} of data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.CodeSet).AppendLine(); + break; + case IdentificationTypes.EUI: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII) + sb.AppendFormat("IEEE EUI-64: {0}", descriptor.ASCII).AppendLine(); + else + sb.AppendFormat("IEEE EUI-64: {0:X16}", descriptor.Binary).AppendLine(); + break; + case IdentificationTypes.FCPH: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII) + sb.AppendFormat("FC-PH Name_Identifier: {0}", descriptor.ASCII).AppendLine(); + else + sb.AppendFormat("FC-PH Name_Identifier: {0:X16}", descriptor.Binary).AppendLine(); + break; + default: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII) + sb.AppendFormat("Unknown descriptor type {1} contains: {0}", descriptor.ASCII, (byte)descriptor.Type).AppendLine(); + else if(descriptor.CodeSet == IdentificationCodeSet.Binary) + sb.AppendFormat("Inquiry descriptor type {1} contains binary data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.Type).AppendLine(); + else + sb.AppendFormat("Inquiry descriptor type {2} contains unknown kind {1} of data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.CodeSet, (byte)descriptor.Type).AppendLine(); + break; + } + } + + return sb.ToString(); + } + + #endregion EVPD Page 0x83: Device identification page } } diff --git a/DiscImageChef/ChangeLog b/DiscImageChef/ChangeLog index 87c6b52b..0d018102 100644 --- a/DiscImageChef/ChangeLog +++ b/DiscImageChef/ChangeLog @@ -1,3 +1,8 @@ +2016-10-13 Natalia Portillo + + * Commands/DeviceInfo.cs: + Added SCSI EVPD page 83h. + 2016-10-13 Natalia Portillo * Commands/DeviceInfo.cs: diff --git a/DiscImageChef/Commands/DeviceInfo.cs b/DiscImageChef/Commands/DeviceInfo.cs index dd276463..8e7c8094 100644 --- a/DiscImageChef/Commands/DeviceInfo.cs +++ b/DiscImageChef/Commands/DeviceInfo.cs @@ -209,12 +209,6 @@ namespace DiscImageChef.Commands Decoders.SCSI.Inquiry.SCSIInquiry? inq = Decoders.SCSI.Inquiry.Decode(inqBuf); DicConsole.WriteLine(Decoders.SCSI.Inquiry.Prettify(inq)); - bool scsi80 = false; - bool scsi82 = false; - string scsiSerial = null; - string scsiAsciiOperatingDefs = null; - StringBuilder sb = null; - sense = dev.ScsiInquiry(out inqBuf, out senseBuf, 0x00); if(!sense) @@ -230,9 +224,7 @@ namespace DiscImageChef.Commands sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); if(!sense) { - if(sb == null) - sb = new StringBuilder(); - sb.AppendFormat("Page 0x{0:X2}: ", Decoders.SCSI.EVPD.DecodeASCIIPage(inqBuf)).AppendLine(); + DicConsole.WriteLine("ASCII Page {0:X2}h: {1}", page, Decoders.SCSI.EVPD.DecodeASCIIPage(inqBuf)); doWriteFile(options.OutputPrefix, string.Format("_scsi_evpd_{0:X2}h.bin", page), string.Format("SCSI INQUIRY EVPD {0:X2}h", page), inqBuf); } @@ -242,9 +234,7 @@ namespace DiscImageChef.Commands sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); if(!sense) { - scsi80 = true; - scsiSerial = Decoders.SCSI.EVPD.DecodePage80(inqBuf); - + DicConsole.WriteLine("Unit Serial Number: {0}", Decoders.SCSI.EVPD.DecodePage80(inqBuf)); doWriteFile(options.OutputPrefix, string.Format("_scsi_evpd_{0:X2}h.bin", page), string.Format("SCSI INQUIRY EVPD {0:X2}h", page), inqBuf); } } @@ -253,9 +243,16 @@ namespace DiscImageChef.Commands sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); if(!sense) { - scsi82 = true; - scsiAsciiOperatingDefs = Decoders.SCSI.EVPD.DecodePage82(inqBuf); - + DicConsole.WriteLine("ASCII implemented operating definitions: {0}", Decoders.SCSI.EVPD.DecodePage82(inqBuf)); + doWriteFile(options.OutputPrefix, string.Format("_scsi_evpd_{0:X2}h.bin", page), string.Format("SCSI INQUIRY EVPD {0:X2}h", page), inqBuf); + } + } + else if(page == 0x83) + { + sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); + if(!sense) + { + DicConsole.WriteLine("{0}", Decoders.SCSI.EVPD.PrettifyPage_83(inqBuf)); doWriteFile(options.OutputPrefix, string.Format("_scsi_evpd_{0:X2}h.bin", page), string.Format("SCSI INQUIRY EVPD {0:X2}h", page), inqBuf); } } @@ -276,17 +273,6 @@ namespace DiscImageChef.Commands } } - if(scsi80) - DicConsole.WriteLine("Unit Serial Number: {0}", scsiSerial); - if(scsi82) - DicConsole.WriteLine("ASCII implemented operating definitions: {0}", scsiAsciiOperatingDefs); - - if(sb != null) - { - DicConsole.WriteLine("ASCII VPDs:"); - DicConsole.WriteLine(sb.ToString()); - } - byte[] modeBuf; double duration; Decoders.SCSI.Modes.DecodedMode? decMode = null;