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) {