From bb69a1b8d927a96c24ef449ba7cc9de1a6893361 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 31 Jan 2016 08:05:56 +0000 Subject: [PATCH] * DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs: * DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj: Added method to calculate MediaType from SCSI parameters (mode, density, medium type, device type, etc). * DiscImageChef.Metadata/DeviceReport.cs: Added command to guess drive and media parameters and output an XML report of them. * DiscImageChef/Commands/DeviceReport.cs: * DiscImageChef.Metadata/DiscImageChef.Metadata.csproj: Added command to guess drive and media parameters and output an XML report of them. * DiscImageChef/Commands/DumpMedia.cs: Added preliminary command to dump media. Only SCSI for now. CDs and tapes are not supported. Errors are blalanty ignored. Options are incomplete. Not yet usable. * DiscImageChef/Core/Checksum.cs: * DiscImageChef/Commands/CreateSidecar.cs: Moved checksum generation to a separate class. * CICMMetadata: Added support for ADIP. * DiscImageChef.CommonTypes/MediaType.cs: Added parameters of UDO media. Moved DataPlay outside of Iomega, as it's not from that manufacturer. Added missing Exatape media and corrected 160m XL one. Added SyJet media. Added all ECMA defined magneto-optical (sectors calculated from specifications, unchecked). Added PD media. Added Imation 320Gb RDX. Added generic USB flash drives. * DiscImageChef.Decoders/SCSI/Enums.cs: Make enumerations public. * DiscImageChef.Decoders/SCSI/Inquiry.cs: * DiscImageChef.Devices/Device/Constructor.cs: Trim space padded strings on SCSI INQUIRY. * DiscImageChef.Devices/Device/ScsiCommands/MMC.cs: Added PREVENT ALLOW MEDIUM REMOVAL. Added START STOP UNIT. * DiscImageChef.Devices/Device/ScsiCommands/NEC.cs: Rename NEC methods. * DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs: Corrected Pioneer transfer length calculation. * DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs: Renamed Plextor methods. * DiscImageChef.Devices/Device/ScsiCommands/SPC.cs: Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with MMC same name but different command. * DiscImageChef.Devices/DiscImageChef.Devices.csproj: Set platform target to x86 (does it really matter?). * DiscImageChef.Devices/Linux/Command.cs: Reduced allocation for readlink() to current kernel MAX_PATH. * DiscImageChef.Devices/Linux/Enums.cs: Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves commands not working on 32-bit environments. * DiscImageChef.DiscImages/ZZZRawImage.cs: Changed ECMA-184 and ECMA-183 enums. * DiscImageChef.Metadata/Dimensions.cs: Added all ECMA defined magneto-opticals. Added PD media. Added 320Gb RDX. Corrected Exatape 160m XL. Added Exatape 22m and 28m. * DiscImageChef.Metadata/MediaType.cs: Added 356mm magneto-optical media. Changed ECMA-184 and ECMA-183 enums. Added USB generic flash drive. * DiscImageChef/Commands/DeviceInfo.cs: Corrected SCSI INQUIRY naming. Corrected SCSI MODE SENSE (6) parameters. Reduced SCSI MODE SENSE timeout, some devices just get stuck with unsupported MODE SENSE commanda and must be left to timeout. Changed FUJITSU vendor string comparison. * DiscImageChef/Commands/MediaInfo.cs: Added method to calculate MediaType from SCSI parameters (mode, density, medium type, device type, etc). Changed some error WriteLine() to debug ones. Too much verbosity. Added DVD media type decoding from PFI. Found a drive that dumps ADIP, enabling it again (not decoded). * DiscImageChef/Commands/MediaScan.cs: Added option to generate ImgBurn compatible log to media-scan command. * DiscImageChef/DiscImageChef.csproj: Moved checksum generation to a separate class. Added command to guess drive and media parameters and output an XML report of them. Added preliminary command to dump media. Only SCSI for now. CDs and tapes are not supported. Errors are blalanty ignored. Options are incomplete. Not yet usable. * DiscImageChef/Main.cs: Added command to guess drive and media parameters and output an XML report of them. Added preliminary command to dump media. Only SCSI for now. CDs and tapes are not supported. Errors are blalanty ignored. Options are incomplete. Not yet usable. * DiscImageChef/Options.cs: Added command to guess drive and media parameters and output an XML report of them. Added preliminary command to dump media. Only SCSI for now. CDs and tapes are not supported. Errors are blalanty ignored. Options are incomplete. Not yet usable. Added option to generate ImgBurn compatible log to media-scan command. --- CICMMetadata | 2 +- .../DiscImageChef.CommonTypes.csproj | 1 + DiscImageChef.CommonTypes/MediaType.cs | 92 +- .../MediaTypeFromSCSI.cs | 1621 ++++++++ DiscImageChef.Decoders/SCSI/Enums.cs | 12 +- DiscImageChef.Decoders/SCSI/Inquiry.cs | 6 +- DiscImageChef.Devices/Device/Constructor.cs | 12 +- .../Device/ScsiCommands/MMC.cs | 84 + .../Device/ScsiCommands/NEC.cs | 2 +- .../Device/ScsiCommands/Pioneer.cs | 3 +- .../Device/ScsiCommands/Plextor.cs | 2 +- .../Device/ScsiCommands/SPC.cs | 16 +- .../DiscImageChef.Devices.csproj | 1 + DiscImageChef.Devices/Linux/Command.cs | 6 +- DiscImageChef.Devices/Linux/Enums.cs | 2 +- DiscImageChef.DiscImages/ZZZRawImage.cs | 4 +- DiscImageChef.Metadata/DeviceReport.cs | 958 +++++ DiscImageChef.Metadata/Dimensions.cs | 75 +- .../DiscImageChef.Metadata.csproj | 5 + DiscImageChef.Metadata/MediaType.cs | 13 +- DiscImageChef/Commands/CreateSidecar.cs | 831 +--- DiscImageChef/Commands/DeviceInfo.cs | 14 +- DiscImageChef/Commands/DeviceReport.cs | 3451 +++++++++++++++++ DiscImageChef/Commands/DumpMedia.cs | 2064 ++++++++++ DiscImageChef/Commands/MediaInfo.cs | 231 +- DiscImageChef/Commands/MediaScan.cs | 291 +- DiscImageChef/Core/Checksum.cs | 558 +++ DiscImageChef/DiscImageChef.csproj | 4 + DiscImageChef/Main.cs | 16 + DiscImageChef/Options.cs | 43 + 30 files changed, 9476 insertions(+), 944 deletions(-) create mode 100644 DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs create mode 100644 DiscImageChef.Metadata/DeviceReport.cs create mode 100644 DiscImageChef/Commands/DeviceReport.cs create mode 100644 DiscImageChef/Commands/DumpMedia.cs create mode 100644 DiscImageChef/Core/Checksum.cs diff --git a/CICMMetadata b/CICMMetadata index 6e069672..ab5967fc 160000 --- a/CICMMetadata +++ b/CICMMetadata @@ -1 +1 @@ -Subproject commit 6e069672873883a22e45bcca15ea2a2c792d31e7 +Subproject commit ab5967fcfff5c05ce34c66a5a530ce394aac6276 diff --git a/DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj b/DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj index 19f4a6ab..0aa63206 100644 --- a/DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj +++ b/DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj @@ -36,6 +36,7 @@ + \ No newline at end of file diff --git a/DiscImageChef.CommonTypes/MediaType.cs b/DiscImageChef.CommonTypes/MediaType.cs index 723645a1..217d2634 100644 --- a/DiscImageChef.CommonTypes/MediaType.cs +++ b/DiscImageChef.CommonTypes/MediaType.cs @@ -184,9 +184,12 @@ namespace DiscImageChef.CommonTypes #endregion MiniDisc based #region Plasmon UDO - /// Ultra Density Optical + /// 5.25", Phase-Change, 1834348 sectors, 8192 bytes/sector, Ultra Density Optical, ECMA-350, ISO 17345 UDO, + /// 5.25", Phase-Change, 3669724 sectors, 8192 bytes/sector, Ultra Density Optical 2, ECMA-380, ISO 11976 UDO2, + /// 5.25", Write-Once, 3668759 sectors, 8192 bytes/sector, Ultra Density Optical 2, ECMA-380, ISO 11976 + UDO2_WORM, #endregion Plasmon UDO #region Sony game media @@ -399,18 +402,6 @@ namespace DiscImageChef.CommonTypes ECMA_78, /// 5,25", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, FM ECMA_78_2, - /// 3,5", M.O., 250000 sectors, 512 bytes/sector - ECMA_154, - /// 5,25", M.O., 940470 sectors, 512 bytes/sector - ECMA_183_512, - /// 5,25", M.O., 520902 sectors, 1024 bytes/sector - ECMA_183_1024, - /// 5,25", M.O., 1165600 sectors, 512 bytes/sector - ECMA_184_512, - /// 5,25", M.O., 639200 sectors, 1024 bytes/sector - ECMA_184_1024, - /// 3,5", M.O., 448500 sectors, 512 bytes/sector - ECMA_201, #endregion ECMA floppy standards #region FDFORMAT, non-standard floppy formats @@ -449,7 +440,6 @@ namespace DiscImageChef.CommonTypes #region Iomega Bernoulli, Bernoulli2, - DataPlay, Ditto, DittoMax, Jaz, @@ -501,7 +491,9 @@ namespace DiscImageChef.CommonTypes #region Exatape Exatape15m, + Exatape22m, Exatape22mAME, + Exatape28m, Exatape40m, Exatape45m, Exatape54m, @@ -509,7 +501,7 @@ namespace DiscImageChef.CommonTypes Exatape76m, Exatape80m, Exatape106m, - Exatape106mXL, + Exatape160mXL, Exatape112m, Exatape125m, Exatape150m, @@ -540,6 +532,7 @@ namespace DiscImageChef.CommonTypes SQ800, SQ1500, SQ2000, + SyJet, #endregion SyQuest #region Nintendo @@ -679,9 +672,64 @@ namespace DiscImageChef.CommonTypes VXA3, #endregion VXA + #region Magneto-optical + /// 5,25", M.O., ??? sectors, 1024 bytes/sector, ECMA-153, ISO 11560 + ECMA_153, + /// 5,25", M.O., ??? sectors, 512 bytes/sector, ECMA-153, ISO 11560 + ECMA_153_512, + /// 3,5", M.O., 249850 sectors, 512 bytes/sector, ECMA-154, ISO 10090 + ECMA_154, + /// 5,25", M.O., 904995 sectors, 512 bytes/sector, ECMA-183, ISO 13481 + ECMA_183_512, + /// 5,25", M.O., 498526 sectors, 1024 bytes/sector, ECMA-183, ISO 13481 + ECMA_183, + /// 5,25", M.O., 1128772 or 1163337 sectors, 512 bytes/sector, ECMA-183, ISO 13549 + ECMA_184_512, + /// 5,25", M.O., 603466 or 637041 sectors, 1024 bytes/sector, ECMA-183, ISO 13549 + ECMA_184, + /// 300mm, M.O., ??? sectors, 1024 bytes/sector, ECMA-189, ISO 13614 + ECMA_189, + /// 300mm, M.O., ??? sectors, 1024 bytes/sector, ECMA-190, ISO 13403 + ECMA_190, + /// 5,25", M.O., 936921 or 948770 sectors, 1024 bytes/sector, ECMA-195, ISO 13842 + ECMA_195, + /// 5,25", M.O., 1644581 or 1647371 sectors, 512 bytes/sector, ECMA-195, ISO 13842 + ECMA_195_512, + /// 3,5", M.O., 446325 sectors, 512 bytes/sector, ECMA-201, ISO 13963 + ECMA_201, + /// 3,5", M.O., 429975 sectors, 512 bytes/sector, embossed, ISO 13963 + ECMA_201_ROM, + /// 3,5", M.O., 371371 sectors, 1024 bytes/sector, ECMA-223 + ECMA_223, + /// 3,5", M.O., 694929 sectors, 512 bytes/sector, ECMA-223 + ECMA_223_512, + /// 5,25", M.O., 1244621 sectors, 1024 bytes/sector, ECMA-238, ISO 15486 + ECMA_238, + /// 3,5", M.O., 318988, 320332 or 321100 sectors, 2048 bytes/sector, ECMA-239, ISO 15498 + ECMA_239, + /// 356mm, M.O., 14476734 sectors, 1024 bytes/sector, ECMA-260, ISO 15898 + ECMA_260, + /// 356mm, M.O., 24445990 sectors, 1024 bytes/sector, ECMA-260, ISO 15898 + ECMA_260_Double, + /// 5,25", M.O., 1128134 sectors, 2048 bytes/sector, ECMA-280, ISO 18093 + ECMA_280, + /// 300mm, M.O., 7355716 sectors, 2048 bytes/sector, ECMA-317, ISO 20162 + ECMA_317, + /// 5,25", M.O., 1095840 sectors, 4096 bytes/sector, ECMA-322, ISO 22092 + ECMA_322, + /// 5,25", M.O., 2043664 sectors, 2048 bytes/sector, ECMA-322, ISO 22092 + ECMA_322_2k, + /// 3,5", M.O., 605846 sectors, 2048 bytes/sector, Cherry Book, GigaMo, ECMA-351, ISO 17346 + GigaMo, + /// 3,5", M.O., 1063146 sectors, 2048 bytes/sector, Cherry Book 2, GigaMo 2, ECMA-353, ISO 22533 + GigaMo2, + UnknownMO, + #endregion Magneto-optical + #region Other floppy standards CompactFloppy, DemiDiskette, + /// 3.5", 652 tracks, 2 sides, 512 bytes/sector, Floptical, ECMA-207, ISO 14169 Floptical, HiFD, LS120, @@ -713,13 +761,23 @@ namespace DiscImageChef.CommonTypes SmartMedia, xD, XQD, + DataPlay, + /// 120mm, Phase-Change, 1298496 sectors, 512 bytes/sector, PD650, ECMA-240, ISO 15485 + PD650, + /// 120mm, Write-Once, 1281856 sectors, 512 bytes/sector, PD650, ECMA-240, ISO 15485 + PD650_WORM, #endregion Miscellaneous #region Generic hard disks Microdrive, RDX, - GENERIC_HDD + /// Imation 320Gb RDX + RDX320, + GENERIC_HDD, + Zone_HDD, + // USB flash drives + FlashDrive #endregion Generic hard disks }; } - + \ No newline at end of file diff --git a/DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs b/DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs new file mode 100644 index 00000000..5687a49a --- /dev/null +++ b/DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs @@ -0,0 +1,1621 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : MediaTypeFromSCSI.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ + +namespace DiscImageChef.CommonTypes +{ + public static class MediaTypeFromSCSI + { + public static MediaType Get(byte scsiPeripheralType, string vendor, string model, byte mediumType, byte densityCode, ulong blocks, uint blockSize) + { + switch (scsiPeripheralType) + { + // Direct access device + case 0x00: + // Simpilified access device + case 0x0E: + { + if (mediumType == 0x03 || mediumType == 0x05 || mediumType == 0x07) + { + goto case 0x07; + } + + if (vendor.ToLowerInvariant() == "syquest") + { + if (blocks == 173400 && blockSize == 256) + return MediaType.SQ400; + if (blockSize == 512) + { + if (model.ToLowerInvariant().StartsWith("syjet")) + return MediaType.SyJet; + + switch (blocks) + { + case 262144: + return MediaType.EZ135; + case 524288: + return MediaType.SQ327; + } + } + + return MediaType.Unknown; + } + + if (model.ToLowerInvariant().StartsWith("zip")) + { + if (blockSize == 512) + { + if (blocks == 196608) + return MediaType.ZIP100; + if (blocks == 489532) + return MediaType.ZIP250; + return MediaType.ZIP750; + } + + return MediaType.Unknown; + } + + if (model.ToLowerInvariant().StartsWith("jaz")) + { + if (blockSize == 512) + { + if (blocks == 2091050) + return MediaType.Jaz; + if (blocks == 3915600) + return MediaType.Jaz2; + } + + return MediaType.Unknown; + } + + if (model.ToLowerInvariant().StartsWith("ls-")) + { + if (blockSize == 512) + { + if (blocks == 246528) + return MediaType.LS120; + if (blocks == 2880) + return MediaType.DOS_35_HD; + if (blocks == 1440) + return MediaType.DOS_35_DS_DD_9; + } + + return MediaType.Unknown; + } + + if (model.ToLowerInvariant().StartsWith("rdx")) + { + if (blockSize == 512) + { + if (blocks == 625134256) + return MediaType.RDX320; + return MediaType.RDX; + } + + return MediaType.Unknown; + } + + switch (mediumType) + { + case 0x01: + switch (blockSize) + { + case 128: + switch (blocks) + { + case 720: + return MediaType.ATARI_525_SD; + case 1040: + return MediaType.ATARI_525_DD; + case 1898: + return MediaType.IBM33FD_128; + case 2002: + return MediaType.ECMA_54; + } + break; + case 256: + switch (blocks) + { + case 322: + return MediaType.ECMA_66; + case 400: + return MediaType.ACORN_525_SS_SD_40; + case 455: + return MediaType.Apple32SS; + case 560: + return MediaType.Apple33SS; + case 640: + return MediaType.ACORN_525_SS_DD_40; + case 720: + return MediaType.ATARI_525_DD; + case 800: + return MediaType.ACORN_525_SS_SD_80; + case 1121: + return MediaType.IBM33FD_256; + case 1280: + return MediaType.ACORN_525_SS_DD_80; + case 2002: + return MediaType.RX02; + } + break; + case 319: + switch (blocks) + { + case 256: + return MediaType.IBM23FD; + } + break; + case 512: + switch (blocks) + { + case 320: + return MediaType.DOS_525_DS_DD_8; + case 360: + return MediaType.DOS_35_SS_DD_9; + case 610: + return MediaType.IBM33FD_512; + case 640: + return MediaType.DOS_35_SS_DD_8; + case 720: + return MediaType.DOS_35_DS_DD_9; + case 800: + return MediaType.AppleSonySS; + case 249850: + return MediaType.ECMA_154; + case 429975: + return MediaType.ECMA_201_ROM; + case 446325: + return MediaType.ECMA_201; + case 694929: + return MediaType.ECMA_223_512; + case 904995: + return MediaType.ECMA_183_512; + case 1128772: + case 1163337: + return MediaType.ECMA_184_512; + case 1281856: + return MediaType.PD650_WORM; + case 1298496: + return MediaType.PD650; + case 1644581: + case 1647371: + return MediaType.ECMA_195_512; + } + break; + case 1024: + { + switch (blocks) + { + case 371371: + return MediaType.ECMA_223; + case 498526: + return MediaType.ECMA_183; + case 603466: + case 637041: + return MediaType.ECMA_184; + case 936921: + case 948770: + return MediaType.ECMA_195; + case 1244621: + return MediaType.ECMA_238; + case 14476734: + return MediaType.ECMA_260; + case 24445990: + return MediaType.ECMA_260_Double; + } + } + break; + case 2048: + { + switch (blocks) + { + case 318988: + case 320332: + case 321100: + return MediaType.ECMA_239; + case 605846: + return MediaType.GigaMo; + case 1063146: + return MediaType.GigaMo2; + case 1128134: + return MediaType.ECMA_280; + case 2043664: + return MediaType.ECMA_322_2k; + case 7355716: + return MediaType.ECMA_317; + } + } + break; + case 4096: + { + switch (blocks) + { + case 1095840: + return MediaType.ECMA_322; + } + } + break; + case 8192: + { + switch (blocks) + { + case 1834348: + return MediaType.UDO; + case 3668759: + return MediaType.UDO2_WORM; + case 3669724: + return MediaType.UDO2; + } + } + break; + } + return MediaType.Unknown; + case 0x02: + switch (blockSize) + { + case 128: + switch (blocks) + { + case 3848: + return MediaType.IBM43FD_128; + case 4004: + return MediaType.ECMA_59; + } + break; + case 256: + switch (blocks) + { + case 910: + return MediaType.Apple32DS; + case 1120: + return MediaType.Apple33DS; + case 1280: + return MediaType.ECMA_70; + case 2560: + return MediaType.ECMA_78; + case 3848: + return MediaType.IBM53FD_256; + case 4004: + return MediaType.ECMA_99_26; + } + break; + case 512: + switch (blocks) + { + case 640: + return MediaType.DOS_525_DS_DD_8; + case 720: + return MediaType.DOS_525_DS_DD_9; + case 1280: + return MediaType.DOS_35_DS_DD_8; + case 1440: + return MediaType.ECMA_100; + case 1600: + return MediaType.ACORN_35_DS_DD; + case 1640: + return MediaType.FDFORMAT_35_DD; + case 1760: + return MediaType.CBM_AMIGA_35_DD; + case 2242: + return MediaType.IBM53FD_512; + case 2332: + return MediaType.ECMA_99_15; + case 2400: + return MediaType.DOS_525_HD; + case 2788: + return MediaType.FDFORMAT_525_HD; + case 2880: + return MediaType.ECMA_125; + case 3360: + return MediaType.DMF; + case 3444: + return MediaType.FDFORMAT_35_HD; + case 3520: + return MediaType.CBM_AMIGA_35_HD; + case 5760: + return MediaType.ECMA_147; + case 249850: + return MediaType.ECMA_154; + case 429975: + return MediaType.ECMA_201_ROM; + case 446325: + return MediaType.ECMA_201; + case 694929: + return MediaType.ECMA_223_512; + case 904995: + return MediaType.ECMA_183_512; + case 1128772: + case 1163337: + return MediaType.ECMA_184_512; + case 1281856: + return MediaType.PD650_WORM; + case 1298496: + return MediaType.PD650; + case 1644581: + case 1647371: + return MediaType.ECMA_195_512; + } + break; + case 1024: + switch (blocks) + { + case 1220: + return MediaType.IBM53FD_1024; + case 1232: + return MediaType.SHARP_35; + case 1268: + return MediaType.ECMA_69_8; + case 1280: + return MediaType.NEC_525_HD; + case 1316: + return MediaType.ECMA_99_8; + case 371371: + return MediaType.ECMA_223; + case 498526: + return MediaType.ECMA_183; + case 603466: + case 637041: + return MediaType.ECMA_184; + case 936921: + case 948770: + return MediaType.ECMA_195; + case 1244621: + return MediaType.ECMA_238; + case 14476734: + return MediaType.ECMA_260; + case 24445990: + return MediaType.ECMA_260_Double; + } + break; + case 2048: + { + switch (blocks) + { + case 318988: + case 320332: + case 321100: + return MediaType.ECMA_239; + case 605846: + return MediaType.GigaMo; + case 1063146: + return MediaType.GigaMo2; + case 1128134: + return MediaType.ECMA_280; + case 2043664: + return MediaType.ECMA_322_2k; + case 7355716: + return MediaType.ECMA_317; + } + } + break; + case 4096: + { + switch (blocks) + { + case 1095840: + return MediaType.ECMA_322; + } + } + break; + case 8192: + { + switch (blocks) + { + case 1834348: + return MediaType.UDO; + case 3668759: + return MediaType.UDO2_WORM; + case 3669724: + return MediaType.UDO2; + } + } + break; + } + return MediaType.Unknown; + case 0x09: + return MediaType.ECMA_54; + case 0x0A: + return MediaType.ECMA_59; + case 0x0B: + switch (blockSize) + { + case 256: + return MediaType.ECMA_69_26; + case 512: + return MediaType.ECMA_69_15; + case 1024: + return MediaType.ECMA_69_8; + } + return MediaType.Unknown; + case 0x0E: + return MediaType.ECMA_66; + case 0x12: + return MediaType.ECMA_70; + case 0x16: + switch (blockSize) + { + case 256: + return MediaType.ECMA_78; + case 512: + return MediaType.ECMA_78_2; + } + return MediaType.Unknown; + case 0x1A: + switch (blockSize) + { + case 256: + return MediaType.ECMA_99_26; + case 512: + return MediaType.ECMA_99_15; + case 1024: + return MediaType.ECMA_99_8; + } + return MediaType.Unknown; + case 0x1E: + return MediaType.ECMA_100; + case 0x93: + return MediaType.NEC_35_HD_15; + case 0x94: + return MediaType.ECMA_125; + } + + switch (blockSize) + { + case 128: + { + switch (blocks) + { + case 720: + return MediaType.ATARI_525_SD; + case 1040: + return MediaType.ATARI_525_ED; + case 1898: + return MediaType.IBM33FD_128; + case 2002: + return MediaType.ECMA_54; + case 3848: + return MediaType.IBM43FD_128; + case 4004: + return MediaType.ECMA_59; + } + } + break; + case 256: + { + switch (blocks) + { + case 322: + return MediaType.ECMA_66; + case 400: + return MediaType.ACORN_525_SS_SD_40; + case 455: + return MediaType.Apple32SS; + case 560: + return MediaType.Apple33SS; + case 640: + return MediaType.ACORN_525_SS_DD_40; + case 720: + return MediaType.ATARI_525_DD; + case 800: + return MediaType.ACORN_525_SS_SD_80; + case 910: + return MediaType.Apple32DS; + case 1120: + return MediaType.Apple33DS; + case 1121: + return MediaType.IBM33FD_256; + case 1280: + return MediaType.ECMA_70; + case 2002: + return MediaType.RX02; + case 2560: + return MediaType.ECMA_78; + case 3848: + return MediaType.IBM53FD_256; + case 4004: + return MediaType.ECMA_99_26; + } + } + break; + case 319: + switch (blocks) + { + case 256: + return MediaType.IBM23FD; + } + break; + case 512: + { + switch (blocks) + { + case 320: + return MediaType.DOS_525_SS_DD_8; + case 360: + return MediaType.DOS_525_SS_DD_9; + case 610: + return MediaType.IBM33FD_512; + case 640: + return MediaType.DOS_525_DS_DD_8; + case 720: + return MediaType.DOS_525_DS_DD_9; + case 800: + return MediaType.AppleSonySS; + case 1280: + return MediaType.DOS_35_DS_DD_8; + case 1440: + return MediaType.ECMA_100; + case 1600: + return MediaType.ACORN_35_DS_DD; + case 1640: + return MediaType.FDFORMAT_35_DD; + case 1760: + return MediaType.CBM_AMIGA_35_DD; + case 2242: + return MediaType.IBM53FD_512; + case 2332: + return MediaType.ECMA_99_15; + case 2400: + return MediaType.DOS_525_HD; + case 2788: + return MediaType.FDFORMAT_525_HD; + case 2880: + return MediaType.ECMA_125; + case 3360: + return MediaType.DMF; + case 3444: + return MediaType.FDFORMAT_35_HD; + case 3520: + return MediaType.CBM_AMIGA_35_HD; + case 5760: + return MediaType.ECMA_147; + } + } + break; + case 1024: + { + switch (blocks) + { + case 1220: + return MediaType.IBM53FD_1024; + case 1232: + return MediaType.SHARP_35; + case 1268: + return MediaType.ECMA_69_8; + case 1280: + return MediaType.NEC_525_HD; + case 1316: + return MediaType.ECMA_99_8; + } + } + break; + } + + return MediaType.Unknown; + } + // Sequential access device + case 0x01: + { + switch (mediumType) + { + case 0x00: + switch (densityCode) + { + case 0x04: + return MediaType.QIC11; + case 0x05: + return MediaType.QIC24; + case 0x09: + return MediaType.IBM3490; + case 0x0F: + return MediaType.QIC120; + case 0x10: + return MediaType.QIC150; + case 0x28: + return MediaType.IBM3490E; + case 0x40: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO; + if (model.ToLowerInvariant().StartsWith("sdz")) + return MediaType.SAIT1; + break; + } + case 0x41: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO2; + break; + } + case 0x42: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO2; + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T9840A; + break; + } + case 0x43: + { + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T9940A; + break; + } + case 0x44: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO3; + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T9940B; + break; + } + case 0x45: + { + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T9840C; + break; + } + case 0x46: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO4; + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T9840D; + break; + } + case 0x4A: + { + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T10000A; + break; + } + case 0x4B: + { + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T10000B; + break; + } + case 0x4C: + { + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T10000C; + break; + } + case 0x4D: + { + if (vendor.ToLowerInvariant() == "stk") + return MediaType.T10000D; + break; + } + case 0x58: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO5; + break; + } + } + break; + case 0x01: + { + switch (densityCode) + { + case 0x44: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO3WORM; + break; + } + case 0x46: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO4WORM; + break; + } + case 0x58: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO5WORM; + break; + } + } + } + break; + case 0x18: + { + switch (densityCode) + { + case 0x00: + case 0x40: + { + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO; + break; + } + } + } + } + break; + case 0x28: + { + switch (densityCode) + { + case 0x00: + case 0x42: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO2; + break; + } + } + } + break; + case 0x33: + { + switch (densityCode) + { + case 0x00: + case 0x25: + { + if (model.ToLowerInvariant().StartsWith("dat")) + return MediaType.DDS3; + break; + } + } + } + break; + case 0x34: + { + switch (densityCode) + { + case 0x00: + case 0x26: + { + if (model.ToLowerInvariant().StartsWith("dat")) + return MediaType.DDS4; + break; + } + } + } + break; + case 0x35: + { + switch (densityCode) + { + case 0x00: + case 0x47: + { + if (model.ToLowerInvariant().StartsWith("dat")) + return MediaType.DAT72; + break; + } + } + } + break; + case 0x38: + { + switch (densityCode) + { + case 0x00: + case 0x44: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO3; + break; + } + } + } + break; + case 0x3C: + { + switch (densityCode) + { + case 0x00: + case 0x44: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO3WORM; + break; + } + } + } + break; + case 0x48: + { + switch (densityCode) + { + case 0x00: + case 0x46: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO4; + break; + } + } + } + break; + case 0x4C: + { + switch (densityCode) + { + case 0x00: + case 0x46: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO4WORM; + break; + } + } + } + break; + case 0x58: + { + switch (densityCode) + { + case 0x00: + case 0x58: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO5; + break; + } + } + } + break; + case 0x5C: + { + switch (densityCode) + { + case 0x00: + case 0x58: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO5WORM; + break; + } + } + } + break; + case 0x68: + { + switch (densityCode) + { + case 0x00: + case 0x5A: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO6; + break; + } + } + } + break; + case 0x6C: + { + switch (densityCode) + { + case 0x00: + case 0x5A: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO6WORM; + break; + } + } + } + break; + case 0x78: + { + switch (densityCode) + { + case 0x00: + case 0x5C: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO7; + break; + } + } + } + break; + case 0x7C: + { + switch (densityCode) + { + case 0x00: + case 0x5C: + { + if (model.ToLowerInvariant().StartsWith("ult")) + return MediaType.LTO7WORM; + break; + } + } + } + break; + case 0x81: + { + switch (densityCode) + { + case 0x00: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape15m; + if (vendor.ToLowerInvariant() == "ibm") + return MediaType.IBM3592; + if (model.ToLowerInvariant().StartsWith("vxa")) + return MediaType.VXA1; + break; + } + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape15m; + break; + } + case 0x29: + case 0x2A: + { + if (vendor.ToLowerInvariant() == "ibm") + return MediaType.IBM3592; + break; + } + case 0x80: + { + if (model.ToLowerInvariant().StartsWith("vxa")) + return MediaType.VXA1; + break; + } + } + } + break; + case 0x82: + { + switch (densityCode) + { + case 0x00: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape28m; + if (vendor.ToLowerInvariant() == "ibm") + return MediaType.IBM3592; + break; + } + case 0x0A: + { + if (model.ToLowerInvariant().StartsWith("dlt")) + return MediaType.CompactTapeI; + break; + } + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape28m; + break; + } + case 0x16: + { + if (model.ToLowerInvariant().StartsWith("dlt")) + return MediaType.CompactTapeII; + break; + } + case 0x29: + case 0x2A: + { + if (vendor.ToLowerInvariant() == "ibm") + return MediaType.IBM3592; + break; + } + case 0x81: + { + if (model.ToLowerInvariant().StartsWith("vxa")) + return MediaType.VXA2; + break; + } + case 0x82: + { + if (model.ToLowerInvariant().StartsWith("vxa")) + return MediaType.VXA3; + break; + } + } + } + break; + case 0x83: + { + switch (densityCode) + { + case 0x00: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape54m; + if (model.ToLowerInvariant().StartsWith("dlt")) + return MediaType.DLTtapeIII; + break; + } + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape54m; + break; + } + case 0x17: + case 0x18: + case 0x19: + case 0x80: + case 0x81: + { + if (model.ToLowerInvariant().StartsWith("dlt")) + return MediaType.DLTtapeIII; + break; + } + } + } + break; + case 0x84: + { + switch (densityCode) + { + case 0x00: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape80m; + if (model.ToLowerInvariant().StartsWith("dlt")) + return MediaType.DLTtapeIIIxt; + break; + } + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape80m; + break; + } + case 0x19: + case 0x80: + case 0x81: + { + if (model.ToLowerInvariant().StartsWith("dlt")) + return MediaType.DLTtapeIIIxt; + break; + } + } + } + break; + case 0x85: + { + switch (densityCode) + { + case 0x00: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape106m; + if (model.ToLowerInvariant().StartsWith("dlt") || + model.ToLowerInvariant().StartsWith("sdlt") || + model.ToLowerInvariant().StartsWith("superdlt")) + return MediaType.DLTtapeIV; + if (model.ToLowerInvariant().StartsWith("stt")) + return MediaType.Travan5; + break; + } + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape106m; + break; + } + case 0x1A: + case 0x1B: + case 0x40: + case 0x41: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + { + if (model.ToLowerInvariant().StartsWith("dlt") || + model.ToLowerInvariant().StartsWith("sdlt") || + model.ToLowerInvariant().StartsWith("superdlt")) + return MediaType.DLTtapeIV; + break; + } + case 0x46: + { + if (model.ToLowerInvariant().StartsWith("stt")) + return MediaType.Travan5; + break; + } + } + } + break; + case 0x86: + { + switch (densityCode) + { + case 0x00: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape160mXL; + if (model.ToLowerInvariant().StartsWith("dlt") || + model.ToLowerInvariant().StartsWith("sdlt") || + model.ToLowerInvariant().StartsWith("superdlt")) + return MediaType.SDLT1; + break; + } + case 0x8C: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape160mXL; + break; + } + case 0x91: + case 0x92: + case 0x93: + { + if (model.ToLowerInvariant().StartsWith("dlt") || + model.ToLowerInvariant().StartsWith("sdlt") || + model.ToLowerInvariant().StartsWith("superdlt")) + return MediaType.SDLT1; + break; + } + } + } + break; + case 0x87: + { + switch (densityCode) + { + case 0x00: + case 0x4A: + { + if (model.ToLowerInvariant().StartsWith("dlt") || + model.ToLowerInvariant().StartsWith("sdlt") || + model.ToLowerInvariant().StartsWith("superdlt")) + return MediaType.SDLT2; + break; + } + } + } + break; + case 0x90: + { + switch (densityCode) + { + case 0x00: + case 0x50: + case 0x98: + case 0x99: + { + if (model.ToLowerInvariant().StartsWith("dlt") || + model.ToLowerInvariant().StartsWith("sdlt") || + model.ToLowerInvariant().StartsWith("superdlt")) + return MediaType.VStapeI; + break; + } + } + } + break; + case 0x95: + { + if (model.ToLowerInvariant().StartsWith("stt")) + return MediaType.Travan7; + } + break; + case 0xC1: + { + switch (densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape22m; + break; + } + } + } + break; + case 0xC2: + { + switch (densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape40m; + break; + } + } + } + break; + case 0xC3: + { + switch (densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape76m; + break; + } + } + } + break; + case 0xC4: + { + switch (densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape112m; + break; + } + } + } + break; + case 0xD1: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape22mAME; + break; + } + } + } + break; + case 0xD2: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape170m; + break; + } + } + } + break; + case 0xD3: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape125m; + break; + } + } + } + break; + case 0xD4: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape45m; + break; + } + } + } + break; + case 0xD5: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape225m; + break; + } + } + } + break; + case 0xD6: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape150m; + break; + } + } + } + break; + case 0xD7: + { + switch (densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if (model.ToLowerInvariant().StartsWith("exb")) + return MediaType.Exatape75m; + break; + } + } + } + break; + } + + return MediaType.Unknown; + } + // Write-once device + case 0x04: + // Optical device + case 0x07: + { + if (mediumType == 0x01 || mediumType == 0x02 || mediumType == 0x03 || mediumType == 0x05 || mediumType == 0x07) + { + switch (blockSize) + { + case 512: + { + switch (blocks) + { + case 249850: + return MediaType.ECMA_154; + case 429975: + return MediaType.ECMA_201_ROM; + case 446325: + return MediaType.ECMA_201; + case 694929: + return MediaType.ECMA_223_512; + case 904995: + return MediaType.ECMA_183_512; + case 1128772: + case 1163337: + return MediaType.ECMA_184_512; + case 1281856: + return MediaType.PD650_WORM; + case 1298496: + return MediaType.PD650; + case 1644581: + case 1647371: + return MediaType.ECMA_195_512; + default: + return MediaType.UnknownMO; + } + } + case 1024: + { + switch (blocks) + { + case 371371: + return MediaType.ECMA_223; + case 498526: + return MediaType.ECMA_183; + case 603466: + case 637041: + return MediaType.ECMA_184; + case 936921: + case 948770: + return MediaType.ECMA_195; + case 1244621: + return MediaType.ECMA_238; + case 14476734: + return MediaType.ECMA_260; + case 24445990: + return MediaType.ECMA_260_Double; + default: + return MediaType.UnknownMO; + } + } + case 2048: + { + switch (blocks) + { + case 318988: + case 320332: + case 321100: + return MediaType.ECMA_239; + case 605846: + return MediaType.GigaMo; + case 1063146: + return MediaType.GigaMo2; + case 1128134: + return MediaType.ECMA_280; + case 2043664: + return MediaType.ECMA_322_2k; + case 7355716: + return MediaType.ECMA_317; + default: + return MediaType.UnknownMO; + } + } + case 4096: + { + switch (blocks) + { + case 1095840: + return MediaType.ECMA_322; + default: + return MediaType.UnknownMO; + } + } + case 8192: + { + switch (blocks) + { + case 1834348: + return MediaType.UDO; + case 3668759: + return MediaType.UDO2_WORM; + case 3669724: + return MediaType.UDO2; + default: + return MediaType.UnknownMO; + } + } + default: + return MediaType.UnknownMO; + } + } + + return MediaType.UnknownMO; + } + // MultiMedia Device + case 0x05: + { + switch (mediumType) + { + case 0x00: + return MediaType.CD; + case 0x01: + case 0x05: + return MediaType.CDROM; + case 0x02: + case 0x06: + return MediaType.CDDA; + case 0x03: + case 0x07: + return MediaType.CDPLUS; + case 0x04: + return MediaType.PCD; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + return MediaType.CDR; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + return MediaType.CDRW; + case 0x80: + if (model.ToLowerInvariant().StartsWith("ult")) + { + switch (densityCode) + { + case 0x42: + return MediaType.LTO2; + case 0x44: + return MediaType.LTO3; + case 0x46: + return MediaType.LTO4; + case 0x58: + return MediaType.LTO5; + } + } + break; + } + } + break; + // Host managed zoned block device + case 0x14: + { + return MediaType.Zone_HDD; + } + } + + return MediaType.Unknown; + } + } +} \ No newline at end of file diff --git a/DiscImageChef.Decoders/SCSI/Enums.cs b/DiscImageChef.Decoders/SCSI/Enums.cs index 0a016f93..bfc3b9e6 100644 --- a/DiscImageChef.Decoders/SCSI/Enums.cs +++ b/DiscImageChef.Decoders/SCSI/Enums.cs @@ -39,7 +39,7 @@ using System; namespace DiscImageChef.Decoders.SCSI { - enum PeripheralQualifiers : byte + public enum PeripheralQualifiers : byte { /// /// Peripheral qualifier: Device is connected and supported @@ -159,7 +159,7 @@ namespace DiscImageChef.Decoders.SCSI UnknownDevice = 0x1F } - enum ANSIVersions : byte + public enum ANSIVersions : byte { /// /// Device does not claim conformance to any ANSI version @@ -191,7 +191,7 @@ namespace DiscImageChef.Decoders.SCSI ANSI2008Version = 0x06 } - enum ECMAVersions : byte + public enum ECMAVersions : byte { /// /// Device does not claim conformance to any ECMA version @@ -203,7 +203,7 @@ namespace DiscImageChef.Decoders.SCSI ECMA111 = 0x01 } - enum ISOVersions : byte + public enum ISOVersions : byte { /// /// Device does not claim conformance to any ISO/IEC version @@ -215,7 +215,7 @@ namespace DiscImageChef.Decoders.SCSI ISO1995Version = 0x02 } - enum SPIClocking : byte + public enum SPIClocking : byte { /// /// Supports only ST @@ -235,7 +235,7 @@ namespace DiscImageChef.Decoders.SCSI STandDT = 0x03, } - enum TGPSValues : byte + public enum TGPSValues : byte { /// /// Assymetrical access not supported diff --git a/DiscImageChef.Decoders/SCSI/Inquiry.cs b/DiscImageChef.Decoders/SCSI/Inquiry.cs index 258783cf..baf0ec4a 100644 --- a/DiscImageChef.Decoders/SCSI/Inquiry.cs +++ b/DiscImageChef.Decoders/SCSI/Inquiry.cs @@ -204,9 +204,9 @@ namespace DiscImageChef.Decoders.SCSI StringBuilder sb = new StringBuilder(); - sb.AppendFormat("Device vendor: {0}", VendorString.Prettify(StringHandlers.SpacePaddedToString(response.VendorIdentification))).AppendLine(); - sb.AppendFormat("Device name: {0}", StringHandlers.SpacePaddedToString(response.ProductIdentification)).AppendLine(); - sb.AppendFormat("Device release level: {0}", StringHandlers.SpacePaddedToString(response.ProductRevisionLevel)).AppendLine(); + sb.AppendFormat("Device vendor: {0}", VendorString.Prettify(StringHandlers.CToString(response.VendorIdentification).Trim())).AppendLine(); + sb.AppendFormat("Device name: {0}", StringHandlers.CToString(response.ProductIdentification).Trim()).AppendLine(); + sb.AppendFormat("Device release level: {0}", StringHandlers.CToString(response.ProductRevisionLevel).Trim()).AppendLine(); switch ((PeripheralQualifiers)response.PeripheralQualifier) { case PeripheralQualifiers.Supported: diff --git a/DiscImageChef.Devices/Device/Constructor.cs b/DiscImageChef.Devices/Device/Constructor.cs index e04cb536..1318c6dd 100644 --- a/DiscImageChef.Devices/Device/Constructor.cs +++ b/DiscImageChef.Devices/Device/Constructor.cs @@ -91,6 +91,9 @@ namespace DiscImageChef.Devices throw new InvalidOperationException(String.Format("Platform {0} not yet supported.", platformID)); } + if (error) + throw new SystemException(String.Format("Error {0} opening device.", lastError)); + type = DeviceType.Unknown; scsiType = Decoders.SCSI.PeripheralDeviceTypes.UnknownDevice; @@ -102,6 +105,9 @@ namespace DiscImageChef.Devices bool scsiSense = ScsiInquiry(out inqBuf, out senseBuf); + if (error) + throw new SystemException(String.Format("Error {0} trying device.", lastError)); + #region USB if(platformID == DiscImageChef.Interop.PlatformID.Linux) { @@ -251,9 +257,9 @@ namespace DiscImageChef.Devices if (Inquiry.HasValue) { - revision = StringHandlers.SpacePaddedToString(Inquiry.Value.ProductRevisionLevel); - model = StringHandlers.SpacePaddedToString(Inquiry.Value.ProductIdentification); - manufacturer = StringHandlers.SpacePaddedToString(Inquiry.Value.VendorIdentification); + revision = StringHandlers.CToString(Inquiry.Value.ProductRevisionLevel).Trim(); + model = StringHandlers.CToString(Inquiry.Value.ProductIdentification).Trim(); + manufacturer = StringHandlers.CToString(Inquiry.Value.VendorIdentification).Trim(); removable = Inquiry.Value.RMB; scsiType = (Decoders.SCSI.PeripheralDeviceTypes)Inquiry.Value.PeripheralDeviceType; diff --git a/DiscImageChef.Devices/Device/ScsiCommands/MMC.cs b/DiscImageChef.Devices/Device/ScsiCommands/MMC.cs index c65704c3..2df39d65 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands/MMC.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands/MMC.cs @@ -492,6 +492,90 @@ namespace DiscImageChef.Devices return sense; } + + public bool PreventMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration) + { + return PreventAllowMediumRemoval(out senseBuffer, false, true, timeout, out duration); + } + + public bool AllowMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration) + { + return PreventAllowMediumRemoval(out senseBuffer, false, false, timeout, out duration); + } + + public bool PreventAllowMediumRemoval(out byte[] senseBuffer, bool persistent, bool prevent, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[6]; + byte[] buffer = new byte[0]; + bool sense; + + cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval; + if (prevent) + cdb[4] += 0x01; + if (persistent) + cdb[4] += 0x02; + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "PREVENT ALLOW MEDIUM REMOVAL took {0} ms.", duration); + + return sense; + } + + public bool LoadTray(out byte[] senseBuffer, uint timeout, out double duration) + { + return StartStopUnit(out senseBuffer, false, 0, 0, false, true, true, timeout, out duration); + } + + public bool EjectTray(out byte[] senseBuffer, uint timeout, out double duration) + { + return StartStopUnit(out senseBuffer, false, 0, 0, false, true, false, timeout, out duration); + } + + public bool StartUnit(out byte[] senseBuffer, uint timeout, out double duration) + { + return StartStopUnit(out senseBuffer, false, 0, 0, false, false, true, timeout, out duration); + } + + public bool StopUnit(out byte[] senseBuffer, uint timeout, out double duration) + { + return StartStopUnit(out senseBuffer, false, 0, 0, false, false, false, timeout, out duration); + } + + public bool StartStopUnit(out byte[] senseBuffer, bool immediate, byte formatLayer, byte powerConditions, bool changeFormatLayer, bool loadEject, bool start, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[6]; + byte[] buffer = new byte[0]; + bool sense; + + cdb[0] = (byte)ScsiCommands.StartStopUnit; + if (immediate) + cdb[1] += 0x01; + if (changeFormatLayer) + { + cdb[3] = (byte)(formatLayer & 0x03); + cdb[4] += 0x04; + } + else + { + if(loadEject) + cdb[4] += 0x02; + if(start) + cdb[4] += 0x01; + } + cdb[4] += (byte)((powerConditions & 0x0F) << 4); + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "START STOP UNIT took {0} ms.", duration); + + return sense; + } + } } diff --git a/DiscImageChef.Devices/Device/ScsiCommands/NEC.cs b/DiscImageChef.Devices/Device/ScsiCommands/NEC.cs index ceba6463..4603221b 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands/NEC.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands/NEC.cs @@ -52,7 +52,7 @@ namespace DiscImageChef.Devices /// Duration in milliseconds it took for the device to execute the command. /// Start block address. /// How many blocks to read. - public bool ReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength, uint timeout, out double duration) + public bool NecReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength, uint timeout, out double duration) { senseBuffer = new byte[32]; byte[] cdb = new byte[10]; diff --git a/DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs b/DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs index 18ddf506..2133ff72 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs @@ -107,8 +107,7 @@ namespace DiscImageChef.Devices cdb[9] = (byte)(endMsf & 0xFF); cdb[10] = (byte)subchannel; - uint transferLength = (uint)((cdb[6] - cdb[3]) * 60 * 75 + (cdb[7] - cdb[4]) * 75 + (cdb[8] - cdb[5])); - + uint transferLength = (uint)((cdb[7] - cdb[3]) * 60 * 75 + (cdb[8] - cdb[4]) * 75 + (cdb[9] - cdb[5])); buffer = new byte[blockSize * transferLength]; lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); diff --git a/DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs b/DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs index 1f1d3454..acf2cd3f 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs @@ -54,7 +54,7 @@ namespace DiscImageChef.Devices /// How many blocks to read. /// Block size. /// Subchannel selection. - public bool ReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint transferLength, PlextorSubchannel subchannel, uint timeout, out double duration) + public bool PlextorReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint transferLength, PlextorSubchannel subchannel, uint timeout, out double duration) { senseBuffer = new byte[32]; byte[] cdb = new byte[12]; diff --git a/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs b/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs index f4375c0a..ab63c636 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs @@ -382,9 +382,9 @@ namespace DiscImageChef.Devices /// Sense buffer. /// Timeout in seconds. /// Duration in milliseconds it took for the device to execute the command. - public bool PreventMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration) + public bool SpcPreventMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration) { - return PreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Prevent, timeout, out duration); + return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Prevent, timeout, out duration); } /// @@ -394,9 +394,9 @@ namespace DiscImageChef.Devices /// Sense buffer. /// Timeout in seconds. /// Duration in milliseconds it took for the device to execute the command. - public bool AllowMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration) + public bool SpcAllowMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration) { - return PreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Allow, timeout, out duration); + return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Allow, timeout, out duration); } /// @@ -407,12 +407,12 @@ namespace DiscImageChef.Devices /// Timeout in seconds. /// Duration in milliseconds it took for the device to execute the command. /// true to prevent medium removal, false to allow it. - public bool PreventAllowMediumRemoval(out byte[] senseBuffer, bool prevent, uint timeout, out double duration) + public bool SpcPreventAllowMediumRemoval(out byte[] senseBuffer, bool prevent, uint timeout, out double duration) { if (prevent) - return PreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Prevent, timeout, out duration); + return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Prevent, timeout, out duration); else - return PreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Allow, timeout, out duration); + return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Allow, timeout, out duration); } /// @@ -423,7 +423,7 @@ namespace DiscImageChef.Devices /// Timeout in seconds. /// Duration in milliseconds it took for the device to execute the command. /// Prevention mode. - public bool PreventAllowMediumRemoval(out byte[] senseBuffer, ScsiPreventAllowMode preventMode, uint timeout, out double duration) + public bool SpcPreventAllowMediumRemoval(out byte[] senseBuffer, ScsiPreventAllowMode preventMode, uint timeout, out double duration) { senseBuffer = new byte[32]; byte[] cdb = new byte[6]; diff --git a/DiscImageChef.Devices/DiscImageChef.Devices.csproj b/DiscImageChef.Devices/DiscImageChef.Devices.csproj index 3a82c25a..4e9899ba 100644 --- a/DiscImageChef.Devices/DiscImageChef.Devices.csproj +++ b/DiscImageChef.Devices/DiscImageChef.Devices.csproj @@ -20,6 +20,7 @@ prompt 4 false + x86 full diff --git a/DiscImageChef.Devices/Linux/Command.cs b/DiscImageChef.Devices/Linux/Command.cs index 6538a5dd..2dce631a 100644 --- a/DiscImageChef.Devices/Linux/Command.cs +++ b/DiscImageChef.Devices/Linux/Command.cs @@ -331,12 +331,12 @@ namespace DiscImageChef.Devices.Linux public static string ReadLink(string path) { - IntPtr buf = Marshal.AllocHGlobal(int.MaxValue); + IntPtr buf = Marshal.AllocHGlobal(4096); int resultSize; if (Interop.DetectOS.Is64Bit()) { - long result64 = Extern.readlink64(path, buf, (long)int.MaxValue); + long result64 = Extern.readlink64(path, buf, (long)4096); if (result64 <= 0) return null; @@ -344,7 +344,7 @@ namespace DiscImageChef.Devices.Linux } else { - int result = Extern.readlink(path, buf, int.MaxValue); + int result = Extern.readlink(path, buf, 4096); if (result <= 0) return null; diff --git a/DiscImageChef.Devices/Linux/Enums.cs b/DiscImageChef.Devices/Linux/Enums.cs index 09372272..639bf3e9 100644 --- a/DiscImageChef.Devices/Linux/Enums.cs +++ b/DiscImageChef.Devices/Linux/Enums.cs @@ -145,7 +145,7 @@ namespace DiscImageChef.Devices.Linux Unknown = -5 } - enum LinuxIoctl : ulong + enum LinuxIoctl : uint { // SCSI IOCtls SG_GET_VERSION_NUM = 0x2282, diff --git a/DiscImageChef.DiscImages/ZZZRawImage.cs b/DiscImageChef.DiscImages/ZZZRawImage.cs index f59044de..381c5620 100644 --- a/DiscImageChef.DiscImages/ZZZRawImage.cs +++ b/DiscImageChef.DiscImages/ZZZRawImage.cs @@ -673,11 +673,11 @@ namespace DiscImageChef.ImagePlugins case 481520640: return MediaType.ECMA_183_512; case 533403648: - return MediaType.ECMA_183_1024; + return MediaType.ECMA_183; case 596787200: return MediaType.ECMA_184_512; case 654540800: - return MediaType.ECMA_184_1024; + return MediaType.ECMA_184; default: return MediaType.GENERIC_HDD; } diff --git a/DiscImageChef.Metadata/DeviceReport.cs b/DiscImageChef.Metadata/DeviceReport.cs new file mode 100644 index 00000000..86ae7de3 --- /dev/null +++ b/DiscImageChef.Metadata/DeviceReport.cs @@ -0,0 +1,958 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : DeviceReport.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using System.Xml.Serialization; +using DiscImageChef.Decoders.ATA; +using DiscImageChef.Decoders.SCSI; + +namespace DiscImageChef.Metadata +{ + [SerializableAttribute()] + [XmlRootAttribute("DicDeviceReport", Namespace="", IsNullable=false)] + public class DeviceReport + { + public usbType USB; + public firewireType FireWire; + public ataType ATA; + public ataType ATAPI; + public scsiType SCSI; + } + + public class usbType + { + public ushort VendorID; + public ushort ProductID; + public string Manufacturer; + public string Product; + public bool RemovableMedia; + } + + public class firewireType + { + public uint VendorID; + public uint ProductID; + public string Manufacturer; + public string Product; + public bool RemovableMedia; + } + + public class ataType + { + public chsType CHS; + public chsType CurrentCHS; + + public string AdditionalPID; + public Identify.TransferMode APIOSupported; + public ushort ATAPIByteCount; + public ushort BufferType; + public ushort BufferSize; + public Identify.CapabilitiesBit Capabilities; + public Identify.CapabilitiesBit2 Capabilities2; + public Identify.CapabilitiesBit3 Capabilities3; + public ushort CFAPowerMode; + public Identify.CommandSetBit CommandSet; + public Identify.CommandSetBit2 CommandSet2; + public Identify.CommandSetBit3 CommandSet3; + public Identify.CommandSetBit4 CommandSet4; + public Identify.CommandSetBit5 CommandSet5; + public byte CurrentAAM; + public ushort CurrentAPM; + public Identify.DataSetMgmtBit DataSetMgmt; + public ushort DataSetMgmtSize; + public Identify.DeviceFormFactorEnum DeviceFormFactor; + public Identify.TransferMode DMAActive; + public Identify.TransferMode DMASupported; + public byte DMATransferTimingMode; + public ushort EccBytes; + public ushort EnhancedSecurityEraseTime; + public Identify.CommandSetBit EnabledCommandSet; + public Identify.CommandSetBit2 EnabledCommandSet2; + public Identify.CommandSetBit3 EnabledCommandSet3; + public Identify.CommandSetBit4 EnabledCommandSet4; + public Identify.SATAFeaturesBit EnabledSATAFeatures; + public ulong ExtendedUserSectors; + public byte FreeFallSensitivity; + public string FirmwareRevision; + public Identify.GeneralConfigurationBit GeneralConfiguration; + public ushort HardwareResetResult; + public ushort InterseekDelay; + public uint LBASectors; + public uint LBASectorsCurrent; + public ulong LBA48Sectors; + public ushort LogicalAlignment; + public uint LogicalSectorWords; + public Identify.MajorVersionBit MajorVersion; + public ushort MasterPasswordRevisionCode; + public ushort MaxDownloadMicroMode3; + public ushort MaxQueueDepth; + public Identify.TransferMode MDMAActive; + public Identify.TransferMode MDMASupported; + public ushort MinDownloadMicroMode3; + public ushort MinMDMACycleTime; + public ushort MinorVersion; + public ushort MinPIOCycleTimeNoFlow; + public ushort MinPIOCycleTimeFlow; + public string Model; + public byte MultipleMaxSectors; + public byte MultipleSectorNumber; + public ushort NVCacheCaps; + public uint NVCacheSize; + public ushort NVCacheWriteSpeed; + public byte NVEstimatedSpinUp; + public ushort NominalRotationRate; + public ushort PacketBusRelease; + public ushort PhysLogSectorSize; + public byte PIOTransferTimingMode; + public byte RecommendedAAM; + public ushort RecommendedMDMACycleTime; + public ushort RemovableStatusSet; + public Identify.SATACapabilitiesBit SATACapabilities; + public Identify.SATACapabilitiesBit2 SATACapabilities2; + public Identify.SATAFeaturesBit SATAFeatures; + public Identify.SCTCommandTransportBit SCTCommandTransport; + public uint SectorsPerCard; + public ushort SecurityEraseTime; + public Identify.SecurityStatusBit SecurityStatus; + public ushort ServiceBusyClear; + public Identify.SpecificConfigurationEnum SpecificConfiguration; + public ushort StreamAccessLatency; + public ushort StreamMinReqSize; + public uint StreamPerformanceGranularity; + public ushort StreamTransferTimeDMA; + public ushort StreamTransferTimePIO; + public ushort TransportMajorVersion; + public ushort TransportMinorVersion; + public Identify.TrustedComputingBit TrustedComputing; + public Identify.TransferMode UDMAActive; + public Identify.TransferMode UDMASupported; + public ushort UnformattedBPT; + public ushort UnformattedBPS; + public byte WRVMode; + public uint WRVSectorCountMode3; + public uint WRVSectorCountMode2; + + [XmlIgnoreAttribute()] + public bool AdditionalPIDSpecified; + [XmlIgnoreAttribute()] + public bool APIOSupportedSpecified; + [XmlIgnoreAttribute()] + public bool ATAPIByteCountSpecified; + [XmlIgnoreAttribute()] + public bool BufferTypeSpecified; + [XmlIgnoreAttribute()] + public bool BufferSizeSpecified; + [XmlIgnoreAttribute()] + public bool CapabilitiesSpecified; + [XmlIgnoreAttribute()] + public bool Capabilities2Specified; + [XmlIgnoreAttribute()] + public bool Capabilities3Specified; + [XmlIgnoreAttribute()] + public bool CFAPowerModeSpecified; + [XmlIgnoreAttribute()] + public bool CommandSetSpecified; + [XmlIgnoreAttribute()] + public bool CommandSet2Specified; + [XmlIgnoreAttribute()] + public bool CommandSet3Specified; + [XmlIgnoreAttribute()] + public bool CommandSet4Specified; + [XmlIgnoreAttribute()] + public bool CommandSet5Specified; + [XmlIgnoreAttribute()] + public bool CurrentAAMSpecified; + [XmlIgnoreAttribute()] + public bool CurrentAPMSpecified; + [XmlIgnoreAttribute()] + public bool DataSetMgmtSpecified; + [XmlIgnoreAttribute()] + public bool DataSetMgmtSizeSpecified; + [XmlIgnoreAttribute()] + public bool DeviceFormFactorSpecified; + [XmlIgnoreAttribute()] + public bool DMAActiveSpecified; + [XmlIgnoreAttribute()] + public bool DMASupportedSpecified; + [XmlIgnoreAttribute()] + public bool DMATransferTimingModeSpecified; + [XmlIgnoreAttribute()] + public bool EccBytesSpecified; + [XmlIgnoreAttribute()] + public bool EnhancedSecurityEraseTimeSpecified; + [XmlIgnoreAttribute()] + public bool EnabledCommandSetSpecified; + [XmlIgnoreAttribute()] + public bool EnabledCommandSet2Specified; + [XmlIgnoreAttribute()] + public bool EnabledCommandSet3Specified; + [XmlIgnoreAttribute()] + public bool EnabledCommandSet4Specified; + [XmlIgnoreAttribute()] + public bool EnabledSATAFeaturesSpecified; + [XmlIgnoreAttribute()] + public bool ExtendedIdentifySpecified; + [XmlIgnoreAttribute()] + public bool ExtendedUserSectorsSpecified; + [XmlIgnoreAttribute()] + public bool FreeFallSensitivitySpecified; + [XmlIgnoreAttribute()] + public bool FirmwareRevisionSpecified; + [XmlIgnoreAttribute()] + public bool GeneralConfigurationSpecified; + [XmlIgnoreAttribute()] + public bool HardwareResetResultSpecified; + [XmlIgnoreAttribute()] + public bool InterseekDelaySpecified; + [XmlIgnoreAttribute()] + public bool LBASectorsSpecified; + [XmlIgnoreAttribute()] + public bool LBASectorsCurrentSpecified; + [XmlIgnoreAttribute()] + public bool LBA48SectorsSpecified; + [XmlIgnoreAttribute()] + public bool LogicalAlignmentSpecified; + [XmlIgnoreAttribute()] + public bool LogicalSectorWordsSpecified; + [XmlIgnoreAttribute()] + public bool MajorVersionSpecified; + [XmlIgnoreAttribute()] + public bool MasterPasswordRevisionCodeSpecified; + [XmlIgnoreAttribute()] + public bool MaxDownloadMicroMode3Specified; + [XmlIgnoreAttribute()] + public bool MaxQueueDepthSpecified; + [XmlIgnoreAttribute()] + public bool MDMAActiveSpecified; + [XmlIgnoreAttribute()] + public bool MDMASupportedSpecified; + [XmlIgnoreAttribute()] + public bool MinDownloadMicroMode3Specified; + [XmlIgnoreAttribute()] + public bool MinMDMACycleTimeSpecified; + [XmlIgnoreAttribute()] + public bool MinorVersionSpecified; + [XmlIgnoreAttribute()] + public bool MinPIOCycleTimeNoFlowSpecified; + [XmlIgnoreAttribute()] + public bool MinPIOCycleTimeFlowSpecified; + [XmlIgnoreAttribute()] + public bool ModelSpecified; + [XmlIgnoreAttribute()] + public bool MultipleMaxSectorsSpecified; + [XmlIgnoreAttribute()] + public bool MultipleSectorNumberSpecified; + [XmlIgnoreAttribute()] + public bool NVCacheCapsSpecified; + [XmlIgnoreAttribute()] + public bool NVCacheSizeSpecified; + [XmlIgnoreAttribute()] + public bool NVCacheWriteSpeedSpecified; + [XmlIgnoreAttribute()] + public bool NVEstimatedSpinUpSpecified; + [XmlIgnoreAttribute()] + public bool NominalRotationRateSpecified; + [XmlIgnoreAttribute()] + public bool PacketBusReleaseSpecified; + [XmlIgnoreAttribute()] + public bool PhysLogSectorSizeSpecified; + [XmlIgnoreAttribute()] + public bool PIOTransferTimingModeSpecified; + [XmlIgnoreAttribute()] + public bool RecommendedAAMSpecified; + [XmlIgnoreAttribute()] + public bool RecommendedMDMACycleTimeSpecified; + [XmlIgnoreAttribute()] + public bool RemovableStatusSetSpecified; + [XmlIgnoreAttribute()] + public bool SATACapabilitiesSpecified; + [XmlIgnoreAttribute()] + public bool SATACapabilities2Specified; + [XmlIgnoreAttribute()] + public bool SATAFeaturesSpecified; + [XmlIgnoreAttribute()] + public bool SCTCommandTransportSpecified; + [XmlIgnoreAttribute()] + public bool SectorsPerCardSpecified; + [XmlIgnoreAttribute()] + public bool SecurityEraseTimeSpecified; + [XmlIgnoreAttribute()] + public bool SecurityStatusSpecified; + [XmlIgnoreAttribute()] + public bool ServiceBusyClearSpecified; + [XmlIgnoreAttribute()] + public bool SpecificConfigurationSpecified; + [XmlIgnoreAttribute()] + public bool StreamAccessLatencySpecified; + [XmlIgnoreAttribute()] + public bool StreamMinReqSizeSpecified; + [XmlIgnoreAttribute()] + public bool StreamPerformanceGranularitySpecified; + [XmlIgnoreAttribute()] + public bool StreamTransferTimeDMASpecified; + [XmlIgnoreAttribute()] + public bool StreamTransferTimePIOSpecified; + [XmlIgnoreAttribute()] + public bool TransportMajorVersionSpecified; + [XmlIgnoreAttribute()] + public bool TransportMinorVersionSpecified; + [XmlIgnoreAttribute()] + public bool TrustedComputingSpecified; + [XmlIgnoreAttribute()] + public bool UDMAActiveSpecified; + [XmlIgnoreAttribute()] + public bool UDMASupportedSpecified; + [XmlIgnoreAttribute()] + public bool UnformattedBPTSpecified; + [XmlIgnoreAttribute()] + public bool UnformattedBPSSpecified; + [XmlIgnoreAttribute()] + public bool WRVModeSpecified; + [XmlIgnoreAttribute()] + public bool WRVSectorCountMode3Specified; + [XmlIgnoreAttribute()] + public bool WRVSectorCountMode2Specified; + } + + public class chsType + { + public ushort Cylinders; + public ushort Heads; + public ushort Sectors; + } + + public class scsiType + { + public scsiInquiryType Inquiry; + public pageType[] EVPDPages; + public bool SupportsModeSense6; + public bool SupportsModeSense10; + public bool SupportsModeSubpages; + public modeType ModeSense; + public mmcType MultiMediaDevice; + public testedMediaType ReadCapabilities; + public testedMediaType[] RemovableMedias; + public sscType SequentialDevice; + + [XmlIgnoreAttribute()] + public bool ReadCapabilitiesSpecified; + } + + public class scsiInquiryType + { + public bool AccessControlCoordinator; + public bool ACKRequests; + public bool AERCSupported; + public bool Address16; + public bool Address32; + public byte ANSIVersion; + public TGPSValues AsymmetricalLUNAccess; + public bool BasicQueueing; + public byte DeviceTypeModifier; + public byte ECMAVersion; + public bool EnclosureServices; + public bool HierarchicalLUN; + public bool IUS; + public byte ISOVersion; + public bool LinkedCommands; + public bool MediumChanger; + public bool MultiPortDevice; + public bool NormalACA; + public PeripheralDeviceTypes PeripheralDeviceType; + public PeripheralQualifiers PeripheralQualifier; + public string ProductIdentification; + public string ProductRevisionLevel; + public bool Protection; + public bool QAS; + public bool RelativeAddressing; + public bool Removable; + public byte ResponseDataFormat; + public bool TaggedCommandQueue; + public bool TerminateTaskSupported; + public bool ThirdPartyCopy; + public bool TranferDisable; + public bool SoftReset; + public SPIClocking SPIClocking; + public bool StorageArrayController; + public bool SyncTransfer; + public string VendorIdentification; + public ushort[] VersionDescriptors; + public bool WideBus16; + public bool WideBus32; + + [XmlIgnoreAttribute()] + public bool ANSIVersionSpecified; + [XmlIgnoreAttribute()] + public bool ECMAVersionSpecified; + [XmlIgnoreAttribute()] + public bool DeviceTypeModifierSpecified; + [XmlIgnoreAttribute()] + public bool ISOVersionSpecified; + [XmlIgnoreAttribute()] + public bool ProductIdentificationSpecified; + [XmlIgnoreAttribute()] + public bool ProductRevisionLevelSpecified; + [XmlIgnoreAttribute()] + public bool ResponseDataFormatSpecified; + [XmlIgnoreAttribute()] + public bool VendorIdentificationSpecified; + } + + [SerializableAttribute()] + public class pageType + { + [XmlAttributeAttribute()] + public byte page; + + [XmlTextAttribute()] + public byte[] value; + } + + public class modeType + { + public byte MediumType; + public bool WriteProtected; + public blockDescriptorType[] BlockDescriptors; + public byte Speed; + public byte BufferedMode; + public bool BlankCheckEnabled; + public bool DPOandFUA; + public modePageType[] ModePages; + + [XmlIgnoreAttribute()] + public bool MediumTypeSpecified; + [XmlIgnoreAttribute()] + public bool SpeedSpecified; + [XmlIgnoreAttribute()] + public bool BufferedModeSpecified; + } + + public class blockDescriptorType + { + public byte Density; + public ulong Blocks; + public uint BlockLength; + + [XmlIgnoreAttribute()] + public bool BlocksSpecified; + [XmlIgnoreAttribute()] + public bool BlockLengthSpecified; + } + + [SerializableAttribute()] + public class modePageType + { + [XmlAttributeAttribute()] + public byte page; + + [XmlAttributeAttribute()] + public byte subpage; + + [XmlTextAttribute()] + public byte[] value; + } + + public class mmcType + { + public mmcModeType ModeSense2A; + public mmcFeaturesType Features; + public testedMediaType[] TestedMedia; + } + + public class mmcModeType + { + public bool AccurateCDDA; + public bool BCK; + public ushort BufferSize; + public bool BufferUnderRunProtection; + public bool CanEject; + public bool CanLockMedia; + public bool CDDACommand; + public bool CompositeAudioVideo; + public bool CSSandCPPMSupported; + public ushort CurrentSpeed; + public ushort CurrentWriteSpeed; + public ushort CurrentWriteSpeedSelected; + public bool DeterministicSlotChanger; + public bool DigitalPort1; + public bool DigitalPort2; + public bool LeadInPW; + public byte LoadingMechanismType; + public bool LockStatus; + public bool LSBF; + public ushort MaximumSpeed; + public ushort MaximumWriteSpeed; + public bool PlaysAudio; + public bool PreventJumperStatus; + public bool RCK; + public bool ReadsBarcode; + public bool ReadsBothSides; + public bool ReadsCDR; + public bool ReadsCDRW; + public bool ReadsDeinterlavedSubchannel; + public bool ReadsDVDR; + public bool ReadsDVDRAM; + public bool ReadsDVDROM; + public bool ReadsISRC; + public bool ReadsMode2Form2; + public bool ReadsMode2Form1; + public bool ReadsPacketCDR; + public bool ReadsSubchannel; + public bool ReadsUPC; + public bool ReturnsC2Pointers; + public byte RotationControlSelected; + public bool SeparateChannelMute; + public bool SeparateChannelVolume; + public bool SSS; + public bool SupportsMultiSession; + public ushort SupportedVolumeLevels; + public bool TestWrite; + public bool WritesCDR; + public bool WritesCDRW; + public bool WritesDVDR; + public bool WritesDVDRAM; + public Modes.ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors; + + [XmlIgnoreAttribute()] + public bool MaximumSpeedSpecified; + [XmlIgnoreAttribute()] + public bool SupportedVolumeLevelsSpecified; + [XmlIgnoreAttribute()] + public bool BufferSizeSpecified; + [XmlIgnoreAttribute()] + public bool CurrentSpeedSpecified; + [XmlIgnoreAttribute()] + public bool MaximumWriteSpeedSpecified; + [XmlIgnoreAttribute()] + public bool CurrentWriteSpeedSpecified; + [XmlIgnoreAttribute()] + public bool RotationControlSelectedSpecified; + [XmlIgnoreAttribute()] + public bool CurrentWriteSpeedSelectedSpecified; + } + + public class mmcFeaturesType + { + public byte AACSVersion; + public byte AGIDs; + public byte BindingNonceBlocks; + public ushort BlocksPerReadableUnit; + public bool BufferUnderrunFreeInDVD; + public bool BufferUnderrunFreeInSAO; + public bool BufferUnderrunFreeInTAO; + public bool CanAudioScan; + public bool CanEject; + public bool CanEraseSector; + public bool CanExpandBDRESpareArea; + public bool CanFormat; + public bool CanFormatBDREWithoutSpare; + public bool CanFormatCert; + public bool CanFormatFRF; + public bool CanFormatQCert; + public bool CanFormatRRM; + public bool CanGenerateBindingNonce; + public bool CanLoad; + public bool CanMuteSeparateChannels; + public bool CanOverwriteSAOTrack; + public bool CanOverwriteTAOTrack; + public bool CanPlayCDAudio; + public bool CanPseudoOverwriteBDR; + public bool CanReadAllDualR; + public bool CanReadAllDualRW; + public bool CanReadBD; + public bool CanReadBDR; + public bool CanReadBDRE1; + public bool CanReadBDRE2; + public bool CanReadBDROM; + public bool CanReadBluBCA; + public bool CanReadCD; + public bool CanReadCDMRW; + public bool CanReadCPRM_MKB; + public bool CanReadDDCD; + public bool CanReadDVD; + public bool CanReadDVDPlusMRW; + public bool CanReadDVDPlusR; + public bool CanReadDVDPlusRDL; + public bool CanReadDVDPlusRW; + public bool CanReadDVDPlusRWDL; + public bool CanReadDriveAACSCertificate; + public bool CanReadHDDVD; + public bool CanReadHDDVDR; + public bool CanReadHDDVDRAM; + public bool CanReadLeadInCDText; + public bool CanReadOldBDR; + public bool CanReadOldBDRE; + public bool CanReadOldBDROM; + public bool CanReadSpareAreaInformation; + public bool CanReportDriveSerial; + public bool CanReportMediaSerial; + public bool CanTestWriteDDCDR; + public bool CanTestWriteDVD; + public bool CanTestWriteInSAO; + public bool CanTestWriteInTAO; + public bool CanUpgradeFirmware; + public bool CanWriteBD; + public bool CanWriteBDR; + public bool CanWriteBDRE1; + public bool CanWriteBDRE2; + public bool CanWriteBusEncryptedBlocks; + public bool CanWriteCDMRW; + public bool CanWriteCDRW; + public bool CanWriteCDRWCAV; + public bool CanWriteCDSAO; + public bool CanWriteCDTAO; + public bool CanWriteCSSManagedDVD; + public bool CanWriteDDCDR; + public bool CanWriteDDCDRW; + public bool CanWriteDVDPlusMRW; + public bool CanWriteDVDPlusR; + public bool CanWriteDVDPlusRDL; + public bool CanWriteDVDPlusRW; + public bool CanWriteDVDPlusRWDL; + public bool CanWriteDVDR; + public bool CanWriteDVDRDL; + public bool CanWriteDVDRW; + public bool CanWriteHDDVDR; + public bool CanWriteHDDVDRAM; + public bool CanWriteOldBDR; + public bool CanWriteOldBDRE; + public bool CanWritePackedSubchannelInTAO; + public bool CanWriteRWSubchannelInSAO; + public bool CanWriteRWSubchannelInTAO; + public bool CanWriteRaw; + public bool CanWriteRawMultiSession; + public bool CanWriteRawSubchannelInTAO; + public bool ChangerIsSideChangeCapable; + public byte ChangerSlots; + public bool ChangerSupportsDiscPresent; + public byte CPRMVersion; + public byte CSSVersion; + public bool DBML; + public bool DVDMultiRead; + public bool EmbeddedChanger; + public bool ErrorRecoveryPage; + [XmlElementAttribute(DataType="date")] + public DateTime FirmwareDate; + public byte LoadingMechanismType; + public bool Locked; + public uint LogicalBlockSize; + public bool MultiRead; + public DiscImageChef.Decoders.SCSI.MMC.PhysicalInterfaces PhysicalInterfaceStandard; + public bool PreventJumper; + public bool SupportsAACS; + public bool SupportsBusEncryption; + public bool SupportsC2; + public bool SupportsCPRM; + public bool SupportsCSS; + public bool SupportsDAP; + public bool SupportsDeviceBusyEvent; + public bool SupportsHybridDiscs; + public bool SupportsModePage1Ch; + public bool SupportsOSSC; + public bool SupportsPWP; + public bool SupportsSWPP; + public bool SupportsSecurDisc; + public bool SupportsSeparateVolume; + public bool SupportsVCPS; + public bool SupportsWriteInhibitDCB; + public bool SupportsWriteProtectPAC; + public ushort VolumeLevels; + + [XmlIgnoreAttribute()] + public bool PhysicalInterfaceStandardSpecified; + [XmlIgnoreAttribute()] + public bool AACSVersionSpecified; + [XmlIgnoreAttribute()] + public bool AGIDsSpecified; + [XmlIgnoreAttribute()] + public bool BindingNonceBlocksSpecified; + [XmlIgnoreAttribute()] + public bool CPRMVersionSpecified; + [XmlIgnoreAttribute()] + public bool CSSVersionSpecified; + [XmlIgnoreAttribute()] + public bool ChangerHighestSlotNumberSpecified; + [XmlIgnoreAttribute()] + public bool LoadingMechanismTypeSpecified; + [XmlIgnoreAttribute()] + public bool LogicalBlockSizeSpecified; + [XmlIgnoreAttribute()] + public bool BlocksPerReadableUnitSpecified; + [XmlIgnoreAttribute()] + public bool FirmwareDateSpecified; + [XmlIgnoreAttribute()] + public bool VolumeLevelsSpecified; + } + + public class testedMediaType + { + public ulong Blocks; + public uint BlockSize; + public bool CanReadAACS; + public bool CanReadADIP; + public bool CanReadATIP; + public bool CanReadBCA; + public bool CanReadC2Pointers; + public bool CanReadCMI; + public bool CanReadCorrectedSubchannel; + public bool CanReadCorrectedSubchannelWithC2; + public bool CanReadDCB; + public bool CanReadDDS; + public bool CanReadDMI; + public bool CanReadDiscInformation; + public bool CanReadFullTOC; + public bool CanReadHDCMI; + public bool CanReadLayerCapacity; + public bool CanReadLeadIn; + public bool CanReadLeadOut; + public bool CanReadMediaID; + public bool CanReadMediaSerial; + public bool CanReadPAC; + public bool CanReadPFI; + public bool CanReadPMA; + public bool CanReadPQSubchannel; + public bool CanReadPQSubchannelWithC2; + public bool CanReadPRI; + public bool CanReadRWSubchannel; + public bool CanReadRWSubchannelWithC2; + public bool CanReadRecordablePFI; + public bool CanReadSpareAreaInformation; + public bool CanReadTOC; + public byte Density; + public uint LongBlockSize; + public string Manufacturer; + public bool MediaIsRecognized; + public byte MediumType; + public string MediumTypeName; + public string Model; + public bool SupportsHLDTSTReadRawDVD; + public bool SupportsNECReadCDDA; + public bool SupportsPioneerReadCDDA; + public bool SupportsPioneerReadCDDAMSF; + public bool SupportsPlextorReadCDDA; + public bool SupportsPlextorReadRawDVD; + public bool SupportsRead10; + public bool SupportsRead12; + public bool SupportsRead16; + public bool SupportsRead; + public bool SupportsReadCapacity16; + public bool SupportsReadCapacity; + public bool SupportsReadCd; + public bool SupportsReadCdMsf; + public bool SupportsReadCdRaw; + public bool SupportsReadCdMsfRaw; + public bool SupportsReadLong16; + public bool SupportsReadLong; + + [XmlIgnoreAttribute()] + public bool BlocksSpecified; + [XmlIgnoreAttribute()] + public bool BlockSizeSpecified; + [XmlIgnoreAttribute()] + public bool CanReadAACSSpecified; + [XmlIgnoreAttribute()] + public bool CanReadADIPSpecified; + [XmlIgnoreAttribute()] + public bool CanReadATIPSpecified; + [XmlIgnoreAttribute()] + public bool CanReadBCASpecified; + [XmlIgnoreAttribute()] + public bool CanReadC2PointersSpecified; + [XmlIgnoreAttribute()] + public bool CanReadCMISpecified; + [XmlIgnoreAttribute()] + public bool CanReadCorrectedSubchannelSpecified; + [XmlIgnoreAttribute()] + public bool CanReadCorrectedSubchannelWithC2Specified; + [XmlIgnoreAttribute()] + public bool CanReadDCBSpecified; + [XmlIgnoreAttribute()] + public bool CanReadDDSSpecified; + [XmlIgnoreAttribute()] + public bool CanReadDMISpecified; + [XmlIgnoreAttribute()] + public bool CanReadDiscInformationSpecified; + [XmlIgnoreAttribute()] + public bool CanReadFullTOCSpecified; + [XmlIgnoreAttribute()] + public bool CanReadHDCMISpecified; + [XmlIgnoreAttribute()] + public bool CanReadLayerCapacitySpecified; + [XmlIgnoreAttribute()] + public bool CanReadLeadInSpecified; + [XmlIgnoreAttribute()] + public bool CanReadLeadOutSpecified; + [XmlIgnoreAttribute()] + public bool CanReadMediaIDSpecified; + [XmlIgnoreAttribute()] + public bool CanReadMediaSerialSpecified; + [XmlIgnoreAttribute()] + public bool CanReadPACSpecified; + [XmlIgnoreAttribute()] + public bool CanReadPFISpecified; + [XmlIgnoreAttribute()] + public bool CanReadPMASpecified; + [XmlIgnoreAttribute()] + public bool CanReadPQSubchannelSpecified; + [XmlIgnoreAttribute()] + public bool CanReadPQSubchannelWithC2Specified; + [XmlIgnoreAttribute()] + public bool CanReadPRISpecified; + [XmlIgnoreAttribute()] + public bool CanReadRWSubchannelSpecified; + [XmlIgnoreAttribute()] + public bool CanReadRWSubchannelWithC2Specified; + [XmlIgnoreAttribute()] + public bool CanReadRecordablePFISpecified; + [XmlIgnoreAttribute()] + public bool CanReadSpareAreaInformationSpecified; + [XmlIgnoreAttribute()] + public bool CanReadTOCSpecified; + [XmlIgnoreAttribute()] + public bool DensitySpecified; + [XmlIgnoreAttribute()] + public bool LongBlockSizeSpecified; + [XmlIgnoreAttribute()] + public bool ManufacturerSpecified; + [XmlIgnoreAttribute()] + public bool MediumTypeSpecified; + [XmlIgnoreAttribute()] + public bool ModelSpecified; + [XmlIgnoreAttribute()] + public bool SupportsHLDTSTReadRawDVDSpecified; + [XmlIgnoreAttribute()] + public bool SupportsNECReadCDDASpecified; + [XmlIgnoreAttribute()] + public bool SupportsPioneerReadCDDASpecified; + [XmlIgnoreAttribute()] + public bool SupportsPioneerReadCDDAMSFSpecified; + [XmlIgnoreAttribute()] + public bool SupportsPlextorReadCDDASpecified; + [XmlIgnoreAttribute()] + public bool SupportsPlextorReadRawDVDSpecified; + [XmlIgnoreAttribute()] + public bool SupportsRead10Specified; + [XmlIgnoreAttribute()] + public bool SupportsRead12Specified; + [XmlIgnoreAttribute()] + public bool SupportsRead16Specified; + [XmlIgnoreAttribute()] + public bool SupportsReadSpecified; + [XmlIgnoreAttribute()] + public bool SupportsReadCapacity16Specified; + [XmlIgnoreAttribute()] + public bool SupportsReadCapacitySpecified; + [XmlIgnoreAttribute()] + public bool SupportsReadCdSpecified; + [XmlIgnoreAttribute()] + public bool SupportsReadCdMsfSpecified; + [XmlIgnoreAttribute()] + public bool SupportsReadCdRawSpecified; + [XmlIgnoreAttribute()] + public bool SupportsReadCdMsfRawSpecified; + [XmlIgnoreAttribute()] + public bool SupportsReadLong16Specified; + [XmlIgnoreAttribute()] + public bool SupportsReadLongSpecified; + } + + public class sscType + { + public byte BlockSizeGranularity; + public uint MaxBlockLength; + public uint MinBlockLength; + + public SupportedDensity[] SupportedDensities; + public SupportedMedia[] SupportedMediaTypes; + public SequentialMedia[] TestedMedia; + + [XmlIgnoreAttribute()] + public bool BlockSizeGranularitySpecified; + [XmlIgnoreAttribute()] + public bool MaxBlockLengthSpecified; + [XmlIgnoreAttribute()] + public bool MinBlockLengthSpecified; + } + + public struct SupportedDensity + { + public byte PrimaryCode; + public byte SecondaryCode; + public bool Writable; + public bool Duplicate; + public bool DefaultDensity; + public uint BitsPerMm; + public ushort Width; + public ushort Tracks; + public uint Capacity; + public string Organization; + public string Name; + public string Description; + } + + public struct SupportedMedia + { + public byte MediumType; + public int[] DensityCodes; + public ushort Width; + public ushort Length; + public string Organization; + public string Name; + public string Description; + } + + public struct SequentialMedia + { + public bool CanReadMediaSerial; + public byte Density; + public string Manufacturer; + public bool MediaIsRecognized; + public byte MediumType; + public string MediumTypeName; + public string Model; + public SupportedDensity[] SupportedDensities; + public SupportedMedia[] SupportedMediaTypes; + + [XmlIgnoreAttribute()] + public bool CanReadMediaSerialSpecified; + [XmlIgnoreAttribute()] + public bool DensitySpecified; + [XmlIgnoreAttribute()] + public bool MediumTypeSpecified; + } +} + diff --git a/DiscImageChef.Metadata/Dimensions.cs b/DiscImageChef.Metadata/Dimensions.cs index 27bb9eae..2a9aa6a7 100644 --- a/DiscImageChef.Metadata/Dimensions.cs +++ b/DiscImageChef.Metadata/Dimensions.cs @@ -152,11 +152,47 @@ namespace DiscImageChef.Metadata return dmns; #endregion 8" floppy disk + #region 356mm magneto optical + case CommonTypes.MediaType.ECMA_260: + case CommonTypes.MediaType.ECMA_260_Double: + // According to ECMA-260 et al + dmns.Height = 421.84; + dmns.HeightSpecified = true; + dmns.Width = 443.76; + dmns.WidthSpecified = true; + dmns.Thickness = 25.4; + return dmns; + #endregion 356mm magneto optical + + #region 300mm magneto optical + case CommonTypes.MediaType.ECMA_189: + case CommonTypes.MediaType.ECMA_190: + case CommonTypes.MediaType.ECMA_317: + // According to ECMA-317 et al + dmns.Height = 340; + dmns.HeightSpecified = true; + dmns.Width = 320; + dmns.WidthSpecified = true; + dmns.Thickness = 17; + return dmns; + #endregion 300mm magneto optical + #region 5.25" magneto optical + case CommonTypes.MediaType.ECMA_153: + case CommonTypes.MediaType.ECMA_153_512: case CommonTypes.MediaType.ECMA_183_512: - case CommonTypes.MediaType.ECMA_183_1024: + case CommonTypes.MediaType.ECMA_183: case CommonTypes.MediaType.ECMA_184_512: - case CommonTypes.MediaType.ECMA_184_1024: + case CommonTypes.MediaType.ECMA_184: + case CommonTypes.MediaType.ECMA_195: + case CommonTypes.MediaType.ECMA_195_512: + case CommonTypes.MediaType.ECMA_238: + case CommonTypes.MediaType.ECMA_280: + case CommonTypes.MediaType.ECMA_322: + case CommonTypes.MediaType.ECMA_322_2k: + case CommonTypes.MediaType.UDO: + case CommonTypes.MediaType.UDO2: + case CommonTypes.MediaType.UDO2_WORM: // According to ECMA-183 et al dmns.Height = 153; dmns.HeightSpecified = true; @@ -169,6 +205,11 @@ namespace DiscImageChef.Metadata #region 3.5" magneto optical case CommonTypes.MediaType.ECMA_154: case CommonTypes.MediaType.ECMA_201: + case CommonTypes.MediaType.ECMA_201_ROM: + case CommonTypes.MediaType.ECMA_223: + case CommonTypes.MediaType.ECMA_223_512: + case CommonTypes.MediaType.GigaMo: + case CommonTypes.MediaType.GigaMo2: // According to ECMA-154 et al dmns.Height = 94; dmns.HeightSpecified = true; @@ -178,6 +219,21 @@ namespace DiscImageChef.Metadata return dmns; #endregion 3.5" magneto optical + case CommonTypes.MediaType.PD650: + case CommonTypes.MediaType.PD650_WORM: + dmns.Height = 135; + dmns.HeightSpecified = true; + dmns.Width = 124; + dmns.WidthSpecified = true; + dmns.Thickness = 7.8; + return dmns; + case CommonTypes.MediaType.ECMA_239: + dmns.Height = 97; + dmns.HeightSpecified = true; + dmns.Width = 92; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + return dmns; case CommonTypes.MediaType.MMCmicro: dmns.Height = 14; dmns.HeightSpecified = true; @@ -483,19 +539,14 @@ namespace DiscImageChef.Metadata dmns.Thickness = 14; return dmns; case CommonTypes.MediaType.RDX: + case CommonTypes.MediaType.RDX320: dmns.Height = 119; dmns.HeightSpecified = true; - dmns.Width = 86.5; + dmns.Width = 87; dmns.WidthSpecified = true; - dmns.Thickness = 23.2; + dmns.Thickness = 23; return dmns; case CommonTypes.MediaType.LS120: - dmns.Height = 94; - dmns.HeightSpecified = true; - dmns.Width = 90; - dmns.WidthSpecified = true; - dmns.Thickness = 3.5; - return dmns; case CommonTypes.MediaType.LS240: dmns.Height = 94; dmns.HeightSpecified = true; @@ -550,14 +601,16 @@ namespace DiscImageChef.Metadata case CommonTypes.MediaType.AIT5: case CommonTypes.MediaType.AITETurbo: case CommonTypes.MediaType.Exatape106m: - case CommonTypes.MediaType.Exatape106mXL: + case CommonTypes.MediaType.Exatape160mXL: case CommonTypes.MediaType.Exatape112m: case CommonTypes.MediaType.Exatape125m: case CommonTypes.MediaType.Exatape150m: case CommonTypes.MediaType.Exatape15m: case CommonTypes.MediaType.Exatape170m: case CommonTypes.MediaType.Exatape225m: + case CommonTypes.MediaType.Exatape22m: case CommonTypes.MediaType.Exatape22mAME: + case CommonTypes.MediaType.Exatape28m: case CommonTypes.MediaType.Exatape40m: case CommonTypes.MediaType.Exatape45m: case CommonTypes.MediaType.Exatape54m: diff --git a/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj b/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj index db7e2043..9bc2a1cb 100644 --- a/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj +++ b/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj @@ -40,6 +40,7 @@ + @@ -47,5 +48,9 @@ {F2B84194-26EB-4227-B1C5-6602517E85AE} DiscImageChef.CommonTypes + + {0BEB3088-B634-4289-AE17-CDF2D25D00D5} + DiscImageChef.Decoders + \ No newline at end of file diff --git a/DiscImageChef.Metadata/MediaType.cs b/DiscImageChef.Metadata/MediaType.cs index 5b855359..f4d1fba6 100644 --- a/DiscImageChef.Metadata/MediaType.cs +++ b/DiscImageChef.Metadata/MediaType.cs @@ -613,13 +613,18 @@ namespace DiscImageChef.Metadata DiscType = "3.5\" floppy"; DiscSubType = "FDFORMAT high-density"; break; + case CommonTypes.MediaType.ECMA_260: + case CommonTypes.MediaType.ECMA_260_Double: + DiscType = "356mm magneto-optical"; + DiscSubType = "ECMA-260 / ISO 15898"; + break; case CommonTypes.MediaType.ECMA_183_512: - case CommonTypes.MediaType.ECMA_183_1024: + case CommonTypes.MediaType.ECMA_183: DiscType = "5.25\" magneto-optical"; DiscSubType = "ECMA-183"; break; case CommonTypes.MediaType.ECMA_184_512: - case CommonTypes.MediaType.ECMA_184_1024: + case CommonTypes.MediaType.ECMA_184: DiscType = "5.25\" magneto-optical"; DiscSubType = "ECMA-184"; break; @@ -631,6 +636,10 @@ namespace DiscImageChef.Metadata DiscType = "3.5\" magneto-optical"; DiscSubType = "ECMA-201"; break; + case DiscImageChef.CommonTypes.MediaType.FlashDrive: + DiscType = "USB flash drive"; + DiscSubType = "USB flash drive"; + break; default: DiscType = "Unknown"; DiscSubType = "Unknown"; diff --git a/DiscImageChef/Commands/CreateSidecar.cs b/DiscImageChef/Commands/CreateSidecar.cs index 0001ea65..0ae3ea66 100644 --- a/DiscImageChef/Commands/CreateSidecar.cs +++ b/DiscImageChef/Commands/CreateSidecar.cs @@ -96,64 +96,7 @@ namespace DiscImageChef.Commands FileInfo fi = new FileInfo(options.InputFile); FileStream fs = new FileStream(options.InputFile, FileMode.Open, FileAccess.Read); - Adler32Context adler32ctx = new Adler32Context(); - CRC16Context crc16ctx = new CRC16Context(); - CRC32Context crc32ctx = new CRC32Context(); - CRC64Context crc64ctx = new CRC64Context(); - MD5Context md5ctx = new MD5Context(); - RIPEMD160Context ripemd160ctx = new RIPEMD160Context(); - SHA1Context sha1ctx = new SHA1Context(); - SHA256Context sha256ctx = new SHA256Context(); - SHA384Context sha384ctx = new SHA384Context(); - SHA512Context sha512ctx = new SHA512Context(); - SpamSumContext ssctx = new SpamSumContext(); - - Thread adlerThread = new Thread(updateAdler); - Thread crc16Thread = new Thread(updateCRC16); - Thread crc32Thread = new Thread(updateCRC32); - Thread crc64Thread = new Thread(updateCRC64); - Thread md5Thread = new Thread(updateMD5); - Thread ripemd160Thread = new Thread(updateRIPEMD160); - Thread sha1Thread = new Thread(updateSHA1); - Thread sha256Thread = new Thread(updateSHA256); - Thread sha384Thread = new Thread(updateSHA384); - Thread sha512Thread = new Thread(updateSHA512); - Thread spamsumThread = new Thread(updateSpamSum); - - adlerPacket adlerPkt = new adlerPacket(); - crc16Packet crc16Pkt = new crc16Packet(); - crc32Packet crc32Pkt = new crc32Packet(); - crc64Packet crc64Pkt = new crc64Packet(); - md5Packet md5Pkt = new md5Packet(); - ripemd160Packet ripemd160Pkt = new ripemd160Packet(); - sha1Packet sha1Pkt = new sha1Packet(); - sha256Packet sha256Pkt = new sha256Packet(); - sha384Packet sha384Pkt = new sha384Packet(); - sha512Packet sha512Pkt = new sha512Packet(); - spamsumPacket spamsumPkt = new spamsumPacket(); - - adler32ctx.Init(); - adlerPkt.context = adler32ctx; - crc16ctx.Init(); - crc16Pkt.context = crc16ctx; - crc32ctx.Init(); - crc32Pkt.context = crc32ctx; - crc64ctx.Init(); - crc64Pkt.context = crc64ctx; - md5ctx.Init(); - md5Pkt.context = md5ctx; - ripemd160ctx.Init(); - ripemd160Pkt.context = ripemd160ctx; - sha1ctx.Init(); - sha1Pkt.context = sha1ctx; - sha256ctx.Init(); - sha256Pkt.context = sha256ctx; - sha384ctx.Init(); - sha384Pkt.context = sha384ctx; - sha512ctx.Init(); - sha512Pkt.context = sha512ctx; - ssctx.Init(); - spamsumPkt.context = ssctx; + Core.Checksum imgChkWorker = new DiscImageChef.Core.Checksum(); byte[] data; long position = 0; @@ -164,49 +107,7 @@ namespace DiscImageChef.Commands DicConsole.Write("\rHashing image file byte {0} of {1}", position, fi.Length); - adlerPkt.data = data; - adlerThread.Start(adlerPkt); - crc16Pkt.data = data; - crc16Thread.Start(crc16Pkt); - crc32Pkt.data = data; - crc32Thread.Start(crc32Pkt); - crc64Pkt.data = data; - crc64Thread.Start(crc64Pkt); - md5Pkt.data = data; - md5Thread.Start(md5Pkt); - ripemd160Pkt.data = data; - ripemd160Thread.Start(ripemd160Pkt); - sha1Pkt.data = data; - sha1Thread.Start(sha1Pkt); - sha256Pkt.data = data; - sha256Thread.Start(sha256Pkt); - sha384Pkt.data = data; - sha384Thread.Start(sha384Pkt); - sha512Pkt.data = data; - sha512Thread.Start(sha512Pkt); - spamsumPkt.data = data; - spamsumThread.Start(spamsumPkt); - - while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) - { - } - - adlerThread = new Thread(updateAdler); - crc16Thread = new Thread(updateCRC16); - crc32Thread = new Thread(updateCRC32); - crc64Thread = new Thread(updateCRC64); - md5Thread = new Thread(updateMD5); - ripemd160Thread = new Thread(updateRIPEMD160); - sha1Thread = new Thread(updateSHA1); - sha256Thread = new Thread(updateSHA256); - sha384Thread = new Thread(updateSHA384); - sha512Thread = new Thread(updateSHA512); - spamsumThread = new Thread(updateSpamSum); + imgChkWorker.Update(data); position += 1048576; } @@ -216,97 +117,12 @@ namespace DiscImageChef.Commands DicConsole.Write("\rHashing image file byte {0} of {1}", position, fi.Length); - adlerPkt.data = data; - adlerThread.Start(adlerPkt); - crc16Pkt.data = data; - crc16Thread.Start(crc16Pkt); - crc32Pkt.data = data; - crc32Thread.Start(crc32Pkt); - crc64Pkt.data = data; - crc64Thread.Start(crc64Pkt); - md5Pkt.data = data; - md5Thread.Start(md5Pkt); - ripemd160Pkt.data = data; - ripemd160Thread.Start(ripemd160Pkt); - sha1Pkt.data = data; - sha1Thread.Start(sha1Pkt); - sha256Pkt.data = data; - sha256Thread.Start(sha256Pkt); - sha384Pkt.data = data; - sha384Thread.Start(sha384Pkt); - sha512Pkt.data = data; - sha512Thread.Start(sha512Pkt); - spamsumPkt.data = data; - spamsumThread.Start(spamsumPkt); - - while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) - { - } + imgChkWorker.Update(data); DicConsole.WriteLine(); fs.Close(); - List imgChecksums = new List(); - - ChecksumType chk = new ChecksumType(); - chk.type = ChecksumTypeType.adler32; - chk.Value = adler32ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc16; - chk.Value = crc16ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc32; - chk.Value = crc32ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc64; - chk.Value = crc64ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.md5; - chk.Value = md5ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.ripemd160; - chk.Value = ripemd160ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha1; - chk.Value = sha1ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha256; - chk.Value = sha256ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha384; - chk.Value = sha384ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha512; - chk.Value = sha512ctx.End(); - imgChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.spamsum; - chk.Value = ssctx.End(); - imgChecksums.Add(chk); + List imgChecksums = imgChkWorker.End(); switch (_imageFormat.ImageInfo.xmlMediaType) { @@ -342,7 +158,7 @@ namespace DiscImageChef.Commands { case MediaTagType.CD_ATIP: sidecar.OpticalDisc[0].ATIP = new DumpType(); - sidecar.OpticalDisc[0].ATIP.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.CD_ATIP)).ToArray(); + sidecar.OpticalDisc[0].ATIP.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.CD_ATIP)).ToArray(); sidecar.OpticalDisc[0].ATIP.Size = _imageFormat.ReadDiskTag(MediaTagType.CD_ATIP).Length; Decoders.CD.ATIP.CDATIP? atip = Decoders.CD.ATIP.Decode(_imageFormat.ReadDiskTag(MediaTagType.CD_ATIP)); if (atip.HasValue) @@ -355,12 +171,12 @@ namespace DiscImageChef.Commands break; case MediaTagType.DVD_BCA: sidecar.OpticalDisc[0].BCA = new DumpType(); - sidecar.OpticalDisc[0].BCA.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_BCA)).ToArray(); + sidecar.OpticalDisc[0].BCA.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_BCA)).ToArray(); sidecar.OpticalDisc[0].BCA.Size = _imageFormat.ReadDiskTag(MediaTagType.DVD_BCA).Length; break; case MediaTagType.BD_BCA: sidecar.OpticalDisc[0].BCA = new DumpType(); - sidecar.OpticalDisc[0].BCA.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.BD_BCA)).ToArray(); + sidecar.OpticalDisc[0].BCA.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.BD_BCA)).ToArray(); sidecar.OpticalDisc[0].BCA.Size = _imageFormat.ReadDiskTag(MediaTagType.BD_BCA).Length; break; case MediaTagType.DVD_CMI: @@ -381,12 +197,12 @@ namespace DiscImageChef.Commands break; } } - sidecar.OpticalDisc[0].CMI.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_CMI)).ToArray(); + sidecar.OpticalDisc[0].CMI.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_CMI)).ToArray(); sidecar.OpticalDisc[0].CMI.Size = _imageFormat.ReadDiskTag(MediaTagType.DVD_CMI).Length; break; case MediaTagType.DVD_DMI: sidecar.OpticalDisc[0].DMI = new DumpType(); - sidecar.OpticalDisc[0].DMI.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_DMI)).ToArray(); + sidecar.OpticalDisc[0].DMI.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_DMI)).ToArray(); sidecar.OpticalDisc[0].DMI.Size = _imageFormat.ReadDiskTag(MediaTagType.DVD_DMI).Length; if (Decoders.Xbox.DMI.IsXbox(_imageFormat.ReadDiskTag(MediaTagType.DVD_DMI))) { @@ -403,7 +219,7 @@ namespace DiscImageChef.Commands break; case MediaTagType.DVD_PFI: sidecar.OpticalDisc[0].PFI = new DumpType(); - sidecar.OpticalDisc[0].PFI.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_PFI)).ToArray(); + sidecar.OpticalDisc[0].PFI.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.DVD_PFI)).ToArray(); sidecar.OpticalDisc[0].PFI.Size = _imageFormat.ReadDiskTag(MediaTagType.DVD_PFI).Length; Decoders.DVD.PFI.PhysicalFormatInformation? pfi = Decoders.DVD.PFI.Decode(_imageFormat.ReadDiskTag(MediaTagType.DVD_PFI)); if (pfi.HasValue) @@ -477,7 +293,7 @@ namespace DiscImageChef.Commands break; case MediaTagType.CD_PMA: sidecar.OpticalDisc[0].PMA = new DumpType(); - sidecar.OpticalDisc[0].PMA.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.CD_PMA)).ToArray(); + sidecar.OpticalDisc[0].PMA.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.CD_PMA)).ToArray(); sidecar.OpticalDisc[0].PMA.Size = _imageFormat.ReadDiskTag(MediaTagType.CD_PMA).Length; break; } @@ -583,64 +399,7 @@ namespace DiscImageChef.Commands uint sectorsToRead = 512; - adler32ctx = new Adler32Context(); - crc16ctx = new CRC16Context(); - crc32ctx = new CRC32Context(); - crc64ctx = new CRC64Context(); - md5ctx = new MD5Context(); - ripemd160ctx = new RIPEMD160Context(); - sha1ctx = new SHA1Context(); - sha256ctx = new SHA256Context(); - sha384ctx = new SHA384Context(); - sha512ctx = new SHA512Context(); - ssctx = new SpamSumContext(); - - adlerThread = new Thread(updateAdler); - crc16Thread = new Thread(updateCRC16); - crc32Thread = new Thread(updateCRC32); - crc64Thread = new Thread(updateCRC64); - md5Thread = new Thread(updateMD5); - ripemd160Thread = new Thread(updateRIPEMD160); - sha1Thread = new Thread(updateSHA1); - sha256Thread = new Thread(updateSHA256); - sha384Thread = new Thread(updateSHA384); - sha512Thread = new Thread(updateSHA512); - spamsumThread = new Thread(updateSpamSum); - - adlerPkt = new adlerPacket(); - crc16Pkt = new crc16Packet(); - crc32Pkt = new crc32Packet(); - crc64Pkt = new crc64Packet(); - md5Pkt = new md5Packet(); - ripemd160Pkt = new ripemd160Packet(); - sha1Pkt = new sha1Packet(); - sha256Pkt = new sha256Packet(); - sha384Pkt = new sha384Packet(); - sha512Pkt = new sha512Packet(); - spamsumPkt = new spamsumPacket(); - - adler32ctx.Init(); - adlerPkt.context = adler32ctx; - crc16ctx.Init(); - crc16Pkt.context = crc16ctx; - crc32ctx.Init(); - crc32Pkt.context = crc32ctx; - crc64ctx.Init(); - crc64Pkt.context = crc64ctx; - md5ctx.Init(); - md5Pkt.context = md5ctx; - ripemd160ctx.Init(); - ripemd160Pkt.context = ripemd160ctx; - sha1ctx.Init(); - sha1Pkt.context = sha1ctx; - sha256ctx.Init(); - sha256Pkt.context = sha256ctx; - sha384ctx.Init(); - sha384Pkt.context = sha384ctx; - sha512ctx.Init(); - sha512Pkt.context = sha512ctx; - ssctx.Init(); - spamsumPkt.context = ssctx; + Core.Checksum trkChkWorker = new DiscImageChef.Core.Checksum(); ulong sectors = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1); ulong doneSectors = 0; @@ -662,107 +421,10 @@ namespace DiscImageChef.Commands doneSectors += (sectors - doneSectors); } - adlerPkt.data = sector; - adlerThread.Start(adlerPkt); - crc16Pkt.data = sector; - crc16Thread.Start(crc16Pkt); - crc32Pkt.data = sector; - crc32Thread.Start(crc32Pkt); - crc64Pkt.data = sector; - crc64Thread.Start(crc64Pkt); - md5Pkt.data = sector; - md5Thread.Start(md5Pkt); - ripemd160Pkt.data = sector; - ripemd160Thread.Start(ripemd160Pkt); - sha1Pkt.data = sector; - sha1Thread.Start(sha1Pkt); - sha256Pkt.data = sector; - sha256Thread.Start(sha256Pkt); - sha384Pkt.data = sector; - sha384Thread.Start(sha384Pkt); - sha512Pkt.data = sector; - sha512Thread.Start(sha512Pkt); - spamsumPkt.data = sector; - spamsumThread.Start(spamsumPkt); - - while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) - { - } - - adlerThread = new Thread(updateAdler); - crc16Thread = new Thread(updateCRC16); - crc32Thread = new Thread(updateCRC32); - crc64Thread = new Thread(updateCRC64); - md5Thread = new Thread(updateMD5); - ripemd160Thread = new Thread(updateRIPEMD160); - sha1Thread = new Thread(updateSHA1); - sha256Thread = new Thread(updateSHA256); - sha384Thread = new Thread(updateSHA384); - sha512Thread = new Thread(updateSHA512); - spamsumThread = new Thread(updateSpamSum); + trkChkWorker.Update(sector); } - List trkChecksums = new List(); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.adler32; - chk.Value = adler32ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc16; - chk.Value = crc16ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc32; - chk.Value = crc32ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc64; - chk.Value = crc64ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.md5; - chk.Value = md5ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.ripemd160; - chk.Value = ripemd160ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha1; - chk.Value = sha1ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha256; - chk.Value = sha256ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha384; - chk.Value = sha384ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha512; - chk.Value = sha512ctx.End(); - trkChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.spamsum; - chk.Value = ssctx.End(); - trkChecksums.Add(chk); + List trkChecksums = trkChkWorker.End(); xmlTrk.Checksums = trkChecksums.ToArray(); @@ -794,64 +456,7 @@ namespace DiscImageChef.Commands // TODO: Packed subchannel has different size? xmlTrk.SubChannel.Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * 96; - adler32ctx = new Adler32Context(); - crc16ctx = new CRC16Context(); - crc32ctx = new CRC32Context(); - crc64ctx = new CRC64Context(); - md5ctx = new MD5Context(); - ripemd160ctx = new RIPEMD160Context(); - sha1ctx = new SHA1Context(); - sha256ctx = new SHA256Context(); - sha384ctx = new SHA384Context(); - sha512ctx = new SHA512Context(); - ssctx = new SpamSumContext(); - - adlerThread = new Thread(updateAdler); - crc16Thread = new Thread(updateCRC16); - crc32Thread = new Thread(updateCRC32); - crc64Thread = new Thread(updateCRC64); - md5Thread = new Thread(updateMD5); - ripemd160Thread = new Thread(updateRIPEMD160); - sha1Thread = new Thread(updateSHA1); - sha256Thread = new Thread(updateSHA256); - sha384Thread = new Thread(updateSHA384); - sha512Thread = new Thread(updateSHA512); - spamsumThread = new Thread(updateSpamSum); - - adlerPkt = new adlerPacket(); - crc16Pkt = new crc16Packet(); - crc32Pkt = new crc32Packet(); - crc64Pkt = new crc64Packet(); - md5Pkt = new md5Packet(); - ripemd160Pkt = new ripemd160Packet(); - sha1Pkt = new sha1Packet(); - sha256Pkt = new sha256Packet(); - sha384Pkt = new sha384Packet(); - sha512Pkt = new sha512Packet(); - spamsumPkt = new spamsumPacket(); - - adler32ctx.Init(); - adlerPkt.context = adler32ctx; - crc16ctx.Init(); - crc16Pkt.context = crc16ctx; - crc32ctx.Init(); - crc32Pkt.context = crc32ctx; - crc64ctx.Init(); - crc64Pkt.context = crc64ctx; - md5ctx.Init(); - md5Pkt.context = md5ctx; - ripemd160ctx.Init(); - ripemd160Pkt.context = ripemd160ctx; - sha1ctx.Init(); - sha1Pkt.context = sha1ctx; - sha256ctx.Init(); - sha256Pkt.context = sha256ctx; - sha384ctx.Init(); - sha384Pkt.context = sha384ctx; - sha512ctx.Init(); - sha512Pkt.context = sha512ctx; - ssctx.Init(); - spamsumPkt.context = ssctx; + Core.Checksum subChkWorker = new DiscImageChef.Core.Checksum(); sectors = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1); doneSectors = 0; @@ -873,107 +478,10 @@ namespace DiscImageChef.Commands doneSectors += (sectors - doneSectors); } - adlerPkt.data = sector; - adlerThread.Start(adlerPkt); - crc16Pkt.data = sector; - crc16Thread.Start(crc16Pkt); - crc32Pkt.data = sector; - crc32Thread.Start(crc32Pkt); - crc64Pkt.data = sector; - crc64Thread.Start(crc64Pkt); - md5Pkt.data = sector; - md5Thread.Start(md5Pkt); - ripemd160Pkt.data = sector; - ripemd160Thread.Start(ripemd160Pkt); - sha1Pkt.data = sector; - sha1Thread.Start(sha1Pkt); - sha256Pkt.data = sector; - sha256Thread.Start(sha256Pkt); - sha384Pkt.data = sector; - sha384Thread.Start(sha384Pkt); - sha512Pkt.data = sector; - sha512Thread.Start(sha512Pkt); - spamsumPkt.data = sector; - spamsumThread.Start(spamsumPkt); - - while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) - { - } - - adlerThread = new Thread(updateAdler); - crc16Thread = new Thread(updateCRC16); - crc32Thread = new Thread(updateCRC32); - crc64Thread = new Thread(updateCRC64); - md5Thread = new Thread(updateMD5); - ripemd160Thread = new Thread(updateRIPEMD160); - sha1Thread = new Thread(updateSHA1); - sha256Thread = new Thread(updateSHA256); - sha384Thread = new Thread(updateSHA384); - sha512Thread = new Thread(updateSHA512); - spamsumThread = new Thread(updateSpamSum); + subChkWorker.Update(sector); } - List subChecksums = new List(); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.adler32; - chk.Value = adler32ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc16; - chk.Value = crc16ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc32; - chk.Value = crc32ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.crc64; - chk.Value = crc64ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.md5; - chk.Value = md5ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.ripemd160; - chk.Value = ripemd160ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha1; - chk.Value = sha1ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha256; - chk.Value = sha256ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha384; - chk.Value = sha384ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.sha512; - chk.Value = sha512ctx.End(); - subChecksums.Add(chk); - - chk = new ChecksumType(); - chk.type = ChecksumTypeType.spamsum; - chk.Value = ssctx.End(); - subChecksums.Add(chk); + List subChecksums = subChkWorker.End(); xmlTrk.SubChannel.Checksums = subChecksums.ToArray(); @@ -1103,46 +611,46 @@ namespace DiscImageChef.Commands case MediaTagType.ATAPI_IDENTIFY: sidecar.BlockMedia[0].ATA = new ATAType(); sidecar.BlockMedia[0].ATA.Identify = new DumpType(); - sidecar.BlockMedia[0].ATA.Identify.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).ToArray(); + sidecar.BlockMedia[0].ATA.Identify.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).ToArray(); sidecar.BlockMedia[0].ATA.Identify.Size = _imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length; break; case MediaTagType.ATA_IDENTIFY: sidecar.BlockMedia[0].ATA = new ATAType(); sidecar.BlockMedia[0].ATA.Identify = new DumpType(); - sidecar.BlockMedia[0].ATA.Identify.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).ToArray(); + sidecar.BlockMedia[0].ATA.Identify.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).ToArray(); sidecar.BlockMedia[0].ATA.Identify.Size = _imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length; break; case MediaTagType.PCMCIA_CIS: sidecar.BlockMedia[0].PCMCIA = new PCMCIAType(); sidecar.BlockMedia[0].PCMCIA.CIS = new DumpType(); - sidecar.BlockMedia[0].PCMCIA.CIS.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS)).ToArray(); + sidecar.BlockMedia[0].PCMCIA.CIS.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS)).ToArray(); sidecar.BlockMedia[0].PCMCIA.CIS.Size = _imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS).Length; break; case MediaTagType.SCSI_INQUIRY: sidecar.BlockMedia[0].SCSI = new SCSIType(); sidecar.BlockMedia[0].SCSI.Inquiry = new DumpType(); - sidecar.BlockMedia[0].SCSI.Inquiry.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).ToArray(); + sidecar.BlockMedia[0].SCSI.Inquiry.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).ToArray(); sidecar.BlockMedia[0].SCSI.Inquiry.Size = _imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length; break; case MediaTagType.SD_CID: if(sidecar.BlockMedia[0].SecureDigital == null) sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital.CID = new DumpType(); - sidecar.BlockMedia[0].SecureDigital.CID.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SD_CID)).ToArray(); + sidecar.BlockMedia[0].SecureDigital.CID.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SD_CID)).ToArray(); sidecar.BlockMedia[0].SecureDigital.CID.Size = _imageFormat.ReadDiskTag(MediaTagType.SD_CID).Length; break; case MediaTagType.SD_CSD: if(sidecar.BlockMedia[0].SecureDigital == null) sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital.CSD = new DumpType(); - sidecar.BlockMedia[0].SecureDigital.CSD.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(); + sidecar.BlockMedia[0].SecureDigital.CSD.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(); sidecar.BlockMedia[0].SecureDigital.CSD.Size = _imageFormat.ReadDiskTag(MediaTagType.SD_CSD).Length; break; case MediaTagType.SD_ExtendedCSD: if(sidecar.BlockMedia[0].SecureDigital == null) sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital.ExtendedCSD = new DumpType(); - sidecar.BlockMedia[0].SecureDigital.ExtendedCSD.Checksums = GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SD_ExtendedCSD)).ToArray(); + sidecar.BlockMedia[0].SecureDigital.ExtendedCSD.Checksums = Core.Checksum.GetChecksums(_imageFormat.ReadDiskTag(MediaTagType.SD_ExtendedCSD)).ToArray(); sidecar.BlockMedia[0].SecureDigital.ExtendedCSD.Size = _imageFormat.ReadDiskTag(MediaTagType.SD_ExtendedCSD).Length; break; } @@ -1360,297 +868,6 @@ namespace DiscImageChef.Commands return String.Format("{3}:{0:D2}:{1:D2}:{2:D2}", m, s, f, h); } - - static List GetChecksums(byte[] data) - { - Adler32Context adler32ctx = new Adler32Context(); - CRC16Context crc16ctx = new CRC16Context(); - CRC32Context crc32ctx = new CRC32Context(); - CRC64Context crc64ctx = new CRC64Context(); - MD5Context md5ctx = new MD5Context(); - RIPEMD160Context ripemd160ctx = new RIPEMD160Context(); - SHA1Context sha1ctx = new SHA1Context(); - SHA256Context sha256ctx = new SHA256Context(); - SHA384Context sha384ctx = new SHA384Context(); - SHA512Context sha512ctx = new SHA512Context(); - SpamSumContext ssctx = new SpamSumContext(); - - Thread adlerThread = new Thread(updateAdler); - Thread crc16Thread = new Thread(updateCRC16); - Thread crc32Thread = new Thread(updateCRC32); - Thread crc64Thread = new Thread(updateCRC64); - Thread md5Thread = new Thread(updateMD5); - Thread ripemd160Thread = new Thread(updateRIPEMD160); - Thread sha1Thread = new Thread(updateSHA1); - Thread sha256Thread = new Thread(updateSHA256); - Thread sha384Thread = new Thread(updateSHA384); - Thread sha512Thread = new Thread(updateSHA512); - Thread spamsumThread = new Thread(updateSpamSum); - - adlerPacket adlerPkt = new adlerPacket(); - crc16Packet crc16Pkt = new crc16Packet(); - crc32Packet crc32Pkt = new crc32Packet(); - crc64Packet crc64Pkt = new crc64Packet(); - md5Packet md5Pkt = new md5Packet(); - ripemd160Packet ripemd160Pkt = new ripemd160Packet(); - sha1Packet sha1Pkt = new sha1Packet(); - sha256Packet sha256Pkt = new sha256Packet(); - sha384Packet sha384Pkt = new sha384Packet(); - sha512Packet sha512Pkt = new sha512Packet(); - spamsumPacket spamsumPkt = new spamsumPacket(); - - adler32ctx.Init(); - adlerPkt.context = adler32ctx; - crc16ctx.Init(); - crc16Pkt.context = crc16ctx; - crc32ctx.Init(); - crc32Pkt.context = crc32ctx; - crc64ctx.Init(); - crc64Pkt.context = crc64ctx; - md5ctx.Init(); - md5Pkt.context = md5ctx; - ripemd160ctx.Init(); - ripemd160Pkt.context = ripemd160ctx; - sha1ctx.Init(); - sha1Pkt.context = sha1ctx; - sha256ctx.Init(); - sha256Pkt.context = sha256ctx; - sha384ctx.Init(); - sha384Pkt.context = sha384ctx; - sha512ctx.Init(); - sha512Pkt.context = sha512ctx; - ssctx.Init(); - spamsumPkt.context = ssctx; - - adlerPkt.data = data; - adlerThread.Start(adlerPkt); - crc16Pkt.data = data; - crc16Thread.Start(crc16Pkt); - crc32Pkt.data = data; - crc32Thread.Start(crc32Pkt); - crc64Pkt.data = data; - crc64Thread.Start(crc64Pkt); - md5Pkt.data = data; - md5Thread.Start(md5Pkt); - ripemd160Pkt.data = data; - ripemd160Thread.Start(ripemd160Pkt); - sha1Pkt.data = data; - sha1Thread.Start(sha1Pkt); - sha256Pkt.data = data; - sha256Thread.Start(sha256Pkt); - sha384Pkt.data = data; - sha384Thread.Start(sha384Pkt); - sha512Pkt.data = data; - sha512Thread.Start(sha512Pkt); - spamsumPkt.data = data; - spamsumThread.Start(spamsumPkt); - - while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) - { - } - - List imgChecksums = new List(); - ChecksumType chk = new ChecksumType(); - - chk.type = ChecksumTypeType.adler32; - chk.Value = adler32ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.crc16; - chk.Value = crc16ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.crc32; - chk.Value = crc32ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.crc64; - chk.Value = crc64ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.md5; - chk.Value = md5ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.ripemd160; - chk.Value = ripemd160ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.sha1; - chk.Value = sha1ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.sha256; - chk.Value = sha256ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.sha384; - chk.Value = sha384ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.sha512; - chk.Value = sha512ctx.End(); - imgChecksums.Add(chk); - - chk.type = ChecksumTypeType.spamsum; - chk.Value = ssctx.End(); - imgChecksums.Add(chk); - - return imgChecksums; - } - - #region Threading helpers - - struct adlerPacket - { - public Adler32Context context; - public byte[] data; - } - - struct crc16Packet - { - public CRC16Context context; - public byte[] data; - } - - struct crc32Packet - { - public CRC32Context context; - public byte[] data; - } - - struct crc64Packet - { - public CRC64Context context; - public byte[] data; - } - - /*struct fletcher16Packet - { - public Fletcher16Context context; - public byte[] data; - } - - struct fletcher32Packet - { - public Fletcher32Context context; - public byte[] data; - }*/ - - struct md5Packet - { - public MD5Context context; - public byte[] data; - } - - struct ripemd160Packet - { - public RIPEMD160Context context; - public byte[] data; - } - - struct sha1Packet - { - public SHA1Context context; - public byte[] data; - } - - struct sha256Packet - { - public SHA256Context context; - public byte[] data; - } - - struct sha384Packet - { - public SHA384Context context; - public byte[] data; - } - - struct sha512Packet - { - public SHA512Context context; - public byte[] data; - } - - struct spamsumPacket - { - public SpamSumContext context; - public byte[] data; - } - - static void updateAdler(object packet) - { - ((adlerPacket)packet).context.Update(((adlerPacket)packet).data); - } - - static void updateCRC16(object packet) - { - ((crc16Packet)packet).context.Update(((crc16Packet)packet).data); - } - - static void updateCRC32(object packet) - { - ((crc32Packet)packet).context.Update(((crc32Packet)packet).data); - } - - static void updateCRC64(object packet) - { - ((crc64Packet)packet).context.Update(((crc64Packet)packet).data); - } - - /*static void updateFletcher16(object packet) - { - ((fletcher16Packet)packet).context.Update(((fletcher16Packet)packet).data); - } - - static void updateFletcher32(object packet) - { - ((fletcher32Packet)packet).context.Update(((fletcher32Packet)packet).data); - }*/ - - static void updateMD5(object packet) - { - ((md5Packet)packet).context.Update(((md5Packet)packet).data); - } - - static void updateRIPEMD160(object packet) - { - ((ripemd160Packet)packet).context.Update(((ripemd160Packet)packet).data); - } - - static void updateSHA1(object packet) - { - ((sha1Packet)packet).context.Update(((sha1Packet)packet).data); - } - - static void updateSHA256(object packet) - { - ((sha256Packet)packet).context.Update(((sha256Packet)packet).data); - } - - static void updateSHA384(object packet) - { - ((sha384Packet)packet).context.Update(((sha384Packet)packet).data); - } - - static void updateSHA512(object packet) - { - ((sha512Packet)packet).context.Update(((sha512Packet)packet).data); - } - - static void updateSpamSum(object packet) - { - ((spamsumPacket)packet).context.Update(((spamsumPacket)packet).data); - } - - #endregion Threading helpers - } } diff --git a/DiscImageChef/Commands/DeviceInfo.cs b/DiscImageChef/Commands/DeviceInfo.cs index 8f011c03..3c9be34b 100644 --- a/DiscImageChef/Commands/DeviceInfo.cs +++ b/DiscImageChef/Commands/DeviceInfo.cs @@ -164,7 +164,7 @@ namespace DiscImageChef.Commands if (dev.Type != DeviceType.ATAPI) DicConsole.WriteLine("SCSI device"); - doWriteFile(options.OutputPrefix, "_scsi_inquiry.bin", "SCSI IDENTIFY", inqBuf); + doWriteFile(options.OutputPrefix, "_scsi_inquiry.bin", "SCSI INQUIRY", inqBuf); Decoders.SCSI.Inquiry.SCSIInquiry? inq = Decoders.SCSI.Inquiry.Decode(inqBuf); DicConsole.WriteLine(Decoders.SCSI.Inquiry.Prettify(inq)); @@ -237,10 +237,10 @@ namespace DiscImageChef.Commands Decoders.SCSI.Modes.DecodedMode? decMode = null; Decoders.SCSI.PeripheralDeviceTypes devType = (DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes)inq.Value.PeripheralDeviceType; - sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, dev.Timeout, out duration); + sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration); if (sense || dev.Error) { - sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, dev.Timeout, out duration); + sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); } if (!sense && !dev.Error) @@ -250,11 +250,11 @@ namespace DiscImageChef.Commands if(sense || dev.Error || !decMode.HasValue) { - sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, dev.Timeout, out duration); + sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration); if (sense || dev.Error) - sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, dev.Timeout, out duration); + sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); if (sense || dev.Error) - sense = dev.ModeSense(out modeBuf, out senseBuf, 15000, out duration); + sense = dev.ModeSense(out modeBuf, out senseBuf, 5, out duration); if (!sense && !dev.Error) decMode = Decoders.SCSI.Modes.DecodeMode6(modeBuf, devType); @@ -477,7 +477,7 @@ namespace DiscImageChef.Commands } case 0x3E: { - if (StringHandlers.SpacePaddedToString(inq.Value.VendorIdentification) == "FUJITSU") + if (StringHandlers.CToString(inq.Value.VendorIdentification).Trim() == "FUJITSU") DicConsole.WriteLine(Decoders.SCSI.Modes.PrettifyFujitsuModePage_3E(page.PageResponse)); else goto default; diff --git a/DiscImageChef/Commands/DeviceReport.cs b/DiscImageChef/Commands/DeviceReport.cs new file mode 100644 index 00000000..ae5062bd --- /dev/null +++ b/DiscImageChef/Commands/DeviceReport.cs @@ -0,0 +1,3451 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : DeviceReport.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using DiscImageChef.Console; +using DiscImageChef.Devices; +using DiscImageChef.Metadata; +using System.IO; +using System.Collections.Generic; + +namespace DiscImageChef.Commands +{ + public static class DeviceReport + { + public static void doDeviceReport(DeviceReportSubOptions options) + { + DicConsole.DebugWriteLine("Device-Report command", "--debug={0}", options.Debug); + DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", options.Verbose); + DicConsole.DebugWriteLine("Device-Report command", "--device={0}", options.DevicePath); + + if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && + options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0])) + { + options.DevicePath = "\\\\.\\" + Char.ToUpper(options.DevicePath[0]) + ':'; + } + + Device dev = new Device(options.DevicePath); + + if (dev.Error) + { + DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); + return; + } + + switch (dev.Type) + { + case DeviceType.ATA: + doATADeviceReport(options, dev); + break; + case DeviceType.MMC: + case DeviceType.SecureDigital: + doSDDeviceReport(options, dev); + break; + case DeviceType.NVMe: + doNVMeDeviceReport(options, dev); + break; + case DeviceType.ATAPI: + case DeviceType.SCSI: + doSCSIDeviceReport(options, dev); + break; + default: + throw new NotSupportedException("Unknown device type."); + } + } + + static void doATADeviceReport(DeviceReportSubOptions options, Device dev) + { + DiscImageChef.Decoders.ATA.AtaErrorRegistersCHS errorRegs; + byte[] buffer; + double duration; + uint timeout = 5; + Metadata.DeviceReport report = new Metadata.DeviceReport(); + string xmlFile; + if (!string.IsNullOrWhiteSpace(dev.Manufacturer) && !string.IsNullOrWhiteSpace(dev.Revision)) + xmlFile = dev.Manufacturer + "_" + dev.Model + "_" + dev.Revision + ".xml"; + else if (!string.IsNullOrWhiteSpace(dev.Manufacturer)) + xmlFile = dev.Manufacturer + "_" + dev.Model + ".xml"; + else if (!string.IsNullOrWhiteSpace(dev.Revision)) + xmlFile = dev.Model + "_" + dev.Revision + ".xml"; + else + xmlFile = dev.Model + ".xml"; + + ConsoleKeyInfo pressedKey; + + if (dev.IsUSB) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the device natively USB (in case of doubt, press Y)? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + report.USB = new usbType(); + report.USB.Manufacturer = dev.USBManufacturerString; + report.USB.Product = dev.USBProductString; + report.USB.ProductID = dev.USBProductID; + report.USB.VendorID = dev.USBVendorID; + + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the media removable from the reading/writing elements? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + report.USB.RemovableMedia = pressedKey.Key == ConsoleKey.Y; + } + } + + if (dev.IsFireWire) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the device natively FireWire (in case of doubt, press Y)? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + report.FireWire = new firewireType(); + report.FireWire.Manufacturer = dev.FireWireVendorName; + report.FireWire.Product = dev.FireWireModelName; + report.FireWire.ProductID = dev.FireWireModel; + report.FireWire.VendorID = dev.FireWireVendor; + + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the media removable from the reading/writing elements? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + report.FireWire.RemovableMedia = pressedKey.Key == ConsoleKey.Y; + } + } + + DicConsole.WriteLine("Querying ATA IDENTIFY..."); + + dev.AtaIdentify(out buffer, out errorRegs, timeout, out duration); + + if (Decoders.ATA.Identify.Decode(buffer).HasValue) + { + Decoders.ATA.Identify.IdentifyDevice ataId = Decoders.ATA.Identify.Decode(buffer).Value; + + report.ATA = new ataType(); + + if (ataId.CurrentCylinders != 0 || + ataId.CurrentHeads != 0 || + ataId.CurrentSectorsPerTrack != 0) + { + report.ATA.CHS = new chsType(); + report.ATA.CHS.Cylinders = ataId.Cylinders; + report.ATA.CHS.Heads = ataId.Heads; + report.ATA.CHS.Sectors = ataId.SectorsPerTrack; + } + + if ((ataId.Cylinders != ataId.CurrentCylinders || + ataId.Heads != ataId.CurrentHeads || + ataId.SectorsPerTrack != ataId.CurrentSectorsPerTrack) && + (ataId.CurrentCylinders != 0 || + ataId.CurrentHeads != 0 || + ataId.CurrentSectorsPerTrack != 0)) + { + report.ATA.CurrentCHS = new chsType(); + report.ATA.CurrentCHS.Cylinders = ataId.CurrentCylinders; + report.ATA.CurrentCHS.Heads = ataId.CurrentHeads; + report.ATA.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack; + } + + if (ataId.Capabilities.HasFlag(Decoders.ATA.Identify.CapabilitiesBit.LBASupport) && ataId.LBASectors != 0) + { + report.ATA.LBASectors = ataId.LBASectors; + report.ATA.LBASectorsSpecified = true; + + if (ataId.LBASectors != 0 && ataId.LBASectors != ataId.CurrentSectors) + { + report.ATA.LBASectorsCurrent = ataId.LBASectors; + report.ATA.LBASectorsCurrentSpecified = true; + } + } + + if (ataId.CommandSet2.HasFlag(Decoders.ATA.Identify.CommandSetBit2.LBA48) && ataId.LBA48Sectors != 0) + { + report.ATA.LBA48Sectors = ataId.LBA48Sectors; + report.ATA.LBA48SectorsSpecified = true; + } + + if (!string.IsNullOrWhiteSpace(ataId.AdditionalPID)) + { + report.ATA.AdditionalPID = ataId.AdditionalPID; + report.ATA.AdditionalPIDSpecified = true; + } + if (ataId.APIOSupported != 0) + { + report.ATA.APIOSupported = ataId.APIOSupported; + report.ATA.APIOSupportedSpecified = true; + } + if (ataId.BufferType != 0) + { + report.ATA.BufferType = ataId.BufferType; + report.ATA.BufferTypeSpecified = true; + } + if (ataId.BufferSize != 0) + { + report.ATA.BufferSize = ataId.BufferSize; + report.ATA.BufferSizeSpecified = true; + } + if (ataId.Capabilities != 0) + { + report.ATA.Capabilities = ataId.Capabilities; + report.ATA.CapabilitiesSpecified = true; + } + if (ataId.Capabilities2 != 0) + { + report.ATA.Capabilities2 = ataId.Capabilities2; + report.ATA.Capabilities2Specified = true; + } + if (ataId.Capabilities3 != 0) + { + report.ATA.Capabilities3 = ataId.Capabilities3; + report.ATA.Capabilities3Specified = true; + } + if (ataId.CFAPowerMode != 0) + { + report.ATA.CFAPowerMode = ataId.CFAPowerMode; + report.ATA.CFAPowerModeSpecified = true; + } + if (ataId.CommandSet != 0) + { + report.ATA.CommandSet = ataId.CommandSet; + report.ATA.CommandSetSpecified = true; + } + if (ataId.CommandSet2 != 0) + { + report.ATA.CommandSet2 = ataId.CommandSet2; + report.ATA.CommandSet2Specified = true; + } + if (ataId.CommandSet3 != 0) + { + report.ATA.CommandSet3 = ataId.CommandSet3; + report.ATA.CommandSet3Specified = true; + } + if (ataId.CommandSet4 != 0) + { + report.ATA.CommandSet4 = ataId.CommandSet4; + report.ATA.CommandSet4Specified = true; + } + if (ataId.CommandSet5 != 0) + { + report.ATA.CommandSet5 = ataId.CommandSet5; + report.ATA.CommandSet5Specified = true; + } + if (ataId.CurrentAAM != 0) + { + report.ATA.CurrentAAM = ataId.CurrentAAM; + report.ATA.CurrentAAMSpecified = true; + } + if (ataId.CurrentAPM != 0) + { + report.ATA.CurrentAPM = ataId.CurrentAPM; + report.ATA.CurrentAPMSpecified = true; + } + if (ataId.DataSetMgmt != 0) + { + report.ATA.DataSetMgmt = ataId.DataSetMgmt; + report.ATA.DataSetMgmtSpecified = true; + } + if (ataId.DataSetMgmtSize != 0) + { + report.ATA.DataSetMgmtSize = ataId.DataSetMgmtSize; + report.ATA.DataSetMgmtSizeSpecified = true; + } + if (ataId.DeviceFormFactor != 0) + { + report.ATA.DeviceFormFactor = ataId.DeviceFormFactor; + report.ATA.DeviceFormFactorSpecified = true; + } + if (ataId.DMAActive != 0) + { + report.ATA.DMAActive = ataId.DMAActive; + report.ATA.DMAActiveSpecified = true; + } + if (ataId.DMASupported != 0) + { + report.ATA.DMASupported = ataId.DMASupported; + report.ATA.DMASupportedSpecified = true; + } + if (ataId.DMATransferTimingMode != 0) + { + report.ATA.DMATransferTimingMode = ataId.DMATransferTimingMode; + report.ATA.DMATransferTimingModeSpecified = true; + } + if (ataId.EccBytes != 0) + { + report.ATA.EccBytes = ataId.EccBytes; + report.ATA.EccBytesSpecified = true; + } + if (ataId.EnhancedSecurityEraseTime != 0) + { + report.ATA.EnhancedSecurityEraseTime = ataId.EnhancedSecurityEraseTime; + report.ATA.EnhancedSecurityEraseTimeSpecified = true; + } + if (ataId.EnabledCommandSet != 0) + { + report.ATA.EnabledCommandSet = ataId.EnabledCommandSet; + report.ATA.EnabledCommandSetSpecified = true; + } + if (ataId.EnabledCommandSet2 != 0) + { + report.ATA.EnabledCommandSet2 = ataId.EnabledCommandSet2; + report.ATA.EnabledCommandSet2Specified = true; + } + if (ataId.EnabledCommandSet3 != 0) + { + report.ATA.EnabledCommandSet3 = ataId.EnabledCommandSet3; + report.ATA.EnabledCommandSet3Specified = true; + } + if (ataId.EnabledCommandSet4 != 0) + { + report.ATA.EnabledCommandSet4 = ataId.EnabledCommandSet4; + report.ATA.EnabledCommandSet4Specified = true; + } + if (ataId.EnabledSATAFeatures != 0) + { + report.ATA.EnabledSATAFeatures = ataId.EnabledSATAFeatures; + report.ATA.EnabledSATAFeaturesSpecified = true; + } + if (ataId.ExtendedUserSectors != 0) + { + report.ATA.ExtendedUserSectors = ataId.ExtendedUserSectors; + report.ATA.ExtendedUserSectorsSpecified = true; + } + if (ataId.FreeFallSensitivity != 0) + { + report.ATA.FreeFallSensitivity = ataId.FreeFallSensitivity; + report.ATA.FreeFallSensitivitySpecified = true; + } + if (!string.IsNullOrWhiteSpace(ataId.FirmwareRevision)) + { + report.ATA.FirmwareRevision = ataId.FirmwareRevision; + report.ATA.FirmwareRevisionSpecified = true; + } + if (ataId.GeneralConfiguration != 0) + { + report.ATA.GeneralConfiguration = ataId.GeneralConfiguration; + report.ATA.GeneralConfigurationSpecified = true; + } + if (ataId.HardwareResetResult != 0) + { + report.ATA.HardwareResetResult = ataId.HardwareResetResult; + report.ATA.HardwareResetResultSpecified = true; + } + if (ataId.InterseekDelay != 0) + { + report.ATA.InterseekDelay = ataId.InterseekDelay; + report.ATA.InterseekDelaySpecified = true; + } + if (ataId.LogicalAlignment != 0) + { + report.ATA.LogicalAlignment = ataId.LogicalAlignment; + report.ATA.LogicalAlignmentSpecified = true; + } + if (ataId.LogicalSectorWords != 0) + { + report.ATA.LogicalSectorWords = ataId.LogicalSectorWords; + report.ATA.LogicalSectorWordsSpecified = true; + } + if (ataId.MajorVersion != 0) + { + report.ATA.MajorVersion = ataId.MajorVersion; + report.ATA.MajorVersionSpecified = true; + } + if (ataId.MasterPasswordRevisionCode != 0) + { + report.ATA.MasterPasswordRevisionCode = ataId.MasterPasswordRevisionCode; + report.ATA.MasterPasswordRevisionCodeSpecified = true; + } + if (ataId.MaxDownloadMicroMode3 != 0) + { + report.ATA.MaxDownloadMicroMode3 = ataId.MaxDownloadMicroMode3; + report.ATA.MaxDownloadMicroMode3Specified = true; + } + if (ataId.MaxQueueDepth != 0) + { + report.ATA.MaxQueueDepth = ataId.MaxQueueDepth; + report.ATA.MaxQueueDepthSpecified = true; + } + if (ataId.MDMAActive != 0) + { + report.ATA.MDMAActive = ataId.MDMAActive; + report.ATA.MDMAActiveSpecified = true; + } + if (ataId.MDMASupported != 0) + { + report.ATA.MDMASupported = ataId.MDMASupported; + report.ATA.MDMASupportedSpecified = true; + } + if (ataId.MinDownloadMicroMode3 != 0) + { + report.ATA.MinDownloadMicroMode3 = ataId.MinDownloadMicroMode3; + report.ATA.MinDownloadMicroMode3Specified = true; + } + if (ataId.MinMDMACycleTime != 0) + { + report.ATA.MinMDMACycleTime = ataId.MinMDMACycleTime; + report.ATA.MinMDMACycleTimeSpecified = true; + } + if (ataId.MinorVersion != 0) + { + report.ATA.MinorVersion = ataId.MinorVersion; + report.ATA.MinorVersionSpecified = true; + } + if (ataId.MinPIOCycleTimeNoFlow != 0) + { + report.ATA.MinPIOCycleTimeNoFlow = ataId.MinPIOCycleTimeNoFlow; + report.ATA.MinPIOCycleTimeNoFlowSpecified = true; + } + if (ataId.MinPIOCycleTimeFlow != 0) + { + report.ATA.MinPIOCycleTimeFlow = ataId.MinPIOCycleTimeFlow; + report.ATA.MinPIOCycleTimeFlowSpecified = true; + } + if (!string.IsNullOrWhiteSpace(ataId.Model)) + { + report.ATA.Model = ataId.Model; + report.ATA.ModelSpecified = true; + } + if (ataId.MultipleMaxSectors != 0) + { + report.ATA.MultipleMaxSectors = ataId.MultipleMaxSectors; + report.ATA.MultipleMaxSectorsSpecified = true; + } + if (ataId.MultipleSectorNumber != 0) + { + report.ATA.MultipleSectorNumber = ataId.MultipleSectorNumber; + report.ATA.MultipleSectorNumberSpecified = true; + } + if (ataId.NVCacheCaps != 0) + { + report.ATA.NVCacheCaps = ataId.NVCacheCaps; + report.ATA.NVCacheCapsSpecified = true; + } + if (ataId.NVCacheSize != 0) + { + report.ATA.NVCacheSize = ataId.NVCacheSize; + report.ATA.NVCacheSizeSpecified = true; + } + if (ataId.NVCacheWriteSpeed != 0) + { + report.ATA.NVCacheWriteSpeed = ataId.NVCacheWriteSpeed; + report.ATA.NVCacheWriteSpeedSpecified = true; + } + if (ataId.NVEstimatedSpinUp != 0) + { + report.ATA.NVEstimatedSpinUp = ataId.NVEstimatedSpinUp; + report.ATA.NVEstimatedSpinUpSpecified = true; + } + if (ataId.NominalRotationRate != 0) + { + report.ATA.NominalRotationRate = ataId.NominalRotationRate; + report.ATA.NominalRotationRateSpecified = true; + } + if (ataId.PacketBusRelease != 0) + { + report.ATA.PacketBusRelease = ataId.PacketBusRelease; + report.ATA.PacketBusReleaseSpecified = true; + } + if (ataId.PhysLogSectorSize != 0) + { + report.ATA.PhysLogSectorSize = ataId.PhysLogSectorSize; + report.ATA.PhysLogSectorSizeSpecified = true; + } + if (ataId.PIOTransferTimingMode != 0) + { + report.ATA.PIOTransferTimingMode = ataId.PIOTransferTimingMode; + report.ATA.PIOTransferTimingModeSpecified = true; + } + if (ataId.RecommendedAAM != 0) + { + report.ATA.RecommendedAAM = ataId.RecommendedAAM; + report.ATA.RecommendedAAMSpecified = true; + } + if (ataId.RecMDMACycleTime != 0) + { + report.ATA.RecommendedMDMACycleTime = ataId.RecMDMACycleTime; + report.ATA.RecommendedMDMACycleTimeSpecified = true; + } + if (ataId.RemovableStatusSet != 0) + { + report.ATA.RemovableStatusSet = ataId.RemovableStatusSet; + report.ATA.RemovableStatusSetSpecified = true; + } + if (ataId.SATACapabilities != 0) + { + report.ATA.SATACapabilities = ataId.SATACapabilities; + report.ATA.SATACapabilitiesSpecified = true; + } + if (ataId.SATACapabilities2 != 0) + { + report.ATA.SATACapabilities2 = ataId.SATACapabilities2; + report.ATA.SATACapabilities2Specified = true; + } + if (ataId.SATAFeatures != 0) + { + report.ATA.SATAFeatures = ataId.SATAFeatures; + report.ATA.SATAFeaturesSpecified = true; + } + if (ataId.SCTCommandTransport != 0) + { + report.ATA.SCTCommandTransport = ataId.SCTCommandTransport; + report.ATA.SCTCommandTransportSpecified = true; + } + if (ataId.SectorsPerCard != 0) + { + report.ATA.SectorsPerCard = ataId.SectorsPerCard; + report.ATA.SectorsPerCardSpecified = true; + } + if (ataId.SecurityEraseTime != 0) + { + report.ATA.SecurityEraseTime = ataId.SecurityEraseTime; + report.ATA.SecurityEraseTimeSpecified = true; + } + if (ataId.SecurityStatus != 0) + { + report.ATA.SecurityStatus = ataId.SecurityStatus; + report.ATA.SecurityStatusSpecified = true; + } + if (ataId.ServiceBusyClear != 0) + { + report.ATA.ServiceBusyClear = ataId.ServiceBusyClear; + report.ATA.ServiceBusyClearSpecified = true; + } + if (ataId.SpecificConfiguration != 0) + { + report.ATA.SpecificConfiguration = ataId.SpecificConfiguration; + report.ATA.SpecificConfigurationSpecified = true; + } + if (ataId.StreamAccessLatency != 0) + { + report.ATA.StreamAccessLatency = ataId.StreamAccessLatency; + report.ATA.StreamAccessLatencySpecified = true; + } + if (ataId.StreamMinReqSize != 0) + { + report.ATA.StreamMinReqSize = ataId.StreamMinReqSize; + report.ATA.StreamMinReqSizeSpecified = true; + } + if (ataId.StreamPerformanceGranularity != 0) + { + report.ATA.StreamPerformanceGranularity = ataId.StreamPerformanceGranularity; + report.ATA.StreamPerformanceGranularitySpecified = true; + } + if (ataId.StreamTransferTimeDMA != 0) + { + report.ATA.StreamTransferTimeDMA = ataId.StreamTransferTimeDMA; + report.ATA.StreamTransferTimeDMASpecified = true; + } + if (ataId.StreamTransferTimePIO != 0) + { + report.ATA.StreamTransferTimePIO = ataId.StreamTransferTimePIO; + report.ATA.StreamTransferTimePIOSpecified = true; + } + if (ataId.TransportMajorVersion != 0) + { + report.ATA.TransportMajorVersion = ataId.TransportMajorVersion; + report.ATA.TransportMajorVersionSpecified = true; + } + if (ataId.TransportMinorVersion != 0) + { + report.ATA.TransportMinorVersion = ataId.TransportMinorVersion; + report.ATA.TransportMinorVersionSpecified = true; + } + if (ataId.TrustedComputing != 0) + { + report.ATA.TrustedComputing = ataId.TrustedComputing; + report.ATA.TrustedComputingSpecified = true; + } + if (ataId.UDMAActive != 0) + { + report.ATA.UDMAActive = ataId.UDMAActive; + report.ATA.UDMAActiveSpecified = true; + } + if (ataId.UDMASupported != 0) + { + report.ATA.UDMASupported = ataId.UDMASupported; + report.ATA.UDMASupportedSpecified = true; + } + if (ataId.UnformattedBPT != 0) + { + report.ATA.UnformattedBPT = ataId.UnformattedBPT; + report.ATA.UnformattedBPTSpecified = true; + } + if (ataId.UnformattedBPS != 0) + { + report.ATA.UnformattedBPS = ataId.UnformattedBPS; + report.ATA.UnformattedBPSSpecified = true; + } + if (ataId.WRVMode != 0) + { + report.ATA.WRVMode = ataId.WRVMode; + report.ATA.WRVModeSpecified = true; + } + if (ataId.WRVSectorCountMode3 != 0) + { + report.ATA.WRVSectorCountMode3 = ataId.WRVSectorCountMode3; + report.ATA.WRVSectorCountMode3Specified = true; + } + if (ataId.WRVSectorCountMode2 != 0) + { + report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2; + report.ATA.WRVSectorCountMode2Specified = true; + } + } + + FileStream xmlFs = new FileStream(xmlFile, FileMode.Create); + + System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(Metadata.DeviceReport)); + xmlSer.Serialize(xmlFs, report); + xmlFs.Close(); + } + + static void doNVMeDeviceReport(DeviceReportSubOptions options, Device dev) + { + throw new NotImplementedException("NVMe devices not yet supported."); + } + + static void doSDDeviceReport(DeviceReportSubOptions options, Device dev) + { + throw new NotImplementedException("MMC/SD devices not yet supported."); + } + + static void doSCSIDeviceReport(DeviceReportSubOptions options, Device dev) + { + byte[] senseBuffer; + byte[] buffer; + double duration; + bool sense; + uint timeout = 5; + Metadata.DeviceReport report = new Metadata.DeviceReport(); + string xmlFile; + if (!string.IsNullOrWhiteSpace(dev.Manufacturer) && !string.IsNullOrWhiteSpace(dev.Revision)) + xmlFile = dev.Manufacturer + "_" + dev.Model + "_" + dev.Revision + ".xml"; + else if (!string.IsNullOrWhiteSpace(dev.Manufacturer)) + xmlFile = dev.Manufacturer + "_" + dev.Model + ".xml"; + else if (!string.IsNullOrWhiteSpace(dev.Revision)) + xmlFile = dev.Model + "_" + dev.Revision + ".xml"; + else + xmlFile = dev.Model + ".xml"; + ConsoleKeyInfo pressedKey; + bool removable = true; + + if (dev.IsUSB) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the device natively USB (in case of doubt, press Y)? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + report.USB = new usbType(); + report.USB.Manufacturer = dev.USBManufacturerString; + report.USB.Product = dev.USBProductString; + report.USB.ProductID = dev.USBProductID; + report.USB.VendorID = dev.USBVendorID; + + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the media removable from the reading/writing elements? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + report.USB.RemovableMedia = pressedKey.Key == ConsoleKey.Y; + removable = report.USB.RemovableMedia; + } + } + + if (dev.IsFireWire) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the device natively FireWire (in case of doubt, press Y)? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + report.FireWire = new firewireType(); + report.FireWire.Manufacturer = dev.FireWireVendorName; + report.FireWire.Product = dev.FireWireModelName; + report.FireWire.ProductID = dev.FireWireModel; + report.FireWire.VendorID = dev.FireWireVendor; + + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the media removable from the reading/writing elements? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + report.FireWire.RemovableMedia = pressedKey.Key == ConsoleKey.Y; + removable = report.FireWire.RemovableMedia; + } + } + + if (!dev.IsUSB && !dev.IsFireWire && dev.IsRemovable) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Is the media removable from the reading/writing elements (flash memories ARE NOT removable)? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + removable = pressedKey.Key == ConsoleKey.Y; + } + + if (dev.Type == DeviceType.ATAPI) + { + DicConsole.WriteLine("Querying ATAPI IDENTIFY..."); + + DiscImageChef.Decoders.ATA.AtaErrorRegistersCHS errorRegs; + dev.AtapiIdentify(out buffer, out errorRegs, timeout, out duration); + + if (Decoders.ATA.Identify.Decode(buffer).HasValue) + { + Decoders.ATA.Identify.IdentifyDevice atapiId = Decoders.ATA.Identify.Decode(buffer).Value; + + report.ATAPI = new ataType(); + + if (atapiId.CurrentCylinders != 0 || + atapiId.CurrentHeads != 0 || + atapiId.CurrentSectorsPerTrack != 0) + { + report.ATAPI.CHS = new chsType(); + report.ATAPI.CHS.Cylinders = atapiId.Cylinders; + report.ATAPI.CHS.Heads = atapiId.Heads; + report.ATAPI.CHS.Sectors = atapiId.SectorsPerTrack; + } + + if ((atapiId.Cylinders != atapiId.CurrentCylinders || + atapiId.Heads != atapiId.CurrentHeads || + atapiId.SectorsPerTrack != atapiId.CurrentSectorsPerTrack) && + (atapiId.CurrentCylinders != 0 || + atapiId.CurrentHeads != 0 || + atapiId.CurrentSectorsPerTrack != 0)) + { + report.ATAPI.CurrentCHS = new chsType(); + report.ATAPI.CurrentCHS.Cylinders = atapiId.CurrentCylinders; + report.ATAPI.CurrentCHS.Heads = atapiId.CurrentHeads; + report.ATAPI.CurrentCHS.Sectors = atapiId.CurrentSectorsPerTrack; + } + + if (atapiId.Capabilities.HasFlag(Decoders.ATA.Identify.CapabilitiesBit.LBASupport) && atapiId.LBASectors != 0) + { + report.ATAPI.LBASectors = atapiId.LBASectors; + report.ATAPI.LBASectorsSpecified = true; + + if (atapiId.LBASectors != 0 && atapiId.LBASectors != atapiId.CurrentSectors) + { + report.ATAPI.LBASectorsCurrent = atapiId.LBASectors; + report.ATAPI.LBASectorsCurrentSpecified = true; + } + } + + if (atapiId.CommandSet2.HasFlag(Decoders.ATA.Identify.CommandSetBit2.LBA48) && atapiId.LBA48Sectors != 0) + { + report.ATAPI.LBA48Sectors = atapiId.LBA48Sectors; + report.ATAPI.LBA48SectorsSpecified = true; + } + + if (!string.IsNullOrWhiteSpace(atapiId.AdditionalPID)) + { + report.ATAPI.AdditionalPID = atapiId.AdditionalPID; + report.ATAPI.AdditionalPIDSpecified = true; + } + if (atapiId.APIOSupported != 0) + { + report.ATAPI.APIOSupported = atapiId.APIOSupported; + report.ATAPI.APIOSupportedSpecified = true; + } + if (atapiId.ATAPIByteCount != 0) + { + report.ATAPI.ATAPIByteCount = atapiId.ATAPIByteCount; + report.ATAPI.ATAPIByteCountSpecified = true; + } + if (atapiId.BufferType != 0) + { + report.ATAPI.BufferType = atapiId.BufferType; + report.ATAPI.BufferTypeSpecified = true; + } + if (atapiId.BufferSize != 0) + { + report.ATAPI.BufferSize = atapiId.BufferSize; + report.ATAPI.BufferSizeSpecified = true; + } + if (atapiId.Capabilities != 0) + { + report.ATAPI.Capabilities = atapiId.Capabilities; + report.ATAPI.CapabilitiesSpecified = true; + } + if (atapiId.Capabilities2 != 0) + { + report.ATAPI.Capabilities2 = atapiId.Capabilities2; + report.ATAPI.Capabilities2Specified = true; + } + if (atapiId.Capabilities3 != 0) + { + report.ATAPI.Capabilities3 = atapiId.Capabilities3; + report.ATAPI.Capabilities3Specified = true; + } + if (atapiId.CFAPowerMode != 0) + { + report.ATAPI.CFAPowerMode = atapiId.CFAPowerMode; + report.ATAPI.CFAPowerModeSpecified = true; + } + if (atapiId.CommandSet != 0) + { + report.ATAPI.CommandSet = atapiId.CommandSet; + report.ATAPI.CommandSetSpecified = true; + } + if (atapiId.CommandSet2 != 0) + { + report.ATAPI.CommandSet2 = atapiId.CommandSet2; + report.ATAPI.CommandSet2Specified = true; + } + if (atapiId.CommandSet3 != 0) + { + report.ATAPI.CommandSet3 = atapiId.CommandSet3; + report.ATAPI.CommandSet3Specified = true; + } + if (atapiId.CommandSet4 != 0) + { + report.ATAPI.CommandSet4 = atapiId.CommandSet4; + report.ATAPI.CommandSet4Specified = true; + } + if (atapiId.CommandSet5 != 0) + { + report.ATAPI.CommandSet5 = atapiId.CommandSet5; + report.ATAPI.CommandSet5Specified = true; + } + if (atapiId.CurrentAAM != 0) + { + report.ATAPI.CurrentAAM = atapiId.CurrentAAM; + report.ATAPI.CurrentAAMSpecified = true; + } + if (atapiId.CurrentAPM != 0) + { + report.ATAPI.CurrentAPM = atapiId.CurrentAPM; + report.ATAPI.CurrentAPMSpecified = true; + } + if (atapiId.DataSetMgmt != 0) + { + report.ATAPI.DataSetMgmt = atapiId.DataSetMgmt; + report.ATAPI.DataSetMgmtSpecified = true; + } + if (atapiId.DataSetMgmtSize != 0) + { + report.ATAPI.DataSetMgmtSize = atapiId.DataSetMgmtSize; + report.ATAPI.DataSetMgmtSizeSpecified = true; + } + if (atapiId.DeviceFormFactor != 0) + { + report.ATAPI.DeviceFormFactor = atapiId.DeviceFormFactor; + report.ATAPI.DeviceFormFactorSpecified = true; + } + if (atapiId.DMAActive != 0) + { + report.ATAPI.DMAActive = atapiId.DMAActive; + report.ATAPI.DMAActiveSpecified = true; + } + if (atapiId.DMASupported != 0) + { + report.ATAPI.DMASupported = atapiId.DMASupported; + report.ATAPI.DMASupportedSpecified = true; + } + if (atapiId.DMATransferTimingMode != 0) + { + report.ATAPI.DMATransferTimingMode = atapiId.DMATransferTimingMode; + report.ATAPI.DMATransferTimingModeSpecified = true; + } + if (atapiId.EccBytes != 0) + { + report.ATAPI.EccBytes = atapiId.EccBytes; + report.ATAPI.EccBytesSpecified = true; + } + if (atapiId.EnhancedSecurityEraseTime != 0) + { + report.ATAPI.EnhancedSecurityEraseTime = atapiId.EnhancedSecurityEraseTime; + report.ATAPI.EnhancedSecurityEraseTimeSpecified = true; + } + if (atapiId.EnabledCommandSet != 0) + { + report.ATAPI.EnabledCommandSet = atapiId.EnabledCommandSet; + report.ATAPI.EnabledCommandSetSpecified = true; + } + if (atapiId.EnabledCommandSet2 != 0) + { + report.ATAPI.EnabledCommandSet2 = atapiId.EnabledCommandSet2; + report.ATAPI.EnabledCommandSet2Specified = true; + } + if (atapiId.EnabledCommandSet3 != 0) + { + report.ATAPI.EnabledCommandSet3 = atapiId.EnabledCommandSet3; + report.ATAPI.EnabledCommandSet3Specified = true; + } + if (atapiId.EnabledCommandSet4 != 0) + { + report.ATAPI.EnabledCommandSet4 = atapiId.EnabledCommandSet4; + report.ATAPI.EnabledCommandSet4Specified = true; + } + if (atapiId.EnabledSATAFeatures != 0) + { + report.ATAPI.EnabledSATAFeatures = atapiId.EnabledSATAFeatures; + report.ATAPI.EnabledSATAFeaturesSpecified = true; + } + if (atapiId.ExtendedUserSectors != 0) + { + report.ATAPI.ExtendedUserSectors = atapiId.ExtendedUserSectors; + report.ATAPI.ExtendedUserSectorsSpecified = true; + } + if (atapiId.FreeFallSensitivity != 0) + { + report.ATAPI.FreeFallSensitivity = atapiId.FreeFallSensitivity; + report.ATAPI.FreeFallSensitivitySpecified = true; + } + if (!string.IsNullOrWhiteSpace(atapiId.FirmwareRevision)) + { + report.ATAPI.FirmwareRevision = atapiId.FirmwareRevision; + report.ATAPI.FirmwareRevisionSpecified = true; + } + if (atapiId.GeneralConfiguration != 0) + { + report.ATAPI.GeneralConfiguration = atapiId.GeneralConfiguration; + report.ATAPI.GeneralConfigurationSpecified = true; + } + if (atapiId.HardwareResetResult != 0) + { + report.ATAPI.HardwareResetResult = atapiId.HardwareResetResult; + report.ATAPI.HardwareResetResultSpecified = true; + } + if (atapiId.InterseekDelay != 0) + { + report.ATAPI.InterseekDelay = atapiId.InterseekDelay; + report.ATAPI.InterseekDelaySpecified = true; + } + if (atapiId.LogicalAlignment != 0) + { + report.ATAPI.LogicalAlignment = atapiId.LogicalAlignment; + report.ATAPI.LogicalAlignmentSpecified = true; + } + if (atapiId.LogicalSectorWords != 0) + { + report.ATAPI.LogicalSectorWords = atapiId.LogicalSectorWords; + report.ATAPI.LogicalSectorWordsSpecified = true; + } + if (atapiId.MajorVersion != 0) + { + report.ATAPI.MajorVersion = atapiId.MajorVersion; + report.ATAPI.MajorVersionSpecified = true; + } + if (atapiId.MasterPasswordRevisionCode != 0) + { + report.ATAPI.MasterPasswordRevisionCode = atapiId.MasterPasswordRevisionCode; + report.ATAPI.MasterPasswordRevisionCodeSpecified = true; + } + if (atapiId.MaxDownloadMicroMode3 != 0) + { + report.ATAPI.MaxDownloadMicroMode3 = atapiId.MaxDownloadMicroMode3; + report.ATAPI.MaxDownloadMicroMode3Specified = true; + } + if (atapiId.MaxQueueDepth != 0) + { + report.ATAPI.MaxQueueDepth = atapiId.MaxQueueDepth; + report.ATAPI.MaxQueueDepthSpecified = true; + } + if (atapiId.MDMAActive != 0) + { + report.ATAPI.MDMAActive = atapiId.MDMAActive; + report.ATAPI.MDMAActiveSpecified = true; + } + if (atapiId.MDMASupported != 0) + { + report.ATAPI.MDMASupported = atapiId.MDMASupported; + report.ATAPI.MDMASupportedSpecified = true; + } + if (atapiId.MinDownloadMicroMode3 != 0) + { + report.ATAPI.MinDownloadMicroMode3 = atapiId.MinDownloadMicroMode3; + report.ATAPI.MinDownloadMicroMode3Specified = true; + } + if (atapiId.MinMDMACycleTime != 0) + { + report.ATAPI.MinMDMACycleTime = atapiId.MinMDMACycleTime; + report.ATAPI.MinMDMACycleTimeSpecified = true; + } + if (atapiId.MinorVersion != 0) + { + report.ATAPI.MinorVersion = atapiId.MinorVersion; + report.ATAPI.MinorVersionSpecified = true; + } + if (atapiId.MinPIOCycleTimeNoFlow != 0) + { + report.ATAPI.MinPIOCycleTimeNoFlow = atapiId.MinPIOCycleTimeNoFlow; + report.ATAPI.MinPIOCycleTimeNoFlowSpecified = true; + } + if (atapiId.MinPIOCycleTimeFlow != 0) + { + report.ATAPI.MinPIOCycleTimeFlow = atapiId.MinPIOCycleTimeFlow; + report.ATAPI.MinPIOCycleTimeFlowSpecified = true; + } + if (!string.IsNullOrWhiteSpace(atapiId.Model)) + { + report.ATAPI.Model = atapiId.Model; + report.ATAPI.ModelSpecified = true; + } + if (atapiId.MultipleMaxSectors != 0) + { + report.ATAPI.MultipleMaxSectors = atapiId.MultipleMaxSectors; + report.ATAPI.MultipleMaxSectorsSpecified = true; + } + if (atapiId.MultipleSectorNumber != 0) + { + report.ATAPI.MultipleSectorNumber = atapiId.MultipleSectorNumber; + report.ATAPI.MultipleSectorNumberSpecified = true; + } + if (atapiId.NVCacheCaps != 0) + { + report.ATAPI.NVCacheCaps = atapiId.NVCacheCaps; + report.ATAPI.NVCacheCapsSpecified = true; + } + if (atapiId.NVCacheSize != 0) + { + report.ATAPI.NVCacheSize = atapiId.NVCacheSize; + report.ATAPI.NVCacheSizeSpecified = true; + } + if (atapiId.NVCacheWriteSpeed != 0) + { + report.ATAPI.NVCacheWriteSpeed = atapiId.NVCacheWriteSpeed; + report.ATAPI.NVCacheWriteSpeedSpecified = true; + } + if (atapiId.NVEstimatedSpinUp != 0) + { + report.ATAPI.NVEstimatedSpinUp = atapiId.NVEstimatedSpinUp; + report.ATAPI.NVEstimatedSpinUpSpecified = true; + } + if (atapiId.NominalRotationRate != 0) + { + report.ATAPI.NominalRotationRate = atapiId.NominalRotationRate; + report.ATAPI.NominalRotationRateSpecified = true; + } + if (atapiId.PacketBusRelease != 0) + { + report.ATAPI.PacketBusRelease = atapiId.PacketBusRelease; + report.ATAPI.PacketBusReleaseSpecified = true; + } + if (atapiId.PhysLogSectorSize != 0) + { + report.ATAPI.PhysLogSectorSize = atapiId.PhysLogSectorSize; + report.ATAPI.PhysLogSectorSizeSpecified = true; + } + if (atapiId.PIOTransferTimingMode != 0) + { + report.ATAPI.PIOTransferTimingMode = atapiId.PIOTransferTimingMode; + report.ATAPI.PIOTransferTimingModeSpecified = true; + } + if (atapiId.RecommendedAAM != 0) + { + report.ATAPI.RecommendedAAM = atapiId.RecommendedAAM; + report.ATAPI.RecommendedAAMSpecified = true; + } + if (atapiId.RecMDMACycleTime != 0) + { + report.ATAPI.RecommendedMDMACycleTime = atapiId.RecMDMACycleTime; + report.ATAPI.RecommendedMDMACycleTimeSpecified = true; + } + if (atapiId.RemovableStatusSet != 0) + { + report.ATAPI.RemovableStatusSet = atapiId.RemovableStatusSet; + report.ATAPI.RemovableStatusSetSpecified = true; + } + if (atapiId.SATACapabilities != 0) + { + report.ATAPI.SATACapabilities = atapiId.SATACapabilities; + report.ATAPI.SATACapabilitiesSpecified = true; + } + if (atapiId.SATACapabilities2 != 0) + { + report.ATAPI.SATACapabilities2 = atapiId.SATACapabilities2; + report.ATAPI.SATACapabilities2Specified = true; + } + if (atapiId.SATAFeatures != 0) + { + report.ATAPI.SATAFeatures = atapiId.SATAFeatures; + report.ATAPI.SATAFeaturesSpecified = true; + } + if (atapiId.SCTCommandTransport != 0) + { + report.ATAPI.SCTCommandTransport = atapiId.SCTCommandTransport; + report.ATAPI.SCTCommandTransportSpecified = true; + } + if (atapiId.SectorsPerCard != 0) + { + report.ATAPI.SectorsPerCard = atapiId.SectorsPerCard; + report.ATAPI.SectorsPerCardSpecified = true; + } + if (atapiId.SecurityEraseTime != 0) + { + report.ATAPI.SecurityEraseTime = atapiId.SecurityEraseTime; + report.ATAPI.SecurityEraseTimeSpecified = true; + } + if (atapiId.SecurityStatus != 0) + { + report.ATAPI.SecurityStatus = atapiId.SecurityStatus; + report.ATAPI.SecurityStatusSpecified = true; + } + if (atapiId.ServiceBusyClear != 0) + { + report.ATAPI.ServiceBusyClear = atapiId.ServiceBusyClear; + report.ATAPI.ServiceBusyClearSpecified = true; + } + if (atapiId.SpecificConfiguration != 0) + { + report.ATAPI.SpecificConfiguration = atapiId.SpecificConfiguration; + report.ATAPI.SpecificConfigurationSpecified = true; + } + if (atapiId.StreamAccessLatency != 0) + { + report.ATAPI.StreamAccessLatency = atapiId.StreamAccessLatency; + report.ATAPI.StreamAccessLatencySpecified = true; + } + if (atapiId.StreamMinReqSize != 0) + { + report.ATAPI.StreamMinReqSize = atapiId.StreamMinReqSize; + report.ATAPI.StreamMinReqSizeSpecified = true; + } + if (atapiId.StreamPerformanceGranularity != 0) + { + report.ATAPI.StreamPerformanceGranularity = atapiId.StreamPerformanceGranularity; + report.ATAPI.StreamPerformanceGranularitySpecified = true; + } + if (atapiId.StreamTransferTimeDMA != 0) + { + report.ATAPI.StreamTransferTimeDMA = atapiId.StreamTransferTimeDMA; + report.ATAPI.StreamTransferTimeDMASpecified = true; + } + if (atapiId.StreamTransferTimePIO != 0) + { + report.ATAPI.StreamTransferTimePIO = atapiId.StreamTransferTimePIO; + report.ATAPI.StreamTransferTimePIOSpecified = true; + } + if (atapiId.TransportMajorVersion != 0) + { + report.ATAPI.TransportMajorVersion = atapiId.TransportMajorVersion; + report.ATAPI.TransportMajorVersionSpecified = true; + } + if (atapiId.TransportMinorVersion != 0) + { + report.ATAPI.TransportMinorVersion = atapiId.TransportMinorVersion; + report.ATAPI.TransportMinorVersionSpecified = true; + } + if (atapiId.TrustedComputing != 0) + { + report.ATAPI.TrustedComputing = atapiId.TrustedComputing; + report.ATAPI.TrustedComputingSpecified = true; + } + if (atapiId.UDMAActive != 0) + { + report.ATAPI.UDMAActive = atapiId.UDMAActive; + report.ATAPI.UDMAActiveSpecified = true; + } + if (atapiId.UDMASupported != 0) + { + report.ATAPI.UDMASupported = atapiId.UDMASupported; + report.ATAPI.UDMASupportedSpecified = true; + } + if (atapiId.UnformattedBPT != 0) + { + report.ATAPI.UnformattedBPT = atapiId.UnformattedBPT; + report.ATAPI.UnformattedBPTSpecified = true; + } + if (atapiId.UnformattedBPS != 0) + { + report.ATAPI.UnformattedBPS = atapiId.UnformattedBPS; + report.ATAPI.UnformattedBPSSpecified = true; + } + if (atapiId.WRVMode != 0) + { + report.ATAPI.WRVMode = atapiId.WRVMode; + report.ATAPI.WRVModeSpecified = true; + } + if (atapiId.WRVSectorCountMode3 != 0) + { + report.ATAPI.WRVSectorCountMode3 = atapiId.WRVSectorCountMode3; + report.ATAPI.WRVSectorCountMode3Specified = true; + } + if (atapiId.WRVSectorCountMode2 != 0) + { + report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2; + report.ATAPI.WRVSectorCountMode2Specified = true; + } + } + } + + DicConsole.WriteLine("Querying SCSI INQUIRY..."); + sense = dev.ScsiInquiry(out buffer, out senseBuffer); + + report.SCSI = new scsiType(); + + if (!sense && Decoders.SCSI.Inquiry.Decode(buffer).HasValue) + { + Decoders.SCSI.Inquiry.SCSIInquiry inq = Decoders.SCSI.Inquiry.Decode(buffer).Value; + + List versionDescriptors = new List(); + report.SCSI.Inquiry = new scsiInquiryType(); + + if (inq.DeviceTypeModifier != 0) + { + report.SCSI.Inquiry.DeviceTypeModifier = inq.DeviceTypeModifier; + report.SCSI.Inquiry.DeviceTypeModifierSpecified = true; + } + if (inq.ISOVersion != 0) + { + report.SCSI.Inquiry.ISOVersion = inq.ISOVersion; + report.SCSI.Inquiry.ISOVersionSpecified = true; + } + if (inq.ECMAVersion != 0) + { + report.SCSI.Inquiry.ECMAVersion = inq.ECMAVersion; + report.SCSI.Inquiry.ECMAVersionSpecified = true; + } + if (inq.ANSIVersion != 0) + { + report.SCSI.Inquiry.ANSIVersion = inq.ANSIVersion; + report.SCSI.Inquiry.ANSIVersionSpecified = true; + } + if (inq.ResponseDataFormat != 0) + { + report.SCSI.Inquiry.ResponseDataFormat = inq.ResponseDataFormat; + report.SCSI.Inquiry.ResponseDataFormatSpecified = true; + } + if (!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.VendorIdentification).Trim())) + { + report.SCSI.Inquiry.VendorIdentification = StringHandlers.CToString(inq.VendorIdentification).Trim(); + report.SCSI.Inquiry.VendorIdentificationSpecified = true; + } + if (!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductIdentification).Trim())) + { + report.SCSI.Inquiry.ProductIdentification = StringHandlers.CToString(inq.ProductIdentification).Trim(); + report.SCSI.Inquiry.ProductIdentificationSpecified = true; + } + if (!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductRevisionLevel).Trim())) + { + report.SCSI.Inquiry.ProductRevisionLevel = StringHandlers.CToString(inq.ProductRevisionLevel).Trim(); + report.SCSI.Inquiry.ProductRevisionLevelSpecified = true; + } + if (inq.VersionDescriptors != null) + { + foreach (UInt16 descriptor in inq.VersionDescriptors) + { + if (descriptor != 0) + versionDescriptors.Add(descriptor); + } + + if (versionDescriptors.Count > 0) + report.SCSI.Inquiry.VersionDescriptors = versionDescriptors.ToArray(); + } + + report.SCSI.Inquiry.PeripheralQualifier = (Decoders.SCSI.PeripheralQualifiers)inq.PeripheralQualifier; + report.SCSI.Inquiry.PeripheralDeviceType = (Decoders.SCSI.PeripheralDeviceTypes)inq.PeripheralDeviceType; + report.SCSI.Inquiry.AsymmetricalLUNAccess = (Decoders.SCSI.TGPSValues)inq.TPGS; + report.SCSI.Inquiry.SPIClocking = (Decoders.SCSI.SPIClocking)inq.Clocking; + + report.SCSI.Inquiry.AccessControlCoordinator = inq.ACC; + report.SCSI.Inquiry.ACKRequests = inq.ACKREQQ; + report.SCSI.Inquiry.AERCSupported = inq.AERC; + report.SCSI.Inquiry.Address16 = inq.Addr16; + report.SCSI.Inquiry.Address32 = inq.Addr32; + report.SCSI.Inquiry.BasicQueueing = inq.BQue; + report.SCSI.Inquiry.EnclosureServices = inq.EncServ; + report.SCSI.Inquiry.HierarchicalLUN = inq.HiSup; + report.SCSI.Inquiry.IUS = inq.IUS; + report.SCSI.Inquiry.LinkedCommands = inq.Linked; + report.SCSI.Inquiry.MediumChanger = inq.MChngr; + report.SCSI.Inquiry.MultiPortDevice = inq.MultiP; + report.SCSI.Inquiry.NormalACA = inq.NormACA; + report.SCSI.Inquiry.Protection = inq.Protect; + report.SCSI.Inquiry.QAS = inq.QAS; + report.SCSI.Inquiry.RelativeAddressing = inq.RelAddr; + report.SCSI.Inquiry.Removable = inq.RMB; + report.SCSI.Inquiry.TaggedCommandQueue = inq.CmdQue; + report.SCSI.Inquiry.TerminateTaskSupported = inq.TrmTsk; + report.SCSI.Inquiry.ThirdPartyCopy = inq.ThreePC; + report.SCSI.Inquiry.TranferDisable = inq.TranDis; + report.SCSI.Inquiry.SoftReset = inq.SftRe; + report.SCSI.Inquiry.StorageArrayController = inq.SCCS; + report.SCSI.Inquiry.SyncTransfer = inq.Sync; + report.SCSI.Inquiry.WideBus16 = inq.WBus16; + report.SCSI.Inquiry.WideBus32 = inq.WBus32; + } + + DicConsole.WriteLine("Querying list of SCSI EVPDs..."); + sense = dev.ScsiInquiry(out buffer, out senseBuffer, 0x00); + + if (!sense) + { + byte[] evpdPages = Decoders.SCSI.EVPD.DecodePage00(buffer); + if (evpdPages != null && evpdPages.Length > 0) + { + List evpds = new List(); + foreach (byte page in evpdPages) + { + if (page != 0x80) + { + DicConsole.WriteLine("Querying SCSI EVPD {0:X2}h...", page); + sense = dev.ScsiInquiry(out buffer, out senseBuffer, page); + if (!sense) + { + pageType evpd = new pageType(); + evpd.page = page; + evpd.value = buffer; + evpds.Add(evpd); + } + } + } + if (evpds.Count > 0) + report.SCSI.EVPDPages = evpds.ToArray(); + } + } + + if (removable) + { + if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) + { + dev.AllowMediumRemoval(out senseBuffer, timeout, out duration); + dev.EjectTray(out senseBuffer, timeout, out duration); + } + else if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess) + { + dev.SpcAllowMediumRemoval(out senseBuffer, timeout, out duration); + DicConsole.WriteLine("Asking drive to unload tape (can take a few minutes)..."); + dev.Unload(out senseBuffer, timeout, out duration); + } + DicConsole.WriteLine("Please remove any media from the device and press any key when it is out."); + System.Console.ReadKey(true); + } + + Decoders.SCSI.Modes.DecodedMode? decMode = null; + Decoders.SCSI.PeripheralDeviceTypes devType = dev.SCSIType; + + DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (10)..."); + if (sense || dev.Error) + { + sense = dev.ModeSense6(out buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration); + DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (6)..."); + } + else + report.SCSI.SupportsModeSubpages = true; + + if (sense || dev.Error) + { + DicConsole.WriteLine("Querying SCSI MODE SENSE (6)..."); + sense = dev.ModeSense(out buffer, out senseBuffer, timeout, out duration); + } + + if (!sense && !dev.Error && !decMode.HasValue) + decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, devType); + + if (!sense && !dev.Error) + report.SCSI.SupportsModeSense6 = true; + + Decoders.SCSI.Modes.ModePage_2A? cdromMode = null; + + if (decMode.HasValue) + { + report.SCSI.ModeSense = new modeType(); + report.SCSI.ModeSense.BlankCheckEnabled = decMode.Value.Header.EBC; + report.SCSI.ModeSense.DPOandFUA = decMode.Value.Header.DPOFUA; + report.SCSI.ModeSense.WriteProtected = decMode.Value.Header.WriteProtected; + + if (decMode.Value.Header.BufferedMode > 0) + { + report.SCSI.ModeSense.BufferedMode = decMode.Value.Header.BufferedMode; + report.SCSI.ModeSense.BufferedModeSpecified = true; + } + + if (decMode.Value.Header.Speed > 0) + { + report.SCSI.ModeSense.Speed = decMode.Value.Header.Speed; + report.SCSI.ModeSense.SpeedSpecified = true; + } + + if (decMode.Value.Pages != null) + { + List modePages = new List(); + foreach (Decoders.SCSI.Modes.ModePage page in decMode.Value.Pages) + { + modePageType modePage = new modePageType(); + modePage.page = page.Page; + modePage.subpage = page.Subpage; + modePage.value = page.PageResponse; + modePages.Add(modePage); + + if (modePage.page == 0x2A && modePage.subpage == 0x00) + { + cdromMode = Decoders.SCSI.Modes.DecodeModePage_2A(page.PageResponse); + } + } + + if (modePages.Count > 0) + report.SCSI.ModeSense.ModePages = modePages.ToArray(); + } + } + + List mediaTypes = new List(); + + #region MultiMediaDevice + if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) + { + report.SCSI.MultiMediaDevice = new mmcType(); + + if (cdromMode.HasValue) + { + report.SCSI.MultiMediaDevice.ModeSense2A = new mmcModeType(); + if (cdromMode.Value.BufferSize != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.BufferSize = cdromMode.Value.BufferSize; + report.SCSI.MultiMediaDevice.ModeSense2A.BufferSizeSpecified = true; + } + if (cdromMode.Value.CurrentSpeed != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.CurrentSpeed = cdromMode.Value.CurrentSpeed; + report.SCSI.MultiMediaDevice.ModeSense2A.CurrentSpeedSpecified = true; + } + if (cdromMode.Value.CurrentWriteSpeed != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.CurrentWriteSpeed = cdromMode.Value.CurrentWriteSpeed; + report.SCSI.MultiMediaDevice.ModeSense2A.CurrentWriteSpeedSpecified = true; + } + if (cdromMode.Value.CurrentWriteSpeedSelected != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.CurrentWriteSpeedSelected = cdromMode.Value.CurrentWriteSpeedSelected; + report.SCSI.MultiMediaDevice.ModeSense2A.CurrentWriteSpeedSelectedSpecified = true; + } + if (cdromMode.Value.MaximumSpeed != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.MaximumSpeed = cdromMode.Value.MaximumSpeed; + report.SCSI.MultiMediaDevice.ModeSense2A.MaximumSpeedSpecified = true; + } + if (cdromMode.Value.MaxWriteSpeed != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.MaximumWriteSpeed = cdromMode.Value.MaxWriteSpeed; + report.SCSI.MultiMediaDevice.ModeSense2A.MaximumWriteSpeedSpecified = true; + } + if (cdromMode.Value.RotationControlSelected != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.RotationControlSelected = cdromMode.Value.RotationControlSelected; + report.SCSI.MultiMediaDevice.ModeSense2A.RotationControlSelectedSpecified = true; + } + if (cdromMode.Value.SupportedVolumeLevels != 0) + { + report.SCSI.MultiMediaDevice.ModeSense2A.SupportedVolumeLevels = cdromMode.Value.SupportedVolumeLevels; + report.SCSI.MultiMediaDevice.ModeSense2A.SupportedVolumeLevelsSpecified = true; + } + + report.SCSI.MultiMediaDevice.ModeSense2A.AccurateCDDA = cdromMode.Value.AccurateCDDA; + report.SCSI.MultiMediaDevice.ModeSense2A.BCK = cdromMode.Value.BCK; + report.SCSI.MultiMediaDevice.ModeSense2A.BufferUnderRunProtection = cdromMode.Value.BUF; + report.SCSI.MultiMediaDevice.ModeSense2A.CanEject = cdromMode.Value.Eject; + report.SCSI.MultiMediaDevice.ModeSense2A.CanLockMedia = cdromMode.Value.Lock; + report.SCSI.MultiMediaDevice.ModeSense2A.CDDACommand = cdromMode.Value.CDDACommand; + report.SCSI.MultiMediaDevice.ModeSense2A.CompositeAudioVideo = cdromMode.Value.Composite; + report.SCSI.MultiMediaDevice.ModeSense2A.CSSandCPPMSupported = cdromMode.Value.CMRSupported == 1; + report.SCSI.MultiMediaDevice.ModeSense2A.DeterministicSlotChanger = cdromMode.Value.SDP; + report.SCSI.MultiMediaDevice.ModeSense2A.DigitalPort1 = cdromMode.Value.DigitalPort1; + report.SCSI.MultiMediaDevice.ModeSense2A.DigitalPort2 = cdromMode.Value.DigitalPort2; + report.SCSI.MultiMediaDevice.ModeSense2A.LeadInPW = cdromMode.Value.LeadInPW; + report.SCSI.MultiMediaDevice.ModeSense2A.LoadingMechanismType = cdromMode.Value.LoadingMechanism; + report.SCSI.MultiMediaDevice.ModeSense2A.LockStatus = cdromMode.Value.LockState; + report.SCSI.MultiMediaDevice.ModeSense2A.LSBF = cdromMode.Value.LSBF; + report.SCSI.MultiMediaDevice.ModeSense2A.PlaysAudio = cdromMode.Value.AudioPlay; + report.SCSI.MultiMediaDevice.ModeSense2A.PreventJumperStatus = cdromMode.Value.PreventJumper; + report.SCSI.MultiMediaDevice.ModeSense2A.RCK = cdromMode.Value.RCK; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsBarcode = cdromMode.Value.ReadBarcode; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsBothSides = cdromMode.Value.SCC; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsCDR = cdromMode.Value.ReadCDR; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsCDRW = cdromMode.Value.ReadCDRW; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsDeinterlavedSubchannel = cdromMode.Value.DeinterlaveSubchannel; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsDVDR = cdromMode.Value.ReadDVDR; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsDVDRAM = cdromMode.Value.ReadDVDRAM; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsDVDROM = cdromMode.Value.ReadDVDROM; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsISRC = cdromMode.Value.ISRC; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsMode2Form2 = cdromMode.Value.Mode2Form2; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsMode2Form1 = cdromMode.Value.Mode2Form1; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsPacketCDR = cdromMode.Value.Method2; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsSubchannel = cdromMode.Value.Subchannel; + report.SCSI.MultiMediaDevice.ModeSense2A.ReadsUPC = cdromMode.Value.UPC; + report.SCSI.MultiMediaDevice.ModeSense2A.ReturnsC2Pointers = cdromMode.Value.C2Pointer; + report.SCSI.MultiMediaDevice.ModeSense2A.SeparateChannelMute = cdromMode.Value.SeparateChannelMute; + report.SCSI.MultiMediaDevice.ModeSense2A.SeparateChannelVolume = cdromMode.Value.SeparateChannelVolume; + report.SCSI.MultiMediaDevice.ModeSense2A.SSS = cdromMode.Value.SSS; + report.SCSI.MultiMediaDevice.ModeSense2A.SupportsMultiSession = cdromMode.Value.MultiSession; + report.SCSI.MultiMediaDevice.ModeSense2A.TestWrite = cdromMode.Value.TestWrite; + report.SCSI.MultiMediaDevice.ModeSense2A.WritesCDR = cdromMode.Value.WriteCDR; + report.SCSI.MultiMediaDevice.ModeSense2A.WritesCDRW = cdromMode.Value.WriteCDRW; + report.SCSI.MultiMediaDevice.ModeSense2A.WritesDVDR = cdromMode.Value.WriteDVDR; + report.SCSI.MultiMediaDevice.ModeSense2A.WritesDVDRAM = cdromMode.Value.WriteDVDRAM; + report.SCSI.MultiMediaDevice.ModeSense2A.WriteSpeedPerformanceDescriptors = cdromMode.Value.WriteSpeedPerformanceDescriptors; + + mediaTypes.Add("CD-ROM"); + mediaTypes.Add("Audio CD"); + if (cdromMode.Value.ReadCDR) + mediaTypes.Add("CD-R"); + if (cdromMode.Value.ReadCDRW) + mediaTypes.Add("CD-RW"); + if (cdromMode.Value.ReadDVDROM) + mediaTypes.Add("DVD-ROM"); + if (cdromMode.Value.ReadDVDRAM) + mediaTypes.Add("DVD-RAM"); + if (cdromMode.Value.ReadDVDR) + mediaTypes.Add("DVD-R"); + } + + DicConsole.WriteLine("Querying MMC GET CONFIGURATION..."); + sense = dev.GetConfiguration(out buffer, out senseBuffer, timeout, out duration); + + if (!sense) + { + Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(buffer); + if (ftr.Descriptors != null && ftr.Descriptors.Length > 0) + { + report.SCSI.MultiMediaDevice.Features = new mmcFeaturesType(); + foreach (Decoders.SCSI.MMC.Features.FeatureDescriptor desc in ftr.Descriptors) + { + switch (desc.Code) + { + case 0x0001: + { + Decoders.SCSI.MMC.Feature_0001? ftr0001 = Decoders.SCSI.MMC.Features.Decode_0001(desc.Data); + if (ftr0001.HasValue) + { + report.SCSI.MultiMediaDevice.Features.PhysicalInterfaceStandard = ftr0001.Value.PhysicalInterfaceStandard; + report.SCSI.MultiMediaDevice.Features.PhysicalInterfaceStandardSpecified = true; + report.SCSI.MultiMediaDevice.Features.SupportsDeviceBusyEvent = ftr0001.Value.DBE; + } + } + break; + case 0x0003: + { + Decoders.SCSI.MMC.Feature_0003? ftr0003 = Decoders.SCSI.MMC.Features.Decode_0003(desc.Data); + if (ftr0003.HasValue) + { + report.SCSI.MultiMediaDevice.Features.LoadingMechanismType = ftr0003.Value.LoadingMechanismType; + report.SCSI.MultiMediaDevice.Features.LoadingMechanismTypeSpecified = true; + report.SCSI.MultiMediaDevice.Features.CanLoad = ftr0003.Value.Load; + report.SCSI.MultiMediaDevice.Features.CanEject = ftr0003.Value.Eject; + report.SCSI.MultiMediaDevice.Features.PreventJumper = ftr0003.Value.PreventJumper; + report.SCSI.MultiMediaDevice.Features.DBML = ftr0003.Value.DBML; + report.SCSI.MultiMediaDevice.Features.Locked = ftr0003.Value.Lock; + } + } + break; + case 0x0004: + { + Decoders.SCSI.MMC.Feature_0004? ftr0004 = Decoders.SCSI.MMC.Features.Decode_0004(desc.Data); + if (ftr0004.HasValue) + { + report.SCSI.MultiMediaDevice.Features.SupportsWriteProtectPAC = ftr0004.Value.DWP; + report.SCSI.MultiMediaDevice.Features.SupportsWriteInhibitDCB = ftr0004.Value.WDCB; + report.SCSI.MultiMediaDevice.Features.SupportsPWP = ftr0004.Value.SPWP; + report.SCSI.MultiMediaDevice.Features.SupportsSWPP = ftr0004.Value.SSWPP; + } + } + break; + case 0x0010: + { + Decoders.SCSI.MMC.Feature_0010? ftr0010 = Decoders.SCSI.MMC.Features.Decode_0010(desc.Data); + if (ftr0010.HasValue) + { + if (ftr0010.Value.LogicalBlockSize > 0) + { + report.SCSI.MultiMediaDevice.Features.LogicalBlockSize = ftr0010.Value.LogicalBlockSize; + report.SCSI.MultiMediaDevice.Features.LogicalBlockSizeSpecified = true; + } + if (ftr0010.Value.Blocking > 0) + { + report.SCSI.MultiMediaDevice.Features.BlocksPerReadableUnit = ftr0010.Value.Blocking; + report.SCSI.MultiMediaDevice.Features.BlocksPerReadableUnitSpecified = true; + } + report.SCSI.MultiMediaDevice.Features.ErrorRecoveryPage = ftr0010.Value.PP; + } + } + break; + case 0x001D: + report.SCSI.MultiMediaDevice.Features.MultiRead = true; + break; + case 0x001E: + { + report.SCSI.MultiMediaDevice.Features.CanReadCD = true; + Decoders.SCSI.MMC.Feature_001E? ftr001E = Decoders.SCSI.MMC.Features.Decode_001E(desc.Data); + if (ftr001E.HasValue) + { + report.SCSI.MultiMediaDevice.Features.SupportsDAP = ftr001E.Value.DAP; + report.SCSI.MultiMediaDevice.Features.SupportsC2 = ftr001E.Value.C2; + report.SCSI.MultiMediaDevice.Features.CanReadLeadInCDText = ftr001E.Value.CDText; + } + } + break; + case 0x001F: + { + report.SCSI.MultiMediaDevice.Features.CanReadDVD = true; + Decoders.SCSI.MMC.Feature_001F? ftr001F = Decoders.SCSI.MMC.Features.Decode_001F(desc.Data); + if (ftr001F.HasValue) + { + report.SCSI.MultiMediaDevice.Features.DVDMultiRead = ftr001F.Value.MULTI110; + report.SCSI.MultiMediaDevice.Features.CanReadAllDualRW = ftr001F.Value.DualRW; + report.SCSI.MultiMediaDevice.Features.CanReadAllDualR = ftr001F.Value.DualRW; + } + } + break; + case 0x0022: + report.SCSI.MultiMediaDevice.Features.CanEraseSector = true; + break; + case 0x0023: + { + report.SCSI.MultiMediaDevice.Features.CanFormat = true; + Decoders.SCSI.MMC.Feature_0023? ftr0023 = Decoders.SCSI.MMC.Features.Decode_0023(desc.Data); + if (ftr0023.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanFormatBDREWithoutSpare = ftr0023.Value.RENoSA; + report.SCSI.MultiMediaDevice.Features.CanExpandBDRESpareArea = ftr0023.Value.Expand; + report.SCSI.MultiMediaDevice.Features.CanFormatQCert = ftr0023.Value.QCert; + report.SCSI.MultiMediaDevice.Features.CanFormatCert = ftr0023.Value.Cert; + report.SCSI.MultiMediaDevice.Features.CanFormatFRF = ftr0023.Value.FRF; + report.SCSI.MultiMediaDevice.Features.CanFormatRRM = ftr0023.Value.RRM; + } + } + break; + case 0x0024: + report.SCSI.MultiMediaDevice.Features.CanReadSpareAreaInformation = true; + break; + case 0x0027: + report.SCSI.MultiMediaDevice.Features.CanWriteCDRWCAV = true; + break; + case 0x0028: + { + report.SCSI.MultiMediaDevice.Features.CanReadCDMRW = true; + Decoders.SCSI.MMC.Feature_0028? ftr0028 = Decoders.SCSI.MMC.Features.Decode_0028(desc.Data); + if (ftr0028.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusMRW = ftr0028.Value.DVDPRead; + report.SCSI.MultiMediaDevice.Features.CanWriteDVDPlusMRW = ftr0028.Value.DVDPWrite; + report.SCSI.MultiMediaDevice.Features.CanWriteCDMRW = ftr0028.Value.Write; + } + } + break; + case 0x002A: + { + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusRW = true; + Decoders.SCSI.MMC.Feature_002A? ftr002A = Decoders.SCSI.MMC.Features.Decode_002A(desc.Data); + if (ftr002A.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanWriteDVDPlusRW = ftr002A.Value.Write; + } + } + break; + case 0x002B: + { + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusR = true; + Decoders.SCSI.MMC.Feature_002B? ftr002B = Decoders.SCSI.MMC.Features.Decode_002B(desc.Data); + if (ftr002B.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanWriteDVDPlusR = ftr002B.Value.Write; + } + } + break; + case 0x002D: + { + report.SCSI.MultiMediaDevice.Features.CanWriteCDTAO = true; + Decoders.SCSI.MMC.Feature_002D? ftr002D = Decoders.SCSI.MMC.Features.Decode_002D(desc.Data); + if (ftr002D.HasValue) + { + report.SCSI.MultiMediaDevice.Features.BufferUnderrunFreeInTAO = ftr002D.Value.BUF; + report.SCSI.MultiMediaDevice.Features.CanWriteRawSubchannelInTAO = ftr002D.Value.RWRaw; + report.SCSI.MultiMediaDevice.Features.CanWritePackedSubchannelInTAO = ftr002D.Value.RWPack; + report.SCSI.MultiMediaDevice.Features.CanTestWriteInTAO = ftr002D.Value.TestWrite; + report.SCSI.MultiMediaDevice.Features.CanOverwriteTAOTrack = ftr002D.Value.CDRW; + report.SCSI.MultiMediaDevice.Features.CanWriteRWSubchannelInTAO = ftr002D.Value.RWSubchannel; + } + } + break; + case 0x002E: + { + report.SCSI.MultiMediaDevice.Features.CanWriteCDSAO = true; + Decoders.SCSI.MMC.Feature_002E? ftr002E = Decoders.SCSI.MMC.Features.Decode_002E(desc.Data); + if (ftr002E.HasValue) + { + report.SCSI.MultiMediaDevice.Features.BufferUnderrunFreeInSAO = ftr002E.Value.BUF; + report.SCSI.MultiMediaDevice.Features.CanWriteRawMultiSession = ftr002E.Value.RAWMS; + report.SCSI.MultiMediaDevice.Features.CanWriteRaw = ftr002E.Value.RAW; + report.SCSI.MultiMediaDevice.Features.CanTestWriteInSAO = ftr002E.Value.TestWrite; + report.SCSI.MultiMediaDevice.Features.CanOverwriteSAOTrack = ftr002E.Value.CDRW; + report.SCSI.MultiMediaDevice.Features.CanWriteRWSubchannelInSAO = ftr002E.Value.RW; + } + } + break; + case 0x002F: + { + report.SCSI.MultiMediaDevice.Features.CanWriteDVDR = true; + Decoders.SCSI.MMC.Feature_002F? ftr002F = Decoders.SCSI.MMC.Features.Decode_002F(desc.Data); + if (ftr002F.HasValue) + { + report.SCSI.MultiMediaDevice.Features.BufferUnderrunFreeInDVD = ftr002F.Value.BUF; + report.SCSI.MultiMediaDevice.Features.CanWriteDVDRDL = ftr002F.Value.RDL; + report.SCSI.MultiMediaDevice.Features.CanTestWriteDVD = ftr002F.Value.TestWrite; + report.SCSI.MultiMediaDevice.Features.CanWriteDVDRW = ftr002F.Value.DVDRW; + } + } + break; + case 0x0030: + report.SCSI.MultiMediaDevice.Features.CanReadDDCD = true; + break; + case 0x0031: + { + report.SCSI.MultiMediaDevice.Features.CanWriteDDCDR = true; + ; + Decoders.SCSI.MMC.Feature_0031? ftr0031 = Decoders.SCSI.MMC.Features.Decode_0031(desc.Data); + if (ftr0031.HasValue) + report.SCSI.MultiMediaDevice.Features.CanTestWriteDDCDR = ftr0031.Value.TestWrite; + } + break; + case 0x0032: + report.SCSI.MultiMediaDevice.Features.CanWriteDDCDRW = true; + break; + case 0x0037: + report.SCSI.MultiMediaDevice.Features.CanWriteCDRW = true; + break; + case 0x0038: + report.SCSI.MultiMediaDevice.Features.CanPseudoOverwriteBDR = true; + break; + case 0x003A: + { + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusRWDL = true; + Decoders.SCSI.MMC.Feature_003A? ftr003A = Decoders.SCSI.MMC.Features.Decode_003A(desc.Data); + if (ftr003A.HasValue) + report.SCSI.MultiMediaDevice.Features.CanWriteDVDPlusRWDL = ftr003A.Value.Write; + } + break; + case 0x003B: + { + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusRDL = true; + Decoders.SCSI.MMC.Feature_003B? ftr003B = Decoders.SCSI.MMC.Features.Decode_003B(desc.Data); + if (ftr003B.HasValue) + report.SCSI.MultiMediaDevice.Features.CanWriteDVDPlusRDL = ftr003B.Value.Write; + } + break; + case 0x0040: + { + report.SCSI.MultiMediaDevice.Features.CanReadBD = true; + Decoders.SCSI.MMC.Feature_0040? ftr0040 = Decoders.SCSI.MMC.Features.Decode_0040(desc.Data); + if (ftr0040.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanReadBluBCA = ftr0040.Value.BCA; + report.SCSI.MultiMediaDevice.Features.CanReadBDRE2 = ftr0040.Value.RE2; + report.SCSI.MultiMediaDevice.Features.CanReadBDRE1 = ftr0040.Value.RE1; + report.SCSI.MultiMediaDevice.Features.CanReadOldBDRE = ftr0040.Value.OldRE; + report.SCSI.MultiMediaDevice.Features.CanReadBDR = ftr0040.Value.R; + report.SCSI.MultiMediaDevice.Features.CanReadOldBDR = ftr0040.Value.OldR; + report.SCSI.MultiMediaDevice.Features.CanReadBDROM = ftr0040.Value.ROM; + report.SCSI.MultiMediaDevice.Features.CanReadOldBDROM = ftr0040.Value.OldROM; + } + } + break; + case 0x0041: + { + report.SCSI.MultiMediaDevice.Features.CanWriteBD = true; + Decoders.SCSI.MMC.Feature_0041? ftr0041 = Decoders.SCSI.MMC.Features.Decode_0041(desc.Data); + if (ftr0041.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanWriteBDRE2 = ftr0041.Value.RE2; + report.SCSI.MultiMediaDevice.Features.CanWriteBDRE1 = ftr0041.Value.RE1; + report.SCSI.MultiMediaDevice.Features.CanReadOldBDRE = ftr0041.Value.OldRE; + report.SCSI.MultiMediaDevice.Features.CanReadBDR = ftr0041.Value.R; + report.SCSI.MultiMediaDevice.Features.CanReadOldBDR = ftr0041.Value.OldR; + } + } + break; + case 0x0050: + { + report.SCSI.MultiMediaDevice.Features.CanReadHDDVD = true; + Decoders.SCSI.MMC.Feature_0050? ftr0050 = Decoders.SCSI.MMC.Features.Decode_0050(desc.Data); + if (ftr0050.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanReadHDDVDR = ftr0050.Value.HDDVDR; + report.SCSI.MultiMediaDevice.Features.CanReadHDDVDRAM = ftr0050.Value.HDDVDRAM; + } + } + break; + case 0x0051: + { + Decoders.SCSI.MMC.Feature_0051? ftr0051 = Decoders.SCSI.MMC.Features.Decode_0051(desc.Data); + if (ftr0051.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanWriteHDDVDR = ftr0051.Value.HDDVDR; + report.SCSI.MultiMediaDevice.Features.CanWriteHDDVDRAM = ftr0051.Value.HDDVDRAM; + } + } + break; + case 0x0080: + report.SCSI.MultiMediaDevice.Features.SupportsHybridDiscs = true; + break; + case 0x0101: + report.SCSI.MultiMediaDevice.Features.SupportsModePage1Ch = true; + break; + case 0x0102: + { + report.SCSI.MultiMediaDevice.Features.EmbeddedChanger = true; + Decoders.SCSI.MMC.Feature_0102? ftr0102 = Decoders.SCSI.MMC.Features.Decode_0102(desc.Data); + if (ftr0102.HasValue) + { + report.SCSI.MultiMediaDevice.Features.ChangerIsSideChangeCapable = ftr0102.Value.SCC; + report.SCSI.MultiMediaDevice.Features.ChangerSupportsDiscPresent = ftr0102.Value.SDP; + report.SCSI.MultiMediaDevice.Features.ChangerSlots = (byte)(ftr0102.Value.HighestSlotNumber + 1); + } + } + break; + case 0x0103: + { + report.SCSI.MultiMediaDevice.Features.CanPlayCDAudio = true; + Decoders.SCSI.MMC.Feature_0103? ftr0103 = Decoders.SCSI.MMC.Features.Decode_0103(desc.Data); + if (ftr0103.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanAudioScan = ftr0103.Value.Scan; + report.SCSI.MultiMediaDevice.Features.CanMuteSeparateChannels = ftr0103.Value.SCM; + report.SCSI.MultiMediaDevice.Features.SupportsSeparateVolume = ftr0103.Value.SV; + if (ftr0103.Value.VolumeLevels > 0) + { + report.SCSI.MultiMediaDevice.Features.VolumeLevelsSpecified = true; + report.SCSI.MultiMediaDevice.Features.VolumeLevels = ftr0103.Value.VolumeLevels; + } + } + } + break; + case 0x0104: + report.SCSI.MultiMediaDevice.Features.CanUpgradeFirmware = true; + break; + case 0x0106: + { + report.SCSI.MultiMediaDevice.Features.SupportsCSS = true; + Decoders.SCSI.MMC.Feature_0106? ftr0106 = Decoders.SCSI.MMC.Features.Decode_0106(desc.Data); + if (ftr0106.HasValue) + { + if (ftr0106.Value.CSSVersion > 0) + { + report.SCSI.MultiMediaDevice.Features.CSSVersionSpecified = true; + report.SCSI.MultiMediaDevice.Features.CSSVersion = ftr0106.Value.CSSVersion; + } + } + } + break; + case 0x0108: + report.SCSI.MultiMediaDevice.Features.CanReportDriveSerial = true; + break; + case 0x0109: + report.SCSI.MultiMediaDevice.Features.CanReportMediaSerial = true; + break; + case 0x010B: + { + report.SCSI.MultiMediaDevice.Features.SupportsCPRM = true; + Decoders.SCSI.MMC.Feature_010B? ftr010B = Decoders.SCSI.MMC.Features.Decode_010B(desc.Data); + if (ftr010B.HasValue) + { + if (ftr010B.Value.CPRMVersion > 0) + { + report.SCSI.MultiMediaDevice.Features.CPRMVersionSpecified = true; + report.SCSI.MultiMediaDevice.Features.CPRMVersion = ftr010B.Value.CPRMVersion; + } + } + } + break; + case 0x010C: + { + Decoders.SCSI.MMC.Feature_010C? ftr010C = Decoders.SCSI.MMC.Features.Decode_010C(desc.Data); + if (ftr010C.HasValue) + { + string syear, smonth, sday, shour, sminute, ssecond; + byte[] temp; + + temp = new byte[4]; + temp[0] = (byte)((ftr010C.Value.Century & 0xFF00) >> 8); + temp[1] = (byte)(ftr010C.Value.Century & 0xFF); + temp[2] = (byte)((ftr010C.Value.Year & 0xFF00) >> 8); + temp[3] = (byte)(ftr010C.Value.Year & 0xFF); + syear = System.Text.Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr010C.Value.Month & 0xFF00) >> 8); + temp[1] = (byte)(ftr010C.Value.Month & 0xFF); + smonth = System.Text.Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr010C.Value.Day & 0xFF00) >> 8); + temp[1] = (byte)(ftr010C.Value.Day & 0xFF); + sday = System.Text.Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr010C.Value.Hour & 0xFF00) >> 8); + temp[1] = (byte)(ftr010C.Value.Hour & 0xFF); + shour = System.Text.Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr010C.Value.Minute & 0xFF00) >> 8); + temp[1] = (byte)(ftr010C.Value.Minute & 0xFF); + sminute = System.Text.Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr010C.Value.Second & 0xFF00) >> 8); + temp[1] = (byte)(ftr010C.Value.Second & 0xFF); + ssecond = System.Text.Encoding.ASCII.GetString(temp); + + try + { + report.SCSI.MultiMediaDevice.Features.FirmwareDate = new DateTime(Int32.Parse(syear), Int32.Parse(smonth), + Int32.Parse(sday), Int32.Parse(shour), Int32.Parse(sminute), + Int32.Parse(ssecond), DateTimeKind.Utc); + + report.SCSI.MultiMediaDevice.Features.FirmwareDateSpecified = true; + } + catch + { + } + } + } + break; + case 0x010D: + { + report.SCSI.MultiMediaDevice.Features.SupportsAACS = true; + Decoders.SCSI.MMC.Feature_010D? ftr010D = Decoders.SCSI.MMC.Features.Decode_010D(desc.Data); + if (ftr010D.HasValue) + { + report.SCSI.MultiMediaDevice.Features.CanReadDriveAACSCertificate = ftr010D.Value.RDC; + report.SCSI.MultiMediaDevice.Features.CanReadCPRM_MKB = ftr010D.Value.RMC; + report.SCSI.MultiMediaDevice.Features.CanWriteBusEncryptedBlocks = ftr010D.Value.WBE; + report.SCSI.MultiMediaDevice.Features.SupportsBusEncryption = ftr010D.Value.BEC; + report.SCSI.MultiMediaDevice.Features.CanGenerateBindingNonce = ftr010D.Value.BNG; + + if (ftr010D.Value.BindNonceBlocks > 0) + { + report.SCSI.MultiMediaDevice.Features.BindingNonceBlocksSpecified = true; + report.SCSI.MultiMediaDevice.Features.BindingNonceBlocks = ftr010D.Value.BindNonceBlocks; + } + + if (ftr010D.Value.AGIDs > 0) + { + report.SCSI.MultiMediaDevice.Features.AGIDsSpecified = true; + report.SCSI.MultiMediaDevice.Features.AGIDs = ftr010D.Value.AGIDs; + } + + if (ftr010D.Value.AACSVersion > 0) + { + report.SCSI.MultiMediaDevice.Features.AACSVersionSpecified = true; + report.SCSI.MultiMediaDevice.Features.AACSVersion = ftr010D.Value.AACSVersion; + } + } + } + break; + case 0x010E: + report.SCSI.MultiMediaDevice.Features.CanWriteCSSManagedDVD = true; + break; + case 0x0113: + report.SCSI.MultiMediaDevice.Features.SupportsSecurDisc = true; + break; + case 0x0142: + report.SCSI.MultiMediaDevice.Features.SupportsOSSC = true; + break; + case 0x0110: + report.SCSI.MultiMediaDevice.Features.SupportsVCPS = true; + break; + } + } + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadBD || + report.SCSI.MultiMediaDevice.Features.CanReadBDR || + report.SCSI.MultiMediaDevice.Features.CanReadBDRE1 || + report.SCSI.MultiMediaDevice.Features.CanReadBDRE2 || + report.SCSI.MultiMediaDevice.Features.CanReadBDROM || + report.SCSI.MultiMediaDevice.Features.CanReadOldBDR || + report.SCSI.MultiMediaDevice.Features.CanReadOldBDRE || + report.SCSI.MultiMediaDevice.Features.CanReadOldBDROM) + { + if (!mediaTypes.Contains("BD-ROM")) + mediaTypes.Add("BD-ROM"); + if (!mediaTypes.Contains("BD-R")) + mediaTypes.Add("BD-R"); + if (!mediaTypes.Contains("BD-RE")) + mediaTypes.Add("BD-RE"); + if (!mediaTypes.Contains("BD-R LTH")) + mediaTypes.Add("BD-R LTH"); + if (!mediaTypes.Contains("BD-R XL")) + mediaTypes.Add("BD-R XL"); + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadCD || + report.SCSI.MultiMediaDevice.Features.MultiRead) + { + if (!mediaTypes.Contains("CD-ROM")) + mediaTypes.Add("CD-ROM"); + if (!mediaTypes.Contains("Audio CD")) + mediaTypes.Add("Audio CD"); + if (!mediaTypes.Contains("CD-R")) + mediaTypes.Add("CD-R"); + if (!mediaTypes.Contains("CD-RW")) + mediaTypes.Add("CD-RW"); + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadCDMRW) + { + if (!mediaTypes.Contains("CD-MRW")) + mediaTypes.Add("CD-MRW"); + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadDDCD) + { + if (!mediaTypes.Contains("DDCD-ROM")) + mediaTypes.Add("DDCD-ROM"); + if (!mediaTypes.Contains("DDCD-R")) + mediaTypes.Add("DDCD-R"); + if (!mediaTypes.Contains("DDCD-RW")) + mediaTypes.Add("DDCD-RW"); + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadDVD || + report.SCSI.MultiMediaDevice.Features.DVDMultiRead || + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusR || + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusRDL || + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusRW || + report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusRWDL) + { + if (!mediaTypes.Contains("DVD-ROM")) + mediaTypes.Add("DVD-ROM"); + if (!mediaTypes.Contains("DVD-R")) + mediaTypes.Add("DVD-R"); + if (!mediaTypes.Contains("DVD-RW")) + mediaTypes.Add("DVD-RW"); + if (!mediaTypes.Contains("DVD+R")) + mediaTypes.Add("DVD+R"); + if (!mediaTypes.Contains("DVD+RW")) + mediaTypes.Add("DVD+RW"); + if (!mediaTypes.Contains("DVD-R DL")) + mediaTypes.Add("DVD-R DL"); + if (!mediaTypes.Contains("DVD+R DL")) + mediaTypes.Add("DVD+R DL"); + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadDVDPlusMRW) + { + if (!mediaTypes.Contains("DVD+MRW")) + mediaTypes.Add("DVD+MRW"); + } + + + if (report.SCSI.MultiMediaDevice.Features.CanReadHDDVD || + report.SCSI.MultiMediaDevice.Features.CanReadHDDVDR) + { + if (!mediaTypes.Contains("HD DVD-ROM")) + mediaTypes.Add("HD DVD-ROM"); + if (!mediaTypes.Contains("HD DVD-R")) + mediaTypes.Add("HD DVD-R"); + if (!mediaTypes.Contains("HD DVD-RW")) + mediaTypes.Add("HD DVD-RW"); + } + + if (report.SCSI.MultiMediaDevice.Features.CanReadHDDVDRAM) + { + if (!mediaTypes.Contains("HD DVD-RAM")) + mediaTypes.Add("HD DVD-RAM"); + } + } + + bool tryPlextor = false, tryHLDTST = false, tryPioneer = false, tryNEC = false; + + tryPlextor |= dev.Manufacturer.ToLowerInvariant() == "plextor"; + tryHLDTST |= dev.Manufacturer.ToLowerInvariant() == "hl-dt-st"; + tryPioneer |= dev.Manufacturer.ToLowerInvariant() == "pioneer"; + tryNEC |= dev.Manufacturer.ToLowerInvariant() == "nec"; + + mediaTypes.Sort(); + List mediaTests = new List(); + foreach (string mediaType in mediaTypes) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have a {0} disc that you can insert in the drive? (Y/N): ", mediaType); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + dev.AllowMediumRemoval(out senseBuffer, timeout, out duration); + dev.EjectTray(out senseBuffer, timeout, out duration); + DicConsole.WriteLine("Please insert it in the drive and press any key when it is ready."); + System.Console.ReadKey(true); + + testedMediaType mediaTest = new testedMediaType(); + mediaTest.MediumTypeName = mediaType; + mediaTest.MediaIsRecognized = true; + + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (sense) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); + if (decSense.HasValue) + { + if (decSense.Value.ASC == 0x3A) + { + int leftRetries = 20; + while (leftRetries > 0) + { + DicConsole.Write("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + mediaTest.MediaIsRecognized &= !sense; + } + else if (decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) + { + int leftRetries = 20; + while (leftRetries > 0) + { + DicConsole.Write("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + mediaTest.MediaIsRecognized &= !sense; + } + else + mediaTest.MediaIsRecognized = false; + } + else + mediaTest.MediaIsRecognized = false; + } + + if (mediaTest.MediaIsRecognized) + { + mediaTest.SupportsReadCapacitySpecified = true; + mediaTest.SupportsReadCapacity16Specified = true; + + DicConsole.WriteLine("Querying SCSI READ CAPACITY..."); + sense = dev.ReadCapacity(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadCapacity = true; + mediaTest.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1; + mediaTest.BlockSize = (uint)((buffer[5] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + mediaTest.BlocksSpecified = true; + mediaTest.BlockSizeSpecified = true; + } + + DicConsole.WriteLine("Querying SCSI READ CAPACITY (16)..."); + sense = dev.ReadCapacity16(out buffer, out buffer, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadCapacity16 = true; + byte[] temp = new byte[8]; + Array.Copy(buffer, 0, temp, 0, 8); + Array.Reverse(temp); + mediaTest.Blocks = BitConverter.ToUInt64(temp, 0) + 1; + mediaTest.BlockSize = (uint)((buffer[5] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + mediaTest.BlocksSpecified = true; + mediaTest.BlockSizeSpecified = true; + } + + decMode = null; + + DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); + sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense10 = true; + decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); + } + DicConsole.WriteLine("Querying SCSI MODE SENSE..."); + sense = dev.ModeSense(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense6 = true; + if (!decMode.HasValue) + decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); + } + + if (decMode.HasValue) + { + mediaTest.MediumType = (byte)decMode.Value.Header.MediumType; + mediaTest.MediumTypeSpecified = true; + if (decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) + { + mediaTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + mediaTest.DensitySpecified = true; + } + } + + if (mediaType.StartsWith("CD-") || mediaType == "Audio CD") + { + mediaTest.CanReadTOCSpecified = true; + mediaTest.CanReadFullTOCSpecified = true; + DicConsole.WriteLine("Querying CD TOC..."); + mediaTest.CanReadTOC = !dev.ReadTocPmaAtip(out buffer, out senseBuffer, false, 0, 0, timeout, out duration); + DicConsole.WriteLine("Querying CD Full TOC..."); + mediaTest.CanReadFullTOC = !dev.ReadRawToc(out buffer, out senseBuffer, 1, timeout, out duration); + } + + if (mediaType.StartsWith("CD-R")) + { + mediaTest.CanReadATIPSpecified = true; + mediaTest.CanReadPMASpecified = true; + DicConsole.WriteLine("Querying CD ATIP..."); + mediaTest.CanReadATIP = !dev.ReadAtip(out buffer, out senseBuffer, timeout, out duration); + DicConsole.WriteLine("Querying CD PMA..."); + mediaTest.CanReadPMA = !dev.ReadPma(out buffer, out senseBuffer, timeout, out duration); + } + + if (mediaType.StartsWith("DVD-") || mediaType.StartsWith("HD DVD-")) + { + mediaTest.CanReadPFISpecified = true; + mediaTest.CanReadDMISpecified = true; + DicConsole.WriteLine("Querying DVD PFI..."); + mediaTest.CanReadPFI = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, timeout, out duration); + DicConsole.WriteLine("Querying DVD DMI..."); + mediaTest.CanReadDMI = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, timeout, out duration); + } + + if (mediaType == "DVD-ROM") + { + mediaTest.CanReadCMISpecified = true; + DicConsole.WriteLine("Querying DVD CMI..."); + mediaTest.CanReadCMI = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, timeout, out duration); + } + + if (mediaType == "DVD-ROM" || mediaType == "HD DVD-ROM") + { + mediaTest.CanReadBCASpecified = true; + DicConsole.WriteLine("Querying DVD BCA..."); + mediaTest.CanReadBCA = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, timeout, out duration); + mediaTest.CanReadAACSSpecified = true; + DicConsole.WriteLine("Querying DVD AACS..."); + mediaTest.CanReadAACS = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVD_AACS, 0, timeout, out duration); + } + + if (mediaType == "BD-ROM") + { + mediaTest.CanReadBCASpecified = true; + DicConsole.WriteLine("Querying BD BCA..."); + mediaTest.CanReadBCA = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_BurstCuttingArea, 0, timeout, out duration); + } + + if (mediaType == "DVD-RAM" || mediaType == "HD DVD-RAM") + { + mediaTest.CanReadDDSSpecified = true; + mediaTest.CanReadSpareAreaInformationSpecified = true; + mediaTest.CanReadDDS = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_DDS, 0, timeout, out duration); + mediaTest.CanReadSpareAreaInformation = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, timeout, out duration); + } + + if (mediaType.StartsWith("BD-R") && mediaType != "BD-ROM") + { + mediaTest.CanReadDDSSpecified = true; + mediaTest.CanReadSpareAreaInformationSpecified = true; + DicConsole.WriteLine("Querying BD DDS..."); + mediaTest.CanReadDDS = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_DDS, 0, timeout, out duration); + DicConsole.WriteLine("Querying BD SAI..."); + mediaTest.CanReadSpareAreaInformation = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_SpareAreaInformation, 0, timeout, out duration); + } + + if (mediaType == "DVD-R" || mediaType == "DVD-RW") + { + mediaTest.CanReadPRISpecified = true; + DicConsole.WriteLine("Querying DVD PRI..."); + mediaTest.CanReadPRI = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, timeout, out duration); + } + + if (mediaType == "DVD-R" || mediaType == "DVD-RW" || mediaType == "HD DVD-R") + { + mediaTest.CanReadMediaIDSpecified = true; + mediaTest.CanReadRecordablePFISpecified = true; + DicConsole.WriteLine("Querying DVD Media ID..."); + mediaTest.CanReadMediaID = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, timeout, out duration); + DicConsole.WriteLine("Querying DVD Embossed PFI..."); + mediaTest.CanReadRecordablePFI = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, timeout, out duration); + } + + if (mediaType.StartsWith("DVD+R")) + { + mediaTest.CanReadADIPSpecified = true; + mediaTest.CanReadDCBSpecified = true; + DicConsole.WriteLine("Querying DVD ADIP..."); + mediaTest.CanReadADIP = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ADIP, 0, timeout, out duration); + DicConsole.WriteLine("Querying DVD DCB..."); + mediaTest.CanReadDCB = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DCB, 0, timeout, out duration); + } + + if (mediaType == "HD DVD-ROM") + { + mediaTest.CanReadHDCMISpecified = true; + DicConsole.WriteLine("Querying HD DVD CMI..."); + mediaTest.CanReadHDCMI = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, timeout, out duration); + } + + if (mediaType.EndsWith(" DL")) + { + mediaTest.CanReadLayerCapacitySpecified = true; + DicConsole.WriteLine("Querying DVD Layer Capacity..."); + mediaTest.CanReadLayerCapacity = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_LayerCapacity, 0, timeout, out duration); + } + + if (mediaType.StartsWith("BD-R")) + { + mediaTest.CanReadDiscInformationSpecified = true; + mediaTest.CanReadPACSpecified = true; + DicConsole.WriteLine("Querying BD Disc Information..."); + mediaTest.CanReadDiscInformation = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, timeout, out duration); + DicConsole.WriteLine("Querying BD PAC..."); + mediaTest.CanReadPAC = !dev.ReadDiscStructure(out buffer, out senseBuffer, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.PAC, 0, timeout, out duration); + } + + mediaTest.SupportsReadSpecified = true; + mediaTest.SupportsRead10Specified = true; + mediaTest.SupportsRead12Specified = true; + mediaTest.SupportsRead16Specified = true; + + DicConsole.WriteLine("Trying SCSI READ (6)..."); + mediaTest.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, 2048, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (10)..."); + mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, 2048, 0, 1, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (12)..."); + mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, 2048, 0, 1, false, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (16)..."); + mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, 2048, 0, 1, false, timeout, out duration); + + if (options.Debug) + { + if (!tryPlextor) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have want to try Plextor vendor commands? THIS IS DANGEROUS AND CAN IRREVERSIBLY DESTROY YOUR DRIVE (IF IN DOUBT PRESS 'N') (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + tryPlextor |= pressedKey.Key == ConsoleKey.Y; + } + } + + if (mediaType.StartsWith("CD-") || mediaType == "Audio CD") + { + mediaTest.CanReadC2PointersSpecified = true; + mediaTest.CanReadCorrectedSubchannelSpecified = true; + mediaTest.CanReadCorrectedSubchannelWithC2Specified = true; + mediaTest.CanReadLeadInSpecified = true; + mediaTest.CanReadLeadOutSpecified = true; + mediaTest.CanReadPQSubchannelSpecified = true; + mediaTest.CanReadPQSubchannelWithC2Specified = true; + mediaTest.CanReadRWSubchannelSpecified = true; + mediaTest.CanReadRWSubchannelWithC2Specified = true; + mediaTest.SupportsReadCdMsfSpecified = true; + mediaTest.SupportsReadCdSpecified = true; + mediaTest.SupportsReadCdMsfRawSpecified = true; + mediaTest.SupportsReadCdRawSpecified = true; + + if (mediaType == "Audio CD") + { + DicConsole.WriteLine("Trying SCSI READ CD..."); + mediaTest.SupportsReadCd = !dev.ReadCd(out buffer, out senseBuffer, 0, 2352, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ CD MSF..."); + mediaTest.SupportsReadCdMsf = !dev.ReadCdMsf(out buffer, out senseBuffer, 0x00000200, 0x00000201, 2352, MmcSectorTypes.CDDA, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + } + else + { + DicConsole.WriteLine("Trying SCSI READ CD..."); + mediaTest.SupportsReadCd = !dev.ReadCd(out buffer, out senseBuffer, 0, 2048, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ CD MSF..."); + mediaTest.SupportsReadCdMsf = !dev.ReadCdMsf(out buffer, out senseBuffer, 0x00000200, 0x00000201, 2048, MmcSectorTypes.AllTypes, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ CD full sector..."); + mediaTest.SupportsReadCdRaw = !dev.ReadCd(out buffer, out senseBuffer, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ CD MSF full sector..."); + mediaTest.SupportsReadCdMsfRaw = !dev.ReadCdMsf(out buffer, out senseBuffer, 0x00000200, 0x00000201, 2352, MmcSectorTypes.AllTypes, false, false, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + } + + if (mediaTest.SupportsReadCdRaw) + { + DicConsole.WriteLine("Trying to read CD Lead-In..."); + for (int i = -150; i < 0; i++) + { + if (mediaType == "Audio CD") + sense = dev.ReadCd(out buffer, out senseBuffer, (uint)i, 2352, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + else + sense = dev.ReadCd(out buffer, out senseBuffer, (uint)i, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + if (!sense) + { + mediaTest.CanReadLeadIn = true; + break; + } + } + + DicConsole.WriteLine("Trying to read CD Lead-Out..."); + mediaTest.CanReadLeadOut = !dev.ReadCd(out buffer, out senseBuffer, (uint)(mediaTest.Blocks + 1), 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, timeout, out duration); + } + + if (mediaType == "Audio CD" && mediaTest.SupportsReadCd) + { + DicConsole.WriteLine("Trying to read C2 Pointers..."); + mediaTest.CanReadC2Pointers = !dev.ReadCd(out buffer, out senseBuffer, 0, 2646, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.None, timeout, out duration); + if (!mediaTest.CanReadC2Pointers) + mediaTest.CanReadC2Pointers = !dev.ReadCd(out buffer, out senseBuffer, 0, 2648, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.None, timeout, out duration); + + DicConsole.WriteLine("Trying to read subchannels..."); + mediaTest.CanReadPQSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2368, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.Q16, timeout, out duration); + mediaTest.CanReadRWSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2448, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.Raw, timeout, out duration); + mediaTest.CanReadCorrectedSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2448, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.RW, timeout, out duration); + + DicConsole.WriteLine("Trying to read subchannels with C2 Pointers..."); + mediaTest.CanReadPQSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2662, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.Q16, timeout, out duration); + if (!mediaTest.CanReadPQSubchannelWithC2) + mediaTest.CanReadPQSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2664, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.Q16, timeout, out duration); + + mediaTest.CanReadRWSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2712, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.Raw, timeout, out duration); + if (!mediaTest.CanReadRWSubchannelWithC2) + mediaTest.CanReadRWSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2714, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.Raw, timeout, out duration); + + mediaTest.CanReadCorrectedSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2712, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.RW, timeout, out duration); + if (!mediaTest.CanReadCorrectedSubchannelWithC2) + mediaTest.CanReadCorrectedSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2714, 1, MmcSectorTypes.CDDA, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.RW, timeout, out duration); + } + else if (mediaTest.SupportsReadCdRaw) + { + DicConsole.WriteLine("Trying to read C2 Pointers..."); + mediaTest.CanReadC2Pointers = !dev.ReadCd(out buffer, out senseBuffer, 0, 2646, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2Pointers, MmcSubchannel.None, timeout, out duration); + if (!mediaTest.CanReadC2Pointers) + mediaTest.CanReadC2Pointers = !dev.ReadCd(out buffer, out senseBuffer, 0, 2646, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2PointersAndBlock, MmcSubchannel.None, timeout, out duration); + + DicConsole.WriteLine("Trying to read subchannels..."); + mediaTest.CanReadPQSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2368, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16, timeout, out duration); + mediaTest.CanReadRWSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2448, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Raw, timeout, out duration); + mediaTest.CanReadCorrectedSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2448, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.RW, timeout, out duration); + + DicConsole.WriteLine("Trying to read subchannels with C2 Pointers..."); + mediaTest.CanReadPQSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2662, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2Pointers, MmcSubchannel.Q16, timeout, out duration); + if (!mediaTest.CanReadPQSubchannelWithC2) + mediaTest.CanReadPQSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2664, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2PointersAndBlock, MmcSubchannel.Q16, timeout, out duration); + + mediaTest.CanReadRWSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2712, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2Pointers, MmcSubchannel.Raw, timeout, out duration); + if (!mediaTest.CanReadRWSubchannelWithC2) + mediaTest.CanReadRWSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2714, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2PointersAndBlock, MmcSubchannel.Raw, timeout, out duration); + + mediaTest.CanReadCorrectedSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2712, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2Pointers, MmcSubchannel.RW, timeout, out duration); + if (!mediaTest.CanReadCorrectedSubchannelWithC2) + mediaTest.CanReadCorrectedSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2714, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.C2PointersAndBlock, MmcSubchannel.RW, timeout, out duration); + } + else + { + DicConsole.WriteLine("Trying to read C2 Pointers..."); + mediaTest.CanReadC2Pointers = !dev.ReadCd(out buffer, out senseBuffer, 0, 2342, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.None, timeout, out duration); + if (!mediaTest.CanReadC2Pointers) + mediaTest.CanReadC2Pointers = !dev.ReadCd(out buffer, out senseBuffer, 0, 2344, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.None, timeout, out duration); + + DicConsole.WriteLine("Trying to read subchannels..."); + mediaTest.CanReadPQSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2064, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.Q16, timeout, out duration); + mediaTest.CanReadRWSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2144, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.Raw, timeout, out duration); + mediaTest.CanReadCorrectedSubchannel = !dev.ReadCd(out buffer, out senseBuffer, 0, 2144, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.RW, timeout, out duration); + + DicConsole.WriteLine("Trying to read subchannels with C2 Pointers..."); + mediaTest.CanReadPQSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2358, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.Q16, timeout, out duration); + if (!mediaTest.CanReadPQSubchannelWithC2) + mediaTest.CanReadPQSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2360, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.Q16, timeout, out duration); + + mediaTest.CanReadRWSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2438, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.Raw, timeout, out duration); + if (!mediaTest.CanReadRWSubchannelWithC2) + mediaTest.CanReadRWSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2440, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.Raw, timeout, out duration); + + mediaTest.CanReadCorrectedSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2438, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2Pointers, MmcSubchannel.RW, timeout, out duration); + if (!mediaTest.CanReadCorrectedSubchannelWithC2) + mediaTest.CanReadCorrectedSubchannelWithC2 = !dev.ReadCd(out buffer, out senseBuffer, 0, 2440, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.C2PointersAndBlock, MmcSubchannel.RW, timeout, out duration); + } + + if (options.Debug) + { + if (!tryNEC) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have want to try NEC vendor commands? THIS IS DANGEROUS AND CAN IRREVERSIBLY DESTROY YOUR DRIVE (IF IN DOUBT PRESS 'N') (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + tryNEC |= pressedKey.Key == ConsoleKey.Y; + } + + if (!tryPioneer) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have want to try Pioneer vendor commands? THIS IS DANGEROUS AND CAN IRREVERSIBLY DESTROY YOUR DRIVE (IF IN DOUBT PRESS 'N') (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + tryPioneer |= pressedKey.Key == ConsoleKey.Y; + } + } + + if (tryPlextor) + { + mediaTest.SupportsPlextorReadCDDASpecified = true; + DicConsole.WriteLine("Trying Plextor READ CD-DA..."); + mediaTest.SupportsPlextorReadCDDA = !dev.PlextorReadCdDa(out buffer, out senseBuffer, 0, 2352, 1, PlextorSubchannel.None, timeout, out duration); + } + + if (tryPioneer) + { + mediaTest.SupportsPioneerReadCDDASpecified = true; + mediaTest.SupportsPioneerReadCDDAMSFSpecified = true; + DicConsole.WriteLine("Trying Pioneer READ CD-DA..."); + mediaTest.SupportsPioneerReadCDDA = !dev.PioneerReadCdDa(out buffer, out senseBuffer, 0, 2352, 1, PioneerSubchannel.None, timeout, out duration); + DicConsole.WriteLine("Trying Pioneer READ CD-DA MSF..."); + mediaTest.SupportsPioneerReadCDDAMSF = !dev.PioneerReadCdDaMsf(out buffer, out senseBuffer, 0x00000200, 0x00000201, 2352, PioneerSubchannel.None, timeout, out duration); + } + + if (tryNEC) + { + mediaTest.SupportsNECReadCDDASpecified = true; + DicConsole.WriteLine("Trying NEC READ CD-DA..."); + mediaTest.SupportsNECReadCDDA = !dev.NecReadCdDa(out buffer, out senseBuffer, 0, 1, timeout, out duration); + } + } + + mediaTest.LongBlockSize = mediaTest.BlockSize; + DicConsole.WriteLine("Trying SCSI READ LONG (10)..."); + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout, out duration); + if (sense && !dev.Error) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + mediaTest.SupportsReadLong = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + mediaTest.LongBlockSize = 0xFFFF - decSense.Value.Information; + mediaTest.LongBlockSizeSpecified = true; + } + } + } + } + + if (options.Debug) + { + if (!tryHLDTST) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have want to try HL-DT-ST (aka LG) vendor commands? THIS IS DANGEROUS AND CAN IRREVERSIBLY DESTROY YOUR DRIVE (IF IN DOUBT PRESS 'N') (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + tryHLDTST |= pressedKey.Key == ConsoleKey.Y; + } + } + + if (mediaTest.SupportsReadLong && mediaTest.LongBlockSize == mediaTest.BlockSize) + { + if (mediaTest.BlockSize == 512) + { + // Long sector sizes for 512-byte magneto-opticals + foreach (ushort testSize in new []{ 600, 610, 630 }) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = testSize; + mediaTest.LongBlockSizeSpecified = true; + break; + } + } + } + else if (mediaTest.BlockSize == 1024) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 1200, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 1200; + mediaTest.LongBlockSizeSpecified = true; + } + } + else if (mediaTest.BlockSize == 2048) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 2380; + mediaTest.LongBlockSizeSpecified = true; + } + } + else if (mediaTest.BlockSize == 4096) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 4760; + mediaTest.LongBlockSizeSpecified = true; + } + } + else if (mediaTest.BlockSize == 8192) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 9424; + mediaTest.LongBlockSizeSpecified = true; + } + } + } + + if (tryPlextor) + { + mediaTest.SupportsPlextorReadRawDVDSpecified = true; + DicConsole.WriteLine("Trying Plextor trick to raw read DVDs..."); + mediaTest.SupportsPlextorReadRawDVD = !dev.PlextorReadRawDvd(out buffer, out senseBuffer, 0, 1, timeout, out duration); + if (mediaTest.SupportsPlextorReadRawDVD) + mediaTest.SupportsPlextorReadRawDVD = !ArrayHelpers.ArrayIsNullOrEmpty(buffer); + } + + if (tryHLDTST) + { + mediaTest.SupportsHLDTSTReadRawDVDSpecified = true; + DicConsole.WriteLine("Trying HL-DT-ST (aka LG) trick to raw read DVDs..."); + mediaTest.SupportsHLDTSTReadRawDVD = !dev.HlDtStReadRawDvd(out buffer, out senseBuffer, 0, 1, timeout, out duration); + } + + if (mediaTest.SupportsReadLong && mediaTest.LongBlockSize == mediaTest.BlockSize) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + for (ushort i = (ushort)mediaTest.BlockSize; i < 0x4000; i++) + { + DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i); + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration); + if (!sense) + { + mediaTest.LongBlockSize = i; + mediaTest.LongBlockSizeSpecified = true; + break; + } + } + DicConsole.WriteLine(); + } + } + } + mediaTests.Add(mediaTest); + } + report.SCSI.MultiMediaDevice.TestedMedia = mediaTests.ToArray(); + } + } + #endregion MultiMediaDevice + #region SequentialAccessDevice + else if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess) + { + report.SCSI.SequentialDevice = new sscType(); + DicConsole.WriteLine("Querying SCSI READ BLOCK LIMITS..."); + sense = dev.ReadBlockLimits(out buffer, out senseBuffer, timeout, out duration); + if (!sense) + { + Decoders.SCSI.SSC.BlockLimits.BlockLimitsData? decBL = Decoders.SCSI.SSC.BlockLimits.Decode(buffer); + if (decBL.HasValue) + { + if (decBL.Value.granularity > 0) + { + report.SCSI.SequentialDevice.BlockSizeGranularitySpecified = true; + report.SCSI.SequentialDevice.BlockSizeGranularity = decBL.Value.granularity; + } + if (decBL.Value.maxBlockLen > 0) + { + report.SCSI.SequentialDevice.MaxBlockLengthSpecified = true; + report.SCSI.SequentialDevice.MaxBlockLength = decBL.Value.maxBlockLen; + } + if (decBL.Value.minBlockLen > 0) + { + report.SCSI.SequentialDevice.MinBlockLengthSpecified = true; + report.SCSI.SequentialDevice.MinBlockLength = decBL.Value.minBlockLen; + } + } + } + + DicConsole.WriteLine("Querying SCSI REPORT DENSITY SUPPORT..."); + sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, false, timeout, out duration); + if (!sense) + { + Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer); + if (dsh.HasValue) + { + report.SCSI.SequentialDevice.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length]; + for (int i = 0; i < dsh.Value.descriptors.Length; i++) + { + report.SCSI.SequentialDevice.SupportedDensities[i].BitsPerMm = dsh.Value.descriptors[i].bpmm; + report.SCSI.SequentialDevice.SupportedDensities[i].Capacity = dsh.Value.descriptors[i].capacity; + report.SCSI.SequentialDevice.SupportedDensities[i].DefaultDensity = dsh.Value.descriptors[i].defaultDensity; + report.SCSI.SequentialDevice.SupportedDensities[i].Description = dsh.Value.descriptors[i].description; + report.SCSI.SequentialDevice.SupportedDensities[i].Duplicate = dsh.Value.descriptors[i].duplicate; + report.SCSI.SequentialDevice.SupportedDensities[i].Name = dsh.Value.descriptors[i].name; + report.SCSI.SequentialDevice.SupportedDensities[i].Organization = dsh.Value.descriptors[i].organization; + report.SCSI.SequentialDevice.SupportedDensities[i].PrimaryCode = dsh.Value.descriptors[i].primaryCode; + report.SCSI.SequentialDevice.SupportedDensities[i].SecondaryCode = dsh.Value.descriptors[i].secondaryCode; + report.SCSI.SequentialDevice.SupportedDensities[i].Tracks = dsh.Value.descriptors[i].tracks; + report.SCSI.SequentialDevice.SupportedDensities[i].Width = dsh.Value.descriptors[i].width; + report.SCSI.SequentialDevice.SupportedDensities[i].Writable = dsh.Value.descriptors[i].writable; + } + } + } + + DicConsole.WriteLine("Querying SCSI REPORT DENSITY SUPPORT for medium types..."); + sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, false, timeout, out duration); + if (!sense) + { + Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer); + if (mtsh.HasValue) + { + report.SCSI.SequentialDevice.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length]; + for (int i = 0; i < mtsh.Value.descriptors.Length; i++) + { + report.SCSI.SequentialDevice.SupportedMediaTypes[i].Description = mtsh.Value.descriptors[i].description; + report.SCSI.SequentialDevice.SupportedMediaTypes[i].Length = mtsh.Value.descriptors[i].length; + report.SCSI.SequentialDevice.SupportedMediaTypes[i].MediumType = mtsh.Value.descriptors[i].mediumType; + report.SCSI.SequentialDevice.SupportedMediaTypes[i].Name = mtsh.Value.descriptors[i].name; + report.SCSI.SequentialDevice.SupportedMediaTypes[i].Organization = mtsh.Value.descriptors[i].organization; + report.SCSI.SequentialDevice.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width; + if (mtsh.Value.descriptors[i].densityCodes != null) + { + report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes = new int[mtsh.Value.descriptors[i].densityCodes.Length]; + for (int j = 0; j < mtsh.Value.descriptors.Length; j++) + report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes[j] = (int)mtsh.Value.descriptors[i].densityCodes[j]; + } + } + } + } + + List seqTests = new List(); + + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.N) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have media that you can insert in the drive? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + DicConsole.WriteLine("Please insert it in the drive and press any key when it is ready."); + System.Console.ReadKey(true); + + SequentialMedia seqTest = new SequentialMedia(); + DicConsole.Write("Please write a description of the media type and press enter: "); + seqTest.MediumTypeName = System.Console.ReadLine(); + DicConsole.Write("Please write the media manufacturer and press enter: "); + seqTest.Manufacturer = System.Console.ReadLine(); + DicConsole.Write("Please write the media model and press enter: "); + seqTest.Model = System.Console.ReadLine(); + + seqTest.MediaIsRecognized = true; + + sense = dev.Load(out senseBuffer, timeout, out duration); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (sense) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); + if (decSense.HasValue) + { + if (decSense.Value.ASC == 0x3A) + { + int leftRetries = 20; + while (leftRetries > 0) + { + DicConsole.Write("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + seqTest.MediaIsRecognized &= !sense; + } + else if (decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) + { + int leftRetries = 20; + while (leftRetries > 0) + { + DicConsole.Write("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + seqTest.MediaIsRecognized &= !sense; + } + else + seqTest.MediaIsRecognized = false; + } + else + seqTest.MediaIsRecognized = false; + } + + if (seqTest.MediaIsRecognized) + { + decMode = null; + + DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); + sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense10 = true; + decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); + } + + DicConsole.WriteLine("Querying SCSI MODE SENSE..."); + sense = dev.ModeSense(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense6 = true; + if (!decMode.HasValue) + decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); + } + + if (decMode.HasValue) + { + seqTest.MediumType = (byte)decMode.Value.Header.MediumType; + seqTest.MediumTypeSpecified = true; + if (decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) + { + seqTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + seqTest.DensitySpecified = true; + } + } + } + + DicConsole.WriteLine("Querying SCSI REPORT DENSITY SUPPORT for current media..."); + sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, true, timeout, out duration); + if (!sense) + { + Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer); + if (dsh.HasValue) + { + seqTest.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length]; + for (int i = 0; i < dsh.Value.descriptors.Length; i++) + { + seqTest.SupportedDensities[i].BitsPerMm = dsh.Value.descriptors[i].bpmm; + seqTest.SupportedDensities[i].Capacity = dsh.Value.descriptors[i].capacity; + seqTest.SupportedDensities[i].DefaultDensity = dsh.Value.descriptors[i].defaultDensity; + seqTest.SupportedDensities[i].Description = dsh.Value.descriptors[i].description; + seqTest.SupportedDensities[i].Duplicate = dsh.Value.descriptors[i].duplicate; + seqTest.SupportedDensities[i].Name = dsh.Value.descriptors[i].name; + seqTest.SupportedDensities[i].Organization = dsh.Value.descriptors[i].organization; + seqTest.SupportedDensities[i].PrimaryCode = dsh.Value.descriptors[i].primaryCode; + seqTest.SupportedDensities[i].SecondaryCode = dsh.Value.descriptors[i].secondaryCode; + seqTest.SupportedDensities[i].Tracks = dsh.Value.descriptors[i].tracks; + seqTest.SupportedDensities[i].Width = dsh.Value.descriptors[i].width; + seqTest.SupportedDensities[i].Writable = dsh.Value.descriptors[i].writable; + } + } + } + + DicConsole.WriteLine("Querying SCSI REPORT DENSITY SUPPORT for medium types for current media..."); + sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, true, timeout, out duration); + if (!sense) + { + Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer); + if (mtsh.HasValue) + { + seqTest.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length]; + for (int i = 0; i < mtsh.Value.descriptors.Length; i++) + { + seqTest.SupportedMediaTypes[i].Description = mtsh.Value.descriptors[i].description; + seqTest.SupportedMediaTypes[i].Length = mtsh.Value.descriptors[i].length; + seqTest.SupportedMediaTypes[i].MediumType = mtsh.Value.descriptors[i].mediumType; + seqTest.SupportedMediaTypes[i].Name = mtsh.Value.descriptors[i].name; + seqTest.SupportedMediaTypes[i].Organization = mtsh.Value.descriptors[i].organization; + seqTest.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width; + if (mtsh.Value.descriptors[i].densityCodes != null) + { + seqTest.SupportedMediaTypes[i].DensityCodes = new int[mtsh.Value.descriptors[i].densityCodes.Length]; + for (int j = 0; j < mtsh.Value.descriptors.Length; j++) + seqTest.SupportedMediaTypes[i].DensityCodes[j] = (int)mtsh.Value.descriptors[i].densityCodes[j]; + } + } + } + } + + seqTest.CanReadMediaSerialSpecified = true; + DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER..."); + seqTest.CanReadMediaSerial = !dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration); + seqTests.Add(seqTest); + } + } + report.SCSI.SequentialDevice.TestedMedia = seqTests.ToArray(); + } + #endregion SequentialAccessDevice + #region OtherDevices + else + { + if (removable) + { + List mediaTests = new List(); + + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.N) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Do you have media that you can insert in the drive? (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + DicConsole.WriteLine("Please insert it in the drive and press any key when it is ready."); + System.Console.ReadKey(true); + + testedMediaType mediaTest = new testedMediaType(); + DicConsole.Write("Please write a description of the media type and press enter: "); + mediaTest.MediumTypeName = System.Console.ReadLine(); + DicConsole.Write("Please write the media manufacturer and press enter: "); + mediaTest.Manufacturer = System.Console.ReadLine(); + DicConsole.Write("Please write the media model and press enter: "); + mediaTest.Model = System.Console.ReadLine(); + + mediaTest.ManufacturerSpecified = true; + mediaTest.ModelSpecified = true; + mediaTest.MediaIsRecognized = true; + + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (sense) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); + if (decSense.HasValue) + { + if (decSense.Value.ASC == 0x3A) + { + int leftRetries = 20; + while (leftRetries > 0) + { + DicConsole.Write("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + mediaTest.MediaIsRecognized &= !sense; + } + else if (decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) + { + int leftRetries = 20; + while (leftRetries > 0) + { + DicConsole.Write("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + mediaTest.MediaIsRecognized &= !sense; + } + else + mediaTest.MediaIsRecognized = false; + } + else + mediaTest.MediaIsRecognized = false; + } + + if (mediaTest.MediaIsRecognized) + { + mediaTest.SupportsReadCapacitySpecified = true; + mediaTest.SupportsReadCapacity16Specified = true; + + DicConsole.WriteLine("Querying SCSI READ CAPACITY..."); + sense = dev.ReadCapacity(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadCapacity = true; + mediaTest.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1; + mediaTest.BlockSize = (uint)((buffer[5] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + mediaTest.BlocksSpecified = true; + mediaTest.BlockSizeSpecified = true; + } + + DicConsole.WriteLine("Querying SCSI READ CAPACITY (16)..."); + sense = dev.ReadCapacity16(out buffer, out buffer, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadCapacity16 = true; + byte[] temp = new byte[8]; + Array.Copy(buffer, 0, temp, 0, 8); + Array.Reverse(temp); + mediaTest.Blocks = BitConverter.ToUInt64(temp, 0) + 1; + mediaTest.BlockSize = (uint)((buffer[5] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + mediaTest.BlocksSpecified = true; + mediaTest.BlockSizeSpecified = true; + } + + decMode = null; + + DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); + sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense10 = true; + decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); + } + + DicConsole.WriteLine("Querying SCSI MODE SENSE..."); + sense = dev.ModeSense(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense6 = true; + if (!decMode.HasValue) + decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); + } + + if (decMode.HasValue) + { + mediaTest.MediumType = (byte)decMode.Value.Header.MediumType; + mediaTest.MediumTypeSpecified = true; + if (decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) + { + mediaTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + mediaTest.DensitySpecified = true; + } + } + + mediaTest.SupportsReadSpecified = true; + mediaTest.SupportsRead10Specified = true; + mediaTest.SupportsRead12Specified = true; + mediaTest.SupportsRead16Specified = true; + mediaTest.SupportsReadLongSpecified = true; + + DicConsole.WriteLine("Trying SCSI READ (6)..."); + mediaTest.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, mediaTest.BlockSize, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (10)..."); + mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, mediaTest.BlockSize, 0, 1, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (12)..."); + mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, mediaTest.BlockSize, 0, 1, false, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (16)..."); + mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, mediaTest.BlockSize, 0, 1, false, timeout, out duration); + + mediaTest.LongBlockSize = mediaTest.BlockSize; + DicConsole.WriteLine("Trying SCSI READ LONG (10)..."); + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout, out duration); + if (sense && !dev.Error) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + mediaTest.SupportsReadLong = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + mediaTest.LongBlockSize = 0xFFFF - decSense.Value.Information; + mediaTest.LongBlockSizeSpecified = true; + } + } + } + } + + if (mediaTest.SupportsReadLong && mediaTest.LongBlockSize == mediaTest.BlockSize) + { + if (mediaTest.BlockSize == 512) + { + // Long sector sizes for 512-byte magneto-opticals + foreach (ushort testSize in new []{ 600, 610, 630 }) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = testSize; + mediaTest.LongBlockSizeSpecified = true; + break; + } + } + } + else if (mediaTest.BlockSize == 1024) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 1200, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 1200; + mediaTest.LongBlockSizeSpecified = true; + } + } + else if (mediaTest.BlockSize == 2048) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 2380; + mediaTest.LongBlockSizeSpecified = true; + } + } + else if (mediaTest.BlockSize == 4096) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 4760; + mediaTest.LongBlockSizeSpecified = true; + } + } + else if (mediaTest.BlockSize == 8192) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration); + if (!sense && !dev.Error) + { + mediaTest.SupportsReadLong = true; + mediaTest.LongBlockSize = 9424; + mediaTest.LongBlockSizeSpecified = true; + } + } + } + + if (mediaTest.SupportsReadLong && mediaTest.LongBlockSize == mediaTest.BlockSize) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + for (ushort i = (ushort)mediaTest.BlockSize; i < 0x4000; i++) + { + DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i); + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration); + if (!sense) + { + mediaTest.LongBlockSize = i; + mediaTest.LongBlockSizeSpecified = true; + break; + } + } + DicConsole.WriteLine(); + } + } + + mediaTest.CanReadMediaSerialSpecified = true; + DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER..."); + mediaTest.CanReadMediaSerial = !dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration); + } + mediaTests.Add(mediaTest); + } + } + report.SCSI.RemovableMedias = mediaTests.ToArray(); + } + else + { + report.SCSI.ReadCapabilities = new testedMediaType(); + report.SCSI.ReadCapabilitiesSpecified = true; + report.SCSI.ReadCapabilities.MediaIsRecognized = true; + + report.SCSI.ReadCapabilities.SupportsReadCapacitySpecified = true; + report.SCSI.ReadCapabilities.SupportsReadCapacity16Specified = true; + + DicConsole.WriteLine("Querying SCSI READ CAPACITY..."); + sense = dev.ReadCapacity(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadCapacity = true; + report.SCSI.ReadCapabilities.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1; + report.SCSI.ReadCapabilities.BlockSize = (uint)((buffer[5] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + report.SCSI.ReadCapabilities.BlocksSpecified = true; + report.SCSI.ReadCapabilities.BlockSizeSpecified = true; + } + + DicConsole.WriteLine("Querying SCSI READ CAPACITY (16)..."); + sense = dev.ReadCapacity16(out buffer, out buffer, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadCapacity16 = true; + byte[] temp = new byte[8]; + Array.Copy(buffer, 0, temp, 0, 8); + Array.Reverse(temp); + report.SCSI.ReadCapabilities.Blocks = BitConverter.ToUInt64(temp, 0) + 1; + report.SCSI.ReadCapabilities.BlockSize = (uint)((buffer[5] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + report.SCSI.ReadCapabilities.BlocksSpecified = true; + report.SCSI.ReadCapabilities.BlockSizeSpecified = true; + } + + decMode = null; + + DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); + sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense10 = true; + decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); + } + + DicConsole.WriteLine("Querying SCSI MODE SENSE..."); + sense = dev.ModeSense(out buffer, out senseBuffer, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.SupportsModeSense6 = true; + if (!decMode.HasValue) + decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); + } + + if (decMode.HasValue) + { + report.SCSI.ReadCapabilities.MediumType = (byte)decMode.Value.Header.MediumType; + report.SCSI.ReadCapabilities.MediumTypeSpecified = true; + if (decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) + { + report.SCSI.ReadCapabilities.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + report.SCSI.ReadCapabilities.DensitySpecified = true; + } + } + + report.SCSI.ReadCapabilities.SupportsReadSpecified = true; + report.SCSI.ReadCapabilities.SupportsRead10Specified = true; + report.SCSI.ReadCapabilities.SupportsRead12Specified = true; + report.SCSI.ReadCapabilities.SupportsRead16Specified = true; + report.SCSI.ReadCapabilities.SupportsReadLongSpecified = true; + + DicConsole.WriteLine("Trying SCSI READ (6)..."); + report.SCSI.ReadCapabilities.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, report.SCSI.ReadCapabilities.BlockSize, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (10)..."); + report.SCSI.ReadCapabilities.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (12)..."); + report.SCSI.ReadCapabilities.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration); + DicConsole.WriteLine("Trying SCSI READ (16)..."); + report.SCSI.ReadCapabilities.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration); + + report.SCSI.ReadCapabilities.LongBlockSize = report.SCSI.ReadCapabilities.BlockSize; + DicConsole.WriteLine("Trying SCSI READ LONG (10)..."); + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout, out duration); + if (sense && !dev.Error) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + report.SCSI.ReadCapabilities.SupportsReadLong = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + report.SCSI.ReadCapabilities.LongBlockSize = 0xFFFF - decSense.Value.Information; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + } + } + } + } + + if (report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize == report.SCSI.ReadCapabilities.BlockSize) + { + if (report.SCSI.ReadCapabilities.BlockSize == 512) + { + // Long sector sizes for 512-byte magneto-opticals + foreach (ushort testSize in new []{ 600, 610, 630 }) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadLong = true; + report.SCSI.ReadCapabilities.LongBlockSize = testSize; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + break; + } + } + } + else if (report.SCSI.ReadCapabilities.BlockSize == 1024) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 1200, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadLong = true; + report.SCSI.ReadCapabilities.LongBlockSize = 1200; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + } + } + else if (report.SCSI.ReadCapabilities.BlockSize == 2048) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadLong = true; + report.SCSI.ReadCapabilities.LongBlockSize = 2380; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + } + } + else if (report.SCSI.ReadCapabilities.BlockSize == 4096) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadLong = true; + report.SCSI.ReadCapabilities.LongBlockSize = 4760; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + } + } + else if (report.SCSI.ReadCapabilities.BlockSize == 8192) + { + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration); + if (!sense && !dev.Error) + { + report.SCSI.ReadCapabilities.SupportsReadLong = true; + report.SCSI.ReadCapabilities.LongBlockSize = 9424; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + } + } + } + + if (report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize == report.SCSI.ReadCapabilities.BlockSize) + { + pressedKey = new ConsoleKeyInfo(); + while (pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + { + DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): "); + pressedKey = System.Console.ReadKey(); + DicConsole.WriteLine(); + } + + if (pressedKey.Key == ConsoleKey.Y) + { + for (ushort i = (ushort)report.SCSI.ReadCapabilities.BlockSize; i < 0x4000; i++) + { + DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i); + sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration); + if (!sense) + { + report.SCSI.ReadCapabilities.LongBlockSize = i; + report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; + break; + } + } + DicConsole.WriteLine(); + } + } + } + } + #endregion OtherDevices + + FileStream xmlFs = new FileStream(xmlFile, FileMode.Create); + + System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(Metadata.DeviceReport)); + xmlSer.Serialize(xmlFs, report); + xmlFs.Close(); + } + } +} + diff --git a/DiscImageChef/Commands/DumpMedia.cs b/DiscImageChef/Commands/DumpMedia.cs new file mode 100644 index 00000000..420c5257 --- /dev/null +++ b/DiscImageChef/Commands/DumpMedia.cs @@ -0,0 +1,2064 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : DumpMedia.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using DiscImageChef.Console; +using System.IO; +using DiscImageChef.Devices; +using System.Text; +using System.Collections.Generic; +using Schemas; +using DiscImageChef.CommonTypes; + +namespace DiscImageChef.Commands +{ + public static class DumpMedia + { + static bool aborted; + static FileStream mhddFs; + static FileStream dataFs; + // TODO: Implement dump map + static FileStream mapFs; + + public static void doDumpMedia(DumpMediaSubOptions options) + { + DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", options.Debug); + DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", options.Verbose); + DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", options.DevicePath); + DicConsole.DebugWriteLine("Dump-Media command", "--output-prefix={0}", options.OutputPrefix); + DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", options.Raw); + DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", options.StopOnError); + DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); + DicConsole.DebugWriteLine("Dump-Media command", "--reset={0}", options.Reset); + + if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && + options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0])) + { + options.DevicePath = "\\\\.\\" + Char.ToUpper(options.DevicePath[0]) + ':'; + } + + mhddFs = null; + + Device dev = new Device(options.DevicePath); + + if (dev.Error) + { + DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); + return; + } + + switch (dev.Type) + { + case DeviceType.ATA: + doATAMediaScan(options, dev); + break; + case DeviceType.MMC: + case DeviceType.SecureDigital: + doSDMediaScan(options, dev); + break; + case DeviceType.NVMe: + doNVMeMediaScan(options, dev); + break; + case DeviceType.ATAPI: + case DeviceType.SCSI: + doSCSIMediaScan(options, dev); + break; + default: + throw new NotSupportedException("Unknown device type."); + } + } + + static void doATAMediaScan(DumpMediaSubOptions options, Device dev) + { + throw new NotImplementedException("ATA devices not yet supported."); + } + + static void doNVMeMediaScan(DumpMediaSubOptions options, Device dev) + { + throw new NotImplementedException("NVMe devices not yet supported."); + } + + static void doSDMediaScan(DumpMediaSubOptions options, Device dev) + { + throw new NotImplementedException("MMC/SD devices not yet supported."); + } + + static void doSCSIMediaScan(DumpMediaSubOptions options, Device dev) + { + byte[] cmdBuf; + byte[] senseBuf; + bool sense = false; + double duration; + ulong blocks = 0; + uint blockSize = 0; + byte[] tmpBuf; + MediaType dskType = MediaType.Unknown; + bool opticalDisc = false; + + if (dev.IsRemovable) + { + bool deviceReset = false; + retryTestReady: + sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); + if (sense) + { + Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); + if (decSense.HasValue) + { + if (decSense.Value.ASC == 0x3A) + { + int leftRetries = 5; + while (leftRetries > 0) + { + DicConsole.WriteLine("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + if (sense) + { + DicConsole.ErrorWriteLine("Please insert media in drive"); + return; + } + } + else if (decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) + { + int leftRetries = 10; + while (leftRetries > 0) + { + DicConsole.WriteLine("\rWaiting for drive to become ready"); + System.Threading.Thread.Sleep(2000); + sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); + if (!sense) + break; + + leftRetries--; + } + + if (sense) + { + DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + return; + } + } + /*else if (decSense.Value.ASC == 0x29 && decSense.Value.ASCQ == 0x00) + { + if (!deviceReset) + { + deviceReset = true; + DicConsole.ErrorWriteLine("Device did reset, retrying..."); + goto retryTestReady; + } + + DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + return; + }*/ + else + { + DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + return; + } + } + else + { + DicConsole.ErrorWriteLine("Unknown testing unit was ready."); + return; + } + } + } + + if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.DirectAccess || + dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice || + dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice || + dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.OpticalDevice || + dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.SimplifiedDevice || + dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.WriteOnceDevice) + { + sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out duration); + if (!sense) + { + blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + (cmdBuf[3])); + blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + (cmdBuf[7])); + } + + if (sense || blocks == 0xFFFFFFFF) + { + sense = dev.ReadCapacity16(out cmdBuf, out senseBuf, dev.Timeout, out duration); + + if (sense && blocks == 0) + { + // Not all MMC devices support READ CAPACITY, as they have READ TOC + if (dev.SCSIType != DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) + { + DicConsole.ErrorWriteLine("Unable to get media capacity"); + DicConsole.ErrorWriteLine("{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + } + } + + if (!sense) + { + byte[] temp = new byte[8]; + + Array.Copy(cmdBuf, 0, temp, 0, 8); + Array.Reverse(temp); + blocks = BitConverter.ToUInt64(temp, 0); + blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + (cmdBuf[7])); + } + } + + if (blocks != 0 && blockSize != 0) + { + blocks++; + DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", + blocks, blockSize, blocks * (ulong)blockSize); + } + } + + if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess) + { + throw new NotImplementedException(); + } + + if (blocks == 0) + { + DicConsole.ErrorWriteLine("Unable to read medium or empty medium present..."); + return; + } + + bool compactDisc = true; + Decoders.CD.FullTOC.CDFullTOC? toc = null; + byte scsiMediumType = 0; + byte scsiDensityCode = 0; + bool containsFloppyPage = false; + + CICMMetadataType sidecar = new CICMMetadataType(); + + #region MultiMediaDevice + if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) + { + sidecar.OpticalDisc = new OpticalDiscType[1]; + sidecar.OpticalDisc[0] = new OpticalDiscType(); + opticalDisc = true; + + sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration); + if (!sense) + { + Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf); + + switch (ftr.CurrentProfile) + { + case 0x0001: + dskType = MediaType.GENERIC_HDD; + goto default; + case 0x0005: + dskType = MediaType.CDMO; + break; + case 0x0008: + dskType = MediaType.CD; + break; + case 0x0009: + dskType = MediaType.CDR; + break; + case 0x000A: + dskType = MediaType.CDRW; + break; + case 0x0010: + dskType = MediaType.DVDROM; + goto default; + case 0x0011: + dskType = MediaType.DVDR; + goto default; + case 0x0012: + dskType = MediaType.DVDRAM; + goto default; + case 0x0013: + case 0x0014: + dskType = MediaType.DVDRW; + goto default; + case 0x0015: + case 0x0016: + dskType = MediaType.DVDRDL; + goto default; + case 0x0017: + dskType = MediaType.DVDRWDL; + goto default; + case 0x0018: + dskType = MediaType.DVDDownload; + goto default; + case 0x001A: + dskType = MediaType.DVDPRW; + goto default; + case 0x001B: + dskType = MediaType.DVDPR; + goto default; + case 0x0020: + dskType = MediaType.DDCD; + goto default; + case 0x0021: + dskType = MediaType.DDCDR; + goto default; + case 0x0022: + dskType = MediaType.DDCDRW; + goto default; + case 0x002A: + dskType = MediaType.DVDPRWDL; + goto default; + case 0x002B: + dskType = MediaType.DVDPRDL; + goto default; + case 0x0040: + dskType = MediaType.BDROM; + goto default; + case 0x0041: + case 0x0042: + dskType = MediaType.BDR; + goto default; + case 0x0043: + dskType = MediaType.BDRE; + goto default; + case 0x0050: + dskType = MediaType.HDDVDROM; + goto default; + case 0x0051: + dskType = MediaType.HDDVDR; + goto default; + case 0x0052: + dskType = MediaType.HDDVDRAM; + goto default; + case 0x0053: + dskType = MediaType.HDDVDRW; + goto default; + case 0x0058: + dskType = MediaType.HDDVDRDL; + goto default; + case 0x005A: + dskType = MediaType.HDDVDRWDL; + goto default; + default: + compactDisc = false; + break; + } + } + + #region CompactDisc + if (compactDisc) + { + // We discarded all discs that falsify a TOC before requesting a real TOC + // No TOC, no CD (or an empty one) + bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out duration); + if (!tocSense) + { + toc = Decoders.CD.FullTOC.Decode(cmdBuf); + if (toc.HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 2]; + Array.Copy(cmdBuf, 2, tmpBuf, 0, cmdBuf.Length - 2); + sidecar.OpticalDisc[0].TOC = new DumpType(); + sidecar.OpticalDisc[0].TOC.Image = options.OutputPrefix + ".toc.bin"; + sidecar.OpticalDisc[0].TOC.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].TOC.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].TOC.Image, tmpBuf); + + // ATIP exists on blank CDs + sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out duration); + if (!sense) + { + Decoders.CD.ATIP.CDATIP? atip = Decoders.CD.ATIP.Decode(cmdBuf); + if (atip.HasValue) + { + if (blocks == 0) + { + DicConsole.ErrorWriteLine("Cannot dump blank media."); + return; + } + + // Only CD-R and CD-RW have ATIP + dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR; + + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].ATIP = new DumpType(); + sidecar.OpticalDisc[0].ATIP.Image = options.OutputPrefix + ".atip.bin"; + sidecar.OpticalDisc[0].ATIP.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].ATIP.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].TOC.Image, tmpBuf); + } + } + + sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out duration); + if (!sense) + { + Decoders.SCSI.MMC.DiscInformation.StandardDiscInformation? discInfo = Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf); + if (discInfo.HasValue) + { + // If it is a read-only CD, check CD type if available + if (dskType == MediaType.CD) + { + switch (discInfo.Value.DiscType) + { + case 0x10: + dskType = MediaType.CDI; + break; + case 0x20: + dskType = MediaType.CDROMXA; + break; + } + } + } + } + + int sessions = 1; + int firstTrackLastSession = 0; + + sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out duration); + if (!sense) + { + Decoders.CD.Session.CDSessionInfo? session = Decoders.CD.Session.Decode(cmdBuf); + if (session.HasValue) + { + sessions = session.Value.LastCompleteSession; + firstTrackLastSession = session.Value.TrackDescriptors[0].TrackNumber; + } + } + + if (dskType == MediaType.CD) + { + bool hasDataTrack = false; + bool hasAudioTrack = false; + bool allFirstSessionTracksAreAudio = true; + bool hasVideoTrack = false; + + if (toc.HasValue) + { + foreach (Decoders.CD.FullTOC.TrackDataDescriptor track in toc.Value.TrackDescriptors) + { + if (track.TNO == 1 && + ((Decoders.CD.TOC_CONTROL)(track.CONTROL & 0x0D) == Decoders.CD.TOC_CONTROL.DataTrack || + (Decoders.CD.TOC_CONTROL)(track.CONTROL & 0x0D) == Decoders.CD.TOC_CONTROL.DataTrackIncremental)) + { + allFirstSessionTracksAreAudio &= firstTrackLastSession != 1; + } + + if ((Decoders.CD.TOC_CONTROL)(track.CONTROL & 0x0D) == Decoders.CD.TOC_CONTROL.DataTrack || + (Decoders.CD.TOC_CONTROL)(track.CONTROL & 0x0D) == Decoders.CD.TOC_CONTROL.DataTrackIncremental) + { + hasDataTrack = true; + allFirstSessionTracksAreAudio &= track.TNO >= firstTrackLastSession; + } + else + hasAudioTrack = true; + + hasVideoTrack |= track.ADR == 4; + } + } + + if (hasDataTrack && hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2) + dskType = MediaType.CDPLUS; + if (!hasDataTrack && hasAudioTrack && sessions == 1) + dskType = MediaType.CDDA; + if (hasDataTrack && !hasAudioTrack && sessions == 1) + dskType = MediaType.CDROM; + if (hasVideoTrack && !hasDataTrack && sessions == 1) + dskType = MediaType.CDV; + } + + sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.CD.PMA.Decode(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].PMA = new DumpType(); + sidecar.OpticalDisc[0].PMA.Image = options.OutputPrefix + ".pma.bin"; + sidecar.OpticalDisc[0].PMA.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].PMA.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].PMA.Image, tmpBuf); + } + } + + sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.CD.CDTextOnLeadIn.Decode(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].LeadInCdText = new DumpType(); + sidecar.OpticalDisc[0].LeadInCdText.Image = options.OutputPrefix + ".cdtext.bin"; + sidecar.OpticalDisc[0].LeadInCdText.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].LeadInCdText.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].LeadInCdText.Image, tmpBuf); + } + } + } + } + } + #endregion CompactDisc + else + { + #region Nintendo + if (dskType == MediaType.Unknown && blocks > 0) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); + if (!sense) + { + Decoders.DVD.PFI.PhysicalFormatInformation? nintendoPfi = Decoders.DVD.PFI.Decode(cmdBuf); + if (nintendoPfi != null) + { + if (nintendoPfi.Value.DiskCategory == DiscImageChef.Decoders.DVD.DiskCategory.Nintendo && + nintendoPfi.Value.PartVersion == 15) + { + throw new NotImplementedException("Dumping Nintendo GameCube or Wii discs is not yet implemented."); + } + } + } + } + #endregion Nintendo + + #region All DVD and HD DVD types + if (dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR || + dskType == MediaType.DVDPRDL || dskType == MediaType.DVDPRW || + dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR || + dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL || + dskType == MediaType.DVDROM || dskType == MediaType.DVDRW || + dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR || + dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL || + dskType == MediaType.HDDVDROM || dskType == MediaType.HDDVDRW || + dskType == MediaType.HDDVDRWDL) + { + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.DVD.PFI.Decode(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].PFI = new DumpType(); + sidecar.OpticalDisc[0].PFI.Image = options.OutputPrefix + ".pfi.bin"; + sidecar.OpticalDisc[0].PFI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].PFI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].PFI.Image, tmpBuf); + + Decoders.DVD.PFI.PhysicalFormatInformation decPfi = Decoders.DVD.PFI.Decode(cmdBuf).Value; + DicConsole.WriteLine("PFI:\n{0}", Decoders.DVD.PFI.Prettify(decPfi)); + + // False book types + if(dskType == MediaType.DVDROM) + { + switch(decPfi.DiskCategory) + { + case Decoders.DVD.DiskCategory.DVDPR: + dskType = MediaType.DVDPR; + break; + case Decoders.DVD.DiskCategory.DVDPRDL: + dskType = MediaType.DVDPRDL; + break; + case Decoders.DVD.DiskCategory.DVDPRW: + dskType = MediaType.DVDPRW; + break; + case Decoders.DVD.DiskCategory.DVDPRWDL: + dskType = MediaType.DVDPRWDL; + break; + case Decoders.DVD.DiskCategory.DVDR: + if(decPfi.PartVersion == 6) + dskType = MediaType.DVDRDL; + else + dskType = MediaType.DVDR; + break; + case Decoders.DVD.DiskCategory.DVDRAM: + dskType = MediaType.DVDRAM; + break; + default: + dskType = MediaType.DVDROM; + break; + case Decoders.DVD.DiskCategory.DVDRW: + if(decPfi.PartVersion == 3) + dskType = MediaType.DVDRWDL; + else + dskType = MediaType.DVDRW; + break; + case Decoders.DVD.DiskCategory.HDDVDR: + dskType = MediaType.HDDVDR; + break; + case Decoders.DVD.DiskCategory.HDDVDRAM: + dskType = MediaType.HDDVDRAM; + break; + case Decoders.DVD.DiskCategory.HDDVDROM: + dskType = MediaType.HDDVDROM; + break; + case Decoders.DVD.DiskCategory.HDDVDRW: + dskType = MediaType.HDDVDRW; + break; + case Decoders.DVD.DiskCategory.Nintendo: + if(decPfi.DiscSize == DiscImageChef.Decoders.DVD.DVDSize.Eighty) + dskType = MediaType.GOD; + else + dskType = MediaType.WOD; + break; + case Decoders.DVD.DiskCategory.UMD: + dskType = MediaType.UMD; + break; + } + } + } + } + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.Xbox.DMI.IsXbox(cmdBuf) || Decoders.Xbox.DMI.IsXbox360(cmdBuf)) + throw new NotImplementedException("Dumping Xbox discs is not yet implemented."); + + if (cmdBuf.Length == 2052) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].DMI = new DumpType(); + sidecar.OpticalDisc[0].DMI.Image = options.OutputPrefix + ".dmi.bin"; + sidecar.OpticalDisc[0].DMI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].DMI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].DMI.Image, tmpBuf); + } + } + } + #endregion All DVD and HD DVD types + + #region DVD-ROM + if (dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].CMI = new DumpType(); + sidecar.OpticalDisc[0].CMI.Image = options.OutputPrefix + ".cmi.bin"; + sidecar.OpticalDisc[0].CMI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].CMI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].CMI.Image, tmpBuf); + + Decoders.DVD.CSS_CPRM.LeadInCopyright cpy = Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).Value; + if(cpy.CopyrightType != DiscImageChef.Decoders.DVD.CopyrightType.NoProtection) + sidecar.OpticalDisc[0].CopyProtection = cpy.CopyrightType.ToString(); + } + } + } + #endregion DVD-ROM + + #region DVD-ROM and HD DVD-ROM + if (dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM || + dskType == MediaType.HDDVDROM) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].BCA = new DumpType(); + sidecar.OpticalDisc[0].BCA.Image = options.OutputPrefix + ".bca.bin"; + sidecar.OpticalDisc[0].BCA.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].BCA.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].BCA.Image, tmpBuf); + } + } + #endregion DVD-ROM and HD DVD-ROM + + #region DVD-RAM and HD DVD-RAM + if (dskType == MediaType.DVDRAM || dskType == MediaType.HDDVDRAM) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.DVD.DDS.Decode(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].DDS = new DumpType(); + sidecar.OpticalDisc[0].DDS.Image = options.OutputPrefix + ".dds.bin"; + sidecar.OpticalDisc[0].DDS.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].DDS.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].DDS.Image, tmpBuf); + } + } + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.DVD.Spare.Decode(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].SAI = new DumpType(); + sidecar.OpticalDisc[0].SAI.Image = options.OutputPrefix + ".sai.bin"; + sidecar.OpticalDisc[0].SAI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].SAI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].SAI.Image, tmpBuf); + } + } + } + #endregion DVD-RAM and HD DVD-RAM + + #region DVD-R and DVD-RW + if (dskType == MediaType.DVDR || dskType == MediaType.DVDRW) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].PRI = new DumpType(); + sidecar.OpticalDisc[0].PRI.Image = options.OutputPrefix + ".pri.bin"; + sidecar.OpticalDisc[0].PRI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].PRI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].SAI.Image, tmpBuf); + } + } + #endregion DVD-R and DVD-RW + + #region DVD-R, DVD-RW and HD DVD-R + if (dskType == MediaType.DVDR || dskType == MediaType.DVDRW || dskType == MediaType.HDDVDR) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].MediaID = new DumpType(); + sidecar.OpticalDisc[0].MediaID.Image = options.OutputPrefix + ".mid.bin"; + sidecar.OpticalDisc[0].MediaID.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].MediaID.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].MediaID.Image, tmpBuf); + } + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].PFIR = new DumpType(); + sidecar.OpticalDisc[0].PFIR.Image = options.OutputPrefix + ".pfir.bin"; + sidecar.OpticalDisc[0].PFIR.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].PFIR.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].PFIR.Image, tmpBuf); + } + } + #endregion DVD-R, DVD-RW and HD DVD-R + + #region All DVD+ + if (dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL || + dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].ADIP = new DumpType(); + sidecar.OpticalDisc[0].ADIP.Image = options.OutputPrefix + ".adip.bin"; + sidecar.OpticalDisc[0].ADIP.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].ADIP.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].ADIP.Image, tmpBuf); + } + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].DCB = new DumpType(); + sidecar.OpticalDisc[0].DCB.Image = options.OutputPrefix + ".dcb.bin"; + sidecar.OpticalDisc[0].DCB.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].DCB.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].DCB.Image, tmpBuf); + } + } + #endregion All DVD+ + + #region HD DVD-ROM + if (dskType == MediaType.HDDVDROM) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].CMI = new DumpType(); + sidecar.OpticalDisc[0].CMI.Image = options.OutputPrefix + ".cmi.bin"; + sidecar.OpticalDisc[0].CMI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].CMI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].CMI.Image, tmpBuf); + } + } + #endregion HD DVD-ROM + + #region All Blu-ray + if (dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDROM || + dskType == MediaType.BDRXL || dskType == MediaType.BDREXL) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration); + if (!sense) + { + if (Decoders.Bluray.DI.Decode(cmdBuf).HasValue) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].DI = new DumpType(); + sidecar.OpticalDisc[0].DI.Image = options.OutputPrefix + ".di.bin"; + sidecar.OpticalDisc[0].DI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].DI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].DI.Image, tmpBuf); + } + } + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].PAC = new DumpType(); + sidecar.OpticalDisc[0].PAC.Image = options.OutputPrefix + ".pac.bin"; + sidecar.OpticalDisc[0].PAC.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].PAC.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].PAC.Image, tmpBuf); + } + } + #endregion All Blu-ray + + + #region BD-ROM only + if (dskType == MediaType.BDROM) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].BCA = new DumpType(); + sidecar.OpticalDisc[0].BCA.Image = options.OutputPrefix + ".bca.bin"; + sidecar.OpticalDisc[0].BCA.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].BCA.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].BCA.Image, tmpBuf); + } + } + #endregion BD-ROM only + + #region Writable Blu-ray only + if (dskType == MediaType.BDR || dskType == MediaType.BDRE || + dskType == MediaType.BDRXL || dskType == MediaType.BDREXL) + { + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].DDS = new DumpType(); + sidecar.OpticalDisc[0].DDS.Image = options.OutputPrefix + ".dds.bin"; + sidecar.OpticalDisc[0].DDS.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].DDS.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].DDS.Image, tmpBuf); + } + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout, out duration); + if (!sense) + { + tmpBuf = new byte[cmdBuf.Length - 4]; + Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); + sidecar.OpticalDisc[0].SAI = new DumpType(); + sidecar.OpticalDisc[0].SAI.Image = options.OutputPrefix + ".sai.bin"; + sidecar.OpticalDisc[0].SAI.Size = tmpBuf.Length; + sidecar.OpticalDisc[0].SAI.Checksums = Core.Checksum.GetChecksums(tmpBuf).ToArray(); + writeToFile(sidecar.OpticalDisc[0].SAI.Image, tmpBuf); + } + } + #endregion Writable Blu-ray only + } + } + #endregion MultiMediaDevice + else + { + compactDisc = false; + sidecar.BlockMedia = new BlockMediaType[1]; + sidecar.BlockMedia[0] = new BlockMediaType(); + + // All USB flash drives report as removable, even if the media is not removable + if (!dev.IsRemovable || dev.IsUSB) + { + if (dev.IsUSB) + { + sidecar.BlockMedia[0].USB = new USBType(); + sidecar.BlockMedia[0].USB.ProductID = dev.USBProductID; + sidecar.BlockMedia[0].USB.VendorID = dev.USBVendorID; + sidecar.BlockMedia[0].USB.Descriptors = new DumpType(); + sidecar.BlockMedia[0].USB.Descriptors.Image = options.OutputPrefix + ".usbdescriptors.bin"; + sidecar.BlockMedia[0].USB.Descriptors.Size = dev.USBDescriptors.Length; + sidecar.BlockMedia[0].USB.Descriptors.Checksums = Core.Checksum.GetChecksums(dev.USBDescriptors).ToArray(); + writeToFile(sidecar.BlockMedia[0].USB.Descriptors.Image, dev.USBDescriptors); + } + + if (dev.Type == DeviceType.ATAPI) + { + DiscImageChef.Decoders.ATA.AtaErrorRegistersCHS errorRegs; + sense = dev.AtapiIdentify(out cmdBuf, out errorRegs); + if (!sense) + { + sidecar.BlockMedia[0].ATA = new ATAType(); + sidecar.BlockMedia[0].ATA.Identify = new DumpType(); + sidecar.BlockMedia[0].ATA.Identify.Image = options.OutputPrefix + ".identify.bin"; + sidecar.BlockMedia[0].ATA.Identify.Size = cmdBuf.Length; + sidecar.BlockMedia[0].ATA.Identify.Checksums = Core.Checksum.GetChecksums(cmdBuf).ToArray(); + writeToFile(sidecar.BlockMedia[0].ATA.Identify.Image, cmdBuf); + } + } + + sense = dev.ScsiInquiry(out cmdBuf, out senseBuf); + if (!sense) + { + sidecar.BlockMedia[0].SCSI = new SCSIType(); + sidecar.BlockMedia[0].SCSI.Inquiry = new DumpType(); + sidecar.BlockMedia[0].SCSI.Inquiry.Image = options.OutputPrefix + ".inquiry.bin"; + sidecar.BlockMedia[0].SCSI.Inquiry.Size = cmdBuf.Length; + sidecar.BlockMedia[0].SCSI.Inquiry.Checksums = Core.Checksum.GetChecksums(cmdBuf).ToArray(); + writeToFile(sidecar.BlockMedia[0].SCSI.Inquiry.Image, cmdBuf); + + sense = dev.ScsiInquiry(out cmdBuf, out senseBuf, 0x00); + if (!sense) + { + byte[] pages = Decoders.SCSI.EVPD.DecodePage00(cmdBuf); + + if (pages != null) + { + List evpds = new List(); + foreach (byte page in pages) + { + sense = dev.ScsiInquiry(out cmdBuf, out senseBuf, page); + if (!sense) + { + EVPDType evpd = new EVPDType(); + evpd.Image = String.Format("{0}.evpd_{1:X2}h.bin", options.OutputPrefix, page); + evpd.Checksums = Core.Checksum.GetChecksums(cmdBuf).ToArray(); + evpd.Size = cmdBuf.Length; + evpd.Checksums = Core.Checksum.GetChecksums(cmdBuf).ToArray(); + writeToFile(evpd.Image, cmdBuf); + evpds.Add(evpd); + } + } + + if (evpds.Count > 0) + sidecar.BlockMedia[0].SCSI.EVPD = evpds.ToArray(); + } + } + + sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration); + if (!sense || dev.Error) + { + sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); + } + + Decoders.SCSI.Modes.DecodedMode? decMode = null; + + if (!sense && !dev.Error) + { + if (Decoders.SCSI.Modes.DecodeMode10(cmdBuf, dev.SCSIType).HasValue) + { + decMode = Decoders.SCSI.Modes.DecodeMode10(cmdBuf, dev.SCSIType); + sidecar.BlockMedia[0].SCSI.ModeSense10 = new DumpType(); + sidecar.BlockMedia[0].SCSI.ModeSense10.Image = options.OutputPrefix + ".modesense10.bin"; + sidecar.BlockMedia[0].SCSI.ModeSense10.Size = cmdBuf.Length; + sidecar.BlockMedia[0].SCSI.ModeSense10.Checksums = Core.Checksum.GetChecksums(cmdBuf).ToArray(); + writeToFile(sidecar.BlockMedia[0].SCSI.ModeSense10.Image, cmdBuf); + } + } + + sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); + if (sense || dev.Error) + sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); + if (sense || dev.Error) + sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration); + + if (!sense && !dev.Error) + { + if (Decoders.SCSI.Modes.DecodeMode6(cmdBuf, dev.SCSIType).HasValue) + { + decMode = Decoders.SCSI.Modes.DecodeMode10(cmdBuf, dev.SCSIType); + sidecar.BlockMedia[0].SCSI.ModeSense = new DumpType(); + sidecar.BlockMedia[0].SCSI.ModeSense.Image = options.OutputPrefix + ".modesense.bin"; + sidecar.BlockMedia[0].SCSI.ModeSense.Size = cmdBuf.Length; + sidecar.BlockMedia[0].SCSI.ModeSense.Checksums = Core.Checksum.GetChecksums(cmdBuf).ToArray(); + writeToFile(sidecar.BlockMedia[0].SCSI.ModeSense.Image, cmdBuf); + } + } + + if(decMode.HasValue) + { + scsiMediumType = (byte)decMode.Value.Header.MediumType; + if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length >= 1) + scsiDensityCode = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + + foreach(Decoders.SCSI.Modes.ModePage modePage in decMode.Value.Pages) + if(modePage.Page == 0x05) + containsFloppyPage = true; + } + } + } + } + + if(dskType == MediaType.Unknown) + dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumType, scsiDensityCode, blocks, blockSize); + + if(dskType == MediaType.Unknown && dev.IsUSB && containsFloppyPage) + dskType = MediaType.FlashDrive; + + DicConsole.WriteLine("Media identified as {0}", dskType); + + byte[] readBuffer; + uint blocksToRead = 255; + + ulong errored = 0; + DateTime start; + DateTime end; + double totalDuration = 0; + double totalChkDuration = 0; + double currentSpeed = 0; + double maxSpeed = double.MinValue; + double minSpeed = double.MaxValue; + List unreadableSectors = new List(); + Core.Checksum dataChk; + + aborted = false; + System.Console.CancelKeyPress += (sender, e) => + { + e.Cancel = aborted = true; + }; + + // TODO: Raw reading + bool read6 = false, read10 = false, read12 = false, read16 = false, readcd; + bool readLong10 = false, readLong16 = false, hldtstReadRaw = false, necReadCDDA = false; + bool pioneerReadCDDA = false, plextorReadCDDA = false, plextorReadRaw = false, syqReadLong6 = false, syqReadLong10 = false; + + if (compactDisc) + { + if (toc == null) + { + DicConsole.ErrorWriteLine("Error trying to decode TOC..."); + return; + } + + if (options.Raw) + { + throw new NotImplementedException("CD dumping not yet implemented"); + } + else + { + // TODO: Check subchannel capabilities + readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, 2448, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, + true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration); + + if (readcd) + DicConsole.WriteLine("Using MMC READ CD command."); + } + + DicConsole.WriteLine("Trying to read Lead-In..."); + bool gotLeadIn = false; + int leadInSectorsGood = 0, leadInSectorsTotal = 0; + + initDataFile(options.OutputPrefix + ".leadin.bin"); + dataChk = new DiscImageChef.Core.Checksum(); + + start = DateTime.UtcNow; + + readBuffer = null; + + for (int leadInBlock = -150; leadInBlock < 0; leadInBlock++) + { + if (aborted) + break; + + double cmdDuration = 0; + + if (currentSpeed > maxSpeed && currentSpeed != 0) + maxSpeed = currentSpeed; + if (currentSpeed < minSpeed && currentSpeed != 0) + minSpeed = currentSpeed; + + DicConsole.Write("\rTrying to read lead-in sector {0} ({1:F3} MiB/sec.)", (int)leadInBlock, currentSpeed); + + sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)leadInBlock, 2448, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, + true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration); + + if (!sense && !dev.Error) + { + dataChk.Update(readBuffer); + writeToDataFile(readBuffer); + gotLeadIn = true; + leadInSectorsGood++; + leadInSectorsTotal++; + } + else + { + if (gotLeadIn) + { + // Write empty data + dataChk.Update(new byte[2448]); + writeToDataFile(new byte[2448]); + leadInSectorsTotal++; + } + } + + currentSpeed = ((double)2448 / (double)1048576) / (cmdDuration / (double)1000); + } + + closeDataFile(); + if (leadInSectorsGood > 0) + { + sidecar.OpticalDisc[0].LeadIn = new BorderType[1]; + sidecar.OpticalDisc[0].LeadIn[0] = new BorderType(); + sidecar.OpticalDisc[0].LeadIn[0].Image = options.OutputPrefix + ".leadin.bin"; + sidecar.OpticalDisc[0].LeadIn[0].Checksums = dataChk.End().ToArray(); + sidecar.OpticalDisc[0].LeadIn[0].Size = leadInSectorsTotal * 2448; + } + else + File.Delete(options.OutputPrefix + ".leadin.bin"); + + DicConsole.WriteLine(); + DicConsole.WriteLine("Got {0} lead-in sectors.", leadInSectorsGood); + + while (true) + { + if (readcd) + { + sense = dev.ReadCd(out readBuffer, out senseBuf, 0, 2448, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, + true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration); + if (dev.Error) + blocksToRead /= 2; + } + + if (!dev.Error || blocksToRead == 1) + break; + } + + if (dev.Error) + { + DicConsole.ErrorWriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError); + return; + } + + DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); + + initDataFile(options.OutputPrefix + ".bin"); + initMHDDLogFile(options.OutputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead); + + for (ulong i = 0; i < blocks; i += blocksToRead) + { + if (aborted) + break; + + double cmdDuration = 0; + + if ((blocks - i) < blocksToRead) + blocksToRead = (uint)(blocks - i); + + if (currentSpeed > maxSpeed && currentSpeed != 0) + maxSpeed = currentSpeed; + if (currentSpeed < minSpeed && currentSpeed != 0) + minSpeed = currentSpeed; + + DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); + + if (readcd) + { + sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, 2448, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, + true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + + if (!sense && !dev.Error) + { + writeMHDDLogFile(i, cmdDuration); + writeToDataFile(readBuffer); + } + else + { + // TODO: Reset device after X errors + if (options.StopOnError) + return; // TODO: Return more cleanly + + // Write empty data + writeToDataFile(new byte[2448 * blocksToRead]); + + // TODO: Record error on mapfile + + errored += blocksToRead; + unreadableSectors.Add(i); + DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + if (cmdDuration < 500) + writeMHDDLogFile(i, 65535); + else + writeMHDDLogFile(i, cmdDuration); + } + + currentSpeed = ((double)2448 * blocksToRead / (double)1048576) / (cmdDuration / (double)1000); + } + DicConsole.WriteLine(); + closeMHDDLogFile(); + + dataChk = new Core.Checksum(); + dataFs.Seek(0, SeekOrigin.Begin); + blocksToRead = 500; + + for (ulong i = 0; i < blocks; i += blocksToRead) + { + if (aborted) + break; + + if ((blocks - i) < blocksToRead) + blocksToRead = (uint)(blocks - i); + + DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); + + DateTime chkStart = DateTime.UtcNow; + byte[] dataToCheck = new byte[blockSize * blocksToRead]; + dataFs.Read(dataToCheck, 0, (int)(blockSize * blocksToRead)); + dataChk.Update(dataToCheck); + DateTime chkEnd = DateTime.UtcNow; + + double chkDuration = (chkEnd - chkStart).TotalMilliseconds; + totalChkDuration += chkDuration; + + currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000); + } + DicConsole.WriteLine(); + closeDataFile(); + end = DateTime.UtcNow; + + // TODO: Correct this + sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray(); + sidecar.OpticalDisc[0].DumpHardwareArray = new DumpHardwareType[1]; + sidecar.OpticalDisc[0].DumpHardwareArray[0] = new DumpHardwareType(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents = new ExtentType[1]; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents[0] = new ExtentType(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents[0].Start = 0; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents[0].End = (int)(blocks - 1); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Manufacturer = dev.Manufacturer; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Model = dev.Model; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Revision = dev.Revision; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software = new SoftwareType(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software.Name = "DiscImageChef"; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software.OperatingSystem = dev.PlatformID.ToString(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software.Version = typeof(MainClass).Assembly.GetName().Version.ToString(); + sidecar.OpticalDisc[0].Image = new ImageType(); + sidecar.OpticalDisc[0].Image.format = "Raw disk image (sector by sector copy)"; + sidecar.OpticalDisc[0].Image.Value = options.OutputPrefix + ".bin"; + sidecar.OpticalDisc[0].Sessions = 1; + sidecar.OpticalDisc[0].Tracks = new []{1}; + sidecar.OpticalDisc[0].Track = new TrackType[1]; + sidecar.OpticalDisc[0].Track[0] = new TrackType(); + sidecar.OpticalDisc[0].Track[0].BytesPerSector = (int)blockSize; + sidecar.OpticalDisc[0].Track[0].Checksums = sidecar.OpticalDisc[0].Checksums; + sidecar.OpticalDisc[0].Track[0].EndSector = (long)(blocks - 1); + sidecar.OpticalDisc[0].Track[0].Image = new ImageType(); + sidecar.OpticalDisc[0].Track[0].Image.format = "BINARY"; + sidecar.OpticalDisc[0].Track[0].Image.offset = 0; + sidecar.OpticalDisc[0].Track[0].Image.offsetSpecified = true; + sidecar.OpticalDisc[0].Track[0].Image.Value = sidecar.OpticalDisc[0].Image.Value; + sidecar.OpticalDisc[0].Track[0].Sequence = new TrackSequenceType(); + sidecar.OpticalDisc[0].Track[0].Sequence.Session = 1; + sidecar.OpticalDisc[0].Track[0].Sequence.TrackNumber = 1; + sidecar.OpticalDisc[0].Track[0].Size = (long)(blocks * blockSize); + sidecar.OpticalDisc[0].Track[0].StartSector = 0; + sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.mode1; + sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType); + string xmlDskTyp, xmlDskSubTyp; + Metadata.MediaType.MediaTypeToString(dskType, out xmlDskTyp, out xmlDskSubTyp); + sidecar.OpticalDisc[0].DiscType = xmlDskTyp; + sidecar.OpticalDisc[0].DiscSubType = xmlDskSubTyp; + } + else + { + uint longBlockSize = blockSize; + bool rawAble = false; + + if (options.Raw) + { + bool testSense; + Decoders.SCSI.FixedSense? decSense; + + if (dev.SCSIType != DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) + { + /*testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 0xFFFF, dev.Timeout, out duration); + if (testSense && !dev.Error) + { + decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + rawAble = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + longBlockSize = 0xFFFF - decSense.Value.Information; + readLong16 = !dev.ReadLong16(out readBuffer, out senseBuf, false, 0, longBlockSize, dev.Timeout, out duration); + } + } + } + }*/ + + testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 0xFFFF, dev.Timeout, out duration); + if (testSense && !dev.Error) + { + decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + rawAble = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + longBlockSize = 0xFFFF - decSense.Value.Information; + readLong10 = !dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, (ushort)longBlockSize, dev.Timeout, out duration); + } + } + } + } + + if (rawAble && longBlockSize == blockSize) + { + if (blockSize == 512) + { + // Long sector sizes for 512-byte magneto-opticals + foreach (ushort testSize in new []{ 600, 610, 630 }) + { + testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong16 = true; + longBlockSize = testSize; + rawAble = true; + break; + } + + testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong10 = true; + longBlockSize = testSize; + rawAble = true; + break; + } + } + } + else if (blockSize == 1024) + { + testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 1200, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong16 = true; + longBlockSize = 1200; + rawAble = true; + } + else + { + testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 1200, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong10 = true; + longBlockSize = 1200; + rawAble = true; + } + } + } + else if (blockSize == 2048) + { + testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 2380, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong16 = true; + longBlockSize = 2380; + rawAble = true; + } + else + { + testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 2380, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong10 = true; + longBlockSize = 2380; + rawAble = true; + } + } + } + else if (blockSize == 4096) + { + testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 4760, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong16 = true; + longBlockSize = 4760; + rawAble = true; + } + else + { + testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 4760, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong10 = true; + longBlockSize = 4760; + rawAble = true; + } + } + } + else if (blockSize == 8192) + { + testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 9424, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong16 = true; + longBlockSize = 9424; + rawAble = true; + } + else + { + testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 9424, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + readLong10 = true; + longBlockSize = 9424; + rawAble = true; + } + } + } + } + + if (!rawAble && dev.Manufacturer == "SYQUEST") + { + testSense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, 0xFFFF, dev.Timeout, out duration); + if (testSense) + { + decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + rawAble = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + longBlockSize = 0xFFFF - decSense.Value.Information; + syqReadLong10 = !dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, longBlockSize, dev.Timeout, out duration); + ; + } + } + else + { + testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 0xFFFF, dev.Timeout, out duration); + if (testSense) + { + decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); + if (decSense.HasValue) + { + if (decSense.Value.SenseKey == DiscImageChef.Decoders.SCSI.SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) + { + rawAble = true; + if (decSense.Value.InformationValid && decSense.Value.ILI) + { + longBlockSize = 0xFFFF - decSense.Value.Information; + syqReadLong6 = !dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, longBlockSize, dev.Timeout, out duration); + ; + } + } + } + } + } + } + } + + if (!rawAble && blockSize == 256) + { + testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 262, dev.Timeout, out duration); + if (!testSense && !dev.Error) + { + syqReadLong6 = true; + longBlockSize = 262; + rawAble = true; + } + } + } + } + else + { + if (dev.Manufacturer == "HL-DT-ST") + hldtstReadRaw = !dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, 0, 1, dev.Timeout, out duration); + + if (dev.Manufacturer == "PLEXTOR") + hldtstReadRaw = !dev.PlextorReadRawDvd(out readBuffer, out senseBuf, 0, 1, dev.Timeout, out duration); + + if (hldtstReadRaw || plextorReadRaw) + { + rawAble = true; + longBlockSize = 2064; + } + } + + if (blockSize == longBlockSize) + { + if (!rawAble) + { + DicConsole.ErrorWriteLine("Device doesn't seem capable of reading raw data from media."); + } + else + { + DicConsole.ErrorWriteLine("Device is capable of reading raw data but I've been unable to guess correct sector size."); + } + + if (!options.Force) + { + DicConsole.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option."); + // TODO: Exit more gracefully + return; + } + + DicConsole.ErrorWriteLine("Continuing dumping cooked data."); + options.Raw = false; + } + else + { + if(readLong16) + DicConsole.WriteLine("Using SCSI READ LONG (16) command."); + else if(readLong10) + DicConsole.WriteLine("Using SCSI READ LONG (10) command."); + else if(syqReadLong10) + DicConsole.WriteLine("Using SyQuest READ LONG (10) command."); + else if(syqReadLong6) + DicConsole.WriteLine("Using SyQuest READ LONG (6) command."); + else if(hldtstReadRaw) + DicConsole.WriteLine("Using HL-DT-ST raw DVD reading."); + else if(plextorReadRaw) + DicConsole.WriteLine("Using Plextor raw DVD reading."); + else + throw new AccessViolationException("Should not arrive here"); + + DicConsole.WriteLine("Reading {0} raw bytes ({1} cooked bytes) per sector.", + longBlockSize, blockSize); + blocksToRead = 1; + blockSize = longBlockSize; + } + } + + if (!options.Raw) + { + read6 = !dev.Read6(out readBuffer, out senseBuf, 0, blockSize, dev.Timeout, out duration); + + read10 = !dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, dev.Timeout, out duration); + + read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false, dev.Timeout, out duration); + + read16 = !dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, 1, false, dev.Timeout, out duration); + + if (!read6 && !read10 && !read12 && !read16) + { + DicConsole.ErrorWriteLine("Cannot read medium, aborting scan..."); + return; + } + + if (read6 && !read10 && !read12 && !read16 && blocks > (0x001FFFFF + 1)) + { + DicConsole.ErrorWriteLine("Device only supports SCSI READ (6) but has more than {0} blocks ({1} blocks total)", 0x001FFFFF + 1, blocks); + return; + } + + if (!read16 && blocks > ((long)0xFFFFFFFF + (long)1)) + { + DicConsole.ErrorWriteLine("Device only supports SCSI READ (10) but has more than {0} blocks ({1} blocks total)", (long)0xFFFFFFFF + (long)1, blocks); + return; + } + + if (read16) + DicConsole.WriteLine("Using SCSI READ (16) command."); + else if (read12) + DicConsole.WriteLine("Using SCSI READ (12) command."); + else if (read10) + DicConsole.WriteLine("Using SCSI READ (10) command."); + else if (read6) + DicConsole.WriteLine("Using SCSI READ (6) command."); + + while (true) + { + if (read16) + { + sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, blocksToRead, false, dev.Timeout, out duration); + if (dev.Error) + blocksToRead /= 2; + } + else if (read12) + { + sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0, blocksToRead, false, dev.Timeout, out duration); + if (dev.Error) + blocksToRead /= 2; + } + else if (read10) + { + sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, (ushort)blocksToRead, dev.Timeout, out duration); + if (dev.Error) + blocksToRead /= 2; + } + else if (read6) + { + sense = dev.Read6(out readBuffer, out senseBuf, 0, blockSize, (byte)blocksToRead, dev.Timeout, out duration); + if (dev.Error) + blocksToRead /= 2; + } + + if (!dev.Error || blocksToRead == 1) + break; + } + + if (dev.Error) + { + DicConsole.ErrorWriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError); + return; + } + } + + DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); + + initMHDDLogFile(options.OutputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead); + initDataFile(options.OutputPrefix + ".bin"); + + start = DateTime.UtcNow; + + readBuffer = null; + + for (ulong i = 0; i < blocks; i += blocksToRead) + { + if (aborted) + break; + + double cmdDuration = 0; + + if ((blocks - i) < blocksToRead) + blocksToRead = (uint)(blocks - i); + + if (currentSpeed > maxSpeed && currentSpeed != 0) + maxSpeed = currentSpeed; + if (currentSpeed < minSpeed && currentSpeed != 0) + minSpeed = currentSpeed; + + DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); + + if(readLong16) + { + sense = dev.ReadLong16(out readBuffer, out senseBuf, false, i, blockSize, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if(readLong10) + { + sense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, (uint)i, (ushort)blockSize, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if(syqReadLong10) + { + sense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, (uint)i, blockSize, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if(syqReadLong6) + { + sense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, (uint)i, blockSize, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if(hldtstReadRaw) + { + sense = dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, (uint)i, blockSize, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if(plextorReadRaw) + { + sense = dev.PlextorReadRawDvd(out readBuffer, out senseBuf, (uint)i, blockSize, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if (read16) + { + sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, i, blockSize, 0, blocksToRead, false, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if (read12) + { + sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)i, blockSize, 0, blocksToRead, false, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if (read10) + { + sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, (uint)i, blockSize, 0, (ushort)blocksToRead, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + else if (read6) + { + sense = dev.Read6(out readBuffer, out senseBuf, (uint)i, blockSize, (byte)blocksToRead, dev.Timeout, out cmdDuration); + totalDuration += cmdDuration; + } + + if (!sense && !dev.Error) + { + writeMHDDLogFile(i, cmdDuration); + writeToDataFile(readBuffer); + } + else + { + // TODO: Reset device after X errors + if (options.StopOnError) + return; // TODO: Return more cleanly + + // Write empty data + writeToDataFile(new byte[blockSize * blocksToRead]); + + // TODO: Record error on mapfile + + errored += blocksToRead; + unreadableSectors.Add(i); + DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + if (cmdDuration < 500) + writeMHDDLogFile(i, 65535); + else + writeMHDDLogFile(i, cmdDuration); + } + + currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (cmdDuration / (double)1000); + } + DicConsole.WriteLine(); + closeMHDDLogFile(); + + dataChk = new Core.Checksum(); + dataFs.Seek(0, SeekOrigin.Begin); + blocksToRead = 500; + + for (ulong i = 0; i < blocks; i += blocksToRead) + { + if (aborted) + break; + + if ((blocks - i) < blocksToRead) + blocksToRead = (uint)(blocks - i); + + DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); + + DateTime chkStart = DateTime.UtcNow; + byte[] dataToCheck = new byte[blockSize * blocksToRead]; + dataFs.Read(dataToCheck, 0, (int)(blockSize * blocksToRead)); + dataChk.Update(dataToCheck); + DateTime chkEnd = DateTime.UtcNow; + + double chkDuration = (chkEnd - chkStart).TotalMilliseconds; + totalChkDuration += chkDuration; + + currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000); + } + DicConsole.WriteLine(); + closeDataFile(); + end = DateTime.UtcNow; + + if (opticalDisc) + { + sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray(); + sidecar.OpticalDisc[0].DumpHardwareArray = new DumpHardwareType[1]; + sidecar.OpticalDisc[0].DumpHardwareArray[0] = new DumpHardwareType(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents = new ExtentType[1]; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents[0] = new ExtentType(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents[0].Start = 0; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Extents[0].End = (int)(blocks - 1); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Manufacturer = dev.Manufacturer; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Model = dev.Model; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Revision = dev.Revision; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software = new SoftwareType(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software.Name = "DiscImageChef"; + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software.OperatingSystem = dev.PlatformID.ToString(); + sidecar.OpticalDisc[0].DumpHardwareArray[0].Software.Version = typeof(MainClass).Assembly.GetName().Version.ToString(); + sidecar.OpticalDisc[0].Image = new ImageType(); + sidecar.OpticalDisc[0].Image.format = "Raw disk image (sector by sector copy)"; + sidecar.OpticalDisc[0].Image.Value = options.OutputPrefix + ".bin"; + // TODO: Implement layers + //sidecar.OpticalDisc[0].Layers = new LayersType(); + sidecar.OpticalDisc[0].Sessions = 1; + sidecar.OpticalDisc[0].Tracks = new []{1}; + sidecar.OpticalDisc[0].Track = new TrackType[1]; + sidecar.OpticalDisc[0].Track[0] = new TrackType(); + sidecar.OpticalDisc[0].Track[0].BytesPerSector = (int)blockSize; + sidecar.OpticalDisc[0].Track[0].Checksums = sidecar.OpticalDisc[0].Checksums; + sidecar.OpticalDisc[0].Track[0].EndSector = (long)(blocks - 1); + sidecar.OpticalDisc[0].Track[0].Image = new ImageType(); + sidecar.OpticalDisc[0].Track[0].Image.format = "BINARY"; + sidecar.OpticalDisc[0].Track[0].Image.offset = 0; + sidecar.OpticalDisc[0].Track[0].Image.offsetSpecified = true; + sidecar.OpticalDisc[0].Track[0].Image.Value = sidecar.OpticalDisc[0].Image.Value; + sidecar.OpticalDisc[0].Track[0].Sequence = new TrackSequenceType(); + sidecar.OpticalDisc[0].Track[0].Sequence.Session = 1; + sidecar.OpticalDisc[0].Track[0].Sequence.TrackNumber = 1; + sidecar.OpticalDisc[0].Track[0].Size = (long)(blocks * blockSize); + sidecar.OpticalDisc[0].Track[0].StartSector = 0; + switch (dskType) + { + case MediaType.DDCD: + case MediaType.DDCDR: + case MediaType.DDCDRW: + sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.ddcd; + break; + case MediaType.DVDROM: + case MediaType.DVDR: + case MediaType.DVDRAM: + case MediaType.DVDRW: + case MediaType.DVDRDL: + case MediaType.DVDRWDL: + case MediaType.DVDDownload: + case MediaType.DVDPRW: + case MediaType.DVDPR: + case MediaType.DVDPRWDL: + case MediaType.DVDPRDL: + sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.dvd; + break; + case MediaType.HDDVDROM: + case MediaType.HDDVDR: + case MediaType.HDDVDRAM: + case MediaType.HDDVDRW: + case MediaType.HDDVDRDL: + case MediaType.HDDVDRWDL: + sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.hddvd; + break; + case MediaType.BDROM: + case MediaType.BDR: + case MediaType.BDRE: + case MediaType.BDREXL: + case MediaType.BDRXL: + sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.bluray; + break; + } + sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType); + string xmlDskTyp, xmlDskSubTyp; + Metadata.MediaType.MediaTypeToString(dskType, out xmlDskTyp, out xmlDskSubTyp); + sidecar.OpticalDisc[0].DiscType = xmlDskTyp; + sidecar.OpticalDisc[0].DiscSubType = xmlDskSubTyp; + } + else + { + sidecar.BlockMedia[0].Checksums = dataChk.End().ToArray(); + sidecar.BlockMedia[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType); + string xmlDskTyp, xmlDskSubTyp; + Metadata.MediaType.MediaTypeToString(dskType, out xmlDskTyp, out xmlDskSubTyp); + sidecar.BlockMedia[0].DiskType = xmlDskTyp; + sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp; + // TODO: Implement device firmware revision + sidecar.BlockMedia[0].Image = new ImageType(); + sidecar.BlockMedia[0].Image.format = "Raw disk image (sector by sector copy)"; + sidecar.BlockMedia[0].Image.Value = options.OutputPrefix + ".bin"; + if (dev.Type == DeviceType.ATAPI) + sidecar.BlockMedia[0].Interface = "ATAPI"; + else if (dev.IsUSB) + sidecar.BlockMedia[0].Interface = "USB"; + else if (dev.IsFireWire) + sidecar.BlockMedia[0].Interface = "FireWire"; + else + sidecar.BlockMedia[0].Interface = "SCSI"; + sidecar.BlockMedia[0].LogicalBlocks = (long)blocks; + sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize; + sidecar.BlockMedia[0].Manufacturer = dev.Manufacturer; + sidecar.BlockMedia[0].Model = dev.Model; + sidecar.BlockMedia[0].Serial = dev.Serial; + sidecar.BlockMedia[0].Size = (long)(blocks * blockSize); + } + } + + DicConsole.WriteLine(); + + DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).", (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000); + DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000)); + DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); + DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed); + DicConsole.WriteLine("{0} sectors could not be read.", errored); + if (unreadableSectors.Count > 0) + { + foreach (ulong bad in unreadableSectors) + DicConsole.WriteLine("Sector {0} could not be read", bad); + } + DicConsole.WriteLine(); + + if (!aborted) + { + DicConsole.WriteLine("Writing metadata sidecar"); + + FileStream xmlFs = new FileStream(options.OutputPrefix + ".cicm.xml", + FileMode.Create); + + System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); + xmlSer.Serialize(xmlFs, sidecar); + xmlFs.Close(); + } + } + + static void initMHDDLogFile(string outputFile, Device dev, ulong blocks, ulong blockSize, ulong blocksToRead) + { + if (dev != null && !string.IsNullOrEmpty(outputFile)) + { + mhddFs = new FileStream(outputFile, FileMode.Create); + + string device; + string mode; + string fw; + string sn; + string sectors; + string sectorsize; + string scanblocksize; + string ver; + + switch (dev.Type) + { + case DeviceType.ATA: + case DeviceType.ATAPI: + mode = "MODE: IDE"; + break; + case DeviceType.SCSI: + mode = "MODE: SCSI"; + break; + case DeviceType.MMC: + mode = "MODE: MMC"; + break; + case DeviceType.NVMe: + mode = "MODE: NVMe"; + break; + case DeviceType.SecureDigital: + mode = "MODE: SD"; + break; + default: + mode = "MODE: IDE"; + break; + } + + device = String.Format("DEVICE: {0} {1}", dev.Manufacturer, dev.Model); + fw = String.Format("F/W: {0}", dev.Revision); + sn = String.Format("S/N: {0}", dev.Serial); + sectors = String.Format(new System.Globalization.CultureInfo("en-US"), "SECTORS: {0:n0}", blocks); + sectorsize = String.Format(new System.Globalization.CultureInfo("en-US"), "SECTOR SIZE: {0:n0} bytes", blockSize); + scanblocksize = String.Format(new System.Globalization.CultureInfo("en-US"), "SCAN BLOCK SIZE: {0:n0} sectors", blocksToRead); + ver = "VER:2 "; + + byte[] deviceBytes = Encoding.ASCII.GetBytes(device); + byte[] modeBytes = Encoding.ASCII.GetBytes(mode); + byte[] fwBytes = Encoding.ASCII.GetBytes(fw); + byte[] snBytes = Encoding.ASCII.GetBytes(sn); + byte[] sectorsBytes = Encoding.ASCII.GetBytes(sectors); + byte[] sectorsizeBytes = Encoding.ASCII.GetBytes(sectorsize); + byte[] scanblocksizeBytes = Encoding.ASCII.GetBytes(scanblocksize); + byte[] verBytes = Encoding.ASCII.GetBytes(ver); + + uint Pointer = (uint)(deviceBytes.Length + modeBytes.Length + fwBytes.Length + + snBytes.Length + sectorsBytes.Length + sectorsizeBytes.Length + + scanblocksizeBytes.Length + verBytes.Length + + 2 * 9 + // New lines + 4); // Pointer + + byte[] newLine = new byte[2]; + newLine[0] = 0x0D; + newLine[1] = 0x0A; + + mhddFs.Write(BitConverter.GetBytes(Pointer), 0, 4); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(verBytes, 0, verBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(modeBytes, 0, modeBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(deviceBytes, 0, deviceBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(fwBytes, 0, fwBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(snBytes, 0, snBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(sectorsBytes, 0, sectorsBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(sectorsizeBytes, 0, sectorsizeBytes.Length); + mhddFs.Write(newLine, 0, 2); + mhddFs.Write(scanblocksizeBytes, 0, scanblocksizeBytes.Length); + mhddFs.Write(newLine, 0, 2); + } + } + + static void closeMHDDLogFile() + { + if (mhddFs != null) + mhddFs.Close(); + } + + static void writeMHDDLogFile(ulong sector, double duration) + { + if (mhddFs != null) + { + byte[] sectorBytes = BitConverter.GetBytes(sector); + byte[] durationBytes = BitConverter.GetBytes((ulong)(duration * 1000)); + + mhddFs.Write(sectorBytes, 0, 8); + mhddFs.Write(durationBytes, 0, 8); + } + } + + static void writeToFile(string file, byte[] data) + { + FileStream fs = new FileStream(file, FileMode.Create, FileAccess.ReadWrite); + fs.Write(data, 0, data.Length); + fs.Close(); + } + + static void initDataFile(string outputFile) + { + dataFs = new FileStream(outputFile, FileMode.OpenOrCreate, FileAccess.ReadWrite); + } + + static void writeToDataFile(byte[] data) + { + dataFs.Write(data, 0, data.Length); + } + + static void closeDataFile() + { + if (dataFs != null) + dataFs.Close(); + } + } +} \ No newline at end of file diff --git a/DiscImageChef/Commands/MediaInfo.cs b/DiscImageChef/Commands/MediaInfo.cs index 1b6436e3..668c1597 100644 --- a/DiscImageChef/Commands/MediaInfo.cs +++ b/DiscImageChef/Commands/MediaInfo.cs @@ -175,6 +175,51 @@ namespace DiscImageChef.Commands } } + byte[] modeBuf; + Decoders.SCSI.Modes.DecodedMode? decMode = null; + Decoders.SCSI.PeripheralDeviceTypes devType = dev.SCSIType; + + sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration); + if (sense || dev.Error) + { + sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); + } + + if (!sense && !dev.Error) + { + decMode = Decoders.SCSI.Modes.DecodeMode10(modeBuf, devType); + } + + if(sense || dev.Error || !decMode.HasValue) + { + sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); + if (sense || dev.Error) + sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); + if (sense || dev.Error) + sense = dev.ModeSense(out modeBuf, out senseBuf, 5, out duration); + + if (!sense && !dev.Error) + decMode = Decoders.SCSI.Modes.DecodeMode6(modeBuf, devType); + } + + if (!sense) + doWriteFile(outputPrefix, "_scsi_modesense.bin", "SCSI MODE SENSE", modeBuf); + + byte scsiMediumType = 0; + byte scsiDensityCode = 0; + bool containsFloppyPage = false; + + if(decMode.HasValue) + { + scsiMediumType = (byte)decMode.Value.Header.MediumType; + if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length >= 1) + scsiDensityCode = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + + foreach(Decoders.SCSI.Modes.ModePage modePage in decMode.Value.Pages) + if(modePage.Page == 0x05) + containsFloppyPage = true; + } + if (dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.DirectAccess || dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice || dev.SCSIType == DiscImageChef.Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice || @@ -280,7 +325,7 @@ namespace DiscImageChef.Commands { sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ GET CONFIGURATION:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ GET CONFIGURATION:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_getconfiguration_current.bin", "SCSI GET CONFIGURATION", cmdBuf); @@ -383,12 +428,12 @@ namespace DiscImageChef.Commands sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.RecognizedFormatLayers, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Recognized Format Layers\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Recognized Format Layers\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_formatlayers.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.WriteProtectionStatus, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Write Protection Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Write Protection Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_writeprotection.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -396,7 +441,7 @@ namespace DiscImageChef.Commands /* sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Capability List\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Capability List\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_capabilitylist.bin", "SCSI READ DISC STRUCTURE", cmdBuf); */ @@ -415,15 +460,78 @@ namespace DiscImageChef.Commands sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: PFI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PFI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvd_pfi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); - DicConsole.WriteLine("PFI:\n{0}", Decoders.DVD.PFI.Prettify(cmdBuf)); + Decoders.DVD.PFI.PhysicalFormatInformation? decPfi = Decoders.DVD.PFI.Decode(cmdBuf); + if(decPfi.HasValue) + { + DicConsole.WriteLine("PFI:\n{0}", Decoders.DVD.PFI.Prettify(decPfi)); + + // False book types + if(dskType == MediaType.DVDROM) + { + switch(decPfi.Value.DiskCategory) + { + case Decoders.DVD.DiskCategory.DVDPR: + dskType = MediaType.DVDPR; + break; + case Decoders.DVD.DiskCategory.DVDPRDL: + dskType = MediaType.DVDPRDL; + break; + case Decoders.DVD.DiskCategory.DVDPRW: + dskType = MediaType.DVDPRW; + break; + case Decoders.DVD.DiskCategory.DVDPRWDL: + dskType = MediaType.DVDPRWDL; + break; + case Decoders.DVD.DiskCategory.DVDR: + if(decPfi.Value.PartVersion == 6) + dskType = MediaType.DVDRDL; + else + dskType = MediaType.DVDR; + break; + case Decoders.DVD.DiskCategory.DVDRAM: + dskType = MediaType.DVDRAM; + break; + default: + dskType = MediaType.DVDROM; + break; + case Decoders.DVD.DiskCategory.DVDRW: + if(decPfi.Value.PartVersion == 3) + dskType = MediaType.DVDRWDL; + else + dskType = MediaType.DVDRW; + break; + case Decoders.DVD.DiskCategory.HDDVDR: + dskType = MediaType.HDDVDR; + break; + case Decoders.DVD.DiskCategory.HDDVDRAM: + dskType = MediaType.HDDVDRAM; + break; + case Decoders.DVD.DiskCategory.HDDVDROM: + dskType = MediaType.HDDVDROM; + break; + case Decoders.DVD.DiskCategory.HDDVDRW: + dskType = MediaType.HDDVDRW; + break; + case Decoders.DVD.DiskCategory.Nintendo: + if(decPfi.Value.DiscSize == DiscImageChef.Decoders.DVD.DVDSize.Eighty) + dskType = MediaType.GOD; + else + dskType = MediaType.WOD; + break; + case Decoders.DVD.DiskCategory.UMD: + dskType = MediaType.UMD; + break; + } + } + } } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvd_dmi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -445,7 +553,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: CMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: CMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvd_cmi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -460,12 +568,12 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: BCA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: BCA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_bca.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVD_AACS, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DVD AACS\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD AACS\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_aacs.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -475,57 +583,57 @@ namespace DiscImageChef.Commands /* sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscKey, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Disc Key\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Disc Key\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_disckey.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.SectorCopyrightInformation, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Sector CMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Sector CMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_sectorcmi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.MediaIdentifier, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_mediaid.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.MediaKeyBlock, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_mkb.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSVolId, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS Volume ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS Volume ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacsvolid.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSMediaSerial, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS Media Serial Number\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS Media Serial Number\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacssn.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSMediaId, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacsmediaid.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSMKB, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacsmkb.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSLBAExtents, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS LBA Extents\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS LBA Extents\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacslbaextents.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSMKBCPRM, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS CPRM MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS CPRM MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacscprmmkb.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.AACSDataKeys, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: AACS Data Keys\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: AACS Data Keys\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_aacsdatakeys.bin", "SCSI READ DISC STRUCTURE", cmdBuf); */ @@ -536,7 +644,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DDS\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DDS\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvdram_dds.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -544,7 +652,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_MediumStatus, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Medium Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Medium Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvdram_status.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -552,7 +660,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: SAI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: SAI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvdram_spare.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -566,7 +674,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.LastBorderOutRMD, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Last-Out Border RMD\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Last-Out Border RMD\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_lastrmd.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -577,7 +685,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Pre-Recorded Info\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Pre-Recorded Info\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_pri.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -588,12 +696,12 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DVD-R Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD-R Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvdr_mediaid.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DVD-R PFI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD-R PFI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvdr_pfi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -603,18 +711,15 @@ namespace DiscImageChef.Commands if (dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL || dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL) { - // TODO: None of my test discs return an ADIP. Also, it just seems to contain pre-recorded PFI, and drive is returning it on blank media using standard PFI command - /* sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration); if(sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: ADIP\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: ADIP\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd+_adip.bin", "SCSI READ DISC STRUCTURE", cmdBuf); - */ sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DCB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DCB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd+_dcb.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -625,7 +730,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: HDDVD CMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: HDDVD CMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_hddvd_cmi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -636,12 +741,12 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVDR_MediumStatus, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: HDDVD-R Medium Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: HDDVD-R Medium Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_hddvdr_status.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVDR_LastRMD, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Last RMD\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Last RMD\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_hddvdr_lastrmd.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -653,7 +758,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_LayerCapacity, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Layer Capacity\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Layer Capacity\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvdr_layercap.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -664,22 +769,22 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.MiddleZoneStart, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Middle Zone Start\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Middle Zone Start\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_mzs.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.JumpIntervalSize, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Jump Interval Size\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Jump Interval Size\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_jis.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ManualLayerJumpStartLBA, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Manual Layer Jump Start LBA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Manual Layer Jump Start LBA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_manuallj.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.RemapAnchorPoint, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Remap Anchor Point\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Remap Anchor Point\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_remapanchor.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -691,7 +796,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_bd_di.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -699,7 +804,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: PAC\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PAC\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_bd_pac.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } @@ -710,7 +815,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: BCA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: BCA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_bd_bca.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -725,7 +830,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DDS\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DDS\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_bd_dds.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -733,7 +838,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Cartridge Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Cartridge Status\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_bd_cartstatus.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -741,7 +846,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Spare Area Information\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Spare Area Information\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_bd_spare.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -749,12 +854,12 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.RawDFL, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: Raw DFL\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Raw DFL\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_bd_dfl.bin", "SCSI READ DISC STRUCTURE", cmdBuf); sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.TrackResources, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC INFORMATION 001b\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 001b\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { DicConsole.WriteLine("Track Resources Information:\n{0}", Decoders.SCSI.MMC.DiscInformation.Prettify(cmdBuf)); @@ -762,7 +867,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.POWResources, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC INFORMATION 010b\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 010b\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { DicConsole.WriteLine("POW Resources Information:\n{0}", Decoders.SCSI.MMC.DiscInformation.Prettify(cmdBuf)); @@ -784,7 +889,7 @@ namespace DiscImageChef.Commands // No TOC, no CD (or an empty one) bool tocSense = dev.ReadTocPmaAtip(out cmdBuf, out senseBuf, false, 0, 0, dev.Timeout, out duration); if (tocSense) - DicConsole.ErrorWriteLine("READ TOC/PMA/ATIP: TOC\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: TOC\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { toc = Decoders.CD.TOC.Decode(cmdBuf); @@ -799,7 +904,7 @@ namespace DiscImageChef.Commands // ATIP exists on blank CDs sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ TOC/PMA/ATIP: ATIP\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: ATIP\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_atip.bin", "SCSI READ TOC/PMA/ATIP", cmdBuf); @@ -817,7 +922,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC INFORMATION 000b\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 000b\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { Decoders.SCSI.MMC.DiscInformation.StandardDiscInformation? discInfo = Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf); @@ -847,7 +952,7 @@ namespace DiscImageChef.Commands sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ TOC/PMA/ATIP: Session info\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: Session info\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_session.bin", "SCSI READ TOC/PMA/ATIP", cmdBuf); @@ -904,7 +1009,7 @@ namespace DiscImageChef.Commands sense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ TOC/PMA/ATIP: Raw TOC\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: Raw TOC\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_rawtoc.bin", "SCSI READ TOC/PMA/ATIP", cmdBuf); @@ -912,7 +1017,7 @@ namespace DiscImageChef.Commands } sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ TOC/PMA/ATIP: PMA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: PMA\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_pma.bin", "SCSI READ TOC/PMA/ATIP", cmdBuf); @@ -921,7 +1026,7 @@ namespace DiscImageChef.Commands sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ TOC/PMA/ATIP: CD-TEXT\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: CD-TEXT\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_cdtext.bin", "SCSI READ TOC/PMA/ATIP", cmdBuf); @@ -937,7 +1042,7 @@ namespace DiscImageChef.Commands { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: PFI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PFI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_readdiscstructure_dvd_pfi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); @@ -957,18 +1062,24 @@ namespace DiscImageChef.Commands } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ DISC STRUCTURE: DMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DMI\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else doWriteFile(outputPrefix, "_readdiscstructure_dvd_dmi.bin", "SCSI READ DISC STRUCTURE", cmdBuf); } #endregion Nintendo } + if(dskType == MediaType.Unknown) + dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumType, scsiDensityCode, blocks, blockSize); + + if(dskType == MediaType.Unknown && dev.IsUSB && containsFloppyPage) + dskType = MediaType.FlashDrive; + DicConsole.WriteLine("Media identified as {0}", dskType); sense = dev.ReadMediaSerialNumber(out cmdBuf, out senseBuf, dev.Timeout, out duration); if (sense) - DicConsole.ErrorWriteLine("READ MEDIA SERIAL NUMBER\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); + DicConsole.DebugWriteLine("Media-Info command", "READ MEDIA SERIAL NUMBER\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); else { doWriteFile(outputPrefix, "_mediaserialnumber.bin", "SCSI READ MEDIA SERIAL NUMBER", cmdBuf); diff --git a/DiscImageChef/Commands/MediaScan.cs b/DiscImageChef/Commands/MediaScan.cs index cd5379e1..bec5db13 100644 --- a/DiscImageChef/Commands/MediaScan.cs +++ b/DiscImageChef/Commands/MediaScan.cs @@ -41,6 +41,7 @@ using System.IO; using DiscImageChef.Devices; using System.Text; using System.Collections.Generic; +using System.Globalization; namespace DiscImageChef.Commands { @@ -48,6 +49,22 @@ namespace DiscImageChef.Commands { static bool aborted; static FileStream mhddFs; + static FileStream ibgFs; + static StringBuilder ibgSb; + static DateTime ibgDatePoint; + static CultureInfo ibgCulture; + static double ibgStartSpeed; + static string ibgMediaType; + static double ibgDivider; + static bool ibgStartSet; + static int ibgMinSampleRate; + static double ibgMaxSpeed; + static double ibgIntSpeed; + static int ibgSnaps; +static ulong ibgIntSector = 0; +static double ibgIntTime = 0; +static int ibgSampleRate; + public static void doMediaScan(MediaScanSubOptions options) { @@ -55,6 +72,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", options.Verbose); DicConsole.DebugWriteLine("Media-Scan command", "--device={0}", options.DevicePath); DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", options.MHDDLogPath); + DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", options.IBGLogPath); if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0])) @@ -63,6 +81,7 @@ namespace DiscImageChef.Commands } mhddFs = null; + ibgFs = null; Device dev = new Device(options.DevicePath); @@ -75,40 +94,40 @@ namespace DiscImageChef.Commands switch (dev.Type) { case DeviceType.ATA: - doATAMediaScan(options.MHDDLogPath, dev); + doATAMediaScan(options.MHDDLogPath, options.IBGLogPath, options.DevicePath, dev); break; case DeviceType.MMC: case DeviceType.SecureDigital: - doSDMediaScan(options.MHDDLogPath, dev); + doSDMediaScan(options.MHDDLogPath, options.IBGLogPath, options.DevicePath, dev); break; case DeviceType.NVMe: - doNVMeMediaScan(options.MHDDLogPath, dev); + doNVMeMediaScan(options.MHDDLogPath, options.IBGLogPath, options.DevicePath, dev); break; case DeviceType.ATAPI: case DeviceType.SCSI: - doSCSIMediaScan(options.MHDDLogPath, dev); + doSCSIMediaScan(options.MHDDLogPath, options.IBGLogPath, options.DevicePath, dev); break; default: throw new NotSupportedException("Unknown device type."); } } - static void doATAMediaScan(string MHDDLogPath, Device dev) + static void doATAMediaScan(string MHDDLogPath, string IBGLogPath, string devicePath, Device dev) { throw new NotImplementedException("ATA devices not yet supported."); } - static void doNVMeMediaScan(string MHDDLogPath, Device dev) + static void doNVMeMediaScan(string MHDDLogPath, string IBGLogPath, string devicePath, Device dev) { throw new NotImplementedException("NVMe devices not yet supported."); } - static void doSDMediaScan(string MHDDLogPath, Device dev) + static void doSDMediaScan(string MHDDLogPath, string IBGLogPath, string devicePath, Device dev) { throw new NotImplementedException("MMC/SD devices not yet supported."); } - static void doSCSIMediaScan(string MHDDLogPath, Device dev) + static void doSCSIMediaScan(string MHDDLogPath, string IBGLogPath, string devicePath, Device dev) { byte[] cmdBuf; byte[] senseBuf; @@ -116,6 +135,7 @@ namespace DiscImageChef.Commands double duration; ulong blocks = 0; uint blockSize = 0; + ushort currentProfile = 0x0001; if (dev.IsRemovable) { @@ -249,6 +269,8 @@ namespace DiscImageChef.Commands { Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf); + currentProfile = ftr.CurrentProfile; + switch (ftr.CurrentProfile) { case 0x0005: @@ -267,6 +289,7 @@ namespace DiscImageChef.Commands if (compactDisc) { + currentProfile = 0x0008; // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out duration); @@ -342,6 +365,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); initMHDDLogFile(MHDDLogPath, dev, blocks, blockSize, blocksToRead); + initIBGLogFile(IBGLogPath, currentProfile); for (ulong i = 0; i < blocks; i += blocksToRead) { @@ -395,6 +419,7 @@ namespace DiscImageChef.Commands } writeMHDDLogFile(i, cmdDuration); + writeIBGLogFile(i, currentSpeed * 1024); } else { @@ -416,6 +441,8 @@ namespace DiscImageChef.Commands writeMHDDLogFile(i, 65535); else writeMHDDLogFile(i, cmdDuration); + + writeIBGLogFile(i, 0); } } else @@ -426,6 +453,8 @@ namespace DiscImageChef.Commands writeMHDDLogFile(i, 65535); else writeMHDDLogFile(i, cmdDuration); + + writeIBGLogFile(i, 0); } } @@ -435,6 +464,7 @@ namespace DiscImageChef.Commands end = DateTime.UtcNow; DicConsole.WriteLine(); closeMHDDLogFile(); + closeIBGLogFile(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); } else { @@ -460,7 +490,7 @@ namespace DiscImageChef.Commands if (!read16 && blocks > ((long)0xFFFFFFFF + (long)1)) { - DicConsole.ErrorWriteLine("Device only supports SCSI READ (16) but has more than {0} blocks ({1} blocks total)", (long)0xFFFFFFFF + (long)1, blocks); + DicConsole.ErrorWriteLine("Device only supports SCSI READ (10) but has more than {0} blocks ({1} blocks total)", (long)0xFFFFFFFF + (long)1, blocks); return; } @@ -515,6 +545,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); initMHDDLogFile(MHDDLogPath, dev, blocks, blockSize, blocksToRead); + initIBGLogFile(IBGLogPath, currentProfile); for (ulong i = 0; i < blocks; i += blocksToRead) { @@ -570,6 +601,7 @@ namespace DiscImageChef.Commands A += blocksToRead; writeMHDDLogFile(i, cmdDuration); + writeIBGLogFile(i, currentSpeed * 1024); } // TODO: Separate errors on kind of errors. else @@ -581,6 +613,7 @@ namespace DiscImageChef.Commands writeMHDDLogFile(i, 65535); else writeMHDDLogFile(i, cmdDuration); + writeIBGLogFile(i, 0); } currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (cmdDuration / (double)1000); @@ -588,6 +621,7 @@ namespace DiscImageChef.Commands end = DateTime.UtcNow; DicConsole.WriteLine(); closeMHDDLogFile(); + closeIBGLogFile(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); } bool seek6, seek10; @@ -800,6 +834,245 @@ namespace DiscImageChef.Commands mhddFs.Write(durationBytes, 0, 8); } } + + static void writeIBGLogFile(ulong sector, double currentSpeed) + { + if (ibgFs != null) + { + ibgIntSpeed += currentSpeed; + ibgSampleRate += (int)Math.Floor((DateTime.Now - ibgDatePoint).TotalMilliseconds); + ibgSnaps++; + + if(ibgSampleRate >= 100) + { + if (ibgIntSpeed > 0 && !ibgStartSet) + { + ibgStartSpeed = ibgIntSpeed / ibgSnaps / ibgDivider; + ibgStartSet = true; + } + + ibgSb.AppendFormat("{0:0.00},{1},{2:0},0", ibgIntSpeed / ibgSnaps / ibgDivider, ibgIntSector, ibgSampleRate).AppendLine(); + if ((ibgIntSpeed / ibgSnaps / ibgDivider) > ibgMaxSpeed) + ibgMaxSpeed = ibgIntSpeed / ibgDivider; + + ibgDatePoint = DateTime.Now; + ibgIntSpeed = 0; + ibgSampleRate = 0; + ibgSnaps = 0; + ibgIntSector = sector; + } + } + } + + static void initIBGLogFile(string outputFile, ushort currentProfile) + { + if (!string.IsNullOrEmpty(outputFile)) + { + ibgFs = new FileStream(outputFile, FileMode.Create); + ibgSb = new StringBuilder(); + ibgDatePoint = DateTime.Now; + ibgCulture = new CultureInfo("en-US"); + ibgStartSet = false; + ibgMinSampleRate = int.MaxValue; + ibgMaxSpeed = 0; + ibgIntSpeed = 0; + ibgSnaps = 0; + ibgIntSector = 0; +ibgIntTime = 0; + + switch (currentProfile) + { + case 0x0001: + ibgMediaType = "HDD"; + ibgDivider = 1353; + break; + case 0x0005: + ibgMediaType = "CD-MO"; + ibgDivider = 150; + break; + case 0x0008: + ibgMediaType = "CD-ROM"; + ibgDivider = 150; + break; + case 0x0009: + ibgMediaType = "CD-R"; + ibgDivider = 150; + break; + case 0x000A: + ibgMediaType = "CD-RW"; + ibgDivider = 150; + break; + case 0x0010: + ibgMediaType = "DVD-ROM"; + ibgDivider = 1353; + break; + case 0x0011: + ibgMediaType = "DVD-R"; + ibgDivider = 1353; + break; + case 0x0012: + ibgMediaType = "DVD-RAM"; + ibgDivider = 1353; + break; + case 0x0013: + case 0x0014: + ibgMediaType = "DVD-RW"; + ibgDivider = 1353; + break; + case 0x0015: + case 0x0016: + ibgMediaType = "DVD-R DL"; + ibgDivider = 1353; + break; + case 0x0017: + ibgMediaType = "DVD-RW DL"; + ibgDivider = 1353; + break; + case 0x0018: + ibgMediaType = "DVD-Download"; + ibgDivider = 1353; + break; + case 0x001A: + ibgMediaType = "DVD+RW"; + ibgDivider = 1353; + break; + case 0x001B: + ibgMediaType = "DVD+R"; + ibgDivider = 1353; + break; + case 0x0020: + ibgMediaType = "DDCD-ROM"; + ibgDivider = 150; + break; + case 0x0021: + ibgMediaType = "DDCD-R"; + ibgDivider = 150; + break; + case 0x0022: + ibgMediaType = "DDCD-RW"; + ibgDivider = 150; + break; + case 0x002A: + ibgMediaType = "DVD+RW DL"; + ibgDivider = 1353; + break; + case 0x002B: + ibgMediaType = "DVD+R DL"; + ibgDivider = 1353; + break; + case 0x0040: + ibgMediaType = "BD-ROM"; + ibgDivider = 4500; + break; + case 0x0041: + case 0x0042: + ibgMediaType = "BD-R"; + ibgDivider = 4500; + break; + case 0x0043: + ibgMediaType = "BD-RE"; + ibgDivider = 4500; + break; + case 0x0050: + ibgMediaType = "HD DVD-ROM"; + ibgDivider = 4500; + break; + case 0x0051: + ibgMediaType = "HD DVD-R"; + ibgDivider = 4500; + break; + case 0x0052: + ibgMediaType = "HD DVD-RAM"; + ibgDivider = 4500; + break; + case 0x0053: + ibgMediaType = "HD DVD-RW"; + ibgDivider = 4500; + break; + case 0x0058: + ibgMediaType = "HD DVD-R DL"; + ibgDivider = 4500; + break; + case 0x005A: + ibgMediaType = "HD DVD-RW DL"; + ibgDivider = 4500; + break; + default: + ibgMediaType = "Unknown"; + ibgDivider = 1353; + break; + } + + } + } + + static void closeIBGLogFile(Device dev, ulong blocks, ulong blockSize, double totalSeconds, double currentSpeed, double averageSpeed, string devicePath) + { + if (ibgFs != null) + { + StringBuilder ibgHeader = new StringBuilder(); + string ibgBusType; + + if (dev.IsUSB) + ibgBusType = "USB"; + else if (dev.IsFireWire) + ibgBusType = "FireWire"; + else + ibgBusType = dev.Type.ToString(); + + ibgHeader.AppendLine("IBGD"); + ibgHeader.AppendLine(); + ibgHeader.AppendLine("[START_CONFIGURATION]"); + ibgHeader.AppendLine("IBGD_VERSION=2"); + ibgHeader.AppendLine(); + ibgHeader.AppendFormat("DATE={0}", DateTime.Now).AppendLine(); + ibgHeader.AppendLine(); + ibgHeader.AppendFormat("SAMPLE_RATE={0}", 100).AppendLine(); + + ibgHeader.AppendLine(); + ibgHeader.AppendFormat("DEVICE=[0:0:0] {0} {1} ({2}) ({3})", + dev.Manufacturer, dev.Model, devicePath, ibgBusType).AppendLine(); + ibgHeader.AppendLine("DEVICE_ADDRESS=0:0:0"); + ibgHeader.AppendFormat("DEVICE_MAKEMODEL={0} {1}", dev.Manufacturer, dev.Model).AppendLine(); + ibgHeader.AppendFormat("DEVICE_FIRMWAREVERSION={0}", dev.Revision).AppendLine(); + ibgHeader.AppendFormat("DEVICE_DRIVELETTER={0}", devicePath).AppendLine(); + ibgHeader.AppendFormat("DEVICE_BUSTYPE={0}", ibgBusType).AppendLine(); + ibgHeader.AppendLine(); + + ibgHeader.AppendFormat("MEDIA_TYPE={0}", ibgMediaType).AppendLine(); + ibgHeader.AppendLine("MEDIA_BOOKTYPE=Unknown"); + ibgHeader.AppendLine("MEDIA_ID=N/A"); + ibgHeader.AppendLine("MEDIA_TRACKPATH=PTP"); + ibgHeader.AppendLine("MEDIA_SPEEDS=N/A"); + ibgHeader.AppendFormat("MEDIA_CAPACITY={0}", blocks).AppendLine(); + ibgHeader.AppendLine("MEDIA_LAYER_BREAK=0"); + ibgHeader.AppendLine(); + ibgHeader.AppendLine("DATA_IMAGEFILE=/dev/null"); + ibgHeader.AppendFormat("DATA_SECTORS={0}", blocks).AppendLine(); + ibgHeader.AppendFormat("DATA_TYPE=MODE1/{0}", blockSize).AppendLine(); + ibgHeader.AppendLine("DATA_VOLUMEIDENTIFIER="); + ibgHeader.AppendLine(); + ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_START={0:0.00}", ibgStartSpeed).AppendLine(); + ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_END={0:0.00}", currentSpeed / ibgDivider).AppendLine(); + ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_AVERAGE={0:0.00}", averageSpeed / ibgDivider).AppendLine(); + ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_MAX={0:0.00}", ibgMaxSpeed).AppendLine(); + ibgHeader.AppendFormat(ibgCulture, "VERIFY_TIME_TAKEN={0:0}", Math.Floor(totalSeconds)).AppendLine(); + ibgHeader.AppendLine("[END_CONFIGURATION]"); + ibgHeader.AppendLine(); + ibgHeader.AppendLine("HRPC=True"); + ibgHeader.AppendLine(); + ibgHeader.AppendLine("[START_VERIFY_GRAPH_VALUES]"); + ibgHeader.Append(ibgSb.ToString()); + ibgHeader.AppendLine("[END_VERIFY_GRAPH_VALUES]"); + ibgHeader.AppendLine(); + ibgHeader.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n"); + + StreamWriter sr = new StreamWriter(ibgFs); + sr.Write(ibgHeader.ToString()); + sr.Close(); + ibgFs.Close(); + } + } } } diff --git a/DiscImageChef/Core/Checksum.cs b/DiscImageChef/Core/Checksum.cs new file mode 100644 index 00000000..80928614 --- /dev/null +++ b/DiscImageChef/Core/Checksum.cs @@ -0,0 +1,558 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : GetChecksum.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using System.Collections.Generic; +using DiscImageChef.Checksums; +using Schemas; +using System.Threading; +using System.IO; + +namespace DiscImageChef.Core +{ + class Checksum + { + Adler32Context adler32ctx; + CRC16Context crc16ctx; + CRC32Context crc32ctx; + CRC64Context crc64ctx; + MD5Context md5ctx; + RIPEMD160Context ripemd160ctx; + SHA1Context sha1ctx; + SHA256Context sha256ctx; + SHA384Context sha384ctx; + SHA512Context sha512ctx; + SpamSumContext ssctx; + + Thread adlerThread; + Thread crc16Thread; + Thread crc32Thread; + Thread crc64Thread; + Thread md5Thread; + Thread ripemd160Thread; + Thread sha1Thread; + Thread sha256Thread; + Thread sha384Thread; + Thread sha512Thread; + Thread spamsumThread; + + adlerPacket adlerPkt; + crc16Packet crc16Pkt; + crc32Packet crc32Pkt; + crc64Packet crc64Pkt; + md5Packet md5Pkt; + ripemd160Packet ripemd160Pkt; + sha1Packet sha1Pkt; + sha256Packet sha256Pkt; + sha384Packet sha384Pkt; + sha512Packet sha512Pkt; + spamsumPacket spamsumPkt; + + internal Checksum() + { + adler32ctx = new Adler32Context(); + crc16ctx = new CRC16Context(); + crc32ctx = new CRC32Context(); + crc64ctx = new CRC64Context(); + md5ctx = new MD5Context(); + ripemd160ctx = new RIPEMD160Context(); + sha1ctx = new SHA1Context(); + sha256ctx = new SHA256Context(); + sha384ctx = new SHA384Context(); + sha512ctx = new SHA512Context(); + ssctx = new SpamSumContext(); + + adlerThread = new Thread(updateAdler); + crc16Thread = new Thread(updateCRC16); + crc32Thread = new Thread(updateCRC32); + crc64Thread = new Thread(updateCRC64); + md5Thread = new Thread(updateMD5); + ripemd160Thread = new Thread(updateRIPEMD160); + sha1Thread = new Thread(updateSHA1); + sha256Thread = new Thread(updateSHA256); + sha384Thread = new Thread(updateSHA384); + sha512Thread = new Thread(updateSHA512); + spamsumThread = new Thread(updateSpamSum); + + adlerPkt = new adlerPacket(); + crc16Pkt = new crc16Packet(); + crc32Pkt = new crc32Packet(); + crc64Pkt = new crc64Packet(); + md5Pkt = new md5Packet(); + ripemd160Pkt = new ripemd160Packet(); + sha1Pkt = new sha1Packet(); + sha256Pkt = new sha256Packet(); + sha384Pkt = new sha384Packet(); + sha512Pkt = new sha512Packet(); + spamsumPkt = new spamsumPacket(); + + adler32ctx.Init(); + adlerPkt.context = adler32ctx; + crc16ctx.Init(); + crc16Pkt.context = crc16ctx; + crc32ctx.Init(); + crc32Pkt.context = crc32ctx; + crc64ctx.Init(); + crc64Pkt.context = crc64ctx; + md5ctx.Init(); + md5Pkt.context = md5ctx; + ripemd160ctx.Init(); + ripemd160Pkt.context = ripemd160ctx; + sha1ctx.Init(); + sha1Pkt.context = sha1ctx; + sha256ctx.Init(); + sha256Pkt.context = sha256ctx; + sha384ctx.Init(); + sha384Pkt.context = sha384ctx; + sha512ctx.Init(); + sha512Pkt.context = sha512ctx; + ssctx.Init(); + spamsumPkt.context = ssctx; + } + + internal void Update(byte[] data) + { + adlerPkt.data = data; + adlerThread.Start(adlerPkt); + crc16Pkt.data = data; + crc16Thread.Start(crc16Pkt); + crc32Pkt.data = data; + crc32Thread.Start(crc32Pkt); + crc64Pkt.data = data; + crc64Thread.Start(crc64Pkt); + md5Pkt.data = data; + md5Thread.Start(md5Pkt); + ripemd160Pkt.data = data; + ripemd160Thread.Start(ripemd160Pkt); + sha1Pkt.data = data; + sha1Thread.Start(sha1Pkt); + sha256Pkt.data = data; + sha256Thread.Start(sha256Pkt); + sha384Pkt.data = data; + sha384Thread.Start(sha384Pkt); + sha512Pkt.data = data; + sha512Thread.Start(sha512Pkt); + spamsumPkt.data = data; + spamsumThread.Start(spamsumPkt); + + while (adlerThread.IsAlive || crc16Thread.IsAlive || + crc32Thread.IsAlive || crc64Thread.IsAlive || + md5Thread.IsAlive || ripemd160Thread.IsAlive || + sha1Thread.IsAlive || sha256Thread.IsAlive || + sha384Thread.IsAlive || sha512Thread.IsAlive || + spamsumThread.IsAlive) + { + } + + adlerThread = new Thread(updateAdler); + crc16Thread = new Thread(updateCRC16); + crc32Thread = new Thread(updateCRC32); + crc64Thread = new Thread(updateCRC64); + md5Thread = new Thread(updateMD5); + ripemd160Thread = new Thread(updateRIPEMD160); + sha1Thread = new Thread(updateSHA1); + sha256Thread = new Thread(updateSHA256); + sha384Thread = new Thread(updateSHA384); + sha512Thread = new Thread(updateSHA512); + spamsumThread = new Thread(updateSpamSum); + } + + internal List End() + { + List Checksums = new List(); + + ChecksumType chk = new ChecksumType(); + chk.type = ChecksumTypeType.adler32; + chk.Value = adler32ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.crc16; + chk.Value = crc16ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.crc32; + chk.Value = crc32ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.crc64; + chk.Value = crc64ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.md5; + chk.Value = md5ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.ripemd160; + chk.Value = ripemd160ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha1; + chk.Value = sha1ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha256; + chk.Value = sha256ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha384; + chk.Value = sha384ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha512; + chk.Value = sha512ctx.End(); + Checksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.spamsum; + chk.Value = ssctx.End(); + Checksums.Add(chk); + + return Checksums; + } + + internal static List GetChecksums(byte[] data) + { + Adler32Context adler32ctxData = new Adler32Context(); + CRC16Context crc16ctxData = new CRC16Context(); + CRC32Context crc32ctxData = new CRC32Context(); + CRC64Context crc64ctxData = new CRC64Context(); + MD5Context md5ctxData = new MD5Context(); + RIPEMD160Context ripemd160ctxData = new RIPEMD160Context(); + SHA1Context sha1ctxData = new SHA1Context(); + SHA256Context sha256ctxData = new SHA256Context(); + SHA384Context sha384ctxData = new SHA384Context(); + SHA512Context sha512ctxData = new SHA512Context(); + SpamSumContext ssctxData = new SpamSumContext(); + + Thread adlerThreadData = new Thread(updateAdler); + Thread crc16ThreadData = new Thread(updateCRC16); + Thread crc32ThreadData = new Thread(updateCRC32); + Thread crc64ThreadData = new Thread(updateCRC64); + Thread md5ThreadData = new Thread(updateMD5); + Thread ripemd160ThreadData = new Thread(updateRIPEMD160); + Thread sha1ThreadData = new Thread(updateSHA1); + Thread sha256ThreadData = new Thread(updateSHA256); + Thread sha384ThreadData = new Thread(updateSHA384); + Thread sha512ThreadData = new Thread(updateSHA512); + Thread spamsumThreadData = new Thread(updateSpamSum); + + adlerPacket adlerPktData = new adlerPacket(); + crc16Packet crc16PktData = new crc16Packet(); + crc32Packet crc32PktData = new crc32Packet(); + crc64Packet crc64PktData = new crc64Packet(); + md5Packet md5PktData = new md5Packet(); + ripemd160Packet ripemd160PktData = new ripemd160Packet(); + sha1Packet sha1PktData = new sha1Packet(); + sha256Packet sha256PktData = new sha256Packet(); + sha384Packet sha384PktData = new sha384Packet(); + sha512Packet sha512PktData = new sha512Packet(); + spamsumPacket spamsumPktData = new spamsumPacket(); + + adler32ctxData.Init(); + adlerPktData.context = adler32ctxData; + crc16ctxData.Init(); + crc16PktData.context = crc16ctxData; + crc32ctxData.Init(); + crc32PktData.context = crc32ctxData; + crc64ctxData.Init(); + crc64PktData.context = crc64ctxData; + md5ctxData.Init(); + md5PktData.context = md5ctxData; + ripemd160ctxData.Init(); + ripemd160PktData.context = ripemd160ctxData; + sha1ctxData.Init(); + sha1PktData.context = sha1ctxData; + sha256ctxData.Init(); + sha256PktData.context = sha256ctxData; + sha384ctxData.Init(); + sha384PktData.context = sha384ctxData; + sha512ctxData.Init(); + sha512PktData.context = sha512ctxData; + ssctxData.Init(); + spamsumPktData.context = ssctxData; + + adlerPktData.data = data; + adlerThreadData.Start(adlerPktData); + crc16PktData.data = data; + crc16ThreadData.Start(crc16PktData); + crc32PktData.data = data; + crc32ThreadData.Start(crc32PktData); + crc64PktData.data = data; + crc64ThreadData.Start(crc64PktData); + md5PktData.data = data; + md5ThreadData.Start(md5PktData); + ripemd160PktData.data = data; + ripemd160ThreadData.Start(ripemd160PktData); + sha1PktData.data = data; + sha1ThreadData.Start(sha1PktData); + sha256PktData.data = data; + sha256ThreadData.Start(sha256PktData); + sha384PktData.data = data; + sha384ThreadData.Start(sha384PktData); + sha512PktData.data = data; + sha512ThreadData.Start(sha512PktData); + spamsumPktData.data = data; + spamsumThreadData.Start(spamsumPktData); + + while (adlerThreadData.IsAlive || crc16ThreadData.IsAlive || + crc32ThreadData.IsAlive || crc64ThreadData.IsAlive || + md5ThreadData.IsAlive || ripemd160ThreadData.IsAlive || + sha1ThreadData.IsAlive || sha256ThreadData.IsAlive || + sha384ThreadData.IsAlive || sha512ThreadData.IsAlive || + spamsumThreadData.IsAlive) + { + } + + List dataChecksums = new List(); + ChecksumType chk; + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.adler32; + chk.Value = adler32ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.crc16; + chk.Value = crc16ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.crc32; + chk.Value = crc32ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.crc64; + chk.Value = crc64ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.md5; + chk.Value = md5ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.ripemd160; + chk.Value = ripemd160ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha1; + chk.Value = sha1ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha256; + chk.Value = sha256ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha384; + chk.Value = sha384ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.sha512; + chk.Value = sha512ctxData.End(); + dataChecksums.Add(chk); + + chk = new ChecksumType(); + chk.type = ChecksumTypeType.spamsum; + chk.Value = ssctxData.End(); + dataChecksums.Add(chk); + + return dataChecksums; + } + + #region Threading helpers + + struct adlerPacket + { + public Adler32Context context; + public byte[] data; + } + + struct crc16Packet + { + public CRC16Context context; + public byte[] data; + } + + struct crc32Packet + { + public CRC32Context context; + public byte[] data; + } + + struct crc64Packet + { + public CRC64Context context; + public byte[] data; + } + + /*struct fletcher16Packet + { + public Fletcher16Context context; + public byte[] data; + } + + struct fletcher32Packet + { + public Fletcher32Context context; + public byte[] data; + }*/ + + struct md5Packet + { + public MD5Context context; + public byte[] data; + } + + struct ripemd160Packet + { + public RIPEMD160Context context; + public byte[] data; + } + + struct sha1Packet + { + public SHA1Context context; + public byte[] data; + } + + struct sha256Packet + { + public SHA256Context context; + public byte[] data; + } + + struct sha384Packet + { + public SHA384Context context; + public byte[] data; + } + + struct sha512Packet + { + public SHA512Context context; + public byte[] data; + } + + struct spamsumPacket + { + public SpamSumContext context; + public byte[] data; + } + + static void updateAdler(object packet) + { + ((adlerPacket)packet).context.Update(((adlerPacket)packet).data); + } + + static void updateCRC16(object packet) + { + ((crc16Packet)packet).context.Update(((crc16Packet)packet).data); + } + + static void updateCRC32(object packet) + { + ((crc32Packet)packet).context.Update(((crc32Packet)packet).data); + } + + static void updateCRC64(object packet) + { + ((crc64Packet)packet).context.Update(((crc64Packet)packet).data); + } + + /*static void updateFletcher16(object packet) + { + ((fletcher16Packet)packet).context.Update(((fletcher16Packet)packet).data); + } + + static void updateFletcher32(object packet) + { + ((fletcher32Packet)packet).context.Update(((fletcher32Packet)packet).data); + }*/ + + static void updateMD5(object packet) + { + ((md5Packet)packet).context.Update(((md5Packet)packet).data); + } + + static void updateRIPEMD160(object packet) + { + ((ripemd160Packet)packet).context.Update(((ripemd160Packet)packet).data); + } + + static void updateSHA1(object packet) + { + ((sha1Packet)packet).context.Update(((sha1Packet)packet).data); + } + + static void updateSHA256(object packet) + { + ((sha256Packet)packet).context.Update(((sha256Packet)packet).data); + } + + static void updateSHA384(object packet) + { + ((sha384Packet)packet).context.Update(((sha384Packet)packet).data); + } + + static void updateSHA512(object packet) + { + ((sha512Packet)packet).context.Update(((sha512Packet)packet).data); + } + + static void updateSpamSum(object packet) + { + ((spamsumPacket)packet).context.Update(((spamsumPacket)packet).data); + } + + #endregion Threading helpers + } +} + diff --git a/DiscImageChef/DiscImageChef.csproj b/DiscImageChef/DiscImageChef.csproj index e30ef941..0dc119cf 100644 --- a/DiscImageChef/DiscImageChef.csproj +++ b/DiscImageChef/DiscImageChef.csproj @@ -58,10 +58,14 @@ + + + + diff --git a/DiscImageChef/Main.cs b/DiscImageChef/Main.cs index 5a0d2c31..f33217f0 100644 --- a/DiscImageChef/Main.cs +++ b/DiscImageChef/Main.cs @@ -186,6 +186,22 @@ namespace DiscImageChef DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Commands.MediaScan.doMediaScan(MediaScanOptions); break; + case "dump-media": + DumpMediaSubOptions DumpMediaOptions = (DumpMediaSubOptions)invokedVerbInstance; + if (DumpMediaOptions.Debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + if (DumpMediaOptions.Verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Commands.DumpMedia.doDumpMedia(DumpMediaOptions); + break; + case "device-report": + DeviceReportSubOptions DeviceReportOptions = (DeviceReportSubOptions)invokedVerbInstance; + if (DeviceReportOptions.Debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + if (DeviceReportOptions.Verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Commands.DeviceReport.doDeviceReport(DeviceReportOptions); + break; default: throw new ArgumentException("Should never arrive here!"); } diff --git a/DiscImageChef/Options.cs b/DiscImageChef/Options.cs index c6c06834..0afc0eb9 100644 --- a/DiscImageChef/Options.cs +++ b/DiscImageChef/Options.cs @@ -239,6 +239,9 @@ namespace DiscImageChef [Option('m', "mhdd-log", Required = false, DefaultValue = "", HelpText = "Write a log of the scan in the format used by MHDD.")] public string MHDDLogPath { get; set; } + + [Option('b', "ibg-log", Required = false, DefaultValue = "", HelpText = "Write a log of the scan in the format used by ImgBurn.")] + public string IBGLogPath { get; set; } } public class FormatsSubOptions : CommonSubOptions @@ -260,6 +263,38 @@ namespace DiscImageChef public string InputFile { get; set; } } + // TODO: Add more options + public class DumpMediaSubOptions : CommonSubOptions + { + [Option('i', "device", Required = true, HelpText = "Device path.")] + public string DevicePath { get; set; } + + [Option('w', "output-prefix", Required = true, HelpText = "Prefix for media dump.")] + public string OutputPrefix { get; set; } + + [Option('r', "raw", DefaultValue = false, + HelpText = "Print sectors with tags included.")] + public bool Raw { get; set; } + + [Option('s', "stop-on-error", DefaultValue = false, + HelpText = "Print sectors with tags included.")] + public bool StopOnError { get; set; } + + [Option('f', "force", DefaultValue = false, + HelpText = "Continue dump whatever happens.")] + public bool Force { get; set; } + + [Option("reset", DefaultValue = (ushort)0, + HelpText = "Reset the device after these many errors. 0 to disable.")] + public ushort Reset { get; set; } + } + + public class DeviceReportSubOptions : CommonSubOptions + { + [Option('i', "device", Required = true, HelpText = "Device path.")] + public string DevicePath { get; set; } + } + public class Options { public Options() @@ -277,6 +312,8 @@ namespace DiscImageChef BenchmarkVerb = new BenchmarkSubOptions(); CreateSidecarVerb = new CreateSidecarSubOptions(); MediaScanVerb = new MediaScanSubOptions(); + DumpMediaVerb = new DumpMediaSubOptions(); + DeviceReportVerb = new DeviceReportSubOptions(); } [VerbOption("analyze", HelpText = "Analyzes a disc image and searches for partitions and/or filesystems.")] @@ -318,6 +355,12 @@ namespace DiscImageChef [VerbOption("media-scan", HelpText = "Scans the media inserted on a device.")] public MediaScanSubOptions MediaScanVerb { get; set; } + [VerbOption("dump-media", HelpText = "Dumps the media inserted on a device to a media image.")] + public DumpMediaSubOptions DumpMediaVerb { get; set; } + + [VerbOption("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")] + public DeviceReportSubOptions DeviceReportVerb { get; set; } + [HelpVerbOption] public string DoHelpForVerb(string verbName) {