diff --git a/DiscImageChef.Server/App_Start/Ata.cs b/DiscImageChef.Server/App_Start/Ata.cs index 7cd67c062..27a5d30bd 100644 --- a/DiscImageChef.Server/App_Start/Ata.cs +++ b/DiscImageChef.Server/App_Start/Ata.cs @@ -36,12 +36,1778 @@ // ****************************************************************************/ // //$Id$ using System; +using System.Collections.Generic; +using DiscImageChef.Decoders.SCSI; +using DiscImageChef.Metadata; +using static DiscImageChef.Decoders.ATA.Identify; + namespace DiscImageChef.Server.App_Start { - public class Ata + public static class Ata { - public Ata() + public static void Report(ataType ataReport, bool cfa, bool atapi, ref bool removable, ref List ataOneValue, ref Dictionary ataTwoValue, ref testedMediaType[] testedMedia) { + string tmpString; + uint logicalsectorsize = 0; + + if(ataReport.ModelSpecified && !string.IsNullOrEmpty(ataReport.Model)) + ataTwoValue.Add("Model", ataReport.Model); + if(ataReport.FirmwareRevisionSpecified && !string.IsNullOrEmpty(ataReport.FirmwareRevision)) + ataTwoValue.Add("Firmware revision", ataReport.FirmwareRevision); + if(ataReport.AdditionalPIDSpecified && !string.IsNullOrEmpty(ataReport.AdditionalPID)) + ataTwoValue.Add("Additional product ID", ataReport.AdditionalPID); + + bool ata1 = false, ata2 = false, ata3 = false, ata4 = false, ata5 = false, ata6 = false, ata7 = false, acs = false, acs2 = false, acs3 = false, acs4 = false; + + if(ataReport.MajorVersionSpecified && ((ushort)ataReport.MajorVersion == 0x0000 || (ushort)ataReport.MajorVersion == 0xFFFF)) + { + // Obsolete in ATA-2, if present, device supports ATA-1 + if(ataReport.GeneralConfigurationSpecified) + ata1 |= ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FastIDE) || + ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SlowIDE) || + ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.UltraFastIDE); + + ata2 |= ataReport.ExtendedIdentifySpecified; + + if(!ata1 && !ata2 && !atapi && !cfa) + ata2 = true; + + ata4 |= atapi; + ata3 |= cfa; + + if(cfa && ata1) + ata1 = false; + if(cfa && ata2) + ata2 = false; + + } + else + { + if(ataReport.MajorVersionSpecified) + { + ata1 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata1); + ata2 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata2); + ata3 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata3); + ata4 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi4); + ata5 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi5); + ata6 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi6); + ata7 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi7); + acs |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata8ACS); + acs2 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.ACS2); + acs3 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.ACS3); + acs4 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.ACS4); + } + } + + int maxatalevel = 0; + int minatalevel = 255; + tmpString = ""; + if(ata1) + { + tmpString += "ATA-1 "; + maxatalevel = 1; + if(minatalevel > 1) + minatalevel = 1; + } + if(ata2) + { + tmpString += "ATA-2 "; + maxatalevel = 2; + if(minatalevel > 2) + minatalevel = 2; + } + if(ata3) + { + tmpString += "ATA-3 "; + maxatalevel = 3; + if(minatalevel > 3) + minatalevel = 3; + } + if(ata4) + { + tmpString += "ATA/ATAPI-4 "; + maxatalevel = 4; + if(minatalevel > 4) + minatalevel = 4; + } + if(ata5) + { + tmpString += "ATA/ATAPI-5 "; + maxatalevel = 5; + if(minatalevel > 5) + minatalevel = 5; + } + if(ata6) + { + tmpString += "ATA/ATAPI-6 "; + maxatalevel = 6; + if(minatalevel > 6) + minatalevel = 6; + } + if(ata7) + { + tmpString += "ATA/ATAPI-7 "; + maxatalevel = 7; + if(minatalevel > 7) + minatalevel = 7; + } + if(acs) + { + tmpString += "ATA8-ACS "; + maxatalevel = 8; + if(minatalevel > 8) + minatalevel = 8; + } + if(acs2) + { + tmpString += "ATA8-ACS2 "; + maxatalevel = 9; + if(minatalevel > 9) + minatalevel = 9; + } + if(acs3) + { + tmpString += "ATA8-ACS3 "; + maxatalevel = 10; + if(minatalevel > 10) + minatalevel = 10; + } + if(acs4) + { + tmpString += "ATA8-ACS4 "; + maxatalevel = 11; + if(minatalevel > 11) + minatalevel = 11; + } + if(tmpString != "") + ataTwoValue.Add("Supported ATA versions", tmpString); + + if(maxatalevel >= 3 && ataReport.MinorVersionSpecified) + { + switch(ataReport.MinorVersion) + { + case 0x0000: + case 0xFFFF: + tmpString = "Minor ATA version not specified"; + break; + case 0x0001: + tmpString = "ATA (ATA-1) X3T9.2 781D prior to revision 4"; + break; + case 0x0002: + tmpString = "ATA-1 published, ANSI X3.221-1994"; + break; + case 0x0003: + tmpString = "ATA (ATA-1) X3T9.2 781D revision 4"; + break; + case 0x0004: + tmpString = "ATA-2 published, ANSI X3.279-1996"; + break; + case 0x0005: + tmpString = "ATA-2 X3T10 948D prior to revision 2k"; + break; + case 0x0006: + tmpString = "ATA-3 X3T10 2008D revision 1"; + break; + case 0x0007: + tmpString = "ATA-2 X3T10 948D revision 2k"; + break; + case 0x0008: + tmpString = "ATA-3 X3T10 2008D revision 0"; + break; + case 0x0009: + tmpString = "ATA-2 X3T10 948D revision 3"; + break; + case 0x000A: + tmpString = "ATA-3 published, ANSI X3.298-1997"; + break; + case 0x000B: + tmpString = "ATA-3 X3T10 2008D revision 6"; + break; + case 0x000C: + tmpString = "ATA-3 X3T13 2008D revision 7"; + break; + case 0x000D: + tmpString = "ATA/ATAPI-4 X3T13 1153D revision 6"; + break; + case 0x000E: + tmpString = "ATA/ATAPI-4 T13 1153D revision 13"; + break; + case 0x000F: + tmpString = "ATA/ATAPI-4 X3T13 1153D revision 7"; + break; + case 0x0010: + tmpString = "ATA/ATAPI-4 T13 1153D revision 18"; + break; + case 0x0011: + tmpString = "ATA/ATAPI-4 T13 1153D revision 15"; + break; + case 0x0012: + tmpString = "ATA/ATAPI-4 published, ANSI INCITS 317-1998"; + break; + case 0x0013: + tmpString = "ATA/ATAPI-5 T13 1321D revision 3"; + break; + case 0x0014: + tmpString = "ATA/ATAPI-4 T13 1153D revision 14"; + break; + case 0x0015: + tmpString = "ATA/ATAPI-5 T13 1321D revision 1"; + break; + case 0x0016: + tmpString = "ATA/ATAPI-5 published, ANSI INCITS 340-2000"; + break; + case 0x0017: + tmpString = "ATA/ATAPI-4 T13 1153D revision 17"; + break; + case 0x0018: + tmpString = "ATA/ATAPI-6 T13 1410D revision 0"; + break; + case 0x0019: + tmpString = "ATA/ATAPI-6 T13 1410D revision 3a"; + break; + case 0x001A: + tmpString = "ATA/ATAPI-7 T13 1532D revision 1"; + break; + case 0x001B: + tmpString = "ATA/ATAPI-6 T13 1410D revision 2"; + break; + case 0x001C: + tmpString = "ATA/ATAPI-6 T13 1410D revision 1"; + break; + case 0x001D: + tmpString = "ATA/ATAPI-7 published ANSI INCITS 397-2005"; + break; + case 0x001E: + tmpString = "ATA/ATAPI-7 T13 1532D revision 0"; + break; + case 0x001F: + tmpString = "ACS-3 Revision 3b"; + break; + case 0x0021: + tmpString = "ATA/ATAPI-7 T13 1532D revision 4a"; + break; + case 0x0022: + tmpString = "ATA/ATAPI-6 published, ANSI INCITS 361-2002"; + break; + case 0x0027: + tmpString = "ATA8-ACS revision 3c"; + break; + case 0x0028: + tmpString = "ATA8-ACS revision 6"; + break; + case 0x0029: + tmpString = "ATA8-ACS revision 4"; + break; + case 0x0031: + tmpString = "ACS-2 Revision 2"; + break; + case 0x0033: + tmpString = "ATA8-ACS Revision 3e"; + break; + case 0x0039: + tmpString = "ATA8-ACS Revision 4c"; + break; + case 0x0042: + tmpString = "ATA8-ACS Revision 3f"; + break; + case 0x0052: + tmpString = "ATA8-ACS revision 3b"; + break; + case 0x006D: + tmpString = "ACS-3 Revision 5"; + break; + case 0x0082: + tmpString = "ACS-2 published, ANSI INCITS 482-2012"; + break; + case 0x0107: + tmpString = "ATA8-ACS revision 2d"; + break; + case 0x0110: + tmpString = "ACS-2 Revision 3"; + break; + case 0x011B: + tmpString = "ACS-3 Revision 4"; + break; + default: + tmpString = string.Format("Unknown ATA revision 0x{0:X4}", ataReport.MinorVersion); + break; + } + ataTwoValue.Add("Maximum ATA revision supported", tmpString); + } + + if(ataReport.TransportMajorVersionSpecified) + { + tmpString = ""; + switch((ataReport.TransportMajorVersion & 0xF000) >> 12) + { + case 0x0: + if((ataReport.TransportMajorVersion & 0x0002) == 0x0002) + tmpString += "ATA/ATAPI-7 "; + if((ataReport.TransportMajorVersion & 0x0001) == 0x0001) + tmpString += "ATA8-APT "; + ataTwoValue.Add("Parallel ATA device", tmpString); + break; + case 0x1: + if((ataReport.TransportMajorVersion & 0x0001) == 0x0001) + tmpString += "ATA8-AST "; + if((ataReport.TransportMajorVersion & 0x0002) == 0x0002) + tmpString += "SATA 1.0a "; + if((ataReport.TransportMajorVersion & 0x0004) == 0x0004) + tmpString += "SATA II Extensions "; + if((ataReport.TransportMajorVersion & 0x0008) == 0x0008) + tmpString += "SATA 2.5 "; + if((ataReport.TransportMajorVersion & 0x0010) == 0x0010) + tmpString += "SATA 2.6 "; + if((ataReport.TransportMajorVersion & 0x0020) == 0x0020) + tmpString += "SATA 3.0 "; + if((ataReport.TransportMajorVersion & 0x0040) == 0x0040) + tmpString += "SATA 3.1 "; + ataTwoValue.Add("Serial ATA device: ", tmpString); + break; + case 0xE: + ataTwoValue.Add("SATA Express device", "No version"); + break; + default: + ataTwoValue.Add("Unknown transport type", string.Format("0x{0:X1}", (ataReport.TransportMajorVersion & 0xF000) >> 12)); + break; + } + } + + if(atapi && ataReport.GeneralConfigurationSpecified) + { + // Bits 12 to 8, SCSI Peripheral Device Type + switch((Decoders.SCSI.PeripheralDeviceTypes)(((ushort)ataReport.GeneralConfiguration & 0x1F00) >> 8)) + { + case Decoders.SCSI.PeripheralDeviceTypes.DirectAccess: //0x00, + ataOneValue.Add("ATAPI Direct-access device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess: //0x01, + ataOneValue.Add("ATAPI Sequential-access device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.PrinterDevice: //0x02, + ataOneValue.Add("ATAPI Printer device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.ProcessorDevice: //0x03, + ataOneValue.Add("ATAPI Processor device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.WriteOnceDevice: //0x04, + ataOneValue.Add("ATAPI Write-once device"); + break; + case PeripheralDeviceTypes.MultiMediaDevice: //0x05, + ataOneValue.Add("ATAPI CD-ROM/DVD/etc device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.ScannerDevice: //0x06, + ataOneValue.Add("ATAPI Scanner device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.OpticalDevice: //0x07, + ataOneValue.Add("ATAPI Optical memory device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.MediumChangerDevice: //0x08, + ataOneValue.Add("ATAPI Medium change device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.CommsDevice: //0x09, + ataOneValue.Add("ATAPI Communications device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.PrePressDevice1: //0x0A, + ataOneValue.Add("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.PrePressDevice2: //0x0B, + ataOneValue.Add("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.ArrayControllerDevice: //0x0C, + ataOneValue.Add("ATAPI Array controller device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.EnclosureServiceDevice: //0x0D, + ataOneValue.Add("ATAPI Enclosure services device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.SimplifiedDevice: //0x0E, + ataOneValue.Add("ATAPI Simplified direct-access device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice: //0x0F, + ataOneValue.Add("ATAPI Optical card reader/writer device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.BridgingExpander: //0x10, + ataOneValue.Add("ATAPI Bridging Expanders"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.ObjectDevice: //0x11, + ataOneValue.Add("ATAPI Object-based Storage Device"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.ADCDevice: //0x12, + ataOneValue.Add("ATAPI Automation/Drive Interface"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.WellKnownDevice: //0x1E, + ataOneValue.Add("ATAPI Well known logical unit"); + break; + case Decoders.SCSI.PeripheralDeviceTypes.UnknownDevice: //0x1F + ataOneValue.Add("ATAPI Unknown or no device type"); + break; + default: + ataOneValue.Add(string.Format("ATAPI Unknown device type field value 0x{0:X2}", ((ushort)ataReport.GeneralConfiguration & 0x1F00) >> 8)); + break; + } + + // ATAPI DRQ behaviour + switch(((ushort)ataReport.GeneralConfiguration & 0x60) >> 5) + { + case 0: + ataOneValue.Add("Device shall set DRQ within 3 ms of receiving PACKET"); + break; + case 1: + ataOneValue.Add("Device shall assert INTRQ when DRQ is set to one"); + break; + case 2: + ataOneValue.Add("Device shall set DRQ within 50 µs of receiving PACKET"); + break; + default: + ataOneValue.Add(string.Format("Unknown ATAPI DRQ behaviour code {0}", ((ushort)ataReport.GeneralConfiguration & 0x60) >> 5)); + break; + } + + // ATAPI PACKET size + switch((ushort)ataReport.GeneralConfiguration & 0x03) + { + case 0: + ataOneValue.Add("ATAPI device uses 12 byte command packet"); + break; + case 1: + ataOneValue.Add("ATAPI device uses 16 byte command packet"); + break; + default: + ataOneValue.Add(string.Format("Unknown ATAPI packet size code {0}", (ushort)ataReport.GeneralConfiguration & 0x03)); + break; + } + + } + else if(!cfa && ataReport.GeneralConfigurationSpecified) + { + if(minatalevel >= 5) + { + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.IncompleteResponse)) + ataOneValue.Add("Incomplete identify response"); + } + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NonMagnetic)) + ataOneValue.Add("Device uses non-magnetic media"); + + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.Removable)) + ataOneValue.Add("Device is removable"); + + if(minatalevel <= 5) + { + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.Fixed)) + ataOneValue.Add("Device is fixed"); + } + + if(ata1) + { + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SlowIDE)) + ataOneValue.Add("Device transfer rate is <= 5 Mb/s"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FastIDE)) + ataOneValue.Add("Device transfer rate is > 5 Mb/s but <= 10 Mb/s"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.UltraFastIDE)) + ataOneValue.Add("Device transfer rate is > 10 Mb/s"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SoftSector)) + ataOneValue.Add("Device is soft sectored"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.HardSector)) + ataOneValue.Add("Device is hard sectored"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NotMFM)) + ataOneValue.Add("Device is not MFM encoded"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FormatGapReq)) + ataOneValue.Add("Format speed tolerance gap is required"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.TrackOffset)) + ataOneValue.Add("Track offset option is available"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.DataStrobeOffset)) + ataOneValue.Add("Data strobe offset option is available"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.RotationalSpeedTolerance)) + ataOneValue.Add("Rotational speed tolerance is higher than 0,5%"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SpindleControl)) + ataOneValue.Add("Spindle motor control is implemented"); + if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.HighHeadSwitch)) + ataOneValue.Add("Head switch time is bigger than 15 µs."); + } + } + + if(ataReport.SpecificConfigurationSpecified && + (ushort)ataReport.SpecificConfiguration != 0x0000 && + (ushort)ataReport.SpecificConfiguration != 0xFFFF) + { + switch(ataReport.SpecificConfiguration) + { + case SpecificConfigurationEnum.RequiresSetIncompleteResponse: + ataOneValue.Add("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); + break; + case SpecificConfigurationEnum.RequiresSetCompleteResponse: + ataOneValue.Add("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); + break; + case SpecificConfigurationEnum.NotRequiresSetIncompleteResponse: + ataOneValue.Add("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); + break; + case SpecificConfigurationEnum.NotRequiresSetCompleteResponse: + ataOneValue.Add("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); + break; + default: + ataOneValue.Add(string.Format("Unknown device specific configuration 0x{0:X4}", (ushort)ataReport.SpecificConfiguration)); + break; + } + } + + // Obsolete since ATA-2, however, it is yet used in ATA-8 devices + if(ataReport.BufferSizeSpecified && ataReport.BufferTypeSpecified && + ataReport.BufferSize != 0x0000 && ataReport.BufferSize != 0xFFFF && + ataReport.BufferType != 0x0000 && ataReport.BufferType != 0xFFFF) + { + switch(ataReport.BufferType) + { + case 1: + ataOneValue.Add(string.Format("{0} KiB of single ported single sector buffer", (ataReport.BufferSize * 512) / 1024)); + break; + case 2: + ataOneValue.Add(string.Format("{0} KiB of dual ported multi sector buffer", (ataReport.BufferSize * 512) / 1024)); + break; + case 3: + ataOneValue.Add(string.Format("{0} KiB of dual ported multi sector buffer with read caching", (ataReport.BufferSize * 512) / 1024)); + break; + default: + ataOneValue.Add(string.Format("{0} KiB of unknown type {1} buffer", (ataReport.BufferSize * 512) / 1024, ataReport.BufferType)); + break; + } + } + + if(ataReport.CapabilitiesSpecified) + { + ataOneValue.Add("Device capabilities:"); + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.StandardStanbyTimer)) + ataOneValue.Add("Standby time values are standard"); + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.IORDY)) + { + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.CanDisableIORDY)) + ataOneValue.Add("IORDY is supported and can be disabled"); + else + ataOneValue.Add("IORDY is supported"); + } + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.DMASupport)) + ataOneValue.Add("DMA is supported"); + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.PhysicalAlignment1) || + ataReport.Capabilities.HasFlag(CapabilitiesBit.PhysicalAlignment0)) + { + ataOneValue.Add(string.Format("Long Physical Alignment setting is {0}", (ushort)ataReport.Capabilities & 0x03)); + } + if(atapi) + { + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.InterleavedDMA)) + ataOneValue.Add("ATAPI device supports interleaved DMA"); + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.CommandQueue)) + ataOneValue.Add("ATAPI device supports command queueing"); + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.OverlapOperation)) + ataOneValue.Add("ATAPI device supports overlapped operations"); + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.RequiresATASoftReset)) + ataOneValue.Add("ATAPI device requires ATA software reset"); + } + } + + if(ataReport.Capabilities2Specified) + { + if(ataReport.Capabilities2.HasFlag(CapabilitiesBit2.MustBeSet) && + !ataReport.Capabilities2.HasFlag(CapabilitiesBit2.MustBeClear)) + { + if(ataReport.Capabilities2.HasFlag(CapabilitiesBit2.SpecificStandbyTimer)) + ataOneValue.Add("Device indicates a specific minimum standby timer value"); + } + } + + if(ataReport.Capabilities3Specified) + { + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.MultipleValid)) + { + ataOneValue.Add(string.Format("A maximum of {0} sectors can be transferred per interrupt on READ/WRITE MULTIPLE", ataReport.MultipleSectorNumber)); + ataOneValue.Add(string.Format("Device supports setting a maximum of {0} sectors", ataReport.MultipleMaxSectors)); + } + } + + if(ata1 && ataReport.TrustedComputingSpecified) + { + if(ataReport.TrustedComputing.HasFlag(TrustedComputingBit.TrustedComputing)) + ataOneValue.Add("Device supports doubleword I/O"); + } + + if(minatalevel <= 3) + { + if(ataReport.PIOTransferTimingModeSpecified) + ataTwoValue.Add("PIO timing mode", string.Format("{0}", ataReport.PIOTransferTimingMode)); + if(ataReport.DMATransferTimingModeSpecified) + ataTwoValue.Add("DMA timing mode", string.Format("{0}", ataReport.DMATransferTimingMode)); + } + + if(ataReport.APIOSupportedSpecified) + { + tmpString = ""; + + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode0)) + { + tmpString += "PIO0 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode1)) + { + tmpString += "PIO1 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode2)) + { + tmpString += "PIO2 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode3)) + { + tmpString += "PIO3 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode4)) + { + tmpString += "PIO4 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode5)) + { + tmpString += "PIO5 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode6)) + { + tmpString += "PIO6 "; + } + if(ataReport.APIOSupported.HasFlag(TransferMode.Mode7)) + { + tmpString += "PIO7 "; + } + + ataTwoValue.Add("Advanced PIO", tmpString); + } + + if(minatalevel <= 3 && !atapi && ataReport.DMASupportedSpecified) + { + tmpString = ""; + if(ataReport.DMASupported.HasFlag(TransferMode.Mode0)) + { + tmpString += "DMA0 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode0) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode1)) + { + tmpString += "DMA1 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode1) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode2)) + { + tmpString += "DMA2 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode2) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode3)) + { + tmpString += "DMA3 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode3) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode4)) + { + tmpString += "DMA4 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode4) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode5)) + { + tmpString += "DMA5 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode5) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode6)) + { + tmpString += "DMA6 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode6) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.DMASupported.HasFlag(TransferMode.Mode7)) + { + tmpString += "DMA7 "; + if(ataReport.DMAActive.HasFlag(TransferMode.Mode7) && ataReport.DMAActiveSpecified) + tmpString += "(active) "; + } + ataTwoValue.Add("Single-word DMA", tmpString); + } + + if(ataReport.MDMASupportedSpecified) + { + tmpString = ""; + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode0)) + { + tmpString += "MDMA0 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode0) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode1)) + { + tmpString += "MDMA1 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode1) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode2)) + { + tmpString += "MDMA2 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode2) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode3)) + { + tmpString += "MDMA3 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode3) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode4)) + { + tmpString += "MDMA4 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode4) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode5)) + { + tmpString += "MDMA5 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode5) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode6)) + { + tmpString += "MDMA6 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode6) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.MDMASupported.HasFlag(TransferMode.Mode7)) + { + tmpString += "MDMA7 "; + if(ataReport.MDMAActive.HasFlag(TransferMode.Mode7) && ataReport.MDMAActiveSpecified) + tmpString += "(active) "; + } + ataTwoValue.Add("Multi-word DMA", tmpString); + } + + if(ataReport.UDMASupportedSpecified) + { + tmpString = ""; + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode0)) + { + tmpString += "UDMA0 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode0) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode1)) + { + tmpString += "UDMA1 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode1) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode2)) + { + tmpString += "UDMA2 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode2) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode3)) + { + tmpString += "UDMA3 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode3) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode4)) + { + tmpString += "UDMA4 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode4) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode5)) + { + tmpString += "UDMA5 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode5) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode6)) + { + tmpString += "UDMA6 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode6) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + if(ataReport.UDMASupported.HasFlag(TransferMode.Mode7)) + { + tmpString += "UDMA7 "; + if(ataReport.UDMAActive.HasFlag(TransferMode.Mode7) && ataReport.UDMAActiveSpecified) + tmpString += "(active) "; + } + ataTwoValue.Add("Ultra DMA", tmpString); + } + + if(ataReport.MinMDMACycleTime != 0 && ataReport.RecommendedMDMACycleTime != 0) + { + ataOneValue.Add(string.Format("At minimum {0} ns. transfer cycle time per word in MDMA, " + + "{1} ns. recommended", ataReport.MinMDMACycleTime, ataReport.RecommendedMDMACycleTime)); + } + if(ataReport.MinPIOCycleTimeNoFlow != 0) + { + ataOneValue.Add(string.Format("At minimum {0} ns. transfer cycle time per word in PIO, " + + "without flow control", ataReport.MinPIOCycleTimeNoFlow)); + } + if(ataReport.MinPIOCycleTimeFlow != 0) + { + ataOneValue.Add(string.Format("At minimum {0} ns. transfer cycle time per word in PIO, " + + "with IORDY flow control", ataReport.MinPIOCycleTimeFlow)); + } + + if(ataReport.MaxQueueDepth != 0) + { + ataOneValue.Add(string.Format("{0} depth of queue maximum", ataReport.MaxQueueDepth + 1)); + } + + if(atapi) + { + if(ataReport.PacketBusRelease != 0) + ataOneValue.Add(string.Format("{0} ns. typical to release bus from receipt of PACKET", ataReport.PacketBusRelease)); + if(ataReport.ServiceBusyClear != 0) + ataOneValue.Add(string.Format("{0} ns. typical to clear BSY bit from receipt of SERVICE", ataReport.ServiceBusyClear)); + } + + if(ataReport.TransportMajorVersionSpecified && + (((ataReport.TransportMajorVersion & 0xF000) >> 12) == 0x1 || + ((ataReport.TransportMajorVersion & 0xF000) >> 12) == 0xE)) + { + if(!ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Clear)) + { + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen1Speed)) + { + ataOneValue.Add(string.Format("SATA 1.5Gb/s is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen2Speed)) + { + ataOneValue.Add(string.Format("SATA 3.0Gb/s is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen3Speed)) + { + ataOneValue.Add(string.Format("SATA 6.0Gb/s is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.PowerReceipt)) + { + ataOneValue.Add(string.Format("Receipt of host initiated power management requests is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.PHYEventCounter)) + { + ataOneValue.Add(string.Format("PHY Event counters are supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.HostSlumbTrans)) + { + ataOneValue.Add(string.Format("Supports host automatic partial to slumber transitions is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.DevSlumbTrans)) + { + ataOneValue.Add(string.Format("Supports device automatic partial to slumber transitions is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQ)) + { + ataOneValue.Add(string.Format("NCQ is supported")); + + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQPriority)) + { + ataOneValue.Add(string.Format("NCQ priority is supported")); + } + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.UnloadNCQ)) + { + ataOneValue.Add(string.Format("Unload is supported with outstanding NCQ commands")); + } + } + } + + if(ataReport.SATACapabilities2Specified && !ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.Clear)) + { + if(ataReport.SATACapabilitiesSpecified && + !ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Clear) && + ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQ)) + { + if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.NCQMgmt)) + { + ataOneValue.Add(string.Format("NCQ queue management is supported")); + } + if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.NCQStream)) + { + ataOneValue.Add(string.Format("NCQ streaming is supported")); + } + } + + if(ataReport.SATACapabilities2Specified && atapi) + { + if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.HostEnvDetect)) + { + ataOneValue.Add(string.Format("ATAPI device supports host environment detection")); + } + if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.DevAttSlimline)) + { + ataOneValue.Add(string.Format("ATAPI device supports attention on slimline connected devices")); + } + } + } + } + + if(ataReport.InterseekDelay != 0x0000 && ataReport.InterseekDelay != 0xFFFF) + { + ataOneValue.Add(string.Format("{0} microseconds of interseek delay for ISO-7779 accoustic testing", ataReport.InterseekDelay)); + } + + if((ushort)ataReport.DeviceFormFactor != 0x0000 && (ushort)ataReport.DeviceFormFactor != 0xFFFF) + { + switch(ataReport.DeviceFormFactor) + { + case DeviceFormFactorEnum.FiveAndQuarter: + ataOneValue.Add("Device nominal size is 5.25\""); + break; + case DeviceFormFactorEnum.ThreeAndHalf: + ataOneValue.Add("Device nominal size is 3.5\""); + break; + case DeviceFormFactorEnum.TwoAndHalf: + ataOneValue.Add("Device nominal size is 2.5\""); + break; + case DeviceFormFactorEnum.OnePointEight: + ataOneValue.Add("Device nominal size is 1.8\""); + break; + case DeviceFormFactorEnum.LessThanOnePointEight: + ataOneValue.Add("Device nominal size is smaller than 1.8\""); + break; + default: + ataOneValue.Add(string.Format("Device nominal size field value {0} is unknown", ataReport.DeviceFormFactor)); + break; + } + } + + if(atapi) + { + if(ataReport.ATAPIByteCount > 0) + ataOneValue.Add(string.Format("{0} bytes count limit for ATAPI", ataReport.ATAPIByteCount)); + } + + if(cfa) + { + if((ataReport.CFAPowerMode & 0x8000) == 0x8000) + { + ataOneValue.Add("CompactFlash device supports power mode 1"); + if((ataReport.CFAPowerMode & 0x2000) == 0x2000) + ataOneValue.Add("CompactFlash power mode 1 required for one or more commands"); + if((ataReport.CFAPowerMode & 0x1000) == 0x1000) + ataOneValue.Add("CompactFlash power mode 1 is disabled"); + + ataOneValue.Add(string.Format("CompactFlash device uses a maximum of {0} mA", (ataReport.CFAPowerMode & 0x0FFF))); + } + } + + if(ataReport.CommandSetSpecified || ataReport.CommandSet2Specified || ataReport.CommandSet3Specified || ataReport.CommandSet4Specified || ataReport.CommandSet5Specified) + ataOneValue.Add("Command set and features:"); + if(ataReport.CommandSetSpecified) + { + if(ataReport.CommandSet.HasFlag(CommandSetBit.Nop)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Nop) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("NOP is supported and enabled"); + else + ataOneValue.Add("NOP is supported"); + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.ReadBuffer)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.ReadBuffer) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("READ BUFFER is supported and enabled"); + else + ataOneValue.Add("READ BUFFER is supported"); + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.WriteBuffer)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.WriteBuffer) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("WRITE BUFFER is supported and enabled"); + else + ataOneValue.Add("WRITE BUFFER is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.HPA)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.HPA) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Host Protected Area is supported and enabled"); + else + ataOneValue.Add("Host Protected Area is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.DeviceReset)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.DeviceReset) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("DEVICE RESET is supported and enabled"); + else + ataOneValue.Add("DEVICE RESET is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.Service)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Service) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("SERVICE interrupt is supported and enabled"); + else + ataOneValue.Add("SERVICE interrupt is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.Release)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Release) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Release is supported and enabled"); + else + ataOneValue.Add("Release is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.LookAhead)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.LookAhead) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Look-ahead read is supported and enabled"); + else + ataOneValue.Add("Look-ahead read is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.WriteCache)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.WriteCache) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Write cache is supported and enabled"); + else + ataOneValue.Add("Write cache is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.Packet)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Packet) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("PACKET is supported and enabled"); + else + ataOneValue.Add("PACKET is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.PowerManagement)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.PowerManagement) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Power management is supported and enabled"); + else + ataOneValue.Add("Power management is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.RemovableMedia)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.RemovableMedia) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Removable media feature set is supported and enabled"); + else + ataOneValue.Add("Removable media feature set is supported"); + + } + if(ataReport.CommandSet.HasFlag(CommandSetBit.SecurityMode)) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.SecurityMode) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("Security mode is supported and enabled"); + else + ataOneValue.Add("Security mode is supported"); + + } + if(ataReport.Capabilities.HasFlag(CapabilitiesBit.LBASupport)) + ataOneValue.Add("28-bit LBA is supported"); + } + + if(ataReport.CommandSet2Specified && ataReport.CommandSet2.HasFlag(CommandSetBit2.MustBeSet) && + !ataReport.CommandSet2.HasFlag(CommandSetBit2.MustBeClear)) + { + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.LBA48)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.LBA48) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("48-bit LBA is supported and enabled"); + else + ataOneValue.Add("48-bit LBA is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.FlushCache)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCache) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("FLUSH CACHE is supported and enabled"); + else + ataOneValue.Add("FLUSH CACHE is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.FlushCacheExt)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCacheExt) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("FLUSH CACHE EXT is supported and enabled"); + else + ataOneValue.Add("FLUSH CACHE EXT is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.DCO)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.DCO) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("Device Configuration Overlay feature set is supported and enabled"); + else + ataOneValue.Add("Device Configuration Overlay feature set is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.AAM)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.AAM) && ataReport.EnabledCommandSet2Specified) + { + ataOneValue.Add(string.Format("Automatic Acoustic Management is supported and enabled with value {0} (vendor recommends {1}", + ataReport.CurrentAAM, ataReport.RecommendedAAM)); + } + else + ataOneValue.Add("Automatic Acoustic Management is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.SetMax)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.SetMax) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("SET MAX security extension is supported and enabled"); + else + ataOneValue.Add("SET MAX security extension is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.AddressOffsetReservedAreaBoot)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.AddressOffsetReservedAreaBoot) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("Address Offset Reserved Area Boot is supported and enabled"); + else + ataOneValue.Add("Address Offset Reserved Area Boot is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.SetFeaturesRequired)) + { + ataOneValue.Add("SET FEATURES is required before spin-up"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("Power-up in standby is supported and enabled"); + else + ataOneValue.Add("Power-up in standby is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.RemovableNotification)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.RemovableNotification) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("Removable Media Status Notification is supported and enabled"); + else + ataOneValue.Add("Removable Media Status Notification is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.APM)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.APM) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add(string.Format("Advanced Power Management is supported and enabled with value {0}", ataReport.CurrentAPM)); + else + ataOneValue.Add("Advanced Power Management is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.CompactFlash)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.CompactFlash) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("CompactFlash feature set is supported and enabled"); + else + ataOneValue.Add("CompactFlash feature set is supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("READ DMA QUEUED and WRITE DMA QUEUED are supported and enabled"); + else + ataOneValue.Add("READ DMA QUEUED and WRITE DMA QUEUED are supported"); + } + if(ataReport.CommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode)) + { + if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode) && ataReport.EnabledCommandSet2Specified) + ataOneValue.Add("DOWNLOAD MICROCODE is supported and enabled"); + else + ataOneValue.Add("DOWNLOAD MICROCODE is supported"); + } + } + + if(ataReport.CommandSet.HasFlag(CommandSetBit.SMART) && ataReport.CommandSetSpecified) + { + if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.SMART) && ataReport.EnabledCommandSetSpecified) + ataOneValue.Add("S.M.A.R.T. is supported and enabled"); + else + ataOneValue.Add("S.M.A.R.T. is supported"); + } + + if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.Supported) && ataReport.SCTCommandTransportSpecified) + ataOneValue.Add("S.M.A.R.T. Command Transport is supported"); + + if(ataReport.CommandSet3Specified && + ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeSet) && + !ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeClear)) + { + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("S.M.A.R.T. self-testing is supported and enabled"); + else + ataOneValue.Add("S.M.A.R.T. self-testing is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.SMARTLog)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTLog) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("S.M.A.R.T. error logging is supported and enabled"); + else + ataOneValue.Add("S.M.A.R.T. error logging is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.IdleImmediate)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.IdleImmediate) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("IDLE IMMEDIATE with UNLOAD FEATURE is supported and enabled"); + else + ataOneValue.Add("IDLE IMMEDIATE with UNLOAD FEATURE is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.WriteURG)) + { + ataOneValue.Add("URG bit is supported in WRITE STREAM DMA EXT and WRITE STREAM EXT"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.ReadURG)) + { + ataOneValue.Add("URG bit is supported in READ STREAM DMA EXT and READ STREAM EXT"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.WWN)) + { + ataOneValue.Add("Device has a World Wide Name"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.FUAWriteQ)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWriteQ) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("WRITE DMA QUEUED FUA EXT is supported and enabled"); + else + ataOneValue.Add("WRITE DMA QUEUED FUA EXT is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.FUAWrite)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWrite) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported and enabled"); + else + ataOneValue.Add("WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.GPL)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.GPL) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("General Purpose Logging is supported and enabled"); + else + ataOneValue.Add("General Purpose Logging is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.Streaming)) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.Streaming) && ataReport.EnabledCommandSet3Specified) + ataOneValue.Add("Streaming feature set is supported and enabled"); + else + ataOneValue.Add("Streaming feature set is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.MCPT) && ataReport.EnabledCommandSet3Specified) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.MCPT)) + ataOneValue.Add("Media Card Pass Through command set is supported and enabled"); + else + ataOneValue.Add("Media Card Pass Through command set is supported"); + } + if(ataReport.CommandSet3.HasFlag(CommandSetBit3.MediaSerial) && ataReport.EnabledCommandSet3Specified) + { + if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.MediaSerial)) + ataOneValue.Add("Media Serial is supported and valid"); + else + ataOneValue.Add("Media Serial is supported"); + } + } + + if(ataReport.CommandSet4Specified && + ataReport.CommandSet4.HasFlag(CommandSetBit4.MustBeSet) && + !ataReport.CommandSet4.HasFlag(CommandSetBit4.MustBeClear)) + { + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.DSN)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.DSN) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("DSN feature set is supported and enabled"); + else + ataOneValue.Add("DSN feature set is supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.AMAC)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.AMAC) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("Accessible Max Address Configuration is supported and enabled"); + else + ataOneValue.Add("Accessible Max Address Configuration is supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.ExtPowerCond)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtPowerCond) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("Extended Power Conditions are supported and enabled"); + else + ataOneValue.Add("Extended Power Conditions are supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.ExtStatusReport)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtStatusReport) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("Extended Status Reporting is supported and enabled"); + else + ataOneValue.Add("Extended Status Reporting is supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.FreeFallControl)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.FreeFallControl) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("Free-fall control feature set is supported and enabled"); + else + ataOneValue.Add("Free-fall control feature set is supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.SegmentedDownloadMicrocode)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.SegmentedDownloadMicrocode) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("Segmented feature in DOWNLOAD MICROCODE is supported and enabled"); + else + ataOneValue.Add("Segmented feature in DOWNLOAD MICROCODE is supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("READ/WRITE DMA EXT GPL are supported and enabled"); + else + ataOneValue.Add("READ/WRITE DMA EXT GPL are supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.WriteUnc)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.WriteUnc) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("WRITE UNCORRECTABLE is supported and enabled"); + else + ataOneValue.Add("WRITE UNCORRECTABLE is supported"); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.WRV)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("Write/Read/Verify is supported and enabled"); + else + ataOneValue.Add("Write/Read/Verify is supported"); + ataOneValue.Add(string.Format("{0} sectors for Write/Read/Verify mode 2", ataReport.WRVSectorCountMode2)); + ataOneValue.Add(string.Format("{0} sectors for Write/Read/Verify mode 3", ataReport.WRVSectorCountMode3)); + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add(string.Format("Current Write/Read/Verify mode: {0}", ataReport.WRVMode)); + } + if(ataReport.CommandSet4.HasFlag(CommandSetBit4.DT1825)) + { + if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.DT1825) && ataReport.EnabledCommandSet4Specified) + ataOneValue.Add("DT1825 is supported and enabled"); + else + ataOneValue.Add("DT1825 is supported"); + } + } + + if(ataReport.Capabilities3Specified) + { + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.BlockErase)) + ataOneValue.Add("BLOCK ERASE EXT is supported"); + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.Overwrite)) + ataOneValue.Add("OVERWRITE EXT is supported"); + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.CyrptoScramble)) + ataOneValue.Add("CRYPTO SCRAMBLE EXT is supported"); + } + + if(ataReport.CommandSet5Specified) + { + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.DeviceConfDMA)) + { + ataOneValue.Add("DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.ReadBufferDMA)) + { + ataOneValue.Add("READ BUFFER DMA is supported"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.WriteBufferDMA)) + { + ataOneValue.Add("WRITE BUFFER DMA is supported"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.DownloadMicroCodeDMA)) + { + ataOneValue.Add("DOWNLOAD MICROCODE DMA is supported"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.SetMaxDMA)) + { + ataOneValue.Add("SET PASSWORD DMA and SET UNLOCK DMA are supported"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.Ata28)) + { + ataOneValue.Add("Not all 28-bit commands are supported"); + } + + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.CFast)) + { + ataOneValue.Add("Device follows CFast specification"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.IEEE1667)) + { + ataOneValue.Add("Device follows IEEE-1667"); + } + + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.DeterministicTrim)) + { + ataOneValue.Add("Read after TRIM is deterministic"); + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.ReadZeroTrim)) + { + ataOneValue.Add("Read after TRIM returns empty data"); + } + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.LongPhysSectorAligError)) + { + ataOneValue.Add("Device supports Long Physical Sector Alignment Error Reporting Control"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.Encrypted)) + { + ataOneValue.Add("Device encrypts all user data"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.AllCacheNV)) + { + ataOneValue.Add("Device's write cache is non-volatile"); + } + if(ataReport.CommandSet5.HasFlag(CommandSetBit5.ZonedBit0) || + ataReport.CommandSet5.HasFlag(CommandSetBit5.ZonedBit1)) + { + ataOneValue.Add("Device is zoned"); + } + } + + if(ataReport.Capabilities3Specified) + { + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.Sanitize)) + { + ataOneValue.Add("Sanitize feature set is supported"); + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.SanitizeCommands)) + ataOneValue.Add("Sanitize commands are specified by ACS-3 or higher"); + else + ataOneValue.Add("Sanitize commands are specified by ACS-2"); + + if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.SanitizeAntifreeze)) + ataOneValue.Add("SANITIZE ANTIFREEZE LOCK EXT is supported"); + } + } + + if(!ata1 && maxatalevel >= 8 && ataReport.TrustedComputingSpecified) + { + if(ataReport.TrustedComputing.HasFlag(TrustedComputingBit.Set) && + !ataReport.TrustedComputing.HasFlag(TrustedComputingBit.Clear) && + ataReport.TrustedComputing.HasFlag(TrustedComputingBit.TrustedComputing)) + ataOneValue.Add("Trusted Computing feature set is supported"); + } + + if(ataReport.TransportMajorVersionSpecified && + (((ataReport.TransportMajorVersion & 0xF000) >> 12) == 0x1 || + ((ataReport.TransportMajorVersion & 0xF000) >> 12) == 0xE)) + { + if(ataReport.SATACapabilitiesSpecified) + { + if(!ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Clear)) + { + if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.ReadLogDMAExt)) + ataOneValue.Add("READ LOG DMA EXT is supported"); + } + } + + if(ataReport.SATACapabilities2Specified) + { + if(!ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.Clear)) + { + if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.FPDMAQ)) + ataOneValue.Add("RECEIVE FPDMA QUEUED and SEND FPDMA QUEUED are supported"); + } + } + + if(ataReport.SATAFeaturesSpecified) + { + if(!ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.Clear)) + { + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.NonZeroBufferOffset)) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.NonZeroBufferOffset) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("Non-zero buffer offsets are supported and enabled"); + else + ataOneValue.Add("Non-zero buffer offsets are supported"); + } + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.DMASetup)) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.DMASetup) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("DMA Setup auto-activation is supported and enabled"); + else + ataOneValue.Add("DMA Setup auto-activation is supported"); + } + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt)) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("Device-initiated power management is supported and enabled"); + else + ataOneValue.Add("Device-initiated power management is supported"); + } + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.InOrderData)) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InOrderData) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("In-order data delivery is supported and enabled"); + else + ataOneValue.Add("In-order data delivery is supported"); + } + if(!atapi) + { + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.HardwareFeatureControl)) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.HardwareFeatureControl) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("Hardware Feature Control is supported and enabled"); + else + ataOneValue.Add("Hardware Feature Control is supported"); + } + } + if(atapi) + { + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.AsyncNotification) && ataReport.EnabledSATAFeaturesSpecified) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.AsyncNotification) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("Asynchronous notification is supported"); + else + ataOneValue.Add("Asynchronous notification is supported"); + } + } + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.SettingsPreserve)) + { + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.SettingsPreserve) && ataReport.EnabledSATAFeaturesSpecified) + ataOneValue.Add("Software Settings Preservation is supported"); + else + ataOneValue.Add("Software Settings Preservation is supported"); + } + if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.NCQAutoSense)) + { + ataOneValue.Add("NCQ Autosense is supported"); + } + if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.EnabledSlumber)) + { + ataOneValue.Add("Automatic Partial to Slumber transitions are enabled"); + } + } + } + } + if((ataReport.RemovableStatusSet & 0x03) > 0) + { + ataOneValue.Add("Removable Media Status Notification feature set is supported"); + } + + if(ataReport.FreeFallSensitivity != 0x00 && ataReport.FreeFallSensitivity != 0xFF) + { + ataOneValue.Add(string.Format("Free-fall sensitivity set to {0}", ataReport.FreeFallSensitivity)); + } + + if(ataReport.DataSetMgmtSpecified && ataReport.DataSetMgmt.HasFlag(DataSetMgmtBit.Trim)) + ataOneValue.Add("TRIM is supported"); + if(ataReport.DataSetMgmtSizeSpecified && ataReport.DataSetMgmtSize > 0) + { + ataOneValue.Add(string.Format("DATA SET MANAGEMENT can receive a maximum of {0} blocks of 512 bytes", ataReport.DataSetMgmtSize)); + } + + if(ataReport.SecurityStatusSpecified && ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Supported)) + { + ataOneValue.Add("Security:"); + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Enabled)) + { + ataOneValue.Add("Security is enabled"); + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Locked)) + ataOneValue.Add("Security is locked"); + else + ataOneValue.Add("Security is not locked"); + + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Frozen)) + ataOneValue.Add("Security is frozen"); + else + ataOneValue.Add("Security is not frozen"); + + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Expired)) + ataOneValue.Add("Security count has expired"); + else + ataOneValue.Add("Security count has notexpired"); + + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Maximum)) + ataOneValue.Add("Security level is maximum"); + else + ataOneValue.Add("Security level is high"); + } + else + ataOneValue.Add("Security is not enabled"); + + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Enhanced)) + ataOneValue.Add("Supports enhanced security erase"); + + ataOneValue.Add(string.Format("{0} minutes to complete secure erase", ataReport.SecurityEraseTime * 2)); + if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Enhanced)) + ataOneValue.Add(string.Format("{0} minutes to complete enhanced secure erase", ataReport.EnhancedSecurityEraseTime * 2)); + + ataOneValue.Add(string.Format("Master password revision code: {0}", ataReport.MasterPasswordRevisionCode)); + } + + if(ataReport.CommandSet3Specified && + ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeSet) && +!ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeClear) && +ataReport.CommandSet3.HasFlag(CommandSetBit3.Streaming)) + { + ataOneValue.Add("Streaming:"); + ataOneValue.Add(string.Format("Minimum request size is {0}", ataReport.StreamMinReqSize)); + ataOneValue.Add(string.Format("Streaming transfer time in PIO is {0}", ataReport.StreamTransferTimePIO)); + ataOneValue.Add(string.Format("Streaming transfer time in DMA is {0}", ataReport.StreamTransferTimeDMA)); + ataOneValue.Add(string.Format("Streaming access latency is {0}", ataReport.StreamAccessLatency)); + ataOneValue.Add(string.Format("Streaming performance granularity is {0}", ataReport.StreamPerformanceGranularity)); + } + + if(ataReport.SCTCommandTransportSpecified && ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.Supported)) + { + ataOneValue.Add("S.M.A.R.T. Command Transport (SCT):"); + if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.LongSectorAccess)) + ataOneValue.Add("SCT Long Sector Address is supported"); + if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.WriteSame)) + ataOneValue.Add("SCT Write Same is supported"); + if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.ErrorRecoveryControl)) + ataOneValue.Add("SCT Error Recovery Control is supported"); + if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.FeaturesControl)) + ataOneValue.Add("SCT Features Control is supported"); + if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.DataTables)) + ataOneValue.Add("SCT Data Tables are supported"); + } + + if(ataReport.NVCacheCapsSpecified && (ataReport.NVCacheCaps & 0x0010) == 0x0010) + { + ataOneValue.Add("Non-Volatile Cache:"); + ataOneValue.Add(string.Format("Version {0}", (ataReport.NVCacheCaps & 0xF000) >> 12)); + if((ataReport.NVCacheCaps & 0x0001) == 0x0001) + { + if((ataReport.NVCacheCaps & 0x0002) == 0x0002) + ataOneValue.Add("Power mode feature set is supported and enabled"); + else + ataOneValue.Add("Power mode feature set is supported"); + + ataOneValue.Add(string.Format("Version {0}", (ataReport.NVCacheCaps & 0x0F00) >> 8)); + } + ataOneValue.Add(string.Format("Non-Volatile Cache is {0} bytes", ataReport.NVCacheSize * logicalsectorsize)); + } + + if(ataReport.ReadCapabilities != null) + { + removable = false; + + if(ataReport.ReadCapabilities.NominalRotationRateSpecified && + ataReport.ReadCapabilities.NominalRotationRate != 0x0000 && + ataReport.ReadCapabilities.NominalRotationRate != 0xFFFF) + { + if(ataReport.ReadCapabilities.NominalRotationRate == 0x0001) + ataOneValue.Add("Device does not rotate."); + else + ataOneValue.Add(string.Format("Device rotates at {0} rpm", ataReport.ReadCapabilities.NominalRotationRate)); + } + + if(!atapi) + { + if(ataReport.ReadCapabilities.BlockSizeSpecified) + { + ataTwoValue.Add("Logical sector size", string.Format("{0} bytes", ataReport.ReadCapabilities.BlockSize)); + logicalsectorsize = ataReport.ReadCapabilities.BlockSize; + } + if(ataReport.ReadCapabilities.PhysicalBlockSizeSpecified) + ataTwoValue.Add("Physical sector size", string.Format("{0} bytes", ataReport.ReadCapabilities.PhysicalBlockSize)); + if(ataReport.ReadCapabilities.LongBlockSizeSpecified) + ataTwoValue.Add("READ LONG sector size", string.Format("{0} bytes", ataReport.ReadCapabilities.LongBlockSize)); + + + if(ataReport.ReadCapabilities.BlockSizeSpecified && + ataReport.ReadCapabilities.PhysicalBlockSizeSpecified && + (ataReport.ReadCapabilities.BlockSize != ataReport.ReadCapabilities.PhysicalBlockSize) && + (ataReport.ReadCapabilities.LogicalAlignment & 0x8000) == 0x0000 && + (ataReport.ReadCapabilities.LogicalAlignment & 0x4000) == 0x4000) + { + ataOneValue.Add(string.Format("Logical sector starts at offset {0} from physical sector", ataReport.ReadCapabilities.LogicalAlignment & 0x3FFF)); + } + + if(ataReport.ReadCapabilities.CHS != null && +ataReport.ReadCapabilities.CurrentCHS != null) + { + int currentSectors = ataReport.ReadCapabilities.CurrentCHS.Cylinders * ataReport.ReadCapabilities.CurrentCHS.Heads * ataReport.ReadCapabilities.CurrentCHS.Sectors; + ataTwoValue.Add("Cylinders", string.Format("{0} max., {1} current", ataReport.ReadCapabilities.CHS.Cylinders, ataReport.ReadCapabilities.CurrentCHS.Cylinders)); + ataTwoValue.Add("Heads", string.Format("{0} max., {1} current", ataReport.ReadCapabilities.CHS.Heads, ataReport.ReadCapabilities.CurrentCHS.Heads)); + ataTwoValue.Add("Sectors per track", string.Format("{0} max., {1} current", ataReport.ReadCapabilities.CHS.Sectors, ataReport.ReadCapabilities.CurrentCHS.Sectors)); + ataTwoValue.Add("Sectors addressable in CHS mode", string.Format("{0} max., {1} current", ataReport.ReadCapabilities.CHS.Cylinders * ataReport.ReadCapabilities.CHS.Heads * ataReport.ReadCapabilities.CHS.Sectors, + currentSectors)); + ataTwoValue.Add("Device size in CHS mode", string.Format("{0} bytes, {1} Mb, {2} MiB", (ulong)currentSectors * logicalsectorsize, + ((ulong)currentSectors * logicalsectorsize) / 1000 / 1000, ((ulong)currentSectors * 512) / 1024 / 1024)); + } + + if(ataReport.ReadCapabilities.LBASectorsSpecified) + { + ataTwoValue.Add("Sectors addressable in sectors in 28-bit LBA mode", string.Format("{0}", ataReport.ReadCapabilities.LBASectors)); + + if((((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1024 / 1024) > 1000000) + { + ataTwoValue.Add("Device size in 28-bit LBA mode", string.Format("{0} bytes, {1} Tb, {2} TiB", (ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize, + ((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1000 / 1000 / 1000 / 1000, ((ulong)ataReport.ReadCapabilities.LBASectors * 512) / 1024 / 1024 / 1024 / 1024)); + } + else if((((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1024 / 1024) > 1000) + { + ataTwoValue.Add("Device size in 28-bit LBA mode", string.Format("{0} bytes, {1} Gb, {2} GiB", (ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize, + ((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1000 / 1000 / 1000, ((ulong)ataReport.ReadCapabilities.LBASectors * 512) / 1024 / 1024 / 1024)); + } + else + { + ataTwoValue.Add("Device size in 28-bit LBA mode", string.Format("{0} bytes, {1} Mb, {2} MiB", (ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize, + ((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1000 / 1000, ((ulong)ataReport.ReadCapabilities.LBASectors * 512) / 1024 / 1024)); + } + } + + if(ataReport.ReadCapabilities.LBA48SectorsSpecified) + { + ataTwoValue.Add("Sectors addressable in sectors in 48-bit LBA mode", string.Format("{0}", ataReport.ReadCapabilities.LBA48Sectors)); + + if(((ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1024 / 1024) > 1000000) + { + ataTwoValue.Add("Device size in 48-bit LBA mode", string.Format("{0} bytes, {1} Tb, {2} TiB", ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize, + (ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1000 / 1000 / 1000 / 1000, (ataReport.ReadCapabilities.LBA48Sectors * 512) / 1024 / 1024 / 1024 / 1024)); + } + else if(((ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1024 / 1024) > 1000) + { + ataTwoValue.Add("Device size in 48-bit LBA mode", string.Format("{0} bytes, {1} Gb, {2} GiB", ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize, + (ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1000 / 1000 / 1000, (ataReport.ReadCapabilities.LBA48Sectors * 512) / 1024 / 1024 / 1024)); + } + else + { + ataTwoValue.Add("Device size in 48-bit LBA mode", string.Format("{0} bytes, {1} Mb, {2} MiB", ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize, + (ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1000 / 1000, (ataReport.ReadCapabilities.LBA48Sectors * 512) / 1024 / 1024)); + } + } + + if(ata1 || cfa) + { + if(ataReport.ReadCapabilities.UnformattedBPT > 0) + ataTwoValue.Add("Bytes per unformatted track", string.Format("{0}", ataReport.ReadCapabilities.UnformattedBPT)); + if(ataReport.ReadCapabilities.UnformattedBPS > 0) + ataTwoValue.Add("Bytes per unformatted sector", string.Format("{0}", ataReport.ReadCapabilities.UnformattedBPS)); + } + } + + if(ataReport.ReadCapabilities.SupportsRead) + ataOneValue.Add("Device supports READ SECTOR(S) command in CHS mode"); + if(ataReport.ReadCapabilities.SupportsReadRetry) + ataOneValue.Add("Device supports READ SECTOR(S) RETRY command in CHS mode"); + if(ataReport.ReadCapabilities.SupportsReadDma) + ataOneValue.Add("Device supports READ DMA command in CHS mode"); + if(ataReport.ReadCapabilities.SupportsReadDmaRetry) + ataOneValue.Add("Device supports READ DMA RETRY command in CHS mode"); + if(ataReport.ReadCapabilities.SupportsReadLong) + ataOneValue.Add("Device supports READ LONG command in CHS mode"); + if(ataReport.ReadCapabilities.SupportsReadLongRetry) + ataOneValue.Add("Device supports READ LONG RETRY command in CHS mode"); + + if(ataReport.ReadCapabilities.SupportsReadLba) + ataOneValue.Add("Device supports READ SECTOR(S) command in 28-bit LBA mode"); + if(ataReport.ReadCapabilities.SupportsReadRetryLba) + ataOneValue.Add("Device supports READ SECTOR(S) RETRY command in 28-bit LBA mode"); + if(ataReport.ReadCapabilities.SupportsReadDmaLba) + ataOneValue.Add("Device supports READ DMA command in 28-bit LBA mode"); + if(ataReport.ReadCapabilities.SupportsReadDmaRetryLba) + ataOneValue.Add("Device supports READ DMA RETRY command in 28-bit LBA mode"); + if(ataReport.ReadCapabilities.SupportsReadLongLba) + ataOneValue.Add("Device supports READ LONG command in 28-bit LBA mode"); + if(ataReport.ReadCapabilities.SupportsReadLongRetryLba) + ataOneValue.Add("Device supports READ LONG RETRY command in 28-bit LBA mode"); + + if(ataReport.ReadCapabilities.SupportsReadLba48) + ataOneValue.Add("Device supports READ SECTOR(S) command in 48-bit LBA mode"); + if(ataReport.ReadCapabilities.SupportsReadDmaLba48) + ataOneValue.Add("Device supports READ DMA command in 48-bit LBA mode"); + + if(ataReport.ReadCapabilities.SupportsSeek) + ataOneValue.Add("Device supports SEEK command in CHS mode"); + if(ataReport.ReadCapabilities.SupportsSeekLba) + ataOneValue.Add("Device supports SEEK command in 28-bit LBA mode"); + } + else + testedMedia = ataReport.RemovableMedias; } } } diff --git a/DiscImageChef.Server/App_Start/ScsiEvpd.cs b/DiscImageChef.Server/App_Start/ScsiEvpd.cs index 7b071c83e..bf958b0f7 100644 --- a/DiscImageChef.Server/App_Start/ScsiEvpd.cs +++ b/DiscImageChef.Server/App_Start/ScsiEvpd.cs @@ -36,12 +36,59 @@ // ****************************************************************************/ // //$Id$ using System; +using System.Collections.Generic; +using DiscImageChef.Metadata; namespace DiscImageChef.Server.App_Start { - public class ScsiEvpd + public static class ScsiEvpd { - public ScsiEvpd() + public static void Report(pageType[] pages, string vendor, ref Dictionary evpdPages) { + foreach(pageType evpd in pages) + { + if(evpd.page >= 0x01 && evpd.page <= 0x7F) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.DecodeASCIIPage(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x81) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_81(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x82) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.DecodePage82(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x83) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_83(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x84) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_84(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x85) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_85(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x86) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_86(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0x89) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_89(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xB0) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_B0(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xB2) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), string.Format("TapeAlert Supported Flags Bitmap: 0x{0:X16}
", Decoders.SCSI.EVPD.DecodePageB2(evpd.value))); + else if(evpd.page == 0xB4) + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.DecodePageB4(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xC0 && vendor.Trim() == "quantum") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C0_Quantum(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xC0 && vendor.Trim() == "seagate") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C0_Seagate(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xC0 && vendor.Trim() == "ibm") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C0_IBM(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xC1 && vendor.Trim() == "ibm") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C1_IBM(evpd.value).Replace("\n", "
")); + else if((evpd.page == 0xC0 || evpd.page == 0xC1) && vendor.Trim() == "certance") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C0_C1_Certance(evpd.value).Replace("\n", "
")); + else if((evpd.page == 0xC2 || evpd.page == 0xC3 || evpd.page == 0xC4 || evpd.page == 0xC5 || evpd.page == 0xC6) && + vendor.Trim() == "certance") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(evpd.value).Replace("\n", "
")); + else if((evpd.page == 0xC0 || evpd.page == 0xC1 || evpd.page == 0xC2 || evpd.page == 0xC3 || evpd.page == 0xC4 || evpd.page == 0xC5) && + vendor.Trim() == "hp") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_C0_to_C5_HP(evpd.value).Replace("\n", "
")); + else if(evpd.page == 0xDF && vendor.Trim() == "certance") + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), Decoders.SCSI.EVPD.PrettifyPage_DF_Certance(evpd.value).Replace("\n", "
")); + else + evpdPages.Add(string.Format("EVPD page {0:X2}h", evpd.page), "Undecoded"); + } } } } diff --git a/DiscImageChef.Server/App_Start/ScsiMmcFeatures.cs b/DiscImageChef.Server/App_Start/ScsiMmcFeatures.cs index e4da63ba3..8b29b71a6 100644 --- a/DiscImageChef.Server/App_Start/ScsiMmcFeatures.cs +++ b/DiscImageChef.Server/App_Start/ScsiMmcFeatures.cs @@ -36,12 +36,346 @@ // ****************************************************************************/ // //$Id$ using System; +using System.Collections.Generic; +using DiscImageChef.Decoders.SCSI.MMC; +using DiscImageChef.Metadata; + namespace DiscImageChef.Server.App_Start { - public class ScsiMmcFeatures + public static class ScsiMmcFeatures { - public ScsiMmcFeatures() + public static void Report(mmcFeaturesType ftr, ref List mmcOneValue) { + if(ftr.SupportsAACS && ftr.AACSVersionSpecified) + mmcOneValue.Add(string.Format("Drive supports AACS version {0}", ftr.AACSVersion)); + else if(ftr.SupportsAACS) + mmcOneValue.Add("Drive supports AACS"); + if(ftr.AGIDsSpecified) + mmcOneValue.Add(string.Format("Drive supports {0} AGIDs concurrently", ftr.AGIDs)); + if(ftr.CanGenerateBindingNonce) + { + mmcOneValue.Add("Drive supports generating the binding nonce"); + if(ftr.BindingNonceBlocksSpecified) + mmcOneValue.Add(string.Format("{0} media blocks are required for the binding nonce", ftr.BindingNonceBlocks)); + } + if(ftr.BlocksPerReadableUnit > 1) + mmcOneValue.Add(string.Format("{0} logical blocks per media writable unit", ftr.BlocksPerReadableUnit)); + if(ftr.BufferUnderrunFreeInDVD) + mmcOneValue.Add("Drive supports zero loss linking writing DVDs"); + if(ftr.BufferUnderrunFreeInSAO) + mmcOneValue.Add("Drive supports zero loss linking in Session at Once Mode"); + if(ftr.BufferUnderrunFreeInTAO) + mmcOneValue.Add("Drive supports zero loss linking in Track at Once Mode"); + if(ftr.CanAudioScan) + mmcOneValue.Add("Drive supports the SCAN command"); + if(ftr.CanEject) + mmcOneValue.Add("Drive can eject media"); + if(ftr.CanEraseSector) + mmcOneValue.Add("Drive supports media that require erasing before writing"); + if(ftr.CanExpandBDRESpareArea) + mmcOneValue.Add("Drive can expand the spare area on a formatted BD-RE disc"); + if(ftr.CanFormat) + mmcOneValue.Add("Drive can format media into logical blocks"); + if(ftr.CanFormatBDREWithoutSpare) + mmcOneValue.Add("Drive can format BD-RE with no spares allocated"); + if(ftr.CanFormatQCert) + mmcOneValue.Add("Drive can format BD-RE discs with quick certification"); + if(ftr.CanFormatCert) + mmcOneValue.Add("Drive can format BD-RE discs with full certification"); + if(ftr.CanFormatFRF) + mmcOneValue.Add("Drive can fast re-format BD-RE discs"); + if(ftr.CanFormatRRM) + mmcOneValue.Add("Drive can format BD-R discs with RRM format"); + if(ftr.CanLoad) + mmcOneValue.Add("Drive can load media"); + if(ftr.CanMuteSeparateChannels) + mmcOneValue.Add("Drive is able to mute channels separately"); + if(ftr.CanOverwriteSAOTrack) + mmcOneValue.Add("Drive can overwrite a SAO track with another in CD-RWs"); + if(ftr.CanOverwriteTAOTrack) + mmcOneValue.Add("Drive can overwrite a TAO track with another in CD-RWs"); + if(ftr.CanPlayCDAudio) + mmcOneValue.Add("Drive has an analogue audio output"); + if(ftr.CanPseudoOverwriteBDR) + mmcOneValue.Add("Drive can write BD-R on Pseudo-OVerwrite SRM mode"); + if(ftr.CanReadAllDualR) + mmcOneValue.Add("Drive can read DVD-R DL from all recording modes"); + if(ftr.CanReadAllDualRW) + mmcOneValue.Add("Drive can read DVD-RW DL from all recording modes"); + if(ftr.CanReadBD) + mmcOneValue.Add("Drive can read BD-ROM"); + if(ftr.CanReadBDR) + mmcOneValue.Add("Drive can read BD-R Ver.1"); + if(ftr.CanReadBDRE1) + mmcOneValue.Add("Drive can read BD-RE Ver.1"); + if(ftr.CanReadBDRE2) + mmcOneValue.Add("Drive can read BD-RE Ver.2"); + if(ftr.CanReadBDROM) + mmcOneValue.Add("Drive can read BD-ROM Ver.1"); + if(ftr.CanReadBluBCA) + mmcOneValue.Add("Drive can read BD's Burst Cutting Area"); + if(ftr.CanReadCD) + mmcOneValue.Add("Drive can read CD-ROM"); + if(ftr.CanWriteCDMRW && ftr.CanReadDVDPlusMRW && ftr.CanWriteDVDPlusMRW) + mmcOneValue.Add("Drive can read and write CD-MRW and DVD+MRW"); + else if(ftr.CanReadDVDPlusMRW && ftr.CanWriteDVDPlusMRW) + mmcOneValue.Add("Drive can read and write DVD+MRW"); + else if(ftr.CanWriteCDMRW && ftr.CanReadDVDPlusMRW) + mmcOneValue.Add("Drive and read DVD+MRW and read and write CD-MRW"); + else if(ftr.CanWriteCDMRW) + mmcOneValue.Add("Drive can read and write CD-MRW"); + else if(ftr.CanReadDVDPlusMRW) + mmcOneValue.Add("Drive can read CD-MRW and DVD+MRW"); + else if(ftr.CanReadCDMRW) + mmcOneValue.Add("Drive can read CD-MRW"); + if(ftr.CanReadCPRM_MKB) + mmcOneValue.Add("Drive supports reading Media Key Block of CPRM"); + if(ftr.CanReadDDCD) + mmcOneValue.Add("Drive can read DDCDs"); + if(ftr.CanReadDVD) + mmcOneValue.Add("Drive can read DVD"); + if(ftr.CanWriteDVDPlusRW) + mmcOneValue.Add("Drive can read and write DVD+RW"); + else if(ftr.CanReadDVDPlusRW) + mmcOneValue.Add("Drive can read DVD+RW"); + if(ftr.CanWriteDVDPlusR) + mmcOneValue.Add("Drive can read and write DVD+R"); + else if(ftr.CanReadDVDPlusR) + mmcOneValue.Add("Drive can read DVD+R"); + if(ftr.CanWriteDVDPlusRDL) + mmcOneValue.Add("Drive can read and write DVD+R DL"); + else if(ftr.CanReadDVDPlusRDL) + mmcOneValue.Add("Drive can read DVD+R DL"); + if(ftr.CanReadDriveAACSCertificate) + mmcOneValue.Add("Drive supports reading the Drive Certificate"); + if(ftr.CanReadHDDVD && ftr.CanReadHDDVDR && ftr.CanReadHDDVDRAM) + mmcOneValue.Add("Drive can read HD DVD-ROM, HD DVD-RW, HD DVD-R and HD DVD-RAM"); + else if(ftr.CanReadHDDVD && ftr.CanReadHDDVDR) + mmcOneValue.Add("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-R"); + else if(ftr.CanReadHDDVD && ftr.CanReadHDDVDRAM) + mmcOneValue.Add("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-RAM"); + else if(ftr.CanReadHDDVD) + mmcOneValue.Add("Drive can read HD DVD-ROM and HD DVD-RW"); + if(ftr.CanReadLeadInCDText) + mmcOneValue.Add("Drive can return CD-Text from Lead-In"); + if(ftr.CanReadOldBDR) + mmcOneValue.Add("Drive can read BD-R pre-1.0"); + if(ftr.CanReadOldBDRE) + mmcOneValue.Add("Drive can read BD-RE pre-1.0"); + if(ftr.CanReadOldBDROM) + mmcOneValue.Add("Drive can read BD-ROM pre-1.0"); + if(ftr.CanReadSpareAreaInformation) + mmcOneValue.Add("Drive can return Spare Area Information"); + if(ftr.CanReportDriveSerial) + mmcOneValue.Add("Drive is to report drive serial number"); + if(ftr.CanReportMediaSerial) + mmcOneValue.Add("Drive is to read media serial number"); + if(ftr.CanTestWriteDDCDR) + mmcOneValue.Add("Drive can do a test writing with DDCD-R"); + if(ftr.CanTestWriteDVD) + mmcOneValue.Add("Drive can do a test writing with DVDs"); + if(ftr.CanTestWriteInSAO) + mmcOneValue.Add("Drive can do a test writing in Session at Once Mode"); + if(ftr.CanTestWriteInTAO) + mmcOneValue.Add("Drive can do a test writing in Track at Once Mode"); + if(ftr.CanUpgradeFirmware) + mmcOneValue.Add("Drive supports Microcode Upgrade"); + if(ftr.ErrorRecoveryPage) + mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); + if(ftr.Locked) + mmcOneValue.Add("Drive can lock media"); + if(ftr.LogicalBlockSize > 0) + mmcOneValue.Add(string.Format("{0} bytes per logical block", ftr.LogicalBlockSize)); + if(ftr.MultiRead) + mmcOneValue.Add("Drive claims capability to read all CD formats according to OSTA Multi-Read Specification"); + + switch(ftr.PhysicalInterfaceStandard) + { + case PhysicalInterfaces.Unspecified: + mmcOneValue.Add("Drive uses an unspecified physical interface"); + break; + case PhysicalInterfaces.SCSI: + mmcOneValue.Add("Drive uses SCSI interface"); + break; + case PhysicalInterfaces.ATAPI: + mmcOneValue.Add("Drive uses ATAPI interface"); + break; + case PhysicalInterfaces.IEEE1394: + mmcOneValue.Add("Drive uses IEEE-1394 interface"); + break; + case PhysicalInterfaces.IEEE1394A: + mmcOneValue.Add("Drive uses IEEE-1394A interface"); + break; + case PhysicalInterfaces.FC: + mmcOneValue.Add("Drive uses Fibre Channel interface"); + break; + case PhysicalInterfaces.IEEE1394B: + mmcOneValue.Add("Drive uses IEEE-1394B interface"); + break; + case PhysicalInterfaces.SerialATAPI: + mmcOneValue.Add("Drive uses Serial ATAPI interface"); + break; + case PhysicalInterfaces.USB: + mmcOneValue.Add("Drive uses USB interface"); + break; + case PhysicalInterfaces.Vendor: + mmcOneValue.Add("Drive uses a vendor unique interface"); + break; + default: + mmcOneValue.Add(string.Format("Drive uses an unknown interface with code {0}", (uint)ftr.PhysicalInterfaceStandard)); + break; + } + + if(ftr.PreventJumper) + mmcOneValue.Add("Drive power ups locked"); + if(ftr.SupportsBusEncryption) + mmcOneValue.Add("Drive supports bus encryption"); + if(ftr.CanWriteBD) + mmcOneValue.Add("Drive can write BD-R or BD-RE"); + if(ftr.CanWriteBDR) + mmcOneValue.Add("Drive can write BD-R Ver.1"); + if(ftr.CanWriteBDRE1) + mmcOneValue.Add("Drive can write BD-RE Ver.1"); + if(ftr.CanWriteBDRE2) + mmcOneValue.Add("Drive can write BD-RE Ver.2"); + if(ftr.CanWriteBusEncryptedBlocks) + mmcOneValue.Add("Drive supports writing with bus encryption"); + if(ftr.CanWriteCDRW) + mmcOneValue.Add("Drive can write CD-RW"); + if(ftr.CanWriteCDRWCAV) + mmcOneValue.Add("Drive can write High-Speed CD-RW"); + if(ftr.CanWriteCDSAO && !ftr.CanWriteRaw) + mmcOneValue.Add("Drive can write CDs in Session at Once Mode:"); + else if(!ftr.CanWriteCDSAO && ftr.CanWriteRaw) + mmcOneValue.Add("Drive can write CDs in raw Mode:"); + else if(ftr.CanWriteCDSAO && ftr.CanWriteRaw) + mmcOneValue.Add("Drive can write CDs in Session at Once and in Raw Modes:"); + if(ftr.CanWriteCDTAO) + mmcOneValue.Add("Drive can write CDs in Track at Once Mode:"); + if(ftr.CanWriteCSSManagedDVD) + mmcOneValue.Add("Drive can write CSS managed DVDs"); + if(ftr.CanWriteDDCDR) + mmcOneValue.Add("Drive supports writing DDCD-R"); + if(ftr.CanWriteDDCDRW) + mmcOneValue.Add("Drive supports writing DDCD-RW"); + if(ftr.CanWriteDVDPlusRWDL) + mmcOneValue.Add("Drive can read and write DVD+RW DL"); + else if(ftr.CanReadDVDPlusRWDL) + mmcOneValue.Add("Drive can read DVD+RW DL"); + if(ftr.CanWriteDVDR && ftr.CanWriteDVDRW && ftr.CanWriteDVDRDL) + mmcOneValue.Add("Drive supports writing DVD-R, DVD-RW and DVD-R DL"); + else if(ftr.CanWriteDVDR && ftr.CanWriteDVDRDL) + mmcOneValue.Add("Drive supports writing DVD-R and DVD-R DL"); + else if(ftr.CanWriteDVDR && ftr.CanWriteDVDRW) + mmcOneValue.Add("Drive supports writing DVD-R and DVD-RW"); + else if(ftr.CanWriteDVDR) + mmcOneValue.Add("Drive supports writing DVD-R"); + if(ftr.CanWriteHDDVDR && ftr.CanWriteHDDVDRAM) + mmcOneValue.Add("Drive can write HD DVD-RW, HD DVD-R and HD DVD-RAM"); + else if(ftr.CanWriteHDDVDR) + mmcOneValue.Add("Drive can write HD DVD-RW and HD DVD-R"); + else if(ftr.CanWriteHDDVDRAM) + mmcOneValue.Add("Drive can write HD DVD-RW and HD DVD-RAM"); + // TODO: Write HD DVD-RW + /* + else + mmcOneValue.Add("Drive can write HD DVD-RW"); + */ + if(ftr.CanWriteOldBDR) + mmcOneValue.Add("Drive can write BD-R pre-1.0"); + if(ftr.CanWriteOldBDRE) + mmcOneValue.Add("Drive can write BD-RE pre-1.0"); + if(ftr.CanWriteRWSubchannelInTAO) + { + mmcOneValue.Add("Drive can write user provided data in the R-W subchannels in Track at Once Mode"); + if(ftr.CanWriteRawSubchannelInTAO) + mmcOneValue.Add("Drive accepts RAW R-W subchannel data in Track at Once Mode"); + if(ftr.CanWritePackedSubchannelInTAO) + mmcOneValue.Add("Drive accepts Packed R-W subchannel data in Track at Once Mode"); + } + if(ftr.CanWriteRWSubchannelInSAO) + mmcOneValue.Add("Drive can write user provided data in the R-W subchannels in Session at Once Mode"); + if(ftr.CanWriteRaw && ftr.CanWriteRawMultiSession) + mmcOneValue.Add("Drive can write multi-session CDs in raw mode"); + if(ftr.EmbeddedChanger) + { + mmcOneValue.Add("Drive contains an embedded changer"); + + if(ftr.ChangerIsSideChangeCapable) + mmcOneValue.Add("Drive can change disc side"); + if(ftr.ChangerSupportsDiscPresent) + mmcOneValue.Add("Drive is able to report slots contents after a reset or change"); + + mmcOneValue.Add(string.Format("Drive has {0} slots", ftr.ChangerSlots + 1)); + } + if(ftr.SupportsCSS && ftr.CSSVersionSpecified) + mmcOneValue.Add(string.Format("Drive supports DVD CSS/CPPM version {0}", ftr.CSSVersion)); + else if(ftr.SupportsCSS) + mmcOneValue.Add("Drive supports DVD CSS/CPRM"); + if(ftr.SupportsCPRM && ftr.CPRMVersionSpecified) + mmcOneValue.Add(string.Format("Drive supports DVD CPPM version {0}", ftr.CPRMVersion)); + else if(ftr.SupportsCPRM) + mmcOneValue.Add("Drive supports DVD CPRM"); + if(ftr.DBML) + mmcOneValue.Add("Drive reports Device Busy Class events during medium loading/unloading"); + if(ftr.DVDMultiRead) + mmcOneValue.Add("Drive conforms to DVD Multi Drive Read-only Specifications"); + if(ftr.FirmwareDateSpecified) + mmcOneValue.Add(string.Format("Drive firmware is dated {0}", ftr.FirmwareDate)); + if(ftr.SupportsC2) + mmcOneValue.Add("Drive supports C2 Error Pointers"); + if(ftr.SupportsDAP) + mmcOneValue.Add("Drive supports the DAP bit in the READ CD and READ CD MSF commands"); + if(ftr.SupportsDeviceBusyEvent) + mmcOneValue.Add("Drive supports Device Busy events"); + + switch(ftr.LoadingMechanismType) + { + case 0: + mmcOneValue.Add("Drive uses media caddy"); + break; + case 1: + mmcOneValue.Add("Drive uses a tray"); + break; + case 2: + mmcOneValue.Add("Drive is pop-up"); + break; + case 4: + mmcOneValue.Add("Drive is a changer with individually changeable discs"); + break; + case 5: + mmcOneValue.Add("Drive is a changer using cartridges"); + break; + default: + mmcOneValue.Add(string.Format("Drive uses unknown loading mechanism type {0}", ftr.LoadingMechanismType)); + break; + } + + if(ftr.SupportsHybridDiscs) + mmcOneValue.Add("Drive is able to access Hybrid discs"); + if(ftr.SupportsModePage1Ch) + mmcOneValue.Add("Drive supports the Informational Exceptions Control mode page 1Ch"); + if(ftr.SupportsOSSC) + mmcOneValue.Add("Drive supports the Trusted Computing Group Optical Security Subsystem Class"); + if(ftr.SupportsPWP) + mmcOneValue.Add("Drive supports set/release of PWP status"); + if(ftr.SupportsSWPP) + mmcOneValue.Add("Drive supports the SWPP bit of the Timeout and Protect mode page"); + if(ftr.SupportsSecurDisc) + mmcOneValue.Add("Drive supports SecurDisc"); + if(ftr.SupportsSeparateVolume) + mmcOneValue.Add("Drive supports separate volume per channel"); + if(ftr.SupportsVCPS) + mmcOneValue.Add("Drive supports VCPS"); + if(ftr.VolumeLevelsSpecified) + mmcOneValue.Add(string.Format("Drive has {0} volume levels", ftr.VolumeLevels + 1)); + if(ftr.SupportsWriteProtectPAC) + mmcOneValue.Add("Drive supports reading/writing the Disc Write Protect PAC on BD-R/-RE media"); + if(ftr.SupportsWriteInhibitDCB) + mmcOneValue.Add("Drive supports writing the Write Inhibit DCB on DVD+RW media"); + + mmcOneValue.Sort(); + mmcOneValue.Add(""); } } } diff --git a/DiscImageChef.Server/App_Start/ScsiMmcMode.cs b/DiscImageChef.Server/App_Start/ScsiMmcMode.cs index 04b0487e3..518bf357a 100644 --- a/DiscImageChef.Server/App_Start/ScsiMmcMode.cs +++ b/DiscImageChef.Server/App_Start/ScsiMmcMode.cs @@ -40,926 +40,183 @@ using DiscImageChef.Metadata; using System.Collections.Generic; namespace DiscImageChef.Server.App_Start { - public static class ScsiMmc + public static class ScsiMmcMode { - public static void Report(mmcType mmc, ref List mmcOneValue, ref testedMediaType[] testedMedia) + public static void Report(mmcModeType mode, ref List mmcOneValue) { - testedMedia = mmc.TestedMedia; + if(mode.PlaysAudio) + mmcOneValue.Add("Drive can play audio"); + if(mode.ReadsMode2Form1) + mmcOneValue.Add("Drive can read sectors in Mode 2 Form 1 format"); + if(mode.ReadsMode2Form2) + mmcOneValue.Add("Drive can read sectors in Mode 2 Form 2 format"); + if(mode.SupportsMultiSession) + mmcOneValue.Add("Drive supports multi-session discs and/or Photo-CD"); - if(mmc.ModeSense2A != null) + if(mode.CDDACommand) + mmcOneValue.Add("Drive can read digital audio"); + if(mode.AccurateCDDA) + mmcOneValue.Add("Drive can continue from streaming loss"); + if(mode.ReadsSubchannel) + mmcOneValue.Add("Drive can read uncorrected and interleaved R-W subchannels"); + if(mode.ReadsDeinterlavedSubchannel) + mmcOneValue.Add("Drive can read, deinterleave and correct R-W subchannels"); + if(mode.ReturnsC2Pointers) + mmcOneValue.Add("Drive supports C2 pointers"); + if(mode.ReadsUPC) + mmcOneValue.Add("Drive can read Media Catalogue Number"); + if(mode.ReadsISRC) + mmcOneValue.Add("Drive can read ISRC"); + + switch(mode.LoadingMechanismType) { - if(mmc.ModeSense2A.PlaysAudio) - mmcOneValue.Add("Drive can play audio"); - if(mmc.ModeSense2A.ReadsMode2Form1) - mmcOneValue.Add("Drive can read sectors in Mode 2 Form 1 format"); - if(mmc.ModeSense2A.ReadsMode2Form2) - mmcOneValue.Add("Drive can read sectors in Mode 2 Form 2 format"); - if(mmc.ModeSense2A.SupportsMultiSession) - mmcOneValue.Add("Drive supports multi-session discs and/or Photo-CD"); - - if(mmc.ModeSense2A.CDDACommand) - mmcOneValue.Add("Drive can read digital audio"); - if(mmc.ModeSense2A.AccurateCDDA) - mmcOneValue.Add("Drive can continue from streaming loss"); - if(mmc.ModeSense2A.ReadsSubchannel) - mmcOneValue.Add("Drive can read uncorrected and interleaved R-W subchannels"); - if(mmc.ModeSense2A.ReadsDeinterlavedSubchannel) - mmcOneValue.Add("Drive can read, deinterleave and correct R-W subchannels"); - if(mmc.ModeSense2A.ReturnsC2Pointers) - mmcOneValue.Add("Drive supports C2 pointers"); - if(mmc.ModeSense2A.ReadsUPC) - mmcOneValue.Add("Drive can read Media Catalogue Number"); - if(mmc.ModeSense2A.ReadsISRC) - mmcOneValue.Add("Drive can read ISRC"); - - switch(mmc.ModeSense2A.LoadingMechanismType) - { - case 0: - mmcOneValue.Add("Drive uses media caddy"); - break; - case 1: - mmcOneValue.Add("Drive uses a tray"); - break; - case 2: - mmcOneValue.Add("Drive is pop-up"); - break; - case 4: - mmcOneValue.Add("Drive is a changer with individually changeable discs"); - break; - case 5: - mmcOneValue.Add("Drive is a changer using cartridges"); - break; - default: - mmcOneValue.Add(string.Format("Drive uses unknown loading mechanism type {0}", mmc.ModeSense2A.LoadingMechanismType)); - break; - } - - if(mmc.ModeSense2A.CanLockMedia) - mmcOneValue.Add("Drive can lock media"); - if(mmc.ModeSense2A.PreventJumperStatus) - { - mmcOneValue.Add("Drive power ups locked"); - if(mmc.ModeSense2A.LockStatus) - mmcOneValue.Add("Drive is locked, media cannot be ejected or inserted"); - else - mmcOneValue.Add("Drive is not locked, media can be ejected and inserted"); - } - else - { - if(mmc.ModeSense2A.LockStatus) - mmcOneValue.Add("Drive is locked, media cannot be ejected, but if empty, can be inserted"); - else - mmcOneValue.Add("Drive is not locked, media can be ejected and inserted"); - } - if(mmc.ModeSense2A.CanEject) - mmcOneValue.Add("Drive can eject media"); - - if(mmc.ModeSense2A.SeparateChannelMute) - mmcOneValue.Add("Each channel can be muted independently"); - if(mmc.ModeSense2A.SeparateChannelVolume) - mmcOneValue.Add("Each channel's volume can be controlled independently"); - - if(mmc.ModeSense2A.SupportedVolumeLevels > 0) - mmcOneValue.Add(string.Format("Drive supports {0} volume levels", mmc.ModeSense2A.SupportedVolumeLevels)); - if(mmc.ModeSense2A.BufferSize > 0) - mmcOneValue.Add(string.Format("Drive has {0} Kbyte of buffer", mmc.ModeSense2A.BufferSize)); - if(mmc.ModeSense2A.MaximumSpeed > 0) - mmcOneValue.Add(string.Format("Drive's maximum reading speed is {0} Kbyte/sec.", mmc.ModeSense2A.MaximumSpeed)); - if(mmc.ModeSense2A.CurrentSpeed > 0) - mmcOneValue.Add(string.Format("Drive's current reading speed is {0} Kbyte/sec.", mmc.ModeSense2A.CurrentSpeed)); - - if(mmc.ModeSense2A.ReadsCDR) - { - if(mmc.ModeSense2A.WritesCDR) - mmcOneValue.Add("Drive can read and write CD-R"); - else - mmcOneValue.Add("Drive can read CD-R"); - - if(mmc.ModeSense2A.ReadsPacketCDR) - mmcOneValue.Add("Drive supports reading CD-R packet media"); - } - - if(mmc.ModeSense2A.ReadsCDRW) - { - if(mmc.ModeSense2A.WritesCDRW) - mmcOneValue.Add("Drive can read and write CD-RW"); - else - mmcOneValue.Add("Drive can read CD-RW"); - } - - if(mmc.ModeSense2A.ReadsDVDROM) - mmcOneValue.Add("Drive can read DVD-ROM"); - if(mmc.ModeSense2A.ReadsDVDR) - { - if(mmc.ModeSense2A.WritesDVDR) - mmcOneValue.Add("Drive can read and write DVD-R"); - else - mmcOneValue.Add("Drive can read DVD-R"); - } - if(mmc.ModeSense2A.ReadsDVDRAM) - { - if(mmc.ModeSense2A.WritesDVDRAM) - mmcOneValue.Add("Drive can read and write DVD-RAM"); - else - mmcOneValue.Add("Drive can read DVD-RAM"); - } - - if(mmc.ModeSense2A.CompositeAudioVideo) - mmcOneValue.Add("Drive can deliver a composite audio and video data stream"); - if(mmc.ModeSense2A.DigitalPort1) - mmcOneValue.Add("Drive supports IEC-958 digital output on port 1"); - if(mmc.ModeSense2A.DigitalPort2) - mmcOneValue.Add("Drive supports IEC-958 digital output on port 2"); - - if(mmc.ModeSense2A.DeterministicSlotChanger) - mmcOneValue.Add("Drive contains a changer that can report the exact contents of the slots"); - if(mmc.ModeSense2A.CurrentWriteSpeedSelected > 0) - { - if(mmc.ModeSense2A.RotationControlSelected == 0) - mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec. in CLV mode", mmc.ModeSense2A.CurrentWriteSpeedSelected)); - else if(mmc.ModeSense2A.RotationControlSelected == 1) - mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec. in pure CAV mode", mmc.ModeSense2A.CurrentWriteSpeedSelected)); - } - else - { - if(mmc.ModeSense2A.MaximumWriteSpeed > 0) - mmcOneValue.Add(string.Format("Drive's maximum writing speed is {0} Kbyte/sec.", mmc.ModeSense2A.MaximumWriteSpeed)); - if(mmc.ModeSense2A.CurrentWriteSpeed > 0) - mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec.", mmc.ModeSense2A.CurrentWriteSpeed)); - } - - if(mmc.ModeSense2A.WriteSpeedPerformanceDescriptors != null) - { - foreach(Decoders.SCSI.Modes.ModePage_2A_WriteDescriptor descriptor in mmc.ModeSense2A.WriteSpeedPerformanceDescriptors) - { - if(descriptor.WriteSpeed > 0) - { - if(descriptor.RotationControl == 0) - mmcOneValue.Add(string.Format("Drive supports writing at {0} Kbyte/sec. in CLV mode", descriptor.WriteSpeed)); - else if(descriptor.RotationControl == 1) - mmcOneValue.Add(string.Format("Drive supports writing at is {0} Kbyte/sec. in pure CAV mode", descriptor.WriteSpeed)); - } - } - } - - if(mmc.ModeSense2A.TestWrite) - mmcOneValue.Add("Drive supports test writing"); - - if(mmc.ModeSense2A.ReadsBarcode) - mmcOneValue.Add("Drive can read barcode"); - - if(mmc.ModeSense2A.ReadsBothSides) - mmcOneValue.Add("Drive can read both sides of a disc"); - if(mmc.ModeSense2A.LeadInPW) - mmcOneValue.Add("Drive an read raw R-W subchannel from the Lead-In"); - - if(mmc.ModeSense2A.CSSandCPPMSupported) - mmcOneValue.Add("Drive supports DVD CSS and/or DVD CPPM"); - - if(mmc.ModeSense2A.BufferUnderRunProtection) - mmcOneValue.Add("Drive supports buffer under-run free recording"); + case 0: + mmcOneValue.Add("Drive uses media caddy"); + break; + case 1: + mmcOneValue.Add("Drive uses a tray"); + break; + case 2: + mmcOneValue.Add("Drive is pop-up"); + break; + case 4: + mmcOneValue.Add("Drive is a changer with individually changeable discs"); + break; + case 5: + mmcOneValue.Add("Drive is a changer using cartridges"); + break; + default: + mmcOneValue.Add(string.Format("Drive uses unknown loading mechanism type {0}", mode.LoadingMechanismType)); + break; } - if(mmc.Features != null) + if(mode.CanLockMedia) + mmcOneValue.Add("Drive can lock media"); + if(mode.PreventJumperStatus) { - - sb.AppendLine("MMC Core Feature:"); - sb.Append("\tDrive uses "); - switch(ftr.PhysicalInterfaceStandard) - { - case PhysicalInterfaces.Unspecified: - sb.AppendLine("an unspecified physical interface"); - break; - case PhysicalInterfaces.SCSI: - sb.AppendLine("SCSI interface"); - break; - case PhysicalInterfaces.ATAPI: - sb.AppendLine("ATAPI interface"); - break; - case PhysicalInterfaces.IEEE1394: - sb.AppendLine("IEEE-1394 interface"); - break; - case PhysicalInterfaces.IEEE1394A: - sb.AppendLine("IEEE-1394A interface"); - break; - case PhysicalInterfaces.FC: - sb.AppendLine("Fibre Channel interface"); - break; - case PhysicalInterfaces.IEEE1394B: - sb.AppendLine("IEEE-1394B interface"); - break; - case PhysicalInterfaces.SerialATAPI: - sb.AppendLine("Serial ATAPI interface"); - break; - case PhysicalInterfaces.USB: - sb.AppendLine("USB interface"); - break; - case PhysicalInterfaces.Vendor: - sb.AppendLine("a vendor unique interface"); - break; - default: - sb.AppendFormat("an unknown interface with code {0}", (uint)ftr.PhysicalInterfaceStandard).AppendLine(); - break; - } - - if(ftr.DBE) - mmcOneValue.Add("Drive supports Device Busy events"); - if(ftr.INQ2) - mmcOneValue.Add("Drive supports EVPD, Page Code and 16-bit Allocation Length as described in SPC-3"); - - if(ftr.Async) - mmcOneValue.Add("Drive supports polling and asynchronous GET EVENT STATUS NOTIFICATION"); - else - mmcOneValue.Add("Drive supports only polling GET EVENT STATUS NOTIFICATION"); - - if(ftr.OCEvent) - mmcOneValue.Add("Drive supports operational change request / notification class events"); - - - switch(ftr.LoadingMechanismType) - { - case 0: - mmcOneValue.Add("Drive uses media caddy"); - break; - case 1: - mmcOneValue.Add("Drive uses a tray"); - break; - case 2: - mmcOneValue.Add("Drive is pop-up"); - break; - case 4: - mmcOneValue.Add("Drive is a changer with individually changeable discs"); - break; - case 5: - mmcOneValue.Add("Drive is a changer using cartridges"); - break; - default: - sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", ftr.LoadingMechanismType).AppendLine(); - break; - } - - if(ftr.Lock) - mmcOneValue.Add("Drive can lock media"); - if(ftr.PreventJumper) - mmcOneValue.Add("Drive power ups locked"); - if(ftr.Eject) - mmcOneValue.Add("Drive can eject media"); - if(ftr.Load) - mmcOneValue.Add("Drive can load media"); - if(ftr.DBML) - mmcOneValue.Add("Drive reports Device Busy Class events during medium loading/unloading"); - - - if(ftr.DWP) - mmcOneValue.Add("Drive supports reading/writing the Disc Write Protect PAC on BD-R/-RE media"); - if(ftr.WDCB) - mmcOneValue.Add("Drive supports writing the Write Inhibit DCB on DVD+RW media"); - if(ftr.SPWP) - mmcOneValue.Add("Drive supports set/release of PWP status"); - if(ftr.SSWPP) - mmcOneValue.Add("Drive supports the SWPP bit of the Timeout and Protect mode page"); - - - - if(ftr.PP) - mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); - if(ftr.LogicalBlockSize > 0) - sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); - if(ftr.Blocking > 1) - sb.AppendFormat("\t{0} logical blocks per media readable unit", ftr.Blocking).AppendLine(); - - - return !feature.HasValue ? null : "Drive claims capability to read all CD formats according to OSTA Multi-Read Specification\n"; - - - - if(ftr.DAP) - mmcOneValue.Add("Drive supports the DAP bit in the READ CD and READ CD MSF commands"); - if(ftr.C2) - mmcOneValue.Add("Drive supports C2 Error Pointers"); - if(ftr.CDText) - mmcOneValue.Add("Drive can return CD-Text from Lead-In"); - - - - mmcOneValue.Add("Drive can read DVD media"); - - if(ftr.DualR) - mmcOneValue.Add("Drive can read DVD-R DL from all recording modes"); - if(ftr.DualRW) - mmcOneValue.Add("Drive can read DVD-RW DL from all recording modes"); - if(ftr.MULTI110) - mmcOneValue.Add("Drive conforms to DVD Multi Drive Read-only Specifications"); - - - if(ftr.PP) - mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); - if(ftr.LogicalBlockSize > 0) - sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); - if(ftr.Blocking > 1) - sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); - if(ftr.LastLBA > 0) - sb.AppendFormat("\tLast adressable logical block is {0}", ftr.LastLBA).AppendLine(); - - - if(ftr.DataTypeSupported > 0) - { - sb.Append("\tDrive supports data block types:"); - if((ftr.DataTypeSupported & 0x0001) == 0x0001) - sb.Append(" 0"); - if((ftr.DataTypeSupported & 0x0002) == 0x0002) - sb.Append(" 1"); - if((ftr.DataTypeSupported & 0x0004) == 0x0004) - sb.Append(" 2"); - if((ftr.DataTypeSupported & 0x0008) == 0x0008) - sb.Append(" 3"); - if((ftr.DataTypeSupported & 0x0010) == 0x0010) - sb.Append(" 4"); - if((ftr.DataTypeSupported & 0x0020) == 0x0020) - sb.Append(" 5"); - if((ftr.DataTypeSupported & 0x0040) == 0x0040) - sb.Append(" 6"); - if((ftr.DataTypeSupported & 0x0080) == 0x0080) - sb.Append(" 7"); - if((ftr.DataTypeSupported & 0x0100) == 0x0100) - sb.Append(" 8"); - if((ftr.DataTypeSupported & 0x0200) == 0x0200) - sb.Append(" 9"); - if((ftr.DataTypeSupported & 0x0400) == 0x0400) - sb.Append(" 10"); - if((ftr.DataTypeSupported & 0x0800) == 0x0800) - sb.Append(" 11"); - if((ftr.DataTypeSupported & 0x1000) == 0x1000) - sb.Append(" 12"); - if((ftr.DataTypeSupported & 0x2000) == 0x2000) - sb.Append(" 13"); - if((ftr.DataTypeSupported & 0x4000) == 0x4000) - sb.Append(" 14"); - if((ftr.DataTypeSupported & 0x8000) == 0x8000) - sb.Append(" 15"); - sb.AppendLine(); - } - - if(ftr.TRIO) - mmcOneValue.Add("Drive claims support to report Track Resources Information"); - if(ftr.ARSV) - mmcOneValue.Add("Drive supports address mode reservation on the RESERVE TRACK command"); - if(ftr.BUF) - mmcOneValue.Add("Drive is capable of zero loss linking"); - - - mmcOneValue.Add("Drive can format media into logical blocks"); - - if(ftr.RENoSA) - mmcOneValue.Add("Drive can format BD-RE with no spares allocated"); - if(ftr.Expand) - mmcOneValue.Add("Drive can expand the spare area on a formatted BD-RE disc"); - if(ftr.QCert) - mmcOneValue.Add("Drive can format BD-RE discs with quick certification"); - if(ftr.Cert) - mmcOneValue.Add("Drive can format BD-RE discs with full certification"); - if(ftr.FRF) - mmcOneValue.Add("Drive can fast re-format BD-RE discs"); - if(ftr.RRM) - mmcOneValue.Add("Drive can format BD-R discs with RRM format"); - - - sb.AppendLine("MMC Hardware Defect Management:"); - mmcOneValue.Add("Drive shall be able to provide a defect-free contiguous address space"); - if(ftr.SSA) - mmcOneValue.Add("Drive can return Spare Area Information"); - - - - if(ftr.PP) - mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); - if(ftr.LogicalBlockSize > 0) - sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); - if(ftr.Blocking > 1) - sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); - - - return !feature.HasValue ? null : "Drive shall have the ability to overwrite logical blocks only in fixed sets at a time\n"; - - - sb.Append("Drive can write High-Speed CD-RW"); - - - if(ftr.Write && ftr.DVDPRead && ftr.DVDPWrite) - sb.Append("Drive can read and write CD-MRW and DVD+MRW"); - else if(ftr.DVDPRead && ftr.DVDPWrite) - sb.Append("Drive can read and write DVD+MRW"); - else if(ftr.Write && ftr.DVDPRead) - sb.Append("Drive and read DVD+MRW and read and write CD-MRW"); - else if(ftr.Write) - sb.Append("Drive can read and write CD-MRW"); - else if(ftr.DVDPRead) - sb.Append("Drive can read CD-MRW and DVD+MRW"); - else - sb.Append("Drive can read CD-MRW"); - - - if(ftr.DRTDM) - mmcOneValue.Add("Drive supports DRT-DM mode"); - else - mmcOneValue.Add("Drive supports Persistent-DM mode"); - - if(ftr.DBICacheZones > 0) - sb.AppendFormat("\tDrive has {0} DBI cache zones", ftr.DBICacheZones).AppendLine(); - if(ftr.Entries > 0) - sb.AppendFormat("\tDrive has {0} DBI entries", ftr.Entries).AppendLine(); - - - - if(ftr.Write) - { - sb.Append("Drive can read and write DVD+RW"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - if(ftr.CloseOnly) - mmcOneValue.Add("Drive supports only the read compatibility stop"); - else - mmcOneValue.Add("Drive supports both forms of background format stopping"); - if(ftr.QuickStart) - mmcOneValue.Add("Drive can do a quick start formatting"); - } - else - { - sb.Append("Drive can read DVD+RW"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - } - - if(ftr.Write) - { - sb.Append("Drive can read and write DVD+R"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - } - else - { - sb.Append("Drive can read DVD+R"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - } - - - if(ftr.Blank) - mmcOneValue.Add("Drive supports the BLANK command"); - if(ftr.Intermediate) - mmcOneValue.Add("Drive supports writing on an intermediate state session and quick formatting"); - if(ftr.DSDR) - mmcOneValue.Add("Drive can read Defect Status data recorded on the medium"); - if(ftr.DSDG) - mmcOneValue.Add("Drive can generate Defect Status data during formatting"); - - - - sb.AppendLine("Drive can write CDs in Track at Once Mode:"); - - if(ftr.RWSubchannel) - { - mmcOneValue.Add("Drive can write user provided data in the R-W subchannels"); - if(ftr.RWRaw) - mmcOneValue.Add("Drive accepts RAW R-W subchannel data"); - if(ftr.RWPack) - mmcOneValue.Add("Drive accepts Packed R-W subchannel data"); - - } - - if(ftr.CDRW) - mmcOneValue.Add("Drive can overwrite a TAO track with another in CD-RWs"); - if(ftr.TestWrite) - mmcOneValue.Add("Drive can do a test writing"); - if(ftr.BUF) - mmcOneValue.Add("Drive supports zero loss linking"); - - if(ftr.DataTypeSupported > 0) - { - sb.Append("\tDrive supports data block types:"); - if((ftr.DataTypeSupported & 0x0001) == 0x0001) - sb.Append(" 0"); - if((ftr.DataTypeSupported & 0x0002) == 0x0002) - sb.Append(" 1"); - if((ftr.DataTypeSupported & 0x0004) == 0x0004) - sb.Append(" 2"); - if((ftr.DataTypeSupported & 0x0008) == 0x0008) - sb.Append(" 3"); - if((ftr.DataTypeSupported & 0x0010) == 0x0010) - sb.Append(" 4"); - if((ftr.DataTypeSupported & 0x0020) == 0x0020) - sb.Append(" 5"); - if((ftr.DataTypeSupported & 0x0040) == 0x0040) - sb.Append(" 6"); - if((ftr.DataTypeSupported & 0x0080) == 0x0080) - sb.Append(" 7"); - if((ftr.DataTypeSupported & 0x0100) == 0x0100) - sb.Append(" 8"); - if((ftr.DataTypeSupported & 0x0200) == 0x0200) - sb.Append(" 9"); - if((ftr.DataTypeSupported & 0x0400) == 0x0400) - sb.Append(" 10"); - if((ftr.DataTypeSupported & 0x0800) == 0x0800) - sb.Append(" 11"); - if((ftr.DataTypeSupported & 0x1000) == 0x1000) - sb.Append(" 12"); - if((ftr.DataTypeSupported & 0x2000) == 0x2000) - sb.Append(" 13"); - if((ftr.DataTypeSupported & 0x4000) == 0x4000) - sb.Append(" 14"); - if((ftr.DataTypeSupported & 0x8000) == 0x8000) - sb.Append(" 15"); - sb.AppendLine(); - - if(ftr.SAO && !ftr.RAW) - sb.AppendLine("Drive can write CDs in Session at Once Mode:"); - else if(!ftr.SAO && ftr.RAW) - sb.AppendLine("Drive can write CDs in raw Mode:"); - else - sb.AppendLine("Drive can write CDs in Session at Once and in Raw Modes:"); - - if(ftr.RAW && ftr.RAWMS) - mmcOneValue.Add("Drive can write multi-session CDs in raw mode"); - - if(ftr.RW) - mmcOneValue.Add("Drive can write user provided data in the R-W subchannels"); - - if(ftr.CDRW) - mmcOneValue.Add("Drive can write CD-RWs"); - if(ftr.TestWrite) - mmcOneValue.Add("Drive can do a test writing"); - if(ftr.BUF) - mmcOneValue.Add("Drive supports zero loss linking"); - - if(ftr.MaxCueSheet > 0) - sb.AppendFormat("\tDrive supports a maximum of {0} bytes in a single cue sheet", ftr.MaxCueSheet).AppendLine(); - - if(ftr.DVDRW && ftr.RDL) - sb.AppendLine("Drive supports writing DVD-R, DVD-RW and DVD-R DL"); - else if(ftr.RDL) - sb.AppendLine("Drive supports writing DVD-R and DVD-R DL"); - else if(ftr.DVDRW) - sb.AppendLine("Drive supports writing DVD-R and DVD-RW"); - else - sb.AppendLine("Drive supports writing DVD-R"); - - if(ftr.TestWrite) - mmcOneValue.Add("Drive can do a test writing"); - if(ftr.BUF) - mmcOneValue.Add("Drive supports zero loss linking"); - - return !feature.HasValue ? null : "Drive can read DDCDs\n"; - - sb.AppendLine("Drive supports writing DDCD-R"); - - if(ftr.TestWrite) - mmcOneValue.Add("Drive can do a test writing"); - - - sb.AppendLine("Drive supports writing DDCD-RW"); - - if(ftr.Blank) - mmcOneValue.Add("Drive supports the BLANK command"); - if(ftr.Intermediate) - mmcOneValue.Add("Drive supports quick formatting"); - - - if(ftr.LinkSizes != null) - { - foreach(byte link in ftr.LinkSizes) - sb.AppendFormat("\tCurrent media has a {0} bytes link available", link).AppendLine(); - } - - - return !feature.HasValue ? null : "Drive can stop a long immediate operation\n"; - - sb.AppendLine("Drive can write CD-RW"); - if(ftr.SubtypeSupport > 0) - { - sb.Append("\tDrive supports CD-RW subtypes"); - if((ftr.SubtypeSupport & 0x01) == 0x01) - sb.Append(" 0"); - if((ftr.SubtypeSupport & 0x02) == 0x02) - sb.Append(" 1"); - if((ftr.SubtypeSupport & 0x04) == 0x04) - sb.Append(" 2"); - if((ftr.SubtypeSupport & 0x08) == 0x08) - sb.Append(" 3"); - if((ftr.SubtypeSupport & 0x10) == 0x10) - sb.Append(" 4"); - if((ftr.SubtypeSupport & 0x20) == 0x20) - sb.Append(" 5"); - if((ftr.SubtypeSupport & 0x40) == 0x40) - sb.Append(" 6"); - if((ftr.SubtypeSupport & 0x80) == 0x80) - sb.Append(" 7"); - sb.AppendLine(); - } - return !feature.HasValue ? null : "Drive can write BD-R on Pseudo-OVerwrite SRM mode\n"; - - if(ftr.Write) - { - sb.Append("Drive can read and write DVD+RW DL"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - if(ftr.CloseOnly) - mmcOneValue.Add("Drive supports only the read compatibility stop"); - else - mmcOneValue.Add("Drive supports both forms of background format stopping"); - if(ftr.QuickStart) - mmcOneValue.Add("Drive can do a quick start formatting"); - } - else - { - sb.Append("Drive can read DVD+RW DL"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - } - - - if(ftr.Write) - { - sb.Append("Drive can read and write DVD+R DL"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - } - else - { - sb.Append("Drive can read DVD+R DL"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - } - - - - if(ftr.OldROM) - mmcOneValue.Add("Drive can read BD-ROM pre-1.0"); - if(ftr.ROM) - mmcOneValue.Add("Drive can read BD-ROM Ver.1"); - if(ftr.OldR) - mmcOneValue.Add("Drive can read BD-R pre-1.0"); - if(ftr.R) - mmcOneValue.Add("Drive can read BD-R Ver.1"); - if(ftr.OldRE) - mmcOneValue.Add("Drive can read BD-RE pre-1.0"); - if(ftr.RE1) - mmcOneValue.Add("Drive can read BD-RE Ver.1"); - if(ftr.RE2) - mmcOneValue.Add("Drive can read BD-RE Ver.2"); - - if(ftr.BCA) - mmcOneValue.Add("Drive can read BD's Burst Cutting Area"); - - - if(ftr.OldR) - mmcOneValue.Add("Drive can write BD-R pre-1.0"); - if(ftr.R) - mmcOneValue.Add("Drive can write BD-R Ver.1"); - if(ftr.OldRE) - mmcOneValue.Add("Drive can write BD-RE pre-1.0"); - if(ftr.RE1) - mmcOneValue.Add("Drive can write BD-RE Ver.1"); - if(ftr.RE2) - mmcOneValue.Add("Drive can write BD-RE Ver.2"); - - if(ftr.SVNR) - mmcOneValue.Add("Drive supports write without verify requirement"); - - return !feature.HasValue ? null : "Drive is able to detect and report defective writable unit and behave accordinly\n"; - if(ftr.HDDVDR && ftr.HDDVDRAM) - sb.Append("Drive can read HD DVD-ROM, HD DVD-RW, HD DVD-R and HD DVD-RAM"); - else if(ftr.HDDVDR) - sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-R"); - else if(ftr.HDDVDRAM) - sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-RAM"); - else - sb.Append("Drive can read HD DVD-ROM and HD DVD-RW"); - - if(ftr.HDDVDR && ftr.HDDVDRAM) - sb.Append("Drive can write HD DVD-RW, HD DVD-R and HD DVD-RAM"); - else if(ftr.HDDVDR) - sb.Append("Drive can write HD DVD-RW and HD DVD-R"); - else if(ftr.HDDVDRAM) - sb.Append("Drive can write HD DVD-RW and HD DVD-RAM"); - else - sb.Append("Drive can write HD DVD-RW"); - - - sb.Append("Drive is able to access Hybrid discs"); - - if(ftr.RI) - mmcOneValue.Add("Drive is able to maintain the online format layer through reset and power cycling"); - - return !feature.HasValue ? null : "Drive is able to perform host and drive directed power management\n"; - - sb.AppendLine("Drive supports S.M.A.R.T."); - if(ftr.PP) - mmcOneValue.Add("Drive supports the Informational Exceptions Control mode page 1Ch"); - - - sb.AppendLine("MMC Embedded Changer:"); - - if(ftr.SCC) - mmcOneValue.Add("Drive can change disc side"); - if(ftr.SDP) - mmcOneValue.Add("Drive is able to report slots contents after a reset or change"); - - sb.AppendFormat("\tDrive has {0} slots", ftr.HighestSlotNumber + 1).AppendLine(); - - - sb.AppendLine("Drive has an analogue audio output"); - - if(ftr.Scan) - mmcOneValue.Add("Drive supports the SCAN command"); - if(ftr.SCM) - mmcOneValue.Add("Drive is able to mute channels separately"); - if(ftr.SV) - mmcOneValue.Add("Drive supports separate volume per channel"); - - sb.AppendFormat("\tDrive has {0} volume levels", ftr.VolumeLevels + 1).AppendLine(); - - - sb.AppendLine("Drive supports Microcode Upgrade"); - if(ftr.M5) - sb.AppendLine("Drive supports validating the 5-bit Mode of the READ BUFFER and WRITE BUFFER commands"); - - - sb.AppendLine("Drive supports Timeout & Protect mode page 1Dh"); - - if(ftr.Group3) - { - mmcOneValue.Add("Drive supports the Group3 in Timeout & Protect mode page 1Dh"); - if(ftr.UnitLength > 0) - sb.AppendFormat("\tDrive has {0} increase of Group 3 time unit", ftr.UnitLength).AppendLine(); - } - - - sb.AppendFormat("Drive supports DVD CSS/CPPM version {0}", ftr.CSSVersion); - if(ftr.Current) - sb.AppendLine(" and current disc is encrypted"); - else - sb.AppendLine(); - - - sb.AppendLine("MMC Real Time Streaming:"); - - if(ftr.SMP) - mmcOneValue.Add("Drive supports Set Minimum Performance with the SET STREAMING command"); - if(ftr.RBCB) - mmcOneValue.Add("Drive supports the block bit in the READ BUFFER CAPACITY command"); - if(ftr.SCS) - mmcOneValue.Add("Drive supports the SET CD SPEED command"); - if(ftr.MP2A) - mmcOneValue.Add("Drive supports the Write Speed Performance Descriptor Blocks in the MMC mode page 2Ah"); - if(ftr.WSPD) - mmcOneValue.Add("Drive supports the Write Speed data of GET PERFORMANCE and the WRC field of SET STREAMING"); - if(ftr.SW) - mmcOneValue.Add("Drive supports stream recording"); - - return !feature.HasValue ? null : "Drive is to read media serial number\n"; - - if(ftr.DCBs != null) - { - foreach(uint DCB in ftr.DCBs) - sb.AppendFormat("Drive supports DCB {0:X8}h", DCB).AppendLine(); - } - - - - sb.AppendFormat("Drive supports DVD CPRM version {0}", ftr.CPRMVersion); - if(ftr.Current) - sb.AppendLine(" and current disc is or can be encrypted"); - else - sb.AppendLine(); - - - string syear, smonth, sday, shour, sminute, ssecond; - byte[] temp; - - temp = new byte[4]; - temp[0] = (byte)((ftr.Century & 0xFF00) >> 8); - temp[1] = (byte)(ftr.Century & 0xFF); - temp[2] = (byte)((ftr.Year & 0xFF00) >> 8); - temp[3] = (byte)(ftr.Year & 0xFF); - syear = Encoding.ASCII.GetString(temp); - temp = new byte[2]; - temp[0] = (byte)((ftr.Month & 0xFF00) >> 8); - temp[1] = (byte)(ftr.Month & 0xFF); - smonth = Encoding.ASCII.GetString(temp); - temp = new byte[2]; - temp[0] = (byte)((ftr.Day & 0xFF00) >> 8); - temp[1] = (byte)(ftr.Day & 0xFF); - sday = Encoding.ASCII.GetString(temp); - temp = new byte[2]; - temp[0] = (byte)((ftr.Hour & 0xFF00) >> 8); - temp[1] = (byte)(ftr.Hour & 0xFF); - shour = Encoding.ASCII.GetString(temp); - temp = new byte[2]; - temp[0] = (byte)((ftr.Minute & 0xFF00) >> 8); - temp[1] = (byte)(ftr.Minute & 0xFF); - sminute = Encoding.ASCII.GetString(temp); - temp = new byte[2]; - temp[0] = (byte)((ftr.Second & 0xFF00) >> 8); - temp[1] = (byte)(ftr.Second & 0xFF); - ssecond = Encoding.ASCII.GetString(temp); - - try - { - DateTime fwDate = new DateTime(int.Parse(syear), int.Parse(smonth), - int.Parse(sday), int.Parse(shour), int.Parse(sminute), - int.Parse(ssecond), DateTimeKind.Utc); - - sb.AppendFormat("Drive firmware is dated {0}", fwDate).AppendLine(); - } -#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body - catch -#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body - { - } - - - sb.AppendFormat("Drive supports AACS version {0}", ftr.AACSVersion); - if(ftr.Current) - sb.AppendLine(" and current disc is encrypted"); - else - sb.AppendLine(); - - if(ftr.RDC) - mmcOneValue.Add("Drive supports reading the Drive Certificate"); - if(ftr.RMC) - mmcOneValue.Add("Drive supports reading Media Key Block of CPRM"); - if(ftr.WBE) - mmcOneValue.Add("Drive supports writing with bus encryption"); - if(ftr.BEC) - mmcOneValue.Add("Drive supports bus encryption"); - if(ftr.BNG) - { - mmcOneValue.Add("Drive supports generating the binding nonce"); - if(ftr.BindNonceBlocks > 0) - sb.AppendFormat("\t{0} media blocks are required for the binding nonce", ftr.BindNonceBlocks).AppendLine(); - } - if(ftr.AGIDs > 0) - sb.AppendFormat("\tDrive supports {0} AGIDs concurrently", ftr.AGIDs).AppendLine(); - - - - sb.Append("Drive supports DVD-Download"); - if(ftr.Current) - sb.AppendLine(" (current)"); - else - sb.AppendLine(); - - if(ftr.MaxScrambleExtent > 0) - sb.AppendFormat("\tMaximum {0} scranble extent information entries", ftr.MaxScrambleExtent).AppendLine(); - - - if(ftr.Current) - sb.AppendLine("Drive and currently inserted media support VCPS"); - else - sb.AppendLine("Drive supports VCPS"); - - - - if(ftr.Current) - sb.AppendLine("Drive and currently inserted media support SecurDisc"); - else - sb.AppendLine("Drive supports SecurDisc"); - - - - sb.AppendLine("Drive supports the Trusted Computing Group Optical Security Subsystem Class"); - - if(ftr.Current) - mmcOneValue.Add("Current media is initialized with TCG OSSC"); - if(ftr.PSAU) - mmcOneValue.Add("Drive supports PSA updates on write-once media"); - if(ftr.LOSPB) - mmcOneValue.Add("Drive supports linked OSPBs"); - if(ftr.ME) - mmcOneValue.Add("Drive will only record on the OSSC Disc Format"); - - if(ftr.Profiles != null) - { - for(int i = 0; i < ftr.Profiles.Length; i++) - sb.AppendFormat("\tProfile {0}: {1}", i, ftr.Profiles[i]).AppendLine(); - } + mmcOneValue.Add("Drive power ups locked"); + if(mode.LockStatus) + mmcOneValue.Add("Drive is locked, media cannot be ejected or inserted"); + else + mmcOneValue.Add("Drive is not locked, media can be ejected and inserted"); } + else + { + if(mode.LockStatus) + mmcOneValue.Add("Drive is locked, media cannot be ejected, but if empty, can be inserted"); + else + mmcOneValue.Add("Drive is not locked, media can be ejected and inserted"); + } + if(mode.CanEject) + mmcOneValue.Add("Drive can eject media"); + + if(mode.SeparateChannelMute) + mmcOneValue.Add("Each channel can be muted independently"); + if(mode.SeparateChannelVolume) + mmcOneValue.Add("Each channel's volume can be controlled independently"); + + if(mode.SupportedVolumeLevels > 0) + mmcOneValue.Add(string.Format("Drive supports {0} volume levels", mode.SupportedVolumeLevels)); + if(mode.BufferSize > 0) + mmcOneValue.Add(string.Format("Drive has {0} Kbyte of buffer", mode.BufferSize)); + if(mode.MaximumSpeed > 0) + mmcOneValue.Add(string.Format("Drive's maximum reading speed is {0} Kbyte/sec.", mode.MaximumSpeed)); + if(mode.CurrentSpeed > 0) + mmcOneValue.Add(string.Format("Drive's current reading speed is {0} Kbyte/sec.", mode.CurrentSpeed)); + + if(mode.ReadsCDR) + { + if(mode.WritesCDR) + mmcOneValue.Add("Drive can read and write CD-R"); + else + mmcOneValue.Add("Drive can read CD-R"); + + if(mode.ReadsPacketCDR) + mmcOneValue.Add("Drive supports reading CD-R packet media"); + } + + if(mode.ReadsCDRW) + { + if(mode.WritesCDRW) + mmcOneValue.Add("Drive can read and write CD-RW"); + else + mmcOneValue.Add("Drive can read CD-RW"); + } + + if(mode.ReadsDVDROM) + mmcOneValue.Add("Drive can read DVD-ROM"); + if(mode.ReadsDVDR) + { + if(mode.WritesDVDR) + mmcOneValue.Add("Drive can read and write DVD-R"); + else + mmcOneValue.Add("Drive can read DVD-R"); + } + if(mode.ReadsDVDRAM) + { + if(mode.WritesDVDRAM) + mmcOneValue.Add("Drive can read and write DVD-RAM"); + else + mmcOneValue.Add("Drive can read DVD-RAM"); + } + + if(mode.CompositeAudioVideo) + mmcOneValue.Add("Drive can deliver a composite audio and video data stream"); + if(mode.DigitalPort1) + mmcOneValue.Add("Drive supports IEC-958 digital output on port 1"); + if(mode.DigitalPort2) + mmcOneValue.Add("Drive supports IEC-958 digital output on port 2"); + + if(mode.DeterministicSlotChanger) + mmcOneValue.Add("Drive contains a changer that can report the exact contents of the slots"); + if(mode.CurrentWriteSpeedSelected > 0) + { + if(mode.RotationControlSelected == 0) + mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec. in CLV mode", mode.CurrentWriteSpeedSelected)); + else if(mode.RotationControlSelected == 1) + mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec. in pure CAV mode", mode.CurrentWriteSpeedSelected)); + } + else + { + if(mode.MaximumWriteSpeed > 0) + mmcOneValue.Add(string.Format("Drive's maximum writing speed is {0} Kbyte/sec.", mode.MaximumWriteSpeed)); + if(mode.CurrentWriteSpeed > 0) + mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec.", mode.CurrentWriteSpeed)); + } + + if(mode.WriteSpeedPerformanceDescriptors != null) + { + foreach(Decoders.SCSI.Modes.ModePage_2A_WriteDescriptor descriptor in mode.WriteSpeedPerformanceDescriptors) + { + if(descriptor.WriteSpeed > 0) + { + if(descriptor.RotationControl == 0) + mmcOneValue.Add(string.Format("Drive supports writing at {0} Kbyte/sec. in CLV mode", descriptor.WriteSpeed)); + else if(descriptor.RotationControl == 1) + mmcOneValue.Add(string.Format("Drive supports writing at is {0} Kbyte/sec. in pure CAV mode", descriptor.WriteSpeed)); + } + } + } + + if(mode.TestWrite) + mmcOneValue.Add("Drive supports test writing"); + + if(mode.ReadsBarcode) + mmcOneValue.Add("Drive can read barcode"); + + if(mode.ReadsBothSides) + mmcOneValue.Add("Drive can read both sides of a disc"); + if(mode.LeadInPW) + mmcOneValue.Add("Drive an read raw R-W subchannel from the Lead-In"); + + if(mode.CSSandCPPMSupported) + mmcOneValue.Add("Drive supports DVD CSS and/or DVD CPPM"); + + if(mode.BufferUnderRunProtection) + mmcOneValue.Add("Drive supports buffer under-run free recording"); + + mmcOneValue.Sort(); + mmcOneValue.Add(""); } } } diff --git a/DiscImageChef.Server/App_Start/ScsiModeSense.cs b/DiscImageChef.Server/App_Start/ScsiModeSense.cs index 9624650bc..2eb152d30 100644 --- a/DiscImageChef.Server/App_Start/ScsiModeSense.cs +++ b/DiscImageChef.Server/App_Start/ScsiModeSense.cs @@ -36,12 +36,395 @@ // ****************************************************************************/ // //$Id$ using System; +using System.Collections.Generic; +using DiscImageChef.Metadata; +using DiscImageChef.Decoders.SCSI; namespace DiscImageChef.Server.App_Start { - public class ScsiModeSense + public static class ScsiModeSense { - public ScsiModeSense() + public static void Report(modeType modeSense, string vendor, PeripheralDeviceTypes deviceType, ref List scsiOneValue, ref Dictionary modePages) { + if(modeSense.MediumTypeSpecified) + scsiOneValue.Add(string.Format("Medium type is {0:X2}h", modeSense.MediumType)); + if(modeSense.WriteProtected) + scsiOneValue.Add("Device is write protected."); + if(modeSense.BlockDescriptors != null) + { + foreach(blockDescriptorType descriptor in modeSense.BlockDescriptors) + { + if(descriptor.BlocksSpecified && descriptor.BlockLengthSpecified) + scsiOneValue.Add(string.Format("Density code {0:X2}h has {1} blocks of {2} bytes each", + descriptor.Density, descriptor.Blocks, descriptor.BlockLength)); + else + scsiOneValue.Add(string.Format("Density code {0:X2}h", descriptor.Density)); + } + } + if(modeSense.DPOandFUA) + scsiOneValue.Add("Drive supports DPO and FUA bits"); + if(modeSense.BlankCheckEnabled) + scsiOneValue.Add("Blank checking during write is enabled"); + if(modeSense.BufferedModeSpecified) + { + switch(modeSense.BufferedMode) + { + case 0: + scsiOneValue.Add("Device writes directly to media"); + break; + case 1: + scsiOneValue.Add("Device uses a write cache"); + break; + case 2: + scsiOneValue.Add("Device uses a write cache but doesn't return until cache is flushed"); + break; + default: + scsiOneValue.Add(string.Format("Unknown buffered mode code 0x{0:X2}", modeSense.BufferedMode)); + break; + } + } + + if(modeSense.ModePages != null) + { + foreach(modePageType page in modeSense.ModePages) + { + switch(page.page) + { + case 0x00: + { + if(deviceType == PeripheralDeviceTypes.MultiMediaDevice && page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_00_SFF(page.value)); + else + { + if(page.subpage != 0) + modePages.Add(string.Format("MODE page {0:X2}h subpage {1:X2}h", page.page, page.subpage), "Unknown vendor mode page"); + else + modePages.Add(string.Format("MODE page {0:X2}h", page.page), "Unknown vendor mode page"); + } + break; + } + case 0x01: + { + if(page.subpage == 0) + { + if(deviceType == PeripheralDeviceTypes.MultiMediaDevice) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_01_MMC(page.value)); + else + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_01(page.value)); + } + else + goto default; + + break; + } + case 0x02: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_02(page.value)); + else + goto default; + + break; + } + case 0x03: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_03(page.value)); + else + goto default; + + break; + } + case 0x04: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_04(page.value)); + else + goto default; + + break; + } + case 0x05: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_05(page.value)); + else + goto default; + + break; + } + case 0x06: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_06(page.value)); + else + goto default; + + break; + } + case 0x07: + { + if(page.subpage == 0) + { + if(deviceType == PeripheralDeviceTypes.MultiMediaDevice) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_07_MMC(page.value)); + else + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_07(page.value)); + } + else + goto default; + + break; + } + case 0x08: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_08(page.value)); + else + goto default; + + break; + } + case 0x0A: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_0A(page.value)); + else if(page.subpage == 1) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_0A_S01(page.value)); + else + goto default; + + break; + } + case 0x0B: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_0B(page.value)); + else + goto default; + + break; + } + case 0x0D: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_0D(page.value)); + else + goto default; + + break; + } + case 0x0E: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_0E(page.value)); + else + goto default; + + break; + } + case 0x0F: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_0F(page.value)); + else + goto default; + + break; + } + case 0x10: + { + if(page.subpage == 0) + { + if(deviceType == Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_10_SSC(page.value)); + else + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_10(page.value)); + } + else + goto default; + + break; + } + case 0x11: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_11(page.value)); + else + goto default; + + break; + } + case 0x12: + case 0x13: + case 0x14: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_12_13_14(page.value)); + else + goto default; + + break; + } + case 0x1A: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1A(page.value)); + else if(page.subpage == 1) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1A_S01(page.value)); + else + goto default; + + break; + } + case 0x1B: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1B(page.value)); + else + goto default; + + break; + } + case 0x1C: + { + if(page.subpage == 0) + { + if(deviceType == PeripheralDeviceTypes.MultiMediaDevice) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1C_SFF(page.value)); + else + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1C(page.value)); + } + else if(page.subpage == 1) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1C_S01(page.value)); + else + goto default; + + break; + } + case 0x1D: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_1D(page.value)); + else + goto default; + + break; + } + case 0x21: + { + if(vendor == "CERTANCE") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyCertanceModePage_21(page.value)); + else + goto default; + + break; + } + case 0x22: + { + if(vendor == "CERTANCE") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyCertanceModePage_22(page.value)); + else + goto default; + + break; + } + case 0x24: + { + if(vendor == "IBM") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyIBMModePage_24(page.value)); + else + goto default; + + break; + } + case 0x2A: + { + if(page.subpage == 0) + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyModePage_2A(page.value)); + else + goto default; + + break; + } + case 0x2F: + { + if(vendor == "IBM") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyIBMModePage_2F(page.value)); + else + goto default; + + break; + } + case 0x30: + { + if(Modes.IsAppleModePage_30(page.value)) + modePages.Add("MODE page 30h", "Drive identifies as an Apple OEM drive"); + else + goto default; + + break; + } + case 0x3B: + { + if(vendor == "HP") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyHPModePage_3B(page.value)); + else + goto default; + + break; + } + case 0x3C: + { + if(vendor == "HP") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyHPModePage_3C(page.value)); + else + goto default; + + break; + } + case 0x3D: + { + if(vendor == "IBM") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyIBMModePage_3D(page.value)); + else if(vendor == "HP") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyHPModePage_3D(page.value)); + else + goto default; + + break; + } + case 0x3E: + { + if(vendor == "FUJITSU") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyFujitsuModePage_3E(page.value)); + else if(vendor == "HP") + modePages.Add(string.Format("MODE page {0:X2}h", page.page), Modes.PrettifyHPModePage_3E(page.value)); + else + goto default; + + break; + } + default: + { + if(page.subpage != 0) + modePages.Add(string.Format("MODE page {0:X2}h subpage {1:X2}h", page.page, page.subpage), "Unknown mode page"); + else + modePages.Add(string.Format("MODE page {0:X2}h", page.page), "Unknown mode page"); + } + break; + } + } + + Dictionary newModePages = new Dictionary(); + foreach(KeyValuePair kvp in modePages) + { + if(string.IsNullOrWhiteSpace(kvp.Value)) + newModePages.Add(kvp.Key, "Undecoded"); + else + newModePages.Add(kvp.Key, kvp.Value.Replace("\n", "
")); + } + modePages = newModePages; + } } } } diff --git a/DiscImageChef.Server/App_Start/SscTestedMedia.cs b/DiscImageChef.Server/App_Start/SscTestedMedia.cs index e1ac27074..85753e92a 100644 --- a/DiscImageChef.Server/App_Start/SscTestedMedia.cs +++ b/DiscImageChef.Server/App_Start/SscTestedMedia.cs @@ -36,12 +36,42 @@ // ****************************************************************************/ // //$Id$ using System; +using System.Collections.Generic; +using DiscImageChef.Metadata; + namespace DiscImageChef.Server.App_Start { - public class SscTestedMedia + public static class SscTestedMedia { - public SscTestedMedia() + public static void Report(SequentialMedia[] testedMedia, ref List mediaOneValue) { + foreach(SequentialMedia media in testedMedia) + { + if(!string.IsNullOrWhiteSpace(media.MediumTypeName)) + { + mediaOneValue.Add(string.Format("Information for medium named \"{0}\"", media.MediumTypeName)); + if(media.MediumTypeSpecified) + mediaOneValue.Add(string.Format("Medium type code: {0:X2}h", media.MediumType)); + } + else if(media.MediumTypeSpecified) + mediaOneValue.Add(string.Format("Information for medium type {0:X2}h", media.MediumType)); + else + mediaOneValue.Add("Information for unknown medium type"); + + if(!string.IsNullOrWhiteSpace(media.Manufacturer)) + mediaOneValue.Add(string.Format("Medium manufactured by: {0}", media.Manufacturer)); + if(!string.IsNullOrWhiteSpace(media.Model)) + mediaOneValue.Add(string.Format("Medium model: {0}", media.Model)); + + if(media.DensitySpecified) + mediaOneValue.Add(string.Format("Medium has density code {0:X2}h", media.Density)); + if(media.CanReadMediaSerial) + mediaOneValue.Add("Drive can read medium serial number."); + if(media.MediaIsRecognized) + mediaOneValue.Add("DiscImageChef recognizes this medium."); + + mediaOneValue.Add(""); + } } } } diff --git a/DiscImageChef.Server/App_Start/TestedMedia.cs b/DiscImageChef.Server/App_Start/TestedMedia.cs index 75e1f99e5..ad159a450 100644 --- a/DiscImageChef.Server/App_Start/TestedMedia.cs +++ b/DiscImageChef.Server/App_Start/TestedMedia.cs @@ -36,12 +36,278 @@ // ****************************************************************************/ // //$Id$ using System; +using System.Collections.Generic; +using DiscImageChef.Metadata; namespace DiscImageChef.Server.App_Start { - public class TestedMedia + public static class TestedMedia { - public TestedMedia() + public static void Report(testedMediaType[] testedMedias, bool ata, ref List mediaOneValue) { + foreach(testedMediaType testedMedia in testedMedias) + { + if(!string.IsNullOrWhiteSpace(testedMedia.MediumTypeName)) + { + mediaOneValue.Add(string.Format("Information for medium named \"{0}\"", testedMedia.MediumTypeName)); + if(testedMedia.MediumTypeSpecified) + mediaOneValue.Add(string.Format("Medium type code: {0:X2}h", testedMedia.MediumType)); + } + else if(testedMedia.MediumTypeSpecified) + mediaOneValue.Add(string.Format("Information for medium type {0:X2}h", testedMedia.MediumType)); + else + mediaOneValue.Add("Information for unknown medium type"); + + if(testedMedia.MediaIsRecognized) + mediaOneValue.Add("Drive recognizes this medium."); + else + mediaOneValue.Add("Drive does not recognize this medium."); + + if(!string.IsNullOrWhiteSpace(testedMedia.Manufacturer)) + mediaOneValue.Add(string.Format("Medium manufactured by: {0}", testedMedia.Manufacturer)); + if(!string.IsNullOrWhiteSpace(testedMedia.Model)) + mediaOneValue.Add(string.Format("Medium model: {0}", testedMedia.Model)); + if(testedMedia.DensitySpecified) + mediaOneValue.Add(string.Format("Density code: {0:X2}h", testedMedia.Density)); + + if(testedMedia.BlockSizeSpecified) + mediaOneValue.Add(string.Format("Logical sector size: {0} bytes", testedMedia.BlockSize)); + if(testedMedia.PhysicalBlockSizeSpecified) + mediaOneValue.Add(string.Format("Physical sector size: {0} bytes", testedMedia.PhysicalBlockSize)); + if(testedMedia.LongBlockSizeSpecified) + mediaOneValue.Add(string.Format("READ LONG sector size: {0} bytes", testedMedia.LongBlockSize)); + + if(testedMedia.BlocksSpecified && testedMedia.BlockSizeSpecified) + { + mediaOneValue.Add(string.Format("Medium has {0} blocks of {1} bytes each", testedMedia.Blocks, testedMedia.BlockSize)); + + if(((testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024) > 1000000) + { + mediaOneValue.Add(string.Format("Medium size: {0} bytes, {1} Tb, {2} TiB", testedMedia.Blocks * testedMedia.BlockSize, + (testedMedia.Blocks * testedMedia.BlockSize) / 1000 / 1000 / 1000 / 1000, (testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024 / 1024 / 1024)); + } + else if(((testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024) > 1000) + { + mediaOneValue.Add(string.Format("Medium size: {0} bytes, {1} Gb, {2} GiB", testedMedia.Blocks * testedMedia.BlockSize, + (testedMedia.Blocks * testedMedia.BlockSize) / 1000 / 1000 / 1000, (testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024 / 1024)); + } + else + { + mediaOneValue.Add(string.Format("Medium size: {0} bytes, {1} Mb, {2} MiB", testedMedia.Blocks * testedMedia.BlockSize, + (testedMedia.Blocks * testedMedia.BlockSize) / 1000 / 1000, (testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024)); + } + } + + if(testedMedia.CHS != null && testedMedia.CurrentCHS != null) + { + int currentSectors = testedMedia.CurrentCHS.Cylinders * testedMedia.CurrentCHS.Heads * testedMedia.CurrentCHS.Sectors; + mediaOneValue.Add(string.Format("Cylinders: {0} max., {1} current", testedMedia.CHS.Cylinders, testedMedia.CurrentCHS.Cylinders)); + mediaOneValue.Add(string.Format("Heads: {0} max., {1} current", testedMedia.CHS.Heads, testedMedia.CurrentCHS.Heads)); + mediaOneValue.Add(string.Format("Sectors per track: {0} max., {1} current", testedMedia.CHS.Sectors, testedMedia.CurrentCHS.Sectors)); + mediaOneValue.Add(string.Format("Sectors addressable in CHS mode: {0} max., {1} current", testedMedia.CHS.Cylinders * testedMedia.CHS.Heads * testedMedia.CHS.Sectors, + currentSectors)); + mediaOneValue.Add(string.Format("Medium size in CHS mode: {0} bytes, {1} Mb, {2} MiB", (ulong)currentSectors * testedMedia.BlockSize, + ((ulong)currentSectors * testedMedia.BlockSize) / 1000 / 1000, ((ulong)currentSectors * testedMedia.BlockSize) / 1024 / 1024)); + } + + if(testedMedia.LBASectorsSpecified) + { + mediaOneValue.Add(string.Format("Sectors addressable in sectors in 28-bit LBA mode: {0}", testedMedia.LBASectors)); + + if((((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024) > 1000000) + { + mediaOneValue.Add(string.Format("Medium size in 28-bit LBA mode: {0} bytes, {1} Tb, {2} TiB", (ulong)testedMedia.LBASectors * testedMedia.BlockSize, + ((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1000 / 1000 / 1000 / 1000, ((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024 / 1024 / 1024)); + } + else if((((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024) > 1000) + { + mediaOneValue.Add(string.Format("Medium size in 28-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", (ulong)testedMedia.LBASectors * testedMedia.BlockSize, + ((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1000 / 1000 / 1000, ((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024 / 1024)); + } + else + { + mediaOneValue.Add(string.Format("Medium size in 28-bit LBA mode: {0} bytes, {1} Mb, {2} MiB", (ulong)testedMedia.LBASectors * testedMedia.BlockSize, + ((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1000 / 1000, ((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024)); + } + } + + if(testedMedia.LBA48SectorsSpecified) + { + mediaOneValue.Add(string.Format("Sectors addressable in sectors in 48-bit LBA mode: {0}", testedMedia.LBA48Sectors)); + + if(((testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024) > 1000000) + { + mediaOneValue.Add(string.Format("Medium size in 48-bit LBA mode: {0} bytes, {1} Tb, {2} TiB", testedMedia.LBA48Sectors * testedMedia.BlockSize, + (testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1000 / 1000 / 1000 / 1000, (testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024 / 1024 / 1024)); + } + else if(((testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024) > 1000) + { + mediaOneValue.Add(string.Format("Medium size in 48-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", testedMedia.LBA48Sectors * testedMedia.BlockSize, + (testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1000 / 1000 / 1000, (testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024 / 1024)); + } + else + { + mediaOneValue.Add(string.Format("Medium size in 48-bit LBA mode: {0} bytes, {1} Mb, {2} MiB", testedMedia.LBA48Sectors * testedMedia.BlockSize, + (testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1000 / 1000, (testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024)); + } + } + + if(testedMedia.NominalRotationRateSpecified && + testedMedia.NominalRotationRate != 0x0000 && + testedMedia.NominalRotationRate != 0xFFFF) + { + if(testedMedia.NominalRotationRate == 0x0001) + mediaOneValue.Add("Medium does not rotate."); + else + mediaOneValue.Add(string.Format("Medium rotates at {0} rpm", testedMedia.NominalRotationRate)); + } + + if(testedMedia.BlockSizeSpecified && + testedMedia.PhysicalBlockSizeSpecified && + (testedMedia.BlockSize != testedMedia.PhysicalBlockSize) && + (testedMedia.LogicalAlignment & 0x8000) == 0x0000 && + (testedMedia.LogicalAlignment & 0x4000) == 0x4000) + { + mediaOneValue.Add(string.Format("Logical sector starts at offset {0} from physical sector", testedMedia.LogicalAlignment & 0x3FFF)); + } + + if(testedMedia.SupportsRead && ata) + mediaOneValue.Add("Device can use the READ SECTOR(S) command in CHS mode with this medium"); + if(testedMedia.SupportsReadRetry) + mediaOneValue.Add("Device can use the READ SECTOR(S) RETRY command in CHS mode with this medium"); + if(testedMedia.SupportsReadDma) + mediaOneValue.Add("Device can use the READ DMA command in CHS mode with this medium"); + if(testedMedia.SupportsReadDmaRetry) + mediaOneValue.Add("Device can use the READ DMA RETRY command in CHS mode with this medium"); + if(testedMedia.SupportsReadLong && ata) + mediaOneValue.Add("Device can use the READ LONG command in CHS mode with this medium"); + if(testedMedia.SupportsReadLongRetry) + mediaOneValue.Add("Device can use the READ LONG RETRY command in CHS mode with this medium"); + + if(testedMedia.SupportsReadLba) + mediaOneValue.Add("Device can use the READ SECTOR(S) command in 28-bit LBA mode with this medium"); + if(testedMedia.SupportsReadRetryLba) + mediaOneValue.Add("Device can use the READ SECTOR(S) RETRY command in 28-bit LBA mode with this medium"); + if(testedMedia.SupportsReadDmaLba) + mediaOneValue.Add("Device can use the READ DMA command in 28-bit LBA mode with this medium"); + if(testedMedia.SupportsReadDmaRetryLba) + mediaOneValue.Add("Device can use the READ DMA RETRY command in 28-bit LBA mode with this medium"); + if(testedMedia.SupportsReadLongLba) + mediaOneValue.Add("Device can use the READ LONG command in 28-bit LBA mode with this medium"); + if(testedMedia.SupportsReadLongRetryLba) + mediaOneValue.Add("Device can use the READ LONG RETRY command in 28-bit LBA mode with this medium"); + + if(testedMedia.SupportsReadLba48) + mediaOneValue.Add("Device can use the READ SECTOR(S) command in 48-bit LBA mode with this medium"); + if(testedMedia.SupportsReadDmaLba48) + mediaOneValue.Add("Device can use the READ DMA command in 48-bit LBA mode with this medium"); + + if(testedMedia.SupportsSeek) + mediaOneValue.Add("Device can use the SEEK command in CHS mode with this medium"); + if(testedMedia.SupportsSeekLba) + mediaOneValue.Add("Device can use the SEEK command in 28-bit LBA mode with this medium"); + + if(testedMedia.SupportsReadCapacity) + mediaOneValue.Add("Device can use the READ CAPACITY (10) command with this medium"); + if(testedMedia.SupportsReadCapacity16) + mediaOneValue.Add("Device can use the READ CAPACITY (16) command with this medium"); + if(testedMedia.SupportsRead && !ata) + mediaOneValue.Add("Device can use the READ (6) command with this medium"); + if(testedMedia.SupportsRead10) + mediaOneValue.Add("Device can use the READ (10) command with this medium"); + if(testedMedia.SupportsRead12) + mediaOneValue.Add("Device can use the READ (12) command with this medium"); + if(testedMedia.SupportsRead16) + mediaOneValue.Add("Device can use the READ (16) command with this medium"); + if(testedMedia.SupportsReadLong && !ata) + mediaOneValue.Add("Device can use the READ LONG (10) command with this medium"); + if(testedMedia.SupportsReadLong16) + mediaOneValue.Add("Device can use the READ LONG (16) command with this medium"); + + if(testedMedia.SupportsReadCd) + mediaOneValue.Add("Device can use the READ CD command with LBA addressing with this medium"); + if(testedMedia.SupportsReadCdMsf) + mediaOneValue.Add("Device can use the READ CD command with MM:SS:FF addressing with this medium"); + if(testedMedia.SupportsReadCdRaw) + mediaOneValue.Add("Device can use the READ CD command with LBA addressing with this medium to read raw sector"); + if(testedMedia.SupportsReadCdMsfRaw) + mediaOneValue.Add("Device can use the READ CD command with MM:SS:FF addressing with this medium read raw sector"); + + if(testedMedia.SupportsHLDTSTReadRawDVD) + mediaOneValue.Add("Device can use the HL-DT-ST vendor READ DVD (RAW) command with this medium"); + if(testedMedia.SupportsNECReadCDDA) + mediaOneValue.Add("Device can use the NEC vendor READ CD-DA command with this medium"); + if(testedMedia.SupportsPioneerReadCDDA) + mediaOneValue.Add("Device can use the PIONEER vendor READ CD-DA command with this medium"); + if(testedMedia.SupportsPioneerReadCDDAMSF) + mediaOneValue.Add("Device can use the PIONEER vendor READ CD-DA MSF command with this medium"); + if(testedMedia.SupportsPlextorReadCDDA) + mediaOneValue.Add("Device can use the PLEXTOR vendor READ CD-DA command with this medium"); + if(testedMedia.SupportsPlextorReadRawDVD) + mediaOneValue.Add("Device can use the PLEXOR vendor READ DVD (RAW) command with this medium"); + + if(testedMedia.CanReadAACS) + mediaOneValue.Add("Device can read the Advanced Access Content System from this medium"); + if(testedMedia.CanReadADIP) + mediaOneValue.Add("Device can read the DVD ADress-In-Pregroove from this medium"); + if(testedMedia.CanReadATIP) + mediaOneValue.Add("Device can read the CD Absolute-Time-In-Pregroove from this medium"); + if(testedMedia.CanReadBCA) + mediaOneValue.Add("Device can read the Burst Cutting Area from this medium"); + if(testedMedia.CanReadC2Pointers) + mediaOneValue.Add("Device can report the C2 pointers when reading from this medium"); + if(testedMedia.CanReadCMI) + mediaOneValue.Add("Device can read the Copyright Management Information from this medium"); + if(testedMedia.CanReadCorrectedSubchannel) + mediaOneValue.Add("Device can correct subchannels when reading from this medium"); + if(testedMedia.CanReadCorrectedSubchannelWithC2) + mediaOneValue.Add("Device can correct subchannels and report the C2 pointers when reading from this medium"); + if(testedMedia.CanReadDCB) + mediaOneValue.Add("Device can read the Disc Control Blocks from this medium"); + if(testedMedia.CanReadDDS) + mediaOneValue.Add("Device can read the Disc Definition Structure from this medium"); + if(testedMedia.CanReadDMI) + mediaOneValue.Add("Device can read the Disc Manufacurer Information from this medium"); + if(testedMedia.CanReadDiscInformation) + mediaOneValue.Add("Device can read the Disc Information from this medium"); + if(testedMedia.CanReadFullTOC) + mediaOneValue.Add("Device can read the Table of Contents from this medium, without processing it"); + if(testedMedia.CanReadHDCMI) + mediaOneValue.Add("Device can read the HD DVD Copyright Management Information from this medium"); + if(testedMedia.CanReadLayerCapacity) + mediaOneValue.Add("Device can read the layer capacity from this medium"); + if(testedMedia.CanReadLeadIn) + mediaOneValue.Add("Device can read the Lead-In from this medium"); + if(testedMedia.CanReadLeadOut) + mediaOneValue.Add("Device can read the Lead-Out from this medium"); + if(testedMedia.CanReadMediaID) + mediaOneValue.Add("Device can read the Media ID from this medium"); + if(testedMedia.CanReadMediaSerial) + mediaOneValue.Add("Device can read the Media Serial Number from this medium"); + if(testedMedia.CanReadPAC) + mediaOneValue.Add("Device can read the PAC from this medium"); + if(testedMedia.CanReadPFI) + mediaOneValue.Add("Device can read the Physical Format Information from this medium"); + if(testedMedia.CanReadPMA) + mediaOneValue.Add("Device can read the Power Management Area from this medium"); + if(testedMedia.CanReadPQSubchannel) + mediaOneValue.Add("Device can read the P to Q subchannels from this medium"); + if(testedMedia.CanReadPQSubchannelWithC2) + mediaOneValue.Add("Device can read the P to Q subchannels from this medium reporting the C2 pointers"); + if(testedMedia.CanReadPRI) + mediaOneValue.Add("Device can read the Pre-Recorded Information from this medium"); + if(testedMedia.CanReadRWSubchannel) + mediaOneValue.Add("Device can read the R to W subchannels from this medium"); + if(testedMedia.CanReadRWSubchannelWithC2) + mediaOneValue.Add("Device can read the R to W subchannels from this medium reporting the C2 pointers"); + if(testedMedia.CanReadRecordablePFI) + mediaOneValue.Add("Device can read the Physical Format Information from Lead-In from this medium"); + if(testedMedia.CanReadSpareAreaInformation) + mediaOneValue.Add("Device can read the Spare Area Information from this medium"); + if(testedMedia.CanReadTOC) + mediaOneValue.Add("Device can read the Table of Contents from this medium"); + + mediaOneValue.Add(""); + } } } } diff --git a/DiscImageChef.Server/App_Start/WebApiConfig.cs b/DiscImageChef.Server/App_Start/WebApiConfig.cs index 5555f6f69..51d8aa0a5 100644 --- a/DiscImageChef.Server/App_Start/WebApiConfig.cs +++ b/DiscImageChef.Server/App_Start/WebApiConfig.cs @@ -1,21 +1,21 @@ using System.Web.Http; namespace DiscImageChef.Server - { +{ public static class WebApiConfig - { + { public static void Register(HttpConfiguration config) - { - // Web API configuration and services + { + // Web API configuration and services - // Web API routes - config.MapHttpAttributeRoutes(); + // Web API routes + config.MapHttpAttributeRoutes(); - config.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - } + config.Routes.MapHttpRoute( + name: "DefaultApi", + routeTemplate: "api/{controller}/{id}", + defaults: new { id = RouteParameter.Optional } + ); } } +} diff --git a/DiscImageChef.Server/ChangeLog b/DiscImageChef.Server/ChangeLog new file mode 100644 index 000000000..4dc517fd7 --- /dev/null +++ b/DiscImageChef.Server/ChangeLog @@ -0,0 +1,27 @@ +2017-06-03 Natalia Portillo + + * dos.css: + * Web.config: + * Default.aspx: + * Global.asax.cs: + * packages.config: + * Default.aspx.cs: + * ViewReport.aspx: + * Ata.cs: + * ViewReport.aspx.cs: + * ScsiEvpd.cs: + * ScsiMmcMode.cs: + * TestedMedia.cs: + * Default.aspx.designer.cs: + * Statistics.xml: + * WebApiConfig.cs: + * ScsiModeSense.cs: + * SscTestedMedia.cs: + * ViewReport.aspx.designer.cs: + * DiscImageChef.Server.csproj: + * ScsiMmcFeatures.cs: + * UploadStatsController.cs: + * UploadReportController.cs: Added server side code for + creating http://discimagechef.claunia.com with statistics and + device reports. + diff --git a/DiscImageChef.Server/Controllers/UploadReportController.cs b/DiscImageChef.Server/Controllers/UploadReportController.cs index 2af338e9e..0065047f9 100644 --- a/DiscImageChef.Server/Controllers/UploadReportController.cs +++ b/DiscImageChef.Server/Controllers/UploadReportController.cs @@ -36,12 +36,67 @@ // ****************************************************************************/ // //$Id$ using System; +using System.IO; +using System.Net.Http; +using System.Web.Http; +using System.Web; +using DiscImageChef.Metadata; +using System.Xml.Serialization; + namespace DiscImageChef.Server.Controllers { - public class UploadReportController + public class UploadReportController : ApiController { - public UploadReportController() + [Route("api/uploadreport")] + [HttpPost] + public HttpResponseMessage UploadReport() { + HttpResponseMessage response = new HttpResponseMessage(); + response.StatusCode = System.Net.HttpStatusCode.OK; + + try + { + DeviceReport newReport = new DeviceReport(); + HttpRequest request = HttpContext.Current.Request; + + if(request.InputStream == null) + { + response.Content = new StringContent("notstats", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + + XmlSerializer xs = new XmlSerializer(newReport.GetType()); + newReport = (DeviceReport)xs.Deserialize(request.InputStream); + + if(newReport == null) + { + response.Content = new StringContent("notstats", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + + Random rng = new Random(); + string filename = string.Format("NewReport_{0:yyyyMMddHHmmssfff}_{1}.xml", DateTime.UtcNow, rng.Next()); + while(File.Exists(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Upload", filename))) + { + filename = string.Format("NewReport_{0:yyyyMMddHHmmssfff}_{1}.xml", DateTime.UtcNow, rng.Next()); + } + + FileStream newFile = new FileStream(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Upload", filename), FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); + xs.Serialize(newFile, newReport); + newFile.Close(); + + response.Content = new StringContent("ok", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + catch + { +#if DEBUG + throw; +#else + response.Content = new StringContent("error", System.Text.Encoding.UTF8, "text/plain"); + return response; +#endif + } } } } diff --git a/DiscImageChef.Server/Controllers/UploadStatsController.cs b/DiscImageChef.Server/Controllers/UploadStatsController.cs index 258d0c8e0..a2b44f7ef 100644 --- a/DiscImageChef.Server/Controllers/UploadStatsController.cs +++ b/DiscImageChef.Server/Controllers/UploadStatsController.cs @@ -36,17 +36,440 @@ // ****************************************************************************/ // //$Id$ using System; +using System.IO; +using System.Net.Http; +using System.Web; using System.Web.Http; +using System.Xml.Serialization; +using DiscImageChef.Metadata; -namespace DiscImageChef.Server.App_Start +namespace DiscImageChef.Server.Controllers { - public class UploadStatsController + public class UploadStatsController : ApiController { - [Route("api/myfileupload")] + [Route("api/uploadstats")] [HttpPost] - public string UploadStats() + public HttpResponseMessage UploadStats() { - return "test"; + HttpResponseMessage response = new HttpResponseMessage(); + response.StatusCode = System.Net.HttpStatusCode.OK; + + try + { + Stats newStats = new Stats(); + HttpRequest request = HttpContext.Current.Request; + + if(request.InputStream == null) + { + response.Content = new StringContent("notstats", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + + XmlSerializer xs = new XmlSerializer(newStats.GetType()); + newStats = (Stats)xs.Deserialize(request.InputStream); + + if(newStats == null) + { + response.Content = new StringContent("notstats", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + + FileStream fs = WaitForFile(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Statistics", "Statistics.xml"), FileMode.Open, FileAccess.ReadWrite, FileShare.None); + + if(fs == null) + { + response.Content = new StringContent("retry", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + + Stats oldStats = new Stats(); + xs = new XmlSerializer(oldStats.GetType()); + oldStats = (Stats)xs.Deserialize(fs); + + if(newStats.Commands != null) + { + if(oldStats.Commands == null) + oldStats.Commands = newStats.Commands; + else + { + oldStats.Commands.Analyze += newStats.Commands.Analyze; + oldStats.Commands.Benchmark += newStats.Commands.Benchmark; + oldStats.Commands.Checksum += newStats.Commands.Checksum; + oldStats.Commands.Compare += newStats.Commands.Compare; + oldStats.Commands.CreateSidecar += newStats.Commands.CreateSidecar; + oldStats.Commands.Decode += newStats.Commands.Decode; + oldStats.Commands.DeviceInfo += newStats.Commands.DeviceInfo; + oldStats.Commands.DeviceReport += newStats.Commands.DeviceReport; + oldStats.Commands.DumpMedia += newStats.Commands.DumpMedia; + oldStats.Commands.Entropy += newStats.Commands.Entropy; + oldStats.Commands.Formats += newStats.Commands.Formats; + oldStats.Commands.MediaInfo += newStats.Commands.MediaInfo; + oldStats.Commands.MediaScan += newStats.Commands.MediaScan; + oldStats.Commands.PrintHex += newStats.Commands.PrintHex; + oldStats.Commands.Verify += newStats.Commands.Verify; + } + } + + if(newStats.OperatingSystems != null) + { + if(oldStats.OperatingSystems == null) + oldStats.OperatingSystems = newStats.OperatingSystems; + else + { + foreach(NameValueStats newNvs in newStats.OperatingSystems) + { + NameValueStats removeNvs = null; + NameValueStats addNvs = null; + + foreach(NameValueStats oldNvs in oldStats.OperatingSystems) + { + if(oldNvs.name == newNvs.name) + { + addNvs = new NameValueStats { name = oldNvs.name, Value = oldNvs.Value + newNvs.Value }; + removeNvs = oldNvs; + break; + } + } + + if(removeNvs != null && addNvs != null) + { + oldStats.OperatingSystems.Remove(removeNvs); + oldStats.OperatingSystems.Add(addNvs); + } + else + oldStats.OperatingSystems.Add(newNvs); + } + } + } + else + { + if(oldStats.OperatingSystems == null) + oldStats.OperatingSystems = new System.Collections.Generic.List + { + new NameValueStats { name = "Linux", Value = 1 } + }; + else + { + NameValueStats removeNvs = null; + NameValueStats addNvs = null; + + foreach(NameValueStats oldNvs in oldStats.OperatingSystems) + { + if(oldNvs.name == "Linux") + { + addNvs = new NameValueStats { name = oldNvs.name, Value = oldNvs.Value + 1 }; + removeNvs = oldNvs; + break; + } + } + + if(removeNvs != null && addNvs != null) + { + oldStats.OperatingSystems.Remove(removeNvs); + oldStats.OperatingSystems.Add(addNvs); + } + else + oldStats.OperatingSystems.Add(new NameValueStats { name = "Linux", Value = 1 }); + } + } + + if(newStats.Filesystems != null) + { + if(oldStats.Filesystems == null) + oldStats.Filesystems = newStats.Filesystems; + else + { + foreach(NameValueStats newNvs in newStats.Filesystems) + { + NameValueStats removeNvs = null; + NameValueStats addNvs = null; + + foreach(NameValueStats oldNvs in oldStats.Filesystems) + { + if(oldNvs.name == newNvs.name) + { + addNvs = new NameValueStats { name = oldNvs.name, Value = oldNvs.Value + newNvs.Value }; + removeNvs = oldNvs; + break; + } + } + + if(removeNvs != null && addNvs != null) + { + oldStats.Filesystems.Remove(removeNvs); + oldStats.Filesystems.Add(addNvs); + } + else + oldStats.Filesystems.Add(newNvs); + } + } + } + + if(newStats.Partitions != null) + { + if(oldStats.Partitions == null) + oldStats.Partitions = newStats.Partitions; + else + { + foreach(NameValueStats newNvs in newStats.Partitions) + { + NameValueStats removeNvs = null; + NameValueStats addNvs = null; + + foreach(NameValueStats oldNvs in oldStats.Partitions) + { + if(oldNvs.name == newNvs.name) + { + addNvs = new NameValueStats { name = oldNvs.name, Value = oldNvs.Value + newNvs.Value }; + removeNvs = oldNvs; + break; + } + } + + if(removeNvs != null && addNvs != null) + { + oldStats.Partitions.Remove(removeNvs); + oldStats.Partitions.Add(addNvs); + } + else + oldStats.Partitions.Add(newNvs); + } + } + } + + if(newStats.MediaImages != null) + { + if(oldStats.MediaImages == null) + oldStats.MediaImages = newStats.MediaImages; + else + { + foreach(NameValueStats newNvs in newStats.MediaImages) + { + NameValueStats removeNvs = null; + NameValueStats addNvs = null; + + foreach(NameValueStats oldNvs in oldStats.MediaImages) + { + if(oldNvs.name == newNvs.name) + { + addNvs = new NameValueStats { name = oldNvs.name, Value = oldNvs.Value + newNvs.Value }; + removeNvs = oldNvs; + break; + } + } + + if(removeNvs != null && addNvs != null) + { + oldStats.MediaImages.Remove(removeNvs); + oldStats.MediaImages.Add(addNvs); + } + else + oldStats.MediaImages.Add(newNvs); + } + } + } + + if(newStats.Filters != null) + { + if(oldStats.Filters == null) + oldStats.Filters = newStats.Filters; + else + { + foreach(NameValueStats newNvs in newStats.Filters) + { + NameValueStats removeNvs = null; + NameValueStats addNvs = null; + + foreach(NameValueStats oldNvs in oldStats.Filters) + { + if(oldNvs.name == newNvs.name) + { + addNvs = new NameValueStats { name = oldNvs.name, Value = oldNvs.Value + newNvs.Value }; + removeNvs = oldNvs; + break; + } + } + + if(removeNvs != null && addNvs != null) + { + oldStats.Filters.Remove(removeNvs); + oldStats.Filters.Add(addNvs); + } + else + oldStats.Filters.Add(newNvs); + } + } + } + + if(newStats.Devices != null) + { + if(oldStats.Devices == null) + oldStats.Devices = newStats.Devices; + else + { + foreach(DeviceStats newDev in newStats.Devices) + { + bool found = false; + + foreach(DeviceStats oldDev in oldStats.Devices) + { + if(oldDev.Manufacturer == newDev.Manufacturer && + oldDev.Model == newDev.Model && + oldDev.Revision == newDev.Revision && + oldDev.Bus == newDev.Bus) + { + found = true; + break; + } + } + + if(!found) + oldStats.Devices.Add(newDev); + } + } + } + + if(newStats.Medias != null) + { + if(oldStats.Medias == null) + oldStats.Medias = newStats.Medias; + else + { + foreach(MediaStats newMstat in newStats.Medias) + { + MediaStats removeMstat = null; + MediaStats addMstat = null; + + foreach(MediaStats oldMstat in oldStats.Medias) + { + if(oldMstat.real == newMstat.real && oldMstat.type == newMstat.type) + { + addMstat = new MediaStats { real = oldMstat.real, type = oldMstat.type, Value = oldMstat.Value + newMstat.Value }; + removeMstat = oldMstat; + break; + } + } + + if(removeMstat != null && addMstat != null) + { + oldStats.Medias.Remove(removeMstat); + oldStats.Medias.Add(addMstat); + } + else + oldStats.Medias.Add(newMstat); + } + } + } + + if(newStats.MediaScan != null) + { + if(oldStats.MediaScan == null) + oldStats.MediaScan = newStats.MediaScan; + else + { + if(oldStats.MediaScan.Sectors == null) + oldStats.MediaScan.Sectors = newStats.MediaScan.Sectors; + else + { + oldStats.MediaScan.Sectors.Correct = newStats.MediaScan.Sectors.Correct; + oldStats.MediaScan.Sectors.Error = newStats.MediaScan.Sectors.Error; + oldStats.MediaScan.Sectors.Total = newStats.MediaScan.Sectors.Total; + oldStats.MediaScan.Sectors.Unverifiable = newStats.MediaScan.Sectors.Unverifiable; + } + + if(oldStats.MediaScan.Times == null) + oldStats.MediaScan.Times = newStats.MediaScan.Times; + else + { + oldStats.MediaScan.Times.LessThan10ms = newStats.MediaScan.Times.LessThan10ms; + oldStats.MediaScan.Times.LessThan150ms = newStats.MediaScan.Times.LessThan150ms; + oldStats.MediaScan.Times.LessThan3ms = newStats.MediaScan.Times.LessThan3ms; + oldStats.MediaScan.Times.LessThan500ms = newStats.MediaScan.Times.LessThan500ms; + oldStats.MediaScan.Times.LessThan50ms = newStats.MediaScan.Times.LessThan50ms; + oldStats.MediaScan.Times.MoreThan500ms = newStats.MediaScan.Times.MoreThan500ms; + } + } + } + + if(newStats.Verify != null) + { + if(oldStats.Verify == null) + oldStats.Verify = newStats.Verify; + else + { + if(oldStats.Verify.Sectors == null) + oldStats.Verify.Sectors = newStats.Verify.Sectors; + else + { + oldStats.Verify.Sectors.Correct = newStats.Verify.Sectors.Correct; + oldStats.Verify.Sectors.Error = newStats.Verify.Sectors.Error; + oldStats.Verify.Sectors.Total = newStats.Verify.Sectors.Total; + oldStats.Verify.Sectors.Unverifiable = newStats.Verify.Sectors.Unverifiable; + } + + if(oldStats.Verify.MediaImages == null) + oldStats.Verify.MediaImages = newStats.Verify.MediaImages; + else + { + oldStats.Verify.MediaImages.Correct = newStats.Verify.MediaImages.Correct; + oldStats.Verify.MediaImages.Failed = newStats.Verify.MediaImages.Failed; + } + } + } + + Random rng = new Random(); + string filename = string.Format("BackupStats_{0:yyyyMMddHHmmssfff}_{1}.xml", DateTime.UtcNow, rng.Next()); + while(File.Exists(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Statistics", filename))) + { + filename = string.Format("BackupStats_{0:yyyyMMddHHmmssfff}_{1}.xml", DateTime.UtcNow, rng.Next()); + } + + FileStream backup = new FileStream(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Statistics", filename), FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); + fs.Seek(0, SeekOrigin.Begin); + fs.CopyTo(backup); + backup.Close(); + fs.Seek(0, SeekOrigin.Begin); + xs = new XmlSerializer(oldStats.GetType()); + xs.Serialize(fs, oldStats); + fs.SetLength(fs.Position); + fs.Close(); + + response.Content = new StringContent("ok", System.Text.Encoding.UTF8, "text/plain"); + return response; + } + catch(Exception ex) + { +#if DEBUG + System.Console.WriteLine("{0} {1}", ex.Message, ex.InnerException); + throw; +#else + response.Content = new StringContent("error", System.Text.Encoding.UTF8, "text/plain"); + return response; +#endif + } + } + + FileStream WaitForFile(string fullPath, FileMode mode, FileAccess access, FileShare share) + { + for(int numTries = 0; numTries < 100; numTries++) + { + FileStream fs = null; + try + { + fs = new FileStream(fullPath, mode, access, share); + return fs; + } + catch(IOException) + { + if(fs != null) + { + fs.Dispose(); + } + System.Threading.Thread.Sleep(50); + } + } + + return null; } } } diff --git a/DiscImageChef.Server/Default.aspx b/DiscImageChef.Server/Default.aspx index d83e2e56b..36db06cef 100644 --- a/DiscImageChef.Server/Default.aspx +++ b/DiscImageChef.Server/Default.aspx @@ -1,12 +1,182 @@ <%@ Page Language="C#" Inherits="DiscImageChef.Server.Default" %> + - Default + + DiscImageChef Statistics - -
- - + +

Welcome to DiscImageChef Server version

+
+
+
+

Commands run:

+

+ analyze command has been run times
+ benchmark command has been run times
+ checksum command has been run times
+ compare command has been run times
+ create-sidecar command has been run times
+ decode command has been run times
+ device-info command has been run times
+ device-report command has been run times
+ dump-media command has been run times
+ entropy command has been run times
+ formats command has been run times
+ media-info command has been run times
+ media-scan command has been run times
+ printhex command has been run times
+ verify command has been run times +

+
+
+ + + + + + + + +
DiscImageChef has run on times.
+
+
+
+

Filters found:

+ + + + + + + + + + + + + +
FilterTimes
+
+
+

Media image formats found:

+ + + + + + + + + + + + + +
Media image formatTimes
+
+
+

Partition schemes found:

+ + + + + + + + + + + + + +
Partition schemeTimes
+
+
+

Filesystems found:

+ + + + + + + + + + + + + +
Filesystem nameTimes
+
+
+

Media types found in images:

+ + + + + + + + + + + + + + + +
Physical typeLogical typeTimes
+
+
+

Media types found in devices:

+ + + + + + + + + + + + + + + +
Physical typeLogical typeTimes
+
+
+

Found devices:

+ + + + + + + + + + + + + + + + + + + +
ManufacturerModelRevisionBusReport
+
+
+
+ diff --git a/DiscImageChef.Server/Default.aspx.cs b/DiscImageChef.Server/Default.aspx.cs index 712c9db13..9832f6e9b 100644 --- a/DiscImageChef.Server/Default.aspx.cs +++ b/DiscImageChef.Server/Default.aspx.cs @@ -1,15 +1,249 @@ using System; using System.Web; using System.Web.UI; +using System.Reflection; +using System.IO; +using DiscImageChef.Metadata; +using System.Xml.Serialization; +using System.Collections.Generic; +using System.CodeDom; +using System.Linq; namespace DiscImageChef.Server - { - +{ public partial class Default : System.Web.UI.Page + { + class MediaItem { - public void button1Clicked(object sender, EventArgs args) + public string Type { get; set; } + public string SubType { get; set; } + public long Count { get; set; } + } + + class DeviceItem + { + public string Manufacturer { get; set; } + public string Model { get; set; } + public string Revision { get; set; } + public string Bus { get; set; } + public string ReportLink { get; set; } + } + + Stats statistics; + List realMedia; + List virtualMedia; + List operatingSystems; + List devices; + + protected void Page_Load(object sender, EventArgs e) + { + lblVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + try { - button1.Text = "You clicked me"; + if(!File.Exists(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Statistics", "Statistics.xml"))) + { +#if DEBUG + content.InnerHtml = string.Format("Sorry, cannot load data file \"{0}\"", Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Statistics", "Statistics.xml")); +#else + content.InnerHtml = "Sorry, cannot load data file"; +#endif + return; + } + + statistics = new Stats(); + + XmlSerializer xs = new XmlSerializer(statistics.GetType()); + FileStream fs = WaitForFile(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Statistics", "Statistics.xml"), FileMode.Open, FileAccess.Read, FileShare.Read); + statistics = (Stats)xs.Deserialize(fs); + fs.Close(); + + if(statistics.OperatingSystems != null) + { + operatingSystems = new List(); + foreach(NameValueStats nvs in statistics.OperatingSystems) + operatingSystems.Add(new NameValueStats { name = Interop.DetectOS.GetPlatformName((Interop.PlatformID)Enum.Parse(typeof(Interop.PlatformID), nvs.name)), Value = nvs.Value }); + repOperatingSystems.DataSource = operatingSystems.OrderBy(os => os.name).ToList(); + repOperatingSystems.DataBind(); + } + else + divOperatingSystems.Visible = false; + + if(statistics.Commands != null) + { + lblAnalyze.Text = statistics.Commands.Analyze.ToString(); + lblCompare.Text = statistics.Commands.Compare.ToString(); + lblChecksum.Text = statistics.Commands.Checksum.ToString(); + lblEntropy.Text = statistics.Commands.Entropy.ToString(); + lblVerify.Text = statistics.Commands.Verify.ToString(); + lblPrintHex.Text = statistics.Commands.PrintHex.ToString(); + lblDecode.Text = statistics.Commands.Decode.ToString(); + lblDeviceInfo.Text = statistics.Commands.DeviceInfo.ToString(); + lblMediaInfo.Text = statistics.Commands.MediaInfo.ToString(); + lblMediaScan.Text = statistics.Commands.MediaScan.ToString(); + lblFormats.Text = statistics.Commands.Formats.ToString(); + lblBenchmark.Text = statistics.Commands.Benchmark.ToString(); + lblCreateSidecar.Text = statistics.Commands.CreateSidecar.ToString(); + lblDumpMedia.Text = statistics.Commands.DumpMedia.ToString(); + lblDeviceReport.Text = statistics.Commands.DeviceReport.ToString(); + } + else + divCommands.Visible = false; + + if(statistics.Filters != null) + { + repFilters.DataSource = statistics.Filters.OrderBy(filter => filter.name).ToList(); + repFilters.DataBind(); + } + else + divFilters.Visible = false; + + if(statistics.MediaImages != null) + { + repMediaImages.DataSource = statistics.MediaImages.OrderBy(filter => filter.name).ToList(); + repMediaImages.DataBind(); + } + else + divMediaImages.Visible = false; + + if(statistics.Partitions != null) + { + repPartitions.DataSource = statistics.Partitions.OrderBy(filter => filter.name).ToList(); + repPartitions.DataBind(); + } + else + divPartitions.Visible = false; + + if(statistics.Filesystems != null) + { + repFilesystems.DataSource = statistics.Filesystems.OrderBy(filter => filter.name).ToList(); + repFilesystems.DataBind(); + } + else + divFilesystems.Visible = false; + + if(statistics.Medias != null) + { + realMedia = new List(); + virtualMedia = new List(); + foreach(MediaStats nvs in statistics.Medias) + { + string type; + string subtype; + + MediaType.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType), nvs.type), out type, out subtype); + + if(nvs.real) + realMedia.Add(new MediaItem { Type = type, SubType = subtype, Count = nvs.Value }); + else + virtualMedia.Add(new MediaItem { Type = type, SubType = subtype, Count = nvs.Value }); + } + + if(realMedia.Count > 0) + { + repRealMedia.DataSource = realMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList(); + repRealMedia.DataBind(); + } + else + divRealMedia.Visible = false; + + if(virtualMedia.Count > 0) + { + repVirtualMedia.DataSource = virtualMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList(); + repVirtualMedia.DataBind(); + } + else + divVirtualMedia.Visible = false; + } + else + { + divRealMedia.Visible = false; + divVirtualMedia.Visible = false; + } + + if(statistics.Devices != null) + { + devices = new List(); + foreach(DeviceStats device in statistics.Devices) + { + string url = null; + string xmlFile; + if(!string.IsNullOrWhiteSpace(device.Manufacturer) && !string.IsNullOrWhiteSpace(device.Model) && !string.IsNullOrWhiteSpace(device.Revision)) + { + xmlFile = device.Manufacturer + "_" + device.Model + "_" + device.Revision + ".xml"; + url = string.Format("ViewReport.aspx?manufacturer={0}&model={1}&revision={2}", + HttpUtility.UrlPathEncode(device.Manufacturer), HttpUtility.UrlPathEncode(device.Model), HttpUtility.UrlPathEncode(device.Revision)); + } + else if(!string.IsNullOrWhiteSpace(device.Manufacturer) && !string.IsNullOrWhiteSpace(device.Model)) + { + xmlFile = device.Manufacturer + "_" + device.Model + ".xml"; + url = string.Format("ViewReport.aspx?manufacturer={0}&model={1}", + HttpUtility.UrlPathEncode(device.Manufacturer), HttpUtility.UrlPathEncode(device.Model)); + } + else if(!string.IsNullOrWhiteSpace(device.Model) && !string.IsNullOrWhiteSpace(device.Revision)) + { + xmlFile = device.Model + "_" + device.Revision + ".xml"; + url = string.Format("ViewReport.aspx?model={0}&revision={1}", + HttpUtility.UrlPathEncode(device.Model), HttpUtility.UrlPathEncode(device.Revision)); + } + else + { + xmlFile = device.Model + ".xml"; + url = string.Format("ViewReport.aspx?model={0}", + HttpUtility.UrlPathEncode(device.Model)); + } + + if(!File.Exists(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Reports", xmlFile))) + { + url = null; + } + + devices.Add(new DeviceItem() + { + Manufacturer = device.Manufacturer, + Model = device.Model, + Revision = device.Revision, + Bus = device.Bus, + ReportLink = url == null ? "No" : string.Format("Yes", url) + }); + } + repDevices.DataSource = devices.OrderBy(device => device.Manufacturer).ThenBy(device => device.Model).ThenBy(device => device.Revision).ThenBy(device => device.Bus).ToList(); + repDevices.DataBind(); + } + else + divDevices.Visible = false; + + } + catch(Exception) + { + content.InnerHtml = "Could not load statistics"; +#if DEBUG + throw; +#endif } } + + FileStream WaitForFile(string fullPath, FileMode mode, FileAccess access, FileShare share) + { + for(int numTries = 0; numTries < 100; numTries++) + { + FileStream fs = null; + try + { + fs = new FileStream(fullPath, mode, access, share); + return fs; + } + catch(IOException) + { + if(fs != null) + { + fs.Dispose(); + } + System.Threading.Thread.Sleep(50); + } + } + + return null; + } } +} diff --git a/DiscImageChef.Server/Default.aspx.designer.cs b/DiscImageChef.Server/Default.aspx.designer.cs index 3e88f5cc2..53d1795b8 100644 --- a/DiscImageChef.Server/Default.aspx.designer.cs +++ b/DiscImageChef.Server/Default.aspx.designer.cs @@ -1,12 +1,86 @@ -using System; -using System.Web; -using System.Web.UI; +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ -namespace DiscImageChef.Server - { - - public partial class Default - { - protected System.Web.UI.WebControls.Button button1; - } - } +namespace DiscImageChef.Server { + + + public partial class Default { + + protected System.Web.UI.HtmlControls.HtmlGenericControl body; + + protected System.Web.UI.WebControls.Label lblVersion; + + protected System.Web.UI.HtmlControls.HtmlGenericControl content; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divCommands; + + protected System.Web.UI.WebControls.Label lblAnalyze; + + protected System.Web.UI.WebControls.Label lblBenchmark; + + protected System.Web.UI.WebControls.Label lblChecksum; + + protected System.Web.UI.WebControls.Label lblCompare; + + protected System.Web.UI.WebControls.Label lblCreateSidecar; + + protected System.Web.UI.WebControls.Label lblDecode; + + protected System.Web.UI.WebControls.Label lblDeviceInfo; + + protected System.Web.UI.WebControls.Label lblDeviceReport; + + protected System.Web.UI.WebControls.Label lblDumpMedia; + + protected System.Web.UI.WebControls.Label lblEntropy; + + protected System.Web.UI.WebControls.Label lblFormats; + + protected System.Web.UI.WebControls.Label lblMediaInfo; + + protected System.Web.UI.WebControls.Label lblMediaScan; + + protected System.Web.UI.WebControls.Label lblPrintHex; + + protected System.Web.UI.WebControls.Label lblVerify; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divOperatingSystems; + + protected System.Web.UI.WebControls.Repeater repOperatingSystems; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divFilters; + + protected System.Web.UI.WebControls.Repeater repFilters; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divMediaImages; + + protected System.Web.UI.WebControls.Repeater repMediaImages; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divPartitions; + + protected System.Web.UI.WebControls.Repeater repPartitions; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divFilesystems; + + protected System.Web.UI.WebControls.Repeater repFilesystems; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divVirtualMedia; + + protected System.Web.UI.WebControls.Repeater repVirtualMedia; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divRealMedia; + + protected System.Web.UI.WebControls.Repeater repRealMedia; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divDevices; + + protected System.Web.UI.WebControls.Repeater repDevices; + } +} diff --git a/DiscImageChef.Server/DiscImageChef.Server.csproj b/DiscImageChef.Server/DiscImageChef.Server.csproj index 77e48e97d..41dcb4992 100644 --- a/DiscImageChef.Server/DiscImageChef.Server.csproj +++ b/DiscImageChef.Server/DiscImageChef.Server.csproj @@ -10,6 +10,7 @@ Library DiscImageChef.Server DiscImageChef.Server + 3.3.99.0 v4.6.1 @@ -32,11 +33,30 @@ + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + + + ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll + + + + + + + @@ -49,12 +69,83 @@ Default.aspx + + ViewReport.aspx + + + ViewReport.aspx + + + + + + + + + + + + + + + + {9F213318-5CB8-4066-A757-074489C9F818} + DiscImageChef.Metadata + + + {F2B84194-26EB-4227-B1C5-6602517E85AE} + DiscImageChef.CommonTypes + + + {9183F2E0-A879-4F23-9EE3-C6908F1332B2} + DiscImageChef.Interop + + + {0BEB3088-B634-4289-AE17-CDF2D25D00D5} + DiscImageChef.Decoders + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiscImageChef.Server/Global.asax.cs b/DiscImageChef.Server/Global.asax.cs index d2dc5bd37..5ce5601d7 100644 --- a/DiscImageChef.Server/Global.asax.cs +++ b/DiscImageChef.Server/Global.asax.cs @@ -39,12 +39,12 @@ using System.Web; using System.Web.Http; namespace DiscImageChef.Server - { +{ public class Global : HttpApplication - { + { protected void Application_Start() - { - GlobalConfiguration.Configure(WebApiConfig.Register); - } + { + GlobalConfiguration.Configure(WebApiConfig.Register); } } +} diff --git a/DiscImageChef.Server/Statistics/Statistics.xml b/DiscImageChef.Server/Statistics/Statistics.xml index d8f0b4e0e..e7962d3e9 100644 --- a/DiscImageChef.Server/Statistics/Statistics.xml +++ b/DiscImageChef.Server/Statistics/Statistics.xml @@ -1,2 +1,2 @@ - + \ No newline at end of file diff --git a/DiscImageChef.Server/ViewReport.aspx b/DiscImageChef.Server/ViewReport.aspx index c2a265cc3..9b4b6f552 100644 --- a/DiscImageChef.Server/ViewReport.aspx +++ b/DiscImageChef.Server/ViewReport.aspx @@ -1,11 +1,157 @@ <%@ Page Language="C#" Inherits="DiscImageChef.Server.ViewReport" %> + - ViewReport + + DiscImageChef Device Report - -
-
+ + DiscImageChef Report for +
+
+ USB characteristics:
+ Manufacturer:
+ Product:
+ Vendor ID:
+ Product ID: +
+
+
+ FireWire characteristics:
+ Manufacturer:
+ Product:
+ Vendor ID:
+ Product ID: +
+
+
+ PCMCIA characteristics:
+ Manufacturer:
+ Product:
+ Manufacturer code:
+ Card code:
+ Compliance: + + + :
+
+
+ +
+
+
+ ATA characteristics:
+
+ + + :
+
+
+ + + <%# Container.DataItem?.ToString() ?? string.Empty%>
+
+
+
+
+
+ SCSI characteristics:
+ Vendor:
+ Product:
+ Revision:
+ + + <%# Container.DataItem?.ToString() ?? string.Empty%>
+
+
+
+
SCSI mode sense pages: + + + + + + + + + + + + + +
ModeContents
+
+
+
SCSI extended vital product data pages: + + + + + + + + + + + + + +
EVPDContents
+
+
+
SCSI CD-ROM capabilities:
+ + + <%# Container.DataItem?.ToString() ?? string.Empty%>
+
+
+
+
+
SCSI MMC features:
+ + + <%# Container.DataItem?.ToString() ?? string.Empty%>
+
+
+
+
+
SCSI Streaming device capabilities:
+ Block size granularity:
+ Maximum block length: bytes
+ Minimum block length: bytes
+ + +
Information for supported density with primary code and secondary code
+ Drive can write this density:
+ Duplicate density:
+ Default density:
+ Density has bits per mm, with tracks in a mm width tape + Name:
+ Organization:
+ Description:
+ Maximum capacity: megabytes
+
+
+ + +
Information for supported media with type code
+ Drive can write this density:
+ Media is meters long in a mm width tape + Name:
+ Organization:
+ Description:
+
+
+
+
+
+
Tested media:
+ + + <%# Container.DataItem?.ToString() ?? string.Empty%>
+
+
+
diff --git a/DiscImageChef.Server/ViewReport.aspx.cs b/DiscImageChef.Server/ViewReport.aspx.cs index 61afdd220..d17021d80 100644 --- a/DiscImageChef.Server/ViewReport.aspx.cs +++ b/DiscImageChef.Server/ViewReport.aspx.cs @@ -1,12 +1,483 @@ using System; using System.Web; using System.Web.UI; +using System.Text; +using System.IO; +using System.Xml.Serialization; +using DiscImageChef.Metadata; +using System.Collections.Generic; +using System.Net; +using static DiscImageChef.Decoders.ATA.Identify; +using DiscImageChef.Decoders.SCSI; +using DiscImageChef.Server.App_Start; +using System.Web.Compilation; +using System.Web.Configuration; namespace DiscImageChef.Server { public partial class ViewReport : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) + { + try + { + string manufacturer = Request.QueryString["manufacturer"]; + string model = Request.QueryString["model"]; + string revision = Request.QueryString["revision"]; + // Strip non-ascii, strip slashes and question marks + if(manufacturer != null) + manufacturer = Encoding.ASCII.GetString(Encoding.Convert(Encoding.UTF8, Encoding.ASCII, Encoding.UTF8.GetBytes(manufacturer))).Replace('/', '_').Replace('\\', '_').Replace('?', '_'); + if(model != null) + model = Encoding.ASCII.GetString(Encoding.Convert(Encoding.UTF8, Encoding.ASCII, Encoding.UTF8.GetBytes(model))).Replace('/', '_').Replace('\\', '_').Replace('?', '_'); + if(revision != null) + revision = Encoding.ASCII.GetString(Encoding.Convert(Encoding.UTF8, Encoding.ASCII, Encoding.UTF8.GetBytes(revision))).Replace('/', '_').Replace('\\', '_').Replace('?', '_'); + + lblManufacturer.Text = manufacturer; + lblModel.Text = model; + lblRevision.Text = revision; + + string xmlFile = null; + if(!string.IsNullOrWhiteSpace(manufacturer) && !string.IsNullOrWhiteSpace(model) && !string.IsNullOrWhiteSpace(revision)) + xmlFile = manufacturer + "_" + model + "_" + revision + ".xml"; + else if(!string.IsNullOrWhiteSpace(manufacturer) && !string.IsNullOrWhiteSpace(model)) + xmlFile = manufacturer + "_" + model + ".xml"; + else if(!string.IsNullOrWhiteSpace(model) && !string.IsNullOrWhiteSpace(revision)) + xmlFile = model + "_" + revision + ".xml"; + else if(!string.IsNullOrWhiteSpace(model)) + xmlFile = model + ".xml"; + + if(xmlFile==null || !File.Exists(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Reports", xmlFile))) + { + content.InnerHtml = "Could not find the specified report"; + return; + } + + DeviceReport report = new DeviceReport(); + XmlSerializer xs = new XmlSerializer(report.GetType()); + StreamReader sr = new StreamReader(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "Reports", xmlFile)); + report = (DeviceReport)xs.Deserialize(sr); + sr.Close(); + + if(report.USB != null) + { + string usbVendorDescription = null; + string usbProductDescription = null; + GetUsbDescriptions(report.USB.VendorID, report.USB.ProductID, out usbVendorDescription, out usbProductDescription); + + lblUsbManufacturer.Text = HttpUtility.HtmlEncode(report.USB.Manufacturer); + lblUsbProduct.Text = HttpUtility.HtmlEncode(report.USB.Product); + lblUsbVendor.Text = string.Format("0x{0:x4}", report.USB.VendorID); + if(usbVendorDescription != null) + lblUsbVendorDescription.Text = string.Format("({0})", HttpUtility.HtmlEncode(usbVendorDescription)); + lblUsbProductId.Text = string.Format("0x{0:x4}", report.USB.ProductID); + if(usbProductDescription != null) + lblUsbProductDescription.Text = string.Format("({0})", HttpUtility.HtmlEncode(usbProductDescription)); + } + else + divUsb.Visible = false; + + if(report.FireWire != null) + { + lblFirewireManufacturer.Text = HttpUtility.HtmlEncode(report.FireWire.Manufacturer); + lblFirewireProduct.Text = HttpUtility.HtmlEncode(report.FireWire.Product); + lblFirewireVendor.Text = string.Format("0x{0:x8}", report.FireWire.VendorID); + lblFirewireProductId.Text = string.Format("0x{0:x8}", report.FireWire.ProductID); + } + else + divFirewire.Visible = false; + + if(report.PCMCIA != null) + { + lblPcmciaManufacturer.Text = HttpUtility.HtmlEncode(report.PCMCIA.Manufacturer); + lblPcmciaProduct.Text = HttpUtility.HtmlEncode(report.PCMCIA.ProductName); + lblPcmciaManufacturerCode.Text = string.Format("0x{0:x4}", report.PCMCIA.ManufacturerCode); + lblPcmciaCardCode.Text = string.Format("0x{0:x4}", report.PCMCIA.CardCode); + lblPcmciaCompliance.Text = HttpUtility.HtmlEncode(report.PCMCIA.Compliance); + Decoders.PCMCIA.Tuple[] tuples = Decoders.PCMCIA.CIS.GetTuples(report.PCMCIA.CIS); + if(tuples != null) + { + Dictionary decodedTuples = new Dictionary(); + foreach(Decoders.PCMCIA.Tuple tuple in tuples) + { + switch(tuple.Code) + { + case Decoders.PCMCIA.TupleCodes.CISTPL_NULL: + case Decoders.PCMCIA.TupleCodes.CISTPL_END: + case Decoders.PCMCIA.TupleCodes.CISTPL_MANFID: + case Decoders.PCMCIA.TupleCodes.CISTPL_VERS_1: + break; + case Decoders.PCMCIA.TupleCodes.CISTPL_DEVICEGEO: + case Decoders.PCMCIA.TupleCodes.CISTPL_DEVICEGEO_A: + Decoders.PCMCIA.DeviceGeometryTuple geom = Decoders.PCMCIA.CIS.DecodeDeviceGeometryTuple(tuple.Data); + if(geom != null && geom.Geometries != null) + { + foreach(Decoders.PCMCIA.DeviceGeometry geometry in geom.Geometries) + { + decodedTuples.Add("Device width", string.Format("{0} bits", (1 << (geometry.CardInterface - 1)) * 8)); + decodedTuples.Add("Erase block", string.Format("{0} bytes", (1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1)))); + decodedTuples.Add("Read block", string.Format("{0} bytes", (1 << (geometry.ReadBlockSize - 1)) * (1 << (geometry.Interleaving - 1)))); + decodedTuples.Add("Write block", string.Format("{0} bytes", (1 << (geometry.WriteBlockSize - 1)) * (1 << (geometry.Interleaving - 1)))); + decodedTuples.Add("Partition alignment", string.Format("{0} bytes", (1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1)) * (1 << (geometry.Partitions - 1)))); + } + } + break; + case Decoders.PCMCIA.TupleCodes.CISTPL_ALTSTR: + case Decoders.PCMCIA.TupleCodes.CISTPL_BAR: + case Decoders.PCMCIA.TupleCodes.CISTPL_BATTERY: + case Decoders.PCMCIA.TupleCodes.CISTPL_BYTEORDER: + case Decoders.PCMCIA.TupleCodes.CISTPL_CFTABLE_ENTRY: + case Decoders.PCMCIA.TupleCodes.CISTPL_CFTABLE_ENTRY_CB: + case Decoders.PCMCIA.TupleCodes.CISTPL_CHECKSUM: + case Decoders.PCMCIA.TupleCodes.CISTPL_CONFIG: + case Decoders.PCMCIA.TupleCodes.CISTPL_CONFIG_CB: + case Decoders.PCMCIA.TupleCodes.CISTPL_DATE: + case Decoders.PCMCIA.TupleCodes.CISTPL_DEVICE: + case Decoders.PCMCIA.TupleCodes.CISTPL_DEVICE_A: + case Decoders.PCMCIA.TupleCodes.CISTPL_DEVICE_OA: + case Decoders.PCMCIA.TupleCodes.CISTPL_DEVICE_OC: + case Decoders.PCMCIA.TupleCodes.CISTPL_EXTDEVIC: + case Decoders.PCMCIA.TupleCodes.CISTPL_FORMAT: + case Decoders.PCMCIA.TupleCodes.CISTPL_FORMAT_A: + case Decoders.PCMCIA.TupleCodes.CISTPL_FUNCE: + case Decoders.PCMCIA.TupleCodes.CISTPL_FUNCID: + case Decoders.PCMCIA.TupleCodes.CISTPL_GEOMETRY: + case Decoders.PCMCIA.TupleCodes.CISTPL_INDIRECT: + case Decoders.PCMCIA.TupleCodes.CISTPL_JEDEC_A: + case Decoders.PCMCIA.TupleCodes.CISTPL_JEDEC_C: + case Decoders.PCMCIA.TupleCodes.CISTPL_LINKTARGET: + case Decoders.PCMCIA.TupleCodes.CISTPL_LONGLINK_A: + case Decoders.PCMCIA.TupleCodes.CISTPL_LONGLINK_C: + case Decoders.PCMCIA.TupleCodes.CISTPL_LONGLINK_CB: + case Decoders.PCMCIA.TupleCodes.CISTPL_LONGLINK_MFC: + case Decoders.PCMCIA.TupleCodes.CISTPL_NO_LINK: + case Decoders.PCMCIA.TupleCodes.CISTPL_ORG: + case Decoders.PCMCIA.TupleCodes.CISTPL_PWR_MGMNT: + case Decoders.PCMCIA.TupleCodes.CISTPL_SPCL: + case Decoders.PCMCIA.TupleCodes.CISTPL_SWIL: + case Decoders.PCMCIA.TupleCodes.CISTPL_VERS_2: + decodedTuples.Add("Undecoded tuple ID", tuple.Code.ToString()); + break; + default: + decodedTuples.Add("Unknown tuple ID", string.Format("0x{0:X2}", (byte)tuple.Code)); + break; + + } + } + + if(decodedTuples.Count > 0) + { + repPcmciaTuples.DataSource = decodedTuples; + repPcmciaTuples.DataBind(); + } + else + repPcmciaTuples.Visible = false; + } + else + repPcmciaTuples.Visible = false; + } + else + divPcmcia.Visible = false; + + bool removable = true; + testedMediaType[] testedMedia = null; + bool ata = false; + bool atapi = false; + bool sscMedia = false; + + if(report.ATA != null || report.ATAPI != null) + { + ata = true; + List ataOneValue = new List(); + Dictionary ataTwoValue = new Dictionary(); + ataType ataReport; + + if(report.ATAPI != null) + { + lblAtapi.Text = "PI"; + ataReport = report.ATAPI; + atapi = true; + } + else + ataReport = report.ATA; + + bool cfa = report.CompactFlashSpecified && report.CompactFlash; + + if(atapi && !cfa) + lblAtaDeviceType.Text = "ATAPI device"; + else if(!atapi && cfa) + lblAtaDeviceType.Text = "CompactFlash device"; + else + lblAtaDeviceType.Text = "ATA device"; + + Ata.Report(ataReport, cfa, atapi, ref removable, ref ataOneValue, ref ataTwoValue, ref testedMedia); + + repAtaOne.DataSource = ataOneValue; + repAtaOne.DataBind(); + repAtaTwo.DataSource = ataTwoValue; + repAtaTwo.DataBind(); + } + else + divAta.Visible = false; + + if(report.SCSI != null) + { + List scsiOneValue = new List(); + Dictionary modePages = new Dictionary(); + Dictionary evpdPages = new Dictionary(); + + if(VendorString.Prettify(report.SCSI.Inquiry.VendorIdentification) != report.SCSI.Inquiry.VendorIdentification) + lblScsiVendor.Text = string.Format("{0} ({1})", report.SCSI.Inquiry.VendorIdentification, VendorString.Prettify(report.SCSI.Inquiry.VendorIdentification)); + else + lblScsiVendor.Text = report.SCSI.Inquiry.VendorIdentification; + lblScsiProduct.Text = report.SCSI.Inquiry.ProductIdentification; + lblScsiRevision.Text = report.SCSI.Inquiry.ProductRevisionLevel; + + scsiOneValue.AddRange(ScsiInquiry.Report(report.SCSI.Inquiry)); + + if(report.SCSI.SupportsModeSense6) + scsiOneValue.Add("Device supports MODE SENSE (6)"); + if(report.SCSI.SupportsModeSense10) + scsiOneValue.Add("Device supports MODE SENSE (10)"); + if(report.SCSI.SupportsModeSubpages) + scsiOneValue.Add("Device supports MODE SENSE subpages"); + + if(report.SCSI.ModeSense != null) + ScsiModeSense.Report(report.SCSI.ModeSense, report.SCSI.Inquiry.VendorIdentification, report.SCSI.Inquiry.PeripheralDeviceType, ref scsiOneValue, ref modePages); + + if(modePages.Count > 0) + { + repModeSense.DataSource = modePages; + repModeSense.DataBind(); + } + else + divScsiModeSense.Visible = false; + + if(report.SCSI.EVPDPages != null) + ScsiEvpd.Report(report.SCSI.EVPDPages, report.SCSI.Inquiry.VendorIdentification, ref evpdPages); + + if(evpdPages.Count > 0) + { + repEvpd.DataSource = evpdPages; + repEvpd.DataBind(); + } + else + divScsiEvpd.Visible = false; + + divScsiMmcMode.Visible = false; + divScsiMmcFeatures.Visible = false; + divScsiSsc.Visible = false; + + if(report.SCSI.MultiMediaDevice != null) + { + testedMedia = report.SCSI.MultiMediaDevice.TestedMedia; + + if(report.SCSI.MultiMediaDevice.ModeSense2A != null) + { + List mmcModeOneValue = new List(); + ScsiMmcMode.Report(report.SCSI.MultiMediaDevice.ModeSense2A, ref mmcModeOneValue); + if(mmcModeOneValue.Count > 0) + { + divScsiMmcMode.Visible = true; + repScsiMmcMode.DataSource = mmcModeOneValue; + repScsiMmcMode.DataBind(); + } + } + + if(report.SCSI.MultiMediaDevice.Features != null) + { + List mmcFeaturesOneValue = new List(); + ScsiMmcFeatures.Report(report.SCSI.MultiMediaDevice.Features, ref mmcFeaturesOneValue); + if(mmcFeaturesOneValue.Count > 0) + { + divScsiMmcFeatures.Visible = true; + repScsiMmcFeatures.DataSource = mmcFeaturesOneValue; + repScsiMmcFeatures.DataBind(); + } + } + } + else if(report.SCSI.SequentialDevice != null) + { + divScsiSsc.Visible = true; + + if(report.SCSI.SequentialDevice.BlockSizeGranularitySpecified) + lblScsiSscGranularity.Text = report.SCSI.SequentialDevice.BlockSizeGranularity.ToString(); + else + lblScsiSscGranularity.Text = "Unspecified"; + + if(report.SCSI.SequentialDevice.MaxBlockLengthSpecified) + lblScsiSscMaxBlock.Text = report.SCSI.SequentialDevice.MaxBlockLength.ToString(); + else + lblScsiSscMaxBlock.Text = "Unspecified"; + + if(report.SCSI.SequentialDevice.MinBlockLengthSpecified) + lblScsiSscMinBlock.Text = report.SCSI.SequentialDevice.MinBlockLength.ToString(); + else + lblScsiSscMinBlock.Text = "Unspecified"; + + if(report.SCSI.SequentialDevice.SupportedDensities != null) + { + repScsiSscDensities.DataSource = report.SCSI.SequentialDevice.SupportedDensities; + repScsiSscDensities.DataBind(); + } + else + repScsiSscDensities.Visible = false; + + if(report.SCSI.SequentialDevice.SupportedMediaTypes != null) + { + repScsiSscMedias.DataSource = report.SCSI.SequentialDevice.SupportedMediaTypes; + repScsiSscMedias.DataBind(); + } + else + repScsiSscMedias.Visible = false; + + if(report.SCSI.SequentialDevice.TestedMedia != null) + { + List mediaOneValue = new List(); + SscTestedMedia.Report(report.SCSI.SequentialDevice.TestedMedia, ref mediaOneValue); + if(mediaOneValue.Count>0) + { + sscMedia = true; + repTestedMedia.DataSource = mediaOneValue; + repTestedMedia.DataBind(); + } + else + divTestedMedia.Visible = false; + } + else + divTestedMedia.Visible = false; + } + else if(report.SCSI.ReadCapabilities != null) + { + removable = false; + if(report.SCSI.ReadCapabilities.BlocksSpecified && report.SCSI.ReadCapabilities.BlockSizeSpecified) + { + scsiOneValue.Add(string.Format("Device has {0} blocks of {1} bytes each", report.SCSI.ReadCapabilities.Blocks, report.SCSI.ReadCapabilities.BlockSize)); + + if(((report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1024 / 1024) > 1000000) + { + scsiOneValue.Add(string.Format("Device size: {0} bytes, {1} Tb, {2} TiB", report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize, + (report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1000 / 1000 / 1000 / 1000, (report.SCSI.ReadCapabilities.Blocks * 512) / 1024 / 1024 / 1024 / 1024)); + } + else if(((report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1024 / 1024) > 1000) + { + scsiOneValue.Add(string.Format("Device size: {0} bytes, {1} Gb, {2} GiB", report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize, + (report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1000 / 1000 / 1000, (report.SCSI.ReadCapabilities.Blocks * 512) / 1024 / 1024 / 1024)); + } + else + { + scsiOneValue.Add(string.Format("Device size: {0} bytes, {1} Mb, {2} MiB", report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize, + (report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1000 / 1000, (report.SCSI.ReadCapabilities.Blocks * 512) / 1024 / 1024)); + } + } + + if(report.SCSI.ReadCapabilities.MediumTypeSpecified) + scsiOneValue.Add(string.Format("Medium type code: {0:X2}h", report.SCSI.ReadCapabilities.MediumType)); + if(report.SCSI.ReadCapabilities.DensitySpecified) + scsiOneValue.Add(string.Format("Density code: {0:X2}h", report.SCSI.ReadCapabilities.Density)); + if((report.SCSI.ReadCapabilities.SupportsReadLong || report.SCSI.ReadCapabilities.SupportsReadLong16) && + report.SCSI.ReadCapabilities.LongBlockSizeSpecified) + scsiOneValue.Add(string.Format("Long block size: {0} bytes", report.SCSI.ReadCapabilities.LongBlockSize)); + if(report.SCSI.ReadCapabilities.SupportsReadCapacity) + scsiOneValue.Add("Device supports READ CAPACITY (10) command."); + if(report.SCSI.ReadCapabilities.SupportsReadCapacity16) + scsiOneValue.Add("Device supports READ CAPACITY (16) command."); + if(report.SCSI.ReadCapabilities.SupportsRead) + scsiOneValue.Add("Device supports READ (6) command."); + if(report.SCSI.ReadCapabilities.SupportsRead10) + scsiOneValue.Add("Device supports READ (10) command."); + if(report.SCSI.ReadCapabilities.SupportsRead12) + scsiOneValue.Add("Device supports READ (12) command."); + if(report.SCSI.ReadCapabilities.SupportsRead16) + scsiOneValue.Add("Device supports READ (16) command."); + if(report.SCSI.ReadCapabilities.SupportsReadLong) + scsiOneValue.Add("Device supports READ LONG (10) command."); + if(report.SCSI.ReadCapabilities.SupportsReadLong16) + scsiOneValue.Add("Device supports READ LONG (16) command."); + } + else + testedMedia = report.SCSI.RemovableMedias; + + repScsi.DataSource = scsiOneValue; + repScsi.DataBind(); + } + else + divScsi.Visible = false; + + if(removable && !sscMedia && testedMedia!=null) + { + List mediaOneValue = new List(); + TestedMedia.Report(testedMedia, ata, ref mediaOneValue); + if(mediaOneValue.Count > 0) + { + sscMedia = true; + repTestedMedia.DataSource = mediaOneValue; + repTestedMedia.DataBind(); + } + else + divTestedMedia.Visible = false; + } + else divTestedMedia.Visible &= sscMedia; + } + catch(Exception) + { + content.InnerHtml = "Could not load device report"; +#if DEBUG + throw; +#endif + } + } + + static void GetUsbDescriptions(ushort vendor, ushort product, out string vendorDescription, out string productDescription) + { + vendorDescription = null; + productDescription = null; + + if(!File.Exists(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "usb.ids"))) + return; + + StreamReader tocStream = new StreamReader(Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~"), "usb.ids")); + string _line; + bool inManufacturer = false; + ushort number; + + while(tocStream.Peek() >= 0) + { + _line = tocStream.ReadLine(); + + if(_line.Length == 0 || _line[0] == '#') + continue; + + if(inManufacturer) + { + // Finished with the manufacturer + if(_line[0] != '\t') + return; + + number = Convert.ToUInt16(_line.Substring(1, 4), 16); + + if(number == product) + { + productDescription = _line.Substring(7); + return; + } + } + else + { + // Skip products + if(_line[0] == '\t') + continue; + + number = Convert.ToUInt16(_line.Substring(0, 4), 16); + + if(number == vendor) + { + vendorDescription = _line.Substring(6); + inManufacturer = true; + } + } + } + } } } diff --git a/DiscImageChef.Server/ViewReport.aspx.designer.cs b/DiscImageChef.Server/ViewReport.aspx.designer.cs index d2dba6de2..8a1f98d59 100644 --- a/DiscImageChef.Server/ViewReport.aspx.designer.cs +++ b/DiscImageChef.Server/ViewReport.aspx.designer.cs @@ -1,12 +1,114 @@ -using System; -using System.Web; -using System.Web.UI; +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ -namespace DiscImageChef.Server -{ - - public partial class ViewReport - { - - } +namespace DiscImageChef.Server { + + + public partial class ViewReport { + + protected System.Web.UI.HtmlControls.HtmlGenericControl content; + + protected System.Web.UI.WebControls.Label lblManufacturer; + + protected System.Web.UI.WebControls.Label lblModel; + + protected System.Web.UI.WebControls.Label lblRevision; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divUsb; + + protected System.Web.UI.WebControls.Label lblUsbManufacturer; + + protected System.Web.UI.WebControls.Label lblUsbProduct; + + protected System.Web.UI.WebControls.Label lblUsbVendor; + + protected System.Web.UI.WebControls.Label lblUsbVendorDescription; + + protected System.Web.UI.WebControls.Label lblUsbProductId; + + protected System.Web.UI.WebControls.Label lblUsbProductDescription; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divFirewire; + + protected System.Web.UI.WebControls.Label lblFirewireManufacturer; + + protected System.Web.UI.WebControls.Label lblFirewireProduct; + + protected System.Web.UI.WebControls.Label lblFirewireVendor; + + protected System.Web.UI.WebControls.Label lblFirewireProductId; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divPcmcia; + + protected System.Web.UI.WebControls.Label lblPcmciaManufacturer; + + protected System.Web.UI.WebControls.Label lblPcmciaProduct; + + protected System.Web.UI.WebControls.Label lblPcmciaManufacturerCode; + + protected System.Web.UI.WebControls.Label lblPcmciaCardCode; + + protected System.Web.UI.WebControls.Label lblPcmciaCompliance; + + protected System.Web.UI.WebControls.Repeater repPcmciaTuples; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divAta; + + protected System.Web.UI.WebControls.Label lblAtapi; + + protected System.Web.UI.WebControls.Label lblAtaDeviceType; + + protected System.Web.UI.WebControls.Repeater repAtaTwo; + + protected System.Web.UI.WebControls.Repeater repAtaOne; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divScsi; + + protected System.Web.UI.WebControls.Label lblScsiVendor; + + protected System.Web.UI.WebControls.Label lblScsiProduct; + + protected System.Web.UI.WebControls.Label lblScsiRevision; + + protected System.Web.UI.WebControls.Repeater repScsi; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divScsiModeSense; + + protected System.Web.UI.WebControls.Repeater repModeSense; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divScsiEvpd; + + protected System.Web.UI.WebControls.Repeater repEvpd; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divScsiMmcMode; + + protected System.Web.UI.WebControls.Repeater repScsiMmcMode; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divScsiMmcFeatures; + + protected System.Web.UI.WebControls.Repeater repScsiMmcFeatures; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divScsiSsc; + + protected System.Web.UI.WebControls.Label lblScsiSscGranularity; + + protected System.Web.UI.WebControls.Label lblScsiSscMaxBlock; + + protected System.Web.UI.WebControls.Label lblScsiSscMinBlock; + + protected System.Web.UI.WebControls.Repeater repScsiSscDensities; + + protected System.Web.UI.WebControls.Repeater repScsiSscMedias; + + protected System.Web.UI.HtmlControls.HtmlGenericControl divTestedMedia; + + protected System.Web.UI.WebControls.Repeater repTestedMedia; + } } diff --git a/DiscImageChef.Server/Web.config b/DiscImageChef.Server/Web.config index b20f60a15..1a421eec2 100644 --- a/DiscImageChef.Server/Web.config +++ b/DiscImageChef.Server/Web.config @@ -8,7 +8,7 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx --> - + diff --git a/DiscImageChef.Server/dos.css b/DiscImageChef.Server/dos.css index 46800d16a..8415a6aaa 100644 --- a/DiscImageChef.Server/dos.css +++ b/DiscImageChef.Server/dos.css @@ -1,2 +1,117 @@ -body { +@font-face { + font-family: 'VGAsquarePx'; + src: url(int10h.org/vga_squarepx.eot); + src: url(int10h.org/vga_squarepx.eot?#iefix) format('embedded-opentype'), + url(int10h.org/vga_squarepx.woff2) format('woff2'), + url(int10h.org/vga_squarepx.woff) format('woff'), + url(int10h.org/vga_squarepx.ttf) format('truetype'); + font-weight: normal; + font-style: normal; } +/* define a black "stipple" background with DOS font */ +body { + background: + radial-gradient(black 15%, transparent 16%) 0 0, + radial-gradient(black 15%, transparent 16%) 8px 8px, + radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px, + radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px; + background-color:#282828; + background-size:16px 16px; + color: #aaa; + font-family: 'VGAsquarePx', serif; + font-size: 20pt; + margin: 0; +} +/* links are cyan, hover is bright yellow */ +a { + color: #0aa; + text-decoration: none; +} +a:hover { + color: #ff5; +} +/* headings and bold text are bright white */ +h1,h2,h3,h4, +b, strong { + color: #fff; + font-size: 1em; + font-style: normal; + font-weight: normal; + margin: 0; +} +/* italic text is green */ +em, i { + color: #0a0; + font-style: normal; +} +/* define content areas */ +header, main, footer { + margin: 0 auto; + padding: 1em 0; + max-width: 800px; +} +/* use black on cyan text for header */ +header { + background-color: #0aa; + color: #000; +} + /* insert the "April 1st" text */ + header > h1::before { + content: "Today is April 1, 2017!"; + } + header > h1 img { + display: block; + width: 300px; + } + header > form { + } + header > form fieldset { + border: none; + } + /* use black on gray for navigation */ + nav { + background-color: #aaa; + color: #000; + } + nav a { + color: #000; + } + nav img { + display: none; + } + nav span { + } + nav > ul { + list-style-type: none; + margin: 0; + padding: 0; + text-align: center; + } + nav > ul li { + display: inline; + margin: 0 .5em; + } +/* use white on blue for main text */ +main { + background-color: #00a; + color: #aaa; +} + main > nav { + } + main > nav li::before { + content: ">"; + } + main > section { + } + main div.third img { + display: block; + } +/* use black on brown text for footer */ +footer { + background-color: #a50; + color: #000; +} + footer > nav { + } + footer > section { + } \ No newline at end of file diff --git a/DiscImageChef.Server/packages.config b/DiscImageChef.Server/packages.config index 80fca9aab..2ed426a8b 100644 --- a/DiscImageChef.Server/packages.config +++ b/DiscImageChef.Server/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/DiscImageChef.sln b/DiscImageChef.sln index 8660c74c4..4904702dc 100644 --- a/DiscImageChef.sln +++ b/DiscImageChef.sln @@ -33,6 +33,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscImageChef.Filters", "Di EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscImageChef.Core", "DiscImageChef.Core\DiscImageChef.Core.csproj", "{679659B8-25D0-4279-B632-56EF8F94ADC0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscImageChef.Server", "DiscImageChef.Server\DiscImageChef.Server.csproj", "{75342D7A-C5EA-4A6F-A511-850B54310E5B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -103,39 +105,23 @@ Global {679659B8-25D0-4279-B632-56EF8F94ADC0}.Debug|x86.Build.0 = Debug|Any CPU {679659B8-25D0-4279-B632-56EF8F94ADC0}.Release|x86.ActiveCfg = Release|Any CPU {679659B8-25D0-4279-B632-56EF8F94ADC0}.Release|x86.Build.0 = Release|Any CPU + {75342D7A-C5EA-4A6F-A511-850B54310E5B}.Debug|x86.ActiveCfg = Debug|Any CPU + {75342D7A-C5EA-4A6F-A511-850B54310E5B}.Debug|x86.Build.0 = Debug|Any CPU + {75342D7A-C5EA-4A6F-A511-850B54310E5B}.Release|x86.ActiveCfg = Release|Any CPU + {75342D7A-C5EA-4A6F-A511-850B54310E5B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 $0.StandardHeader = $1 $1.Text = @/***************************************************************************\nThe Disc Image Chef\n----------------------------------------------------------------------------\n \nFilename : ${FileName}\nVersion : 1.0\nAuthor(s) : ${AuthorName}\n \nComponent : Component\n\nRevision : $Revision$\nLast change by : $Author$\nDate : $Date$\n \n--[ Description ] ----------------------------------------------------------\n \nDescription\n \n--[ License ] --------------------------------------------------------------\n \n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with this program. If not, see .\n\n----------------------------------------------------------------------------\nCopyright (C) 2011-2015 Claunia.com\n****************************************************************************/\n//$Id$ - $1.IncludeInNewFiles = True $0.TextStylePolicy = $2 $2.scope = text/x-csharp - $2.FileWidth = 120 - $2.inheritsSet = VisualStudio - $2.inheritsScope = text/plain + $2.TabsToSpaces = True $0.CSharpFormattingPolicy = $3 $3.scope = text/x-csharp $3.IndentBraces = True $3.IndentBlock = False $3.IndentSwitchCaseSection = False - $3.SpaceAfterControlFlowStatementKeyword = False - $3.IndentSwitchSection = True - $3.NewLinesForBracesInProperties = True - $3.NewLinesForBracesInAccessors = True - $3.NewLinesForBracesInAnonymousMethods = True - $3.NewLinesForBracesInControlBlocks = True - $3.NewLinesForBracesInAnonymousTypes = True - $3.NewLinesForBracesInObjectCollectionArrayInitializers = True - $3.NewLinesForBracesInLambdaExpressionBody = True - $3.NewLineForElse = True - $3.NewLineForCatch = True - $3.NewLineForFinally = True - $3.SpacingAfterMethodDeclarationName = False - $3.SpaceAfterMethodCallName = False - $3.SpaceBeforeOpenSquareBracket = False - $3.inheritsSet = Mono - $3.inheritsScope = text/x-csharp $0.DotNetNamingPolicy = $4 $4.DirectoryNamespaceAssociation = Hierarchical $4.ResourceNamePolicy = MSBuild @@ -279,7 +265,6 @@ Global $31.LastFilePostfix = "@:\n " $31.IncludeDirectoryPaths = True $31.LineAlign = 0 - $30.inheritsSet = Mono description = The Disc Image Chef. version = 3.3.99.0 EndGlobalSection