diff --git a/.idea/.idea.Aaru/.idea/contentModel.xml b/.idea/.idea.Aaru/.idea/contentModel.xml index 43e204c2b..08ca96ec2 100644 --- a/.idea/.idea.Aaru/.idea/contentModel.xml +++ b/.idea/.idea.Aaru/.idea/contentModel.xml @@ -2196,6 +2196,7 @@ + diff --git a/Aaru.Tests.Devices/Aaru.Tests.Devices.csproj b/Aaru.Tests.Devices/Aaru.Tests.Devices.csproj index 9c6931c18..ae3ce601a 100644 --- a/Aaru.Tests.Devices/Aaru.Tests.Devices.csproj +++ b/Aaru.Tests.Devices/Aaru.Tests.Devices.csproj @@ -54,6 +54,7 @@ + diff --git a/Aaru.Tests.Devices/SCSI_MMC/LeadOutTrap.cs b/Aaru.Tests.Devices/SCSI_MMC/LeadOutTrap.cs new file mode 100644 index 000000000..0b5ef0626 --- /dev/null +++ b/Aaru.Tests.Devices/SCSI_MMC/LeadOutTrap.cs @@ -0,0 +1,539 @@ +using System.Linq; +using System.Threading; +using Aaru.Console; +using Aaru.Decoders.CD; +using Aaru.Decoders.SCSI; +using Aaru.Devices; + +namespace Aaru.Tests.Devices +{ + internal static partial class ScsiMmc + { + static void ReadLeadOutUsingTrapDisc(string devPath, Device dev) + { + string strDev; + int item; + bool tocIsNotBcd = false; + + parameters: + + while(true) + { + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine(); + AaruConsole.WriteLine("Choose what to do:"); + AaruConsole.WriteLine("1.- Try to read Lead-Out using a trap disc."); + AaruConsole.WriteLine("0.- Return to special SCSI MultiMedia Commands menu."); + + strDev = System.Console.ReadLine(); + + if(!int.TryParse(strDev, out item)) + { + AaruConsole.WriteLine("Not a number. Press any key to continue..."); + System.Console.ReadKey(); + + continue; + } + + switch(item) + { + case 0: + AaruConsole.WriteLine("Returning to special SCSI MultiMedia Commands menu..."); + + return; + case 1: goto start; + } + } + + start: + System.Console.Clear(); + + AaruConsole.WriteLine("Ejecting disc..."); + + dev.AllowMediumRemoval(out _, dev.Timeout, out _); + dev.EjectTray(out _, dev.Timeout, out _); + + AaruConsole.WriteLine("Please insert a data only disc inside..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + AaruConsole.WriteLine("Waiting 5 seconds..."); + Thread.Sleep(5000); + + AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); + + dev.ScsiTestUnitReady(out _, dev.Timeout, out _); + + bool sense = dev.ReadRawToc(out byte[] buffer, out byte[] senseBuffer, 1, dev.Timeout, out _); + + if(sense) + { + AaruConsole.WriteLine("READ FULL TOC failed..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + FullTOC.CDFullTOC? decodedToc = FullTOC.Decode(buffer); + + if(decodedToc is null) + { + AaruConsole.WriteLine("Could not decode TOC..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + FullTOC.CDFullTOC toc = decodedToc.Value; + + FullTOC.TrackDataDescriptor leadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); + + if(leadOutTrack.POINT != 0xA2) + { + AaruConsole.WriteLine("Cannot find lead-out..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + int min = ((leadOutTrack.PMIN >> 4) * 10) + (leadOutTrack.PMIN & 0x0F); + int sec = ((leadOutTrack.PSEC >> 4) * 10) + (leadOutTrack.PSEC & 0x0F); + int frame = ((leadOutTrack.PFRAME >> 4) * 10) + (leadOutTrack.PFRAME & 0x0F); + + int sectors = ((min * 60 * 75) + (sec * 75) + frame) - 150; + + AaruConsole.WriteLine("Data disc shows {0} sectors...", sectors); + + AaruConsole.WriteLine("Ejecting disc..."); + + dev.AllowMediumRemoval(out _, dev.Timeout, out _); + dev.EjectTray(out _, dev.Timeout, out _); + + AaruConsole.WriteLine("Please insert the trap disc inside..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + AaruConsole.WriteLine("Waiting 5 seconds..."); + Thread.Sleep(5000); + + AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); + + dev.ScsiTestUnitReady(out _, dev.Timeout, out _); + sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); + + if(sense) + { + AaruConsole.WriteLine("READ FULL TOC failed..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + decodedToc = FullTOC.Decode(buffer); + + if(decodedToc is null) + { + AaruConsole.WriteLine("Could not decode TOC..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + toc = decodedToc.Value; + + leadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); + + if(leadOutTrack.POINT != 0xA2) + { + AaruConsole.WriteLine("Cannot find lead-out..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + min = 0; + + if(leadOutTrack.PMIN == 122) + tocIsNotBcd = true; + + if(leadOutTrack.PMIN >= 0xA0 && + !tocIsNotBcd) + { + min += 90; + leadOutTrack.PMIN -= 0x90; + } + + if(tocIsNotBcd) + { + min = leadOutTrack.PMIN; + sec = leadOutTrack.PSEC; + frame = leadOutTrack.PFRAME; + } + else + { + min += ((leadOutTrack.PMIN >> 4) * 10) + (leadOutTrack.PMIN & 0x0F); + sec = ((leadOutTrack.PSEC >> 4) * 10) + (leadOutTrack.PSEC & 0x0F); + frame = ((leadOutTrack.PFRAME >> 4) * 10) + (leadOutTrack.PFRAME & 0x0F); + } + + int trapSectors = ((min * 60 * 75) + (sec * 75) + frame) - 150; + + AaruConsole.WriteLine("Trap disc shows {0} sectors...", trapSectors); + + if(trapSectors < sectors + 100) + { + AaruConsole.WriteLine("Trap disc doesn't have enough sectors..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + AaruConsole.WriteLine("Stopping motor..."); + + dev.StopUnit(out _, dev.Timeout, out _); + + AaruConsole.WriteLine("Please MANUALLY get the trap disc out and put the data disc back inside..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + AaruConsole.WriteLine("Waiting 5 seconds..."); + Thread.Sleep(5000); + + AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); + + sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); + + // Just try again to clear any "disc changed" events + if(sense) + sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); + + if(sense) + { + AaruConsole.WriteLine("READ FULL TOC failed..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + decodedToc = FullTOC.Decode(buffer); + + if(decodedToc is null) + { + AaruConsole.WriteLine("Could not decode TOC..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + toc = decodedToc.Value; + + FullTOC.TrackDataDescriptor newLeadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); + + if(newLeadOutTrack.POINT != 0xA2) + { + AaruConsole.WriteLine("Cannot find lead-out..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + if(newLeadOutTrack.PMIN >= 0xA0 && + !tocIsNotBcd) + newLeadOutTrack.PMIN -= 0x90; + + if(newLeadOutTrack.PMIN != leadOutTrack.PMIN || + newLeadOutTrack.PSEC != leadOutTrack.PSEC || + newLeadOutTrack.PFRAME != leadOutTrack.PFRAME) + { + AaruConsole.WriteLine("Lead-out has changed, this drive does not support hot swapping discs..."); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadLine(); + + goto parameters; + } + + AaruConsole.Write("Reading LBA {0}... ", sectors + 5); + + bool dataResult = dev.ReadCd(out byte[] dataBuffer, out byte[] dataSense, (uint)(sectors + 5), 2352, 1, + MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, + true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); + + AaruConsole.WriteLine(dataResult ? "FAIL!" : "Success!"); + + AaruConsole.Write("Reading LBA {0} as audio (scrambled)... ", sectors + 5); + + bool scrambledResult = dev.ReadCd(out byte[] scrambledBuffer, out byte[] scrambledSense, + (uint)(sectors + 5), 2352, 1, MmcSectorTypes.Cdda, false, false, false, + MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, + dev.Timeout, out _); + + AaruConsole.WriteLine(scrambledResult ? "FAIL!" : "Success!"); + + AaruConsole.Write("Reading LBA {0}'s PQ subchannel... ", sectors + 5); + + bool pqResult = dev.ReadCd(out byte[] pqBuffer, out byte[] pqSense, (uint)(sectors + 5), 16, 1, + MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, false, false, + MmcErrorField.None, MmcSubchannel.Q16, dev.Timeout, out _); + + if(pqResult) + pqResult = dev.ReadCd(out pqBuffer, out pqSense, (uint)(sectors + 5), 16, 1, MmcSectorTypes.AllTypes, + false, false, false, MmcHeaderCodes.None, false, false, MmcErrorField.None, + MmcSubchannel.Q16, dev.Timeout, out _); + + AaruConsole.WriteLine(pqResult ? "FAIL!" : "Success!"); + + AaruConsole.Write("Reading LBA {0}'s PQ subchannel... ", sectors + 5); + + bool rwResult = dev.ReadCd(out byte[] rwBuffer, out byte[] rwSense, (uint)(sectors + 5), 16, 1, + MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, false, false, + MmcErrorField.None, MmcSubchannel.Rw, dev.Timeout, out _); + + if(rwResult) + rwResult = dev.ReadCd(out rwBuffer, out rwSense, (uint)(sectors + 5), 16, 1, MmcSectorTypes.Cdda, false, + false, false, MmcHeaderCodes.None, false, false, MmcErrorField.None, + MmcSubchannel.Rw, dev.Timeout, out _); + + AaruConsole.WriteLine(pqResult ? "FAIL!" : "Success!"); + + menu: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("Device {0} read Lead-Out.", dataResult && scrambledResult ? "cannot" : "can"); + + AaruConsole.WriteLine("LBA {0} sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, dataResult, + dataBuffer is null + ? "null" + : ArrayHelpers.ArrayIsNullOrEmpty(dataBuffer) + ? "empty" + : $"{dataBuffer.Length} bytes", dataSense is null + ? "null" + : ArrayHelpers. + ArrayIsNullOrEmpty(dataSense) + ? "empty" + : $"{dataSense.Length}"); + + AaruConsole.WriteLine("LBA {0} (scrambled) sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, + scrambledResult, scrambledBuffer is null + ? "null" + : ArrayHelpers.ArrayIsNullOrEmpty(scrambledBuffer) + ? "empty" + : $"{scrambledBuffer.Length} bytes", scrambledSense is null + ? "null" + : ArrayHelpers. + ArrayIsNullOrEmpty(scrambledSense) + ? "empty" + : $"{scrambledSense.Length}"); + + AaruConsole.WriteLine("LBA {0}'s PQ sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, + pqResult, pqBuffer is null + ? "null" + : ArrayHelpers.ArrayIsNullOrEmpty(pqBuffer) + ? "empty" + : $"{pqBuffer.Length} bytes", pqSense is null + ? "null" + : ArrayHelpers. + ArrayIsNullOrEmpty(pqSense) + ? "empty" + : $"{pqSense.Length}"); + + AaruConsole.WriteLine("LBA {0}'s RW sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, + dataResult, rwBuffer is null + ? "null" + : ArrayHelpers.ArrayIsNullOrEmpty(rwBuffer) + ? "empty" + : $"{rwBuffer.Length} bytes", rwSense is null + ? "null" + : ArrayHelpers. + ArrayIsNullOrEmpty(rwSense) + ? "empty" + : $"{rwSense.Length}"); + + AaruConsole.WriteLine(); + AaruConsole.WriteLine("Choose what to do:"); + AaruConsole.WriteLine("1.- Print LBA {0} buffer.", sectors + 5); + AaruConsole.WriteLine("2.- Print LBA {0} sense buffer.", sectors + 5); + AaruConsole.WriteLine("3.- Decode LBA {0} sense buffer.", sectors + 5); + AaruConsole.WriteLine("4.- Print LBA {0} (scrambled) buffer.", sectors + 5); + AaruConsole.WriteLine("5.- Print LBA {0} (scrambled) sense buffer.", sectors + 5); + AaruConsole.WriteLine("6.- Decode LBA {0} (scrambled) sense buffer.", sectors + 5); + AaruConsole.WriteLine("7.- Print LBA {0}'s PQ buffer.", sectors + 5); + AaruConsole.WriteLine("8.- Print LBA {0}'s PQ sense buffer.", sectors + 5); + AaruConsole.WriteLine("9.- Decode LBA {0}'s PQ sense buffer.", sectors + 5); + AaruConsole.WriteLine("10.- Print LBA {0}'s RW buffer.", sectors + 5); + AaruConsole.WriteLine("11.- Print LBA {0}'s RW sense buffer.", sectors + 5); + AaruConsole.WriteLine("12.- Decode LBA {0}'s RW sense buffer.", sectors + 5); + AaruConsole.WriteLine("13.- Send command again."); + AaruConsole.WriteLine("0.- Return to special SCSI MultiMedia Commands menu."); + AaruConsole.Write("Choose: "); + + strDev = System.Console.ReadLine(); + + if(!int.TryParse(strDev, out item)) + { + AaruConsole.WriteLine("Not a number. Press any key to continue..."); + System.Console.ReadKey(); + System.Console.Clear(); + + goto menu; + } + + switch(item) + { + case 0: + AaruConsole.WriteLine("Returning to special SCSI MultiMedia Commands menu..."); + + return; + case 1: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA {0} response:", sectors + 5); + + if(buffer != null) + PrintHex.PrintHexArray(dataBuffer, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 2: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA {0} sense:", sectors + 5); + + if(senseBuffer != null) + PrintHex.PrintHexArray(dataSense, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 3: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA {0} decoded sense:", sectors + 5); + AaruConsole.Write("{0}", Sense.PrettifySense(dataSense)); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 4: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA {0} (scrambled) response:", sectors + 5); + + if(buffer != null) + PrintHex.PrintHexArray(scrambledBuffer, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 5: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA {0} (scrambled) sense:", sectors + 5); + + if(senseBuffer != null) + PrintHex.PrintHexArray(scrambledSense, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 6: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA {0} (scrambled) decoded sense:", sectors + 5); + AaruConsole.Write("{0}", Sense.PrettifySense(scrambledSense)); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 7: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA's PQ {0} response:", sectors + 5); + + if(buffer != null) + PrintHex.PrintHexArray(pqBuffer, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 8: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA's PQ {0} sense:", sectors + 5); + + if(senseBuffer != null) + PrintHex.PrintHexArray(pqSense, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 9: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA's PQ {0} decoded sense:", sectors + 5); + AaruConsole.Write("{0}", Sense.PrettifySense(pqSense)); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 10: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA's RW {0} response:", sectors + 5); + + if(buffer != null) + PrintHex.PrintHexArray(rwBuffer, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 11: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA's RW {0} sense:", sectors + 5); + + if(senseBuffer != null) + PrintHex.PrintHexArray(rwSense, 64); + + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 12: + System.Console.Clear(); + AaruConsole.WriteLine("Device: {0}", devPath); + AaruConsole.WriteLine("LBA's RW {0} decoded sense:", sectors + 5); + AaruConsole.Write("{0}", Sense.PrettifySense(rwSense)); + AaruConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + + goto menu; + case 13: goto start; + default: + AaruConsole.WriteLine("Incorrect option. Press any key to continue..."); + System.Console.ReadKey(); + System.Console.Clear(); + + goto menu; + } + } + } +} \ No newline at end of file diff --git a/Aaru.Tests.Devices/SCSI_MMC/SCSI_MMC.cs b/Aaru.Tests.Devices/SCSI_MMC/SCSI_MMC.cs index e57f493d3..2d3e52d26 100644 --- a/Aaru.Tests.Devices/SCSI_MMC/SCSI_MMC.cs +++ b/Aaru.Tests.Devices/SCSI_MMC/SCSI_MMC.cs @@ -45,6 +45,7 @@ namespace Aaru.Tests.Devices WriteLine("1.- Try to read the cache data from a device with a MediaTek chipset (F1h command 06h subcommand)."); AaruConsole.WriteLine("2.- Try to read a GD-ROM using a trap disc."); + AaruConsole.WriteLine("3.- Try to read Lead-Out using a trap disc."); AaruConsole.WriteLine("0.- Return to command class menu."); AaruConsole.Write("Choose: "); @@ -72,6 +73,10 @@ namespace Aaru.Tests.Devices case 2: CheckGdromReadability(devPath, dev); + continue; + case 3: + ReadLeadOutUsingTrapDisc(devPath, dev); + continue; default: AaruConsole.WriteLine("Incorrect option. Press any key to continue...");