// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : ScsiInfo.cs // Author(s) : Natalia Portillo // // Component : Core. // // --[ Description ] ---------------------------------------------------------- // // Retrieves the media info for a SCSI device. // // --[ 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 © 2011-2025 Natalia Portillo // ****************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Threading; using Aaru.CommonTypes; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Structs.Devices.SCSI; using Aaru.Core.Media.Detection; using Aaru.Decoders.CD; using Aaru.Decoders.DVD; using Aaru.Decoders.SCSI; using Aaru.Decoders.SCSI.MMC; using Aaru.Decoders.SCSI.SSC; using Aaru.Decoders.Xbox; using Aaru.Devices; using Aaru.Logging; using DeviceInfo = Aaru.Core.Devices.Info.DeviceInfo; using DMI = Aaru.Decoders.Xbox.DMI; using DVDDecryption = Aaru.Decryption.DVD.Dump; using Inquiry = Aaru.CommonTypes.Structs.Devices.SCSI.Inquiry; namespace Aaru.Core.Media.Info; /// Retrieves information from a SCSI device public sealed class ScsiInfo { const string MODULE_NAME = "Media information"; /// Initializes this class with the specific device, and fills in the information /// Device public ScsiInfo(Device dev) { if(dev.Type != DeviceType.SCSI && dev.Type != DeviceType.ATAPI) return; MediaType = MediaType.Unknown; MediaInserted = false; int resets = 0; bool sense; byte[] cmdBuf; ReadOnlySpan senseBuf; bool containsFloppyPage = false; int sessions = 1; int firstTrackLastSession = 1; if(dev.IsRemovable) { deviceGotReset: sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if(sense) { DecodedSense? decSense = Sense.Decode(senseBuf); if(decSense.HasValue) { // Just retry, for 5 times if(decSense?.ASC == 0x29) { resets++; if(resets < 5) goto deviceGotReset; } switch(decSense?.ASC) { case 0x3A: { int leftRetries = 5; while(leftRetries > 0) { //AaruLogging.WriteLine("\rWaiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if(!sense) break; leftRetries--; } if(sense) { AaruLogging.Error(Localization.Core.Please_insert_media_in_drive); return; } break; } case 0x04 when decSense?.ASCQ == 0x01: { int leftRetries = 10; while(leftRetries > 0) { //AaruLogging.WriteLine("\rWaiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if(!sense) break; leftRetries--; } if(sense) { AaruLogging.Error(Localization.Core.Error_testing_unit_was_ready_0, Sense.PrettifySense(senseBuf.ToArray())); return; } break; } default: AaruLogging.Error(Localization.Core.Error_testing_unit_was_ready_0, Sense.PrettifySense(senseBuf.ToArray())); return; } } else { AaruLogging.Error(Localization.Core.Unknown_sense_testing_unit_was_ready); return; } } } MediaInserted = true; DeviceInfo = new DeviceInfo(dev); byte scsiMediumType = 0; byte scsiDensityCode = 0; if(DeviceInfo.ScsiMode.HasValue) { scsiMediumType = (byte)DeviceInfo.ScsiMode.Value.Header.MediumType; if(DeviceInfo.ScsiMode?.Header.BlockDescriptors?.Length > 0) scsiDensityCode = (byte)DeviceInfo.ScsiMode.Value.Header.BlockDescriptors[0].Density; if(DeviceInfo.ScsiMode?.Pages != null) containsFloppyPage = DeviceInfo.ScsiMode.Value.Pages.Any(p => p.Page == 0x05); } Blocks = 0; BlockSize = 0; switch(dev.ScsiType) { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: case PeripheralDeviceTypes.OCRWDevice: case PeripheralDeviceTypes.OpticalDevice: case PeripheralDeviceTypes.SimplifiedDevice: case PeripheralDeviceTypes.WriteOnceDevice: sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); if(!sense) { ReadCapacity = cmdBuf; Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) & 0xFFFFFFFF; BlockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); } sense = dev.ReadCapacity16(out cmdBuf, out senseBuf, dev.Timeout, out _); if(!sense) ReadCapacity16 = cmdBuf; if(ReadCapacity == null || Blocks is 0xFFFFFFFF or 0) { if(ReadCapacity16 == null && Blocks == 0) { if(dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice) { AaruLogging.Error(Localization.Core.Unable_to_get_media_capacity); AaruLogging.Error("{0}", Sense.PrettifySense(senseBuf.ToArray())); } } if(ReadCapacity16 != null) { byte[] temp = new byte[8]; Array.Copy(cmdBuf, 0, temp, 0, 8); Array.Reverse(temp); Blocks = BitConverter.ToUInt64(temp, 0); BlockSize = (uint)((cmdBuf[8] << 24) + (cmdBuf[9] << 16) + (cmdBuf[10] << 8) + cmdBuf[11]); } } if(Blocks != 0 && BlockSize != 0) Blocks++; break; case PeripheralDeviceTypes.SequentialAccess: byte[] medBuf; sense = dev.ReportDensitySupport(out byte[] seqBuf, out senseBuf, false, dev.Timeout, out _); if(!sense) { sense = dev.ReportDensitySupport(out medBuf, out senseBuf, true, dev.Timeout, out _); if(!sense && !seqBuf.SequenceEqual(medBuf)) { DensitySupport = seqBuf; DensitySupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(seqBuf); } } sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, true, false, dev.Timeout, out _); if(!sense) { sense = dev.ReportDensitySupport(out medBuf, out senseBuf, true, true, dev.Timeout, out _); if(!sense && !seqBuf.SequenceEqual(medBuf)) { MediaTypeSupport = medBuf; MediaTypeSupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(seqBuf); } } // TODO: Get a machine where 16-byte CDBs don't get DID_ABORT /* sense = dev.ReadAttribute(out seqBuf, out senseBuf, ScsiAttributeAction.List, 0, dev.Timeout, out _); if (sense) AaruLogging.ErrorWriteLine("SCSI READ ATTRIBUTE:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else { DataFile.WriteTo(MODULE_NAME, outputPrefix, "_scsi_readattribute.bin", "SCSI READ ATTRIBUTE", seqBuf); } */ break; case PeripheralDeviceTypes.BridgingExpander when dev.Model.StartsWith("MDM", StringComparison.Ordinal) || dev.Model.StartsWith("MDH", StringComparison.Ordinal): sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); if(!sense) { ReadCapacity = cmdBuf; Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) & 0xFFFFFFFF; BlockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); } break; } if(dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) { sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, "READ GET CONFIGURATION:\n{0}", Sense.PrettifySense(senseBuf.ToArray())); if(dev.IsUsb && scsiMediumType is 0x40 or 0x41 or 0x42) MediaType = MediaType.FlashDrive; } else { MmcConfiguration = cmdBuf; Features.SeparatedFeatures ftr = Features.Separate(cmdBuf); AaruLogging.Debug(MODULE_NAME, Localization.Core.GET_CONFIGURATION_current_profile_is_0, ftr.CurrentProfile); MediaType = ftr.CurrentProfile switch { 0x0001 => MediaType.GENERIC_HDD, 0x0002 => scsiMediumType switch { 0x01 => MediaType.PD650, 0x41 => Blocks switch { 58620544 => MediaType.REV120, 17090880 => MediaType.REV35, 34185728 => MediaType.REV70, _ => MediaType }, _ => MediaType.Unknown }, 0x0005 => MediaType.CDMO, 0x0008 => MediaType.CD, 0x0009 => MediaType.CDR, 0x000A => MediaType.CDRW, 0x0010 => MediaType.DVDROM, 0x0011 => MediaType.DVDR, 0x0012 => MediaType.DVDRAM, 0x0013 or 0x0014 => MediaType.DVDRW, 0x0015 or 0x0016 => MediaType.DVDRDL, 0x0017 => MediaType.DVDRWDL, 0x0018 => MediaType.DVDDownload, 0x001A => MediaType.DVDPRW, 0x001B => MediaType.DVDPR, 0x0020 => MediaType.DDCD, 0x0021 => MediaType.DDCDR, 0x0022 => MediaType.DDCDRW, 0x002A => MediaType.DVDPRWDL, 0x002B => MediaType.DVDPRDL, 0x0040 => MediaType.BDROM, 0x0041 or 0x0042 => MediaType.BDR, 0x0043 => MediaType.BDRE, 0x0050 => MediaType.HDDVDROM, 0x0051 => MediaType.HDDVDR, 0x0052 => MediaType.HDDVDRAM, 0x0053 => MediaType.HDDVDRW, 0x0058 => MediaType.HDDVDRDL, 0x005A => MediaType.HDDVDRWDL, _ => MediaType }; } if(MediaType == MediaType.PD650 && Blocks == 1281856) MediaType = MediaType.PD650_WORM; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.RecognizedFormatLayers, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Recognized_Format_Layers_0, Sense.PrettifySense(senseBuf.ToArray())); } else RecognizedFormatLayers = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.WriteProtectionStatus, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Write_Protection_Status_0, Sense.PrettifySense(senseBuf.ToArray())); } else WriteProtectionStatus = cmdBuf; // More like a drive information /* sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: Capability List\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, outputPrefix, "_readdiscstructure_capabilitylist.bin", "SCSI READ DISC STRUCTURE", cmdBuf); */ #region All DVD and HD DVD types if(MediaType is MediaType.DVDDownload or MediaType.DVDPR or MediaType.DVDPRDL or MediaType.DVDPRW or MediaType.DVDPRWDL or MediaType.DVDR or MediaType.DVDRAM or MediaType.DVDRDL or MediaType.DVDROM or MediaType.DVDRW or MediaType.DVDRWDL or MediaType.HDDVDR or MediaType.HDDVDRAM or MediaType.HDDVDRDL or MediaType.HDDVDROM or MediaType.HDDVDRW or MediaType.HDDVDRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_PFI_0, Sense.PrettifySense(senseBuf.ToArray())); } else { DvdPfi = cmdBuf; DecodedPfi = PFI.Decode(cmdBuf, MediaType); if(DecodedPfi.HasValue) { if(MediaType == MediaType.DVDROM) { MediaType = DecodedPfi.Value.DiskCategory switch { DiskCategory.DVDPR => MediaType.DVDPR, DiskCategory.DVDPRDL => MediaType.DVDPRDL, DiskCategory.DVDPRW => MediaType.DVDPRW, DiskCategory.DVDPRWDL => MediaType.DVDPRWDL, DiskCategory.DVDR => DecodedPfi.Value.PartVersion >= 6 ? MediaType.DVDRDL : MediaType.DVDR, DiskCategory.DVDRAM => MediaType.DVDRAM, DiskCategory.DVDRW => DecodedPfi.Value.PartVersion >= 15 ? MediaType.DVDRWDL : MediaType.DVDRW, DiskCategory.HDDVDR => MediaType.HDDVDR, DiskCategory.HDDVDRAM => MediaType.HDDVDRAM, DiskCategory.HDDVDROM => MediaType.HDDVDROM, DiskCategory.HDDVDRW => MediaType.HDDVDRW, DiskCategory.Nintendo => DecodedPfi.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD, DiskCategory.UMD => MediaType.UMD, _ => MediaType.DVDROM }; } } } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DMI_0, Sense.PrettifySense(senseBuf.ToArray())); } else { DvdDmi = cmdBuf; if(DMI.IsXbox(cmdBuf)) MediaType = MediaType.XGD; else if(DMI.IsXbox360(cmdBuf)) { MediaType = MediaType.XGD2; // All XGD3 all have the same number of blocks if(Blocks is 25063 or 4229664 or 4246304) // Wxripper unlock MediaType = MediaType.XGD3; } } } #endregion All DVD and HD DVD types #region DVD-ROM if(MediaType is MediaType.DVDDownload or MediaType.DVDROM) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_CMI_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdCmi = cmdBuf; } #endregion DVD-ROM switch(MediaType) { #region DVD-ROM and HD DVD-ROM case MediaType.DVDDownload: case MediaType.DVDROM: case MediaType.HDDVDROM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_BCA_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdBca = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdAacs, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DVD_AACS_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdAacs = cmdBuf; break; #endregion DVD-ROM and HD DVD-ROM #region DVD-RAM and HD DVD-RAM case MediaType.DVDRAM: case MediaType.HDDVDRAM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DDS_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdRamDds = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdramMediumStatus, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Medium_Status_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdRamCartridgeStatus = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_SAI_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdRamSpareArea = cmdBuf; break; #endregion DVD-RAM and HD DVD-RAM #region DVD-R and HD DVD-R case MediaType.DVDR: case MediaType.HDDVDR: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.LastBorderOutRmd, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Last_Out_Border_RMD_0, Sense.PrettifySense(senseBuf.ToArray())); } else LastBorderOutRmd = cmdBuf; break; #endregion DVD-R and HD DVD-R } var dvdDecrypt = new DVDDecryption(dev); sense = dvdDecrypt.ReadBusKey(out cmdBuf, out senseBuf, CopyrightType.CSS, dev.Timeout, out _); if(!sense) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DiscKey, dvdDecrypt.Agid, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Disc_Key_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdDiscKey = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.SectorCopyrightInformation, dvdDecrypt.Agid, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Sector_CMI_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdSectorCmi = cmdBuf; } #region Require drive authentication, won't work /* sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.MediaIdentifier, 0, dev.Timeout, out _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS Volume ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS Media Serial Number\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS Media ID\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS LBA Extents\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS CPRM MKB\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, 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 _); if(sense) AaruLogging.DebugWriteLine(MODULE_NAME, "READ DISC STRUCTURE: AACS Data Keys\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf.ToArray())); else DataFile.WriteTo(MODULE_NAME, outputPrefix, "_readdiscstructure_aacsdatakeys.bin", "SCSI READ DISC STRUCTURE", cmdBuf); */ #endregion Require drive authentication, won't work #region DVD-R and DVD-RW if(MediaType is MediaType.DVDR or MediaType.DVDRW or MediaType.DVDRDL or MediaType.DVDRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Pre_Recorded_Info_0, Sense.PrettifySense(senseBuf.ToArray())); } else { DvdPreRecordedInfo = cmdBuf; DecodedDvdPrePitInformation = PRI.Decode(cmdBuf); } } #endregion DVD-R and DVD-RW switch(MediaType) { #region DVD-R, DVD-RW and HD DVD-R case MediaType.DVDR: case MediaType.DVDRW: case MediaType.DVDRDL: case MediaType.DVDRWDL: case MediaType.HDDVDR: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DVD_R_Media_ID_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdrMediaIdentifier = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdrPhysicalInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DVD_R_PFI_0, Sense.PrettifySense(senseBuf.ToArray())); } else { DvdrPhysicalInformation = cmdBuf; DecodedDvdrPfi = PFI.Decode(cmdBuf, MediaType); } break; #endregion DVD-R, DVD-RW and HD DVD-R #region All DVD+ case MediaType.DVDPR: case MediaType.DVDPRDL: case MediaType.DVDPRW: case MediaType.DVDPRWDL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_ADIP_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdPlusAdip = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DCB_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdPlusDcb = cmdBuf; break; #endregion All DVD+ #region HD DVD-ROM case MediaType.HDDVDROM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.HddvdCopyrightInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_HD_DVD_CMI_0, Sense.PrettifySense(senseBuf.ToArray())); } else HddvdCopyrightInformation = cmdBuf; break; #endregion HD DVD-ROM } switch(MediaType) { #region HD DVD-R case MediaType.HDDVDR: { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.HddvdrMediumStatus, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_HD_DVD_R_Medium_Status, Sense.PrettifySense(senseBuf.ToArray())); } else HddvdrMediumStatus = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.HddvdrLastRmd, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Last_RMD_0, Sense.PrettifySense(senseBuf.ToArray())); } else HddvdrLastRmd = cmdBuf; break; } #endregion HD DVD-R #region DVD-R DL, DVD-RW DL, DVD+R DL, DVD+RW DL case MediaType.DVDPRDL or MediaType.DVDRDL or MediaType.DVDRWDL or MediaType.DVDPRWDL: { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdrLayerCapacity, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Layer_Capacity_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdrLayerCapacity = cmdBuf; break; } #endregion DVD-R DL, DVD-RW DL, DVD+R DL, DVD+RW DL } switch(MediaType) { #region DVD-R DL case MediaType.DVDRDL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.MiddleZoneStart, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Middle_Zone_Start_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdrDlMiddleZoneStart = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.JumpIntervalSize, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Jump_Interval_Size_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdrDlJumpIntervalSize = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.ManualLayerJumpStartLba, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Manual_Layer_Jump_Start_LBA_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdrDlManualLayerJumpStartLba = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.RemapAnchorPoint, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Remap_Anchor_Point_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdrDlRemapAnchorPoint = cmdBuf; break; #endregion DVD-R DL #region All Blu-ray case MediaType.BDR: case MediaType.BDRE: case MediaType.BDROM: case MediaType.UHDBD: case MediaType.BDRXL: case MediaType.BDREXL: case MediaType.PS4BD: case MediaType.PS5BD: case MediaType.XGD4: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DI_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayDiscInformation = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.Pac, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_PAC_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayPac = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_BCA_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayBurstCuttingArea = cmdBuf; break; #endregion All Blu-ray } switch(MediaType) { #region Writable Blu-ray only case MediaType.BDR: case MediaType.BDRE: case MediaType.BDRXL: case MediaType.BDREXL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DDS_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayDds = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Cartridge_Status_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayCartridgeStatus = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, "READ DISC STRUCTURE: Spare Area Information\n{0}", Sense.PrettifySense(senseBuf.ToArray())); } else BluraySpareAreaInformation = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.RawDfl, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_Raw_DFL_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayRawDfl = cmdBuf; sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.TrackResources, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_001b_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayTrackResources = cmdBuf; sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.PowResources, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_010b_0, Sense.PrettifySense(senseBuf.ToArray())); } else BlurayPowResources = cmdBuf; break; #endregion Writable Blu-ray only #region CDs case MediaType.CD: case MediaType.CDR: case MediaType.CDROM: case MediaType.CDRW: case MediaType.Unknown: // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) bool tocSense = dev.ReadTocPmaAtip(out cmdBuf, out senseBuf, false, 0, 0, dev.Timeout, out _); if(tocSense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_TOC_PMA_ATIP_TOC_0, Sense.PrettifySense(senseBuf.ToArray())); } else { Toc = cmdBuf; DecodedToc = TOC.Decode(cmdBuf); // As we have a TOC we know it is a CD if(MediaType == MediaType.Unknown) MediaType = MediaType.CD; } // ATIP exists on blank CDs sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_TOC_PMA_ATIP_ATIP_0, Sense.PrettifySense(senseBuf.ToArray())); } else { Atip = cmdBuf; DecodedAtip = ATIP.Decode(cmdBuf); if(DecodedAtip != null) // Only CD-R and CD-RW have ATIP MediaType = DecodedAtip.DiscType ? MediaType.CDRW : MediaType.CDR; else Atip = null; } // We got a TOC, get information about a recorded/mastered CD if(!tocSense) { sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_TOC_PMA_ATIP_Session_Info_0, Sense.PrettifySense(senseBuf.ToArray())); } else if(cmdBuf.Length > 4) { Session = cmdBuf; DecodedSession = Decoders.CD.Session.Decode(cmdBuf); if(DecodedSession.HasValue) { sessions = DecodedSession.Value.LastCompleteSession; firstTrackLastSession = DecodedSession.Value.TrackDescriptors[0].TrackNumber; } } sense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_TOC_PMA_ATIP_Raw_TOC_0, Sense.PrettifySense(senseBuf.ToArray())); } else if(cmdBuf.Length > 4) { RawToc = cmdBuf; FullToc = FullTOC.Decode(cmdBuf); } sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_TOC_PMA_ATIP_PMA_0, Sense.PrettifySense(senseBuf.ToArray())); } else if(cmdBuf.Length > 4) Pma = cmdBuf; sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_TOC_PMA_ATIP_CD_TEXT_0, Sense.PrettifySense(senseBuf.ToArray())); } else if(cmdBuf.Length > 4) { CdTextLeadIn = cmdBuf; DecodedCdTextLeadIn = CDTextOnLeadIn.Decode(cmdBuf); } sense = dev.ReadMcn(out string mcn, out _, out _, dev.Timeout, out _); if(!sense && mcn != null && mcn != "0000000000000") Mcn = mcn; Isrcs = new Dictionary(); for(byte i = DecodedToc.Value.FirstTrack; i <= DecodedToc.Value.LastTrack; i++) { sense = dev.ReadIsrc(i, out string isrc, out _, out _, dev.Timeout, out _); if(!sense && isrc != null && isrc != "000000000000") Isrcs.Add(i, isrc); } if(Isrcs.Count == 0) Isrcs = null; } break; #endregion CDs } #region Nintendo if(MediaType == MediaType.Unknown && Blocks > 0) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_PFI_0, Sense.PrettifySense(senseBuf.ToArray())); } else { DvdPfi = cmdBuf; PFI.PhysicalFormatInformation? nintendoPfi = PFI.Decode(cmdBuf, MediaType); if(nintendoPfi != null) { AaruLogging.WriteLine("PFI:\n{0}", PFI.Prettify(cmdBuf, MediaType)); if(nintendoPfi is { DiskCategory: DiskCategory.Nintendo, PartVersion: 15 }) { MediaType = nintendoPfi.Value.DiscSize switch { DVDSize.Eighty => MediaType.GOD, DVDSize.OneTwenty => MediaType.WOD, _ => MediaType }; } } } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_STRUCTURE_DMI_0, Sense.PrettifySense(senseBuf.ToArray())); } else DvdDmi = cmdBuf; } #endregion Nintendo } sense = dev.ReadMediaSerialNumber(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_MEDIA_SERIAL_NUMBER_0, Sense.PrettifySense(senseBuf.ToArray())); else { if(cmdBuf.Length >= 4) MediaSerialNumber = cmdBuf; } switch(MediaType) { #region Xbox case MediaType.XGD: case MediaType.XGD2: case MediaType.XGD3: // We need to get INQUIRY to know if it is a Kreon drive sense = dev.ScsiInquiry(out byte[] inqBuffer, out senseBuf); if(!sense) { Inquiry? inq = Inquiry.Decode(inqBuffer); if(inq?.KreonPresent == true) { sense = dev.KreonExtractSs(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.KREON_EXTRACT_SS_0, Sense.PrettifySense(senseBuf.ToArray())); } else XboxSecuritySector = cmdBuf; DecodedXboxSecuritySector = SS.Decode(cmdBuf); // Get video partition size AaruLogging.Debug(MODULE_NAME, Localization.Core.Getting_video_partition_size); sense = dev.KreonLock(out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_lock_drive_not_continuing); break; } sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_get_disc_capacity); break; } ulong totalSize = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) & 0xFFFFFFFF; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_get_PFI); break; } AaruLogging.Debug(MODULE_NAME, Localization.Core.Video_partition_total_size_0_sectors, totalSize); ulong l0Video = PFI.Decode(cmdBuf, MediaType).Value.Layer0EndPSN - PFI.Decode(cmdBuf, MediaType).Value.DataAreaStartPSN + 1; ulong l1Video = totalSize - l0Video + 1; // Get game partition size AaruLogging.Debug(MODULE_NAME, Localization.Core.Getting_game_partition_size); sense = dev.KreonUnlockXtreme(out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_unlock_drive_not_continuing); break; } sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_get_disc_capacity); return; } ulong gameSize = ((ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) & 0xFFFFFFFF) + 1; AaruLogging.Debug(MODULE_NAME, Localization.Core.Game_partition_total_size_0_sectors, gameSize); // Get middle zone size AaruLogging.Debug(MODULE_NAME, Localization.Core.Getting_middle_zone_size); sense = dev.KreonUnlockWxripper(out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_unlock_drive_not_continuing); break; } sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_get_disc_capacity); break; } totalSize = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) & 0xFFFFFFFF; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); if(sense) { AaruLogging.Error(Localization.Core.Cannot_get_PFI); break; } AaruLogging.Debug(MODULE_NAME, Localization.Core.Unlocked_total_size_0_sectors, totalSize); ulong middleZone = totalSize - (PFI.Decode(cmdBuf, MediaType).Value.Layer0EndPSN - PFI.Decode(cmdBuf, MediaType).Value.DataAreaStartPSN + 1) - gameSize + 1; totalSize = l0Video + l1Video + middleZone * 2 + gameSize; ulong layerBreak = l0Video + middleZone + gameSize / 2; XgdInfo = new XgdInfo { L0Video = l0Video, L1Video = l1Video, MiddleZone = middleZone, GameSize = gameSize, TotalSize = totalSize, LayerBreak = layerBreak }; } } break; #endregion Xbox case MediaType.Unknown: MediaType = MediaTypeFromDevice.GetFromScsi((byte)dev.ScsiType, dev.Manufacturer, dev.Model, scsiMediumType, scsiDensityCode, Blocks, BlockSize, dev.IsUsb, true); break; } if(MediaType == MediaType.Unknown && dev.IsUsb && containsFloppyPage) MediaType = MediaType.FlashDrive; if(MediaType == MediaType.Unknown && !dev.IsRemovable) MediaType = MediaType.GENERIC_HDD; if(DeviceInfo.ScsiType != PeripheralDeviceTypes.MultiMediaDevice || dev.IsUsb && scsiMediumType is 0x40 or 0x41 or 0x42) return; sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out _); if(sense) { AaruLogging.Debug(MODULE_NAME, Localization.Core.READ_DISC_INFORMATION_000b_0, Sense.PrettifySense(senseBuf.ToArray())); } else { DiscInformation = cmdBuf; DecodedDiscInformation = Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf); if(DecodedDiscInformation.HasValue) { if(MediaType == MediaType.CD) { MediaType = DecodedDiscInformation.Value.DiscType switch { 0x10 => MediaType.CDI, 0x20 => MediaType.CDROMXA, _ => MediaType }; } } } MediaType tmpType = MediaType; MMC.DetectDiscType(ref tmpType, sessions, FullToc, dev, out _, out _, firstTrackLastSession, Blocks); MediaType = tmpType; } /// Decoded DVD Pre-Recorded Information public PRI.PreRecordedInformation? DecodedDvdPrePitInformation { get; } /// Decoded recordable DVD Physical Format Information public PFI.PhysicalFormatInformation? DecodedDvdrPfi { get; } /// Raw media serial number public byte[] MediaSerialNumber { get; } /// Raw Xbox security sectors public byte[] XboxSecuritySector { get; } /// Decoded Xbox security sectors public SS.SecuritySector? DecodedXboxSecuritySector { get; } /// Information about an XGD, XGD2 or XGD3 media public XgdInfo XgdInfo { get; } /// MMC drive raw GET CONFIGURATION public byte[] MmcConfiguration { get; } /// Raw recognized format layers public byte[] RecognizedFormatLayers { get; } /// Raw write protection status public byte[] WriteProtectionStatus { get; } /// Raw DVD Physical Format Information public byte[] DvdPfi { get; } /// Decoded DVD Physical Format Information public PFI.PhysicalFormatInformation? DecodedPfi { get; } /// Raw DVD Disc Manufacturing Information public byte[] DvdDmi { get; } /// Raw DVD Copyright Management Information public byte[] DvdCmi { get; } /// Raw DVD Burst Cutting Area public byte[] DvdBca { get; } /// Raw DVD AACS information public byte[] DvdAacs { get; } /// Raw DVD-RAM Disc Definition Structure public byte[] DvdRamDds { get; } /// Raw DVD-RAM Cartridge Status public byte[] DvdRamCartridgeStatus { get; } /// Raw DVD-RAM Spare Area Information public byte[] DvdRamSpareArea { get; } /// Raw DVD-R(W) Last Border-Out RMD public byte[] LastBorderOutRmd { get; } /// Raw DVD-R(W) Pre-Recorded Information public byte[] DvdPreRecordedInfo { get; } /// Raw DVD-R Media ID public byte[] DvdrMediaIdentifier { get; } /// Raw recordable DVD Physical Format Information public byte[] DvdrPhysicalInformation { get; } /// Raw DVD+R(W) ADIP public byte[] DvdPlusAdip { get; } /// Raw DVD+R(W) Disc Control Blocks public byte[] DvdPlusDcb { get; } /// Raw HD DVD Copyright Management Information public byte[] HddvdCopyrightInformation { get; } /// Raw HD DVD-R Medium Status public byte[] HddvdrMediumStatus { get; } /// Raw HD DVD-R(W) Last Border-Out RMD public byte[] HddvdrLastRmd { get; } /// Raw DVD-R(W) Layer Capacity public byte[] DvdrLayerCapacity { get; } /// Raw DVD-R DL Middle Zone start public byte[] DvdrDlMiddleZoneStart { get; } /// Raw DVD-R DL Jump Interval size public byte[] DvdrDlJumpIntervalSize { get; } /// Raw DVD-R DL Manual Layer Jump Start LBA public byte[] DvdrDlManualLayerJumpStartLba { get; } /// Raw DVD-R DL Remap Anchor Point public byte[] DvdrDlRemapAnchorPoint { get; } /// Raw Blu-ray Disc Information public byte[] BlurayDiscInformation { get; } /// Raw Blu-ray PAC public byte[] BlurayPac { get; } /// Raw Blu-ray Burst Cutting Area public byte[] BlurayBurstCuttingArea { get; } /// Raw Blu-ray Disc Definition Structure public byte[] BlurayDds { get; } /// Raw Blu-ray Cartridge Status public byte[] BlurayCartridgeStatus { get; } /// Raw Blu-ray Spare Area Information public byte[] BluraySpareAreaInformation { get; } /// Raw Blu-ray DFL public byte[] BlurayRawDfl { get; } /// Raw Blu-ray Pseudo OverWrite Resources public byte[] BlurayPowResources { get; } /// Raw READ TOC response public byte[] Toc { get; } /// Raw READ ATIP response public byte[] Atip { get; } /// Raw READ DISC INFORMATION response public byte[] DiscInformation { get; } /// Raw READ SESSION response public byte[] Session { get; } /// Raw READ FULL TOC response public byte[] RawToc { get; } /// Raw READ PMA response public byte[] Pma { get; } /// Raw Lead-In's CD-TEXT response public byte[] CdTextLeadIn { get; } /// Decoded READ TOC response public TOC.CDTOC? DecodedToc { get; } /// Decoded READ ATIP response public ATIP.CDATIP DecodedAtip { get; } /// Decoded READ SESSION response public Session.CDSessionInfo? DecodedSession { get; } /// Decoded READ FULL TOC response public FullTOC.CDFullTOC? FullToc { get; } /// Decoded Lead-In CD-TEXT response public CDTextOnLeadIn.CDText? DecodedCdTextLeadIn { get; } /// Raw Blu-ray track resources public byte[] BlurayTrackResources { get; } /// Decoded Blu-ray Disc Information public DiscInformation.StandardDiscInformation? DecodedDiscInformation { get; } /// Decoded Media Catalogue Number public string Mcn { get; } /// List of decoded track ISRCs public Dictionary Isrcs { get; } /// Set if media is inserted in drive public bool MediaInserted { get; } /// Detected media type public MediaType MediaType { get; } /// Device information public DeviceInfo DeviceInfo { get; } /// Raw READ CAPACITY(10) response public byte[] ReadCapacity { get; } /// Number of blocks in media public ulong Blocks { get; } /// Logical block size public uint BlockSize { get; } /// Raw READ CAPACITY(16) response public byte[] ReadCapacity16 { get; } /// Raw SSC Density support public byte[] DensitySupport { get; } /// Decoded SSC Density support public DensitySupport.DensitySupportHeader? DensitySupportHeader { get; } /// Raw SSC media support public byte[] MediaTypeSupport { get; } /// Decoded SSC media support public DensitySupport.MediaTypeSupportHeader? MediaTypeSupportHeader { get; } /// Raw data from DVD sector Copyright Management Information public byte[] DvdSectorCmi { get; } /// Raw DVD Disc Key public byte[] DvdDiscKey { get; } }