/// <summary>Dumps an optical disc</summary> void Mmc() { MediaType dskType = MediaType.Unknown; bool sense; byte[] tmpBuf; bool compactDisc = true; bool gotConfiguration = false; bool isXbox = false; DVDDecryption dvdDecrypt = null; _speedMultiplier = 1; // TODO: Log not only what is it reading, but if it was read correctly or not. sense = _dev.GetConfiguration(out byte[] cmdBuf, out _, 0, MmcGetConfigurationRt.Current, _dev.Timeout, out _); if (!sense) { gotConfiguration = true; Features.SeparatedFeatures ftr = Features.Separate(cmdBuf); _dumpLog.WriteLine("Device reports current profile is 0x{0:X4}", ftr.CurrentProfile); switch (ftr.CurrentProfile) { case 0x0001: dskType = MediaType.GENERIC_HDD; _speedMultiplier = -1; goto default; case 0x0002: dskType = MediaType.PD650; _speedMultiplier = -1; 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; _speedMultiplier = 9; goto default; case 0x0011: dskType = MediaType.DVDR; _speedMultiplier = 9; goto default; case 0x0012: dskType = MediaType.DVDRAM; _speedMultiplier = 9; goto default; case 0x0013: case 0x0014: dskType = MediaType.DVDRW; _speedMultiplier = 9; goto default; case 0x0015: case 0x0016: dskType = MediaType.DVDRDL; _speedMultiplier = 9; goto default; case 0x0017: dskType = MediaType.DVDRWDL; _speedMultiplier = 9; goto default; case 0x0018: dskType = MediaType.DVDDownload; _speedMultiplier = 9; goto default; case 0x001A: dskType = MediaType.DVDPRW; _speedMultiplier = 9; goto default; case 0x001B: dskType = MediaType.DVDPR; _speedMultiplier = 9; 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; _speedMultiplier = 9; goto default; case 0x002B: dskType = MediaType.DVDPRDL; _speedMultiplier = 9; goto default; case 0x0040: dskType = MediaType.BDROM; _speedMultiplier = 30; goto default; case 0x0041: case 0x0042: dskType = MediaType.BDR; _speedMultiplier = 30; goto default; case 0x0043: dskType = MediaType.BDRE; _speedMultiplier = 30; goto default; case 0x0050: dskType = MediaType.HDDVDROM; _speedMultiplier = 30; goto default; case 0x0051: dskType = MediaType.HDDVDR; _speedMultiplier = 30; goto default; case 0x0052: dskType = MediaType.HDDVDRAM; _speedMultiplier = 30; goto default; case 0x0053: dskType = MediaType.HDDVDRW; _speedMultiplier = 30; goto default; case 0x0058: dskType = MediaType.HDDVDRDL; _speedMultiplier = 30; goto default; case 0x005A: dskType = MediaType.HDDVDRWDL; _speedMultiplier = 30; goto default; default: compactDisc = false; break; } } Modes.DecodedMode?decMode = null; sense = _dev.ModeSense6(out cmdBuf, out _, true, ScsiModeSensePageControl.Current, 0x00, _dev.Timeout, out _); if (sense || _dev.Error) { sense = _dev.ModeSense6(out cmdBuf, out _, false, ScsiModeSensePageControl.Current, 0x00, _dev.Timeout, out _); if (!sense && !_dev.Error) { decMode = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); } } else { decMode = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); } if (decMode is null) { sense = _dev.ModeSense10(out cmdBuf, out _, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, _dev.Timeout, out _); if (sense || _dev.Error) { sense = _dev.ModeSense10(out cmdBuf, out _, false, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, _dev.Timeout, out _); if (sense || _dev.Error) { sense = _dev.ModeSense10(out cmdBuf, out _, false, true, ScsiModeSensePageControl.Current, 0x00, 0x00, _dev.Timeout, out _); if (sense || _dev.Error) { sense = _dev.ModeSense10(out cmdBuf, out _, false, false, ScsiModeSensePageControl.Current, 0x00, 0x00, _dev.Timeout, out _); if (!sense && !_dev.Error) { decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); } } else { decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); } } else { decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); } } else { decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); } } if (decMode.HasValue && _dev.IsUsb && !gotConfiguration && (decMode.Value.Header.MediumType == MediumTypes.UnknownBlockDevice || decMode.Value.Header.MediumType == MediumTypes.ReadOnlyBlockDevice || decMode.Value.Header.MediumType == MediumTypes.ReadWriteBlockDevice)) { _speedMultiplier = -1; Sbc(null, MediaType.Unknown, false); return; } if (compactDisc) { _speedMultiplier *= 177; CompactDisc(); return; } _speedMultiplier *= 150; var scsiReader = new Reader(_dev, _dev.Timeout, null, _errorLog, _dumpRaw); ulong blocks = scsiReader.GetDeviceBlocks(); _dumpLog.WriteLine("Device reports disc has {0} blocks", blocks); Dictionary <MediaTagType, byte[]> mediaTags = new Dictionary <MediaTagType, byte[]>(); if (dskType == MediaType.PD650) { switch (blocks + 1) { case 1281856: dskType = MediaType.PD650_WORM; break; case 58620544: dskType = MediaType.REV120; break; case 17090880: dskType = MediaType.REV35; break; case 34185728: dskType = MediaType.REV70; break; } } #region Nintendo switch (dskType) { case MediaType.Unknown when blocks > 0: _dumpLog.WriteLine("Reading Physical Format Information"); sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, _dev.Timeout, out _); if (!sense) { PFI.PhysicalFormatInformation?nintendoPfi = PFI.Decode(cmdBuf); if (nintendoPfi?.DiskCategory == DiskCategory.Nintendo && nintendoPfi.Value.PartVersion == 15) { _dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented."); StoppingErrorMessage?. Invoke("Dumping Nintendo GameCube or Wii discs is not yet implemented."); return; } } break; case MediaType.DVDDownload: case MediaType.DVDPR: case MediaType.DVDPRDL: case MediaType.DVDPRW: case MediaType.DVDPRWDL: case MediaType.DVDR: case MediaType.DVDRAM: case MediaType.DVDRDL: case MediaType.DVDROM: case MediaType.DVDRW: case MediaType.DVDRWDL: case MediaType.HDDVDR: case MediaType.HDDVDRAM: case MediaType.HDDVDRDL: case MediaType.HDDVDROM: case MediaType.HDDVDRW: case MediaType.HDDVDRWDL: _dumpLog.WriteLine("Reading Physical Format Information"); sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, _dev.Timeout, out _); if (!sense) { if (PFI.Decode(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.DVD_PFI, tmpBuf); PFI.PhysicalFormatInformation decPfi = PFI.Decode(cmdBuf).Value; UpdateStatus?.Invoke($"PFI:\n{PFI.Prettify(decPfi)}"); // False book types switch (decPfi.DiskCategory) { case DiskCategory.DVDPR: dskType = MediaType.DVDPR; break; case DiskCategory.DVDPRDL: dskType = MediaType.DVDPRDL; break; case DiskCategory.DVDPRW: dskType = MediaType.DVDPRW; break; case DiskCategory.DVDPRWDL: dskType = MediaType.DVDPRWDL; break; case DiskCategory.DVDR: dskType = decPfi.PartVersion >= 6 ? MediaType.DVDRDL : MediaType.DVDR; break; case DiskCategory.DVDRAM: dskType = MediaType.DVDRAM; break; default: dskType = MediaType.DVDROM; break; case DiskCategory.DVDRW: dskType = decPfi.PartVersion >= 15 ? MediaType.DVDRWDL : MediaType.DVDRW; break; case DiskCategory.HDDVDR: dskType = MediaType.HDDVDR; break; case DiskCategory.HDDVDRAM: dskType = MediaType.HDDVDRAM; break; case DiskCategory.HDDVDROM: dskType = MediaType.HDDVDROM; break; case DiskCategory.HDDVDRW: dskType = MediaType.HDDVDRW; break; case DiskCategory.Nintendo: dskType = decPfi.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; break; case DiskCategory.UMD: dskType = MediaType.UMD; break; } } } _dumpLog.WriteLine("Reading Disc Manufacturing Information"); sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, _dev.Timeout, out _); if (!sense) { if (DMI.IsXbox(cmdBuf) || DMI.IsXbox360(cmdBuf)) { if (DMI.IsXbox(cmdBuf)) { dskType = MediaType.XGD; } else if (DMI.IsXbox360(cmdBuf)) { dskType = MediaType.XGD2; // All XGD3 all have the same number of blocks if (blocks + 1 == 25063 || // Locked (or non compatible drive) blocks + 1 == 4229664 || // Xtreme unlock blocks + 1 == 4246304) // Wxripper unlock { dskType = MediaType.XGD3; } } isXbox = true; sense = _dev.ScsiInquiry(out byte[] inqBuf, out _); if (sense || !Inquiry.Decode(inqBuf).HasValue || (Inquiry.Decode(inqBuf).HasValue&& !Inquiry.Decode(inqBuf).Value.KreonPresent)) { _dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware."); StoppingErrorMessage?. Invoke("Dumping Xbox Game Discs requires a drive with Kreon firmware."); if (!_force) { return; } isXbox = false; } if (_dumpRaw && !_force) { StoppingErrorMessage?. Invoke("Not continuing. If you want to continue reading cooked data when raw is not available use the force option."); // TODO: Exit more gracefully return; } } if (cmdBuf.Length == 2052) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.DVD_DMI, tmpBuf); } } break; } #endregion Nintendo #region All DVD and HD DVD types #endregion All DVD and HD DVD types #region DVD-ROM if (dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM) { _dumpLog.WriteLine("Reading Lead-in Copyright Information."); sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, _dev.Timeout, out _); if (!sense) { if (CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.DVD_CMI, tmpBuf); CSS_CPRM.LeadInCopyright?cmi = CSS_CPRM.DecodeLeadInCopyright(cmdBuf); if (cmi !.Value.CopyrightType == CopyrightType.NoProtection) { UpdateStatus?.Invoke("Drive reports no copy protection on disc."); } else { if (!Settings.Settings.Current.EnableDecryption) { UpdateStatus?.Invoke("Drive reports the disc uses copy protection. " + "The dump will be incorrect unless decryption is enabled."); } else { if (cmi !.Value.CopyrightType == CopyrightType.CSS) { UpdateStatus?.Invoke("Drive reports disc uses CSS copy protection."); dvdDecrypt = new DVDDecryption(_dev); sense = dvdDecrypt.ReadBusKey(out cmdBuf, out _, CSS_CPRM.DecodeLeadInCopyright(cmdBuf) !.Value. CopyrightType, _dev.Timeout, out _); if (!sense) { byte[] busKey = cmdBuf; UpdateStatus?.Invoke("Reading disc key."); sense = dvdDecrypt.ReadDiscKey(out cmdBuf, out _, _dev.Timeout, out _); if (!sense) { CSS_CPRM.DiscKey?decodedDiscKey = CSS.DecodeDiscKey(cmdBuf, busKey); sense = dvdDecrypt.ReadAsf(out cmdBuf, out _, DvdCssKeyClass.DvdCssCppmOrCprm, _dev.Timeout, out _); if (!sense) { if (cmdBuf[7] == 1) { UpdateStatus?.Invoke("Disc and drive authentication succeeded."); sense = dvdDecrypt.ReadRpc(out cmdBuf, out _, DvdCssKeyClass.DvdCssCppmOrCprm, _dev.Timeout, out _); if (!sense) { CSS_CPRM.RegionalPlaybackControlState?rpc = CSS_CPRM.DecodeRegionalPlaybackControlState(cmdBuf); if (rpc.HasValue) { UpdateStatus?.Invoke(CSS.CheckRegion(rpc.Value, cmi.Value) ? "Disc and drive regions match." : "Disc and drive regions do not match. The dump will be incorrect"); } } if (decodedDiscKey.HasValue) { mediaTags.Add(MediaTagType.DVD_DiscKey, decodedDiscKey.Value.Key); UpdateStatus?.Invoke("Decrypting disc key."); CSS.DecryptDiscKey(decodedDiscKey.Value.Key, out byte[] discKey); if (discKey != null) { UpdateStatus?.Invoke("Decryption of disc key succeeded."); mediaTags.Add(MediaTagType.DVD_DiscKey_Decrypted, discKey); } else { UpdateStatus?.Invoke("Decryption of disc key failed."); } } } } } } } else { UpdateStatus?. Invoke($"Drive reports disc uses {CSS_CPRM.DecodeLeadInCopyright(cmdBuf)!.Value.CopyrightType.ToString()} copy protection. " + "This is not yet supported and the dump will be incorrect."); } } }
public DeviceInfo(Device dev) { Type = dev.Type; Manufacturer = dev.Manufacturer; Model = dev.Model; FirmwareRevision = dev.FirmwareRevision; Serial = dev.Serial; ScsiType = dev.ScsiType; IsRemovable = dev.IsRemovable; IsUsb = dev.IsUsb; UsbVendorId = dev.UsbVendorId; UsbProductId = dev.UsbProductId; UsbDescriptors = dev.UsbDescriptors; UsbManufacturerString = dev.UsbManufacturerString; UsbProductString = dev.UsbProductString; UsbSerialString = dev.UsbSerialString; IsFireWire = dev.IsFireWire; FireWireGuid = dev.FireWireGuid; FireWireModel = dev.FireWireModel; FireWireModelName = dev.FireWireModelName; FireWireVendor = dev.FireWireVendor; FireWireVendorName = dev.FireWireVendorName; IsCompactFlash = dev.IsCompactFlash; IsPcmcia = dev.IsPcmcia; Cis = dev.Cis; switch (dev.Type) { case DeviceType.ATA: { bool sense = dev.AtaIdentify(out byte[] ataBuf, out AtaErrorRegistersChs errorRegisters); if (sense) { AaruConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.Status); AaruConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.Error); AaruConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}", errorRegisters.SectorCount); AaruConsole.DebugWriteLine("Device-Info command", "SECTOR = 0x{0:X2}", errorRegisters.Sector); AaruConsole.DebugWriteLine("Device-Info command", "CYLHIGH = 0x{0:X2}", errorRegisters.CylinderHigh); AaruConsole.DebugWriteLine("Device-Info command", "CYLLOW = 0x{0:X2}", errorRegisters.CylinderLow); AaruConsole.DebugWriteLine("Device-Info command", "DEVICE = 0x{0:X2}", errorRegisters.DeviceHead); AaruConsole.DebugWriteLine("Device-Info command", "Error code = {0}", dev.LastError); break; } if (dev.Error) { AaruConsole.ErrorWriteLine("Error {0} querying ATA IDENTIFY", dev.LastError); break; } AtaIdentify = ataBuf; dev.EnableMediaCardPassThrough(out errorRegisters, dev.Timeout, out _); if (errorRegisters.Sector == 0xAA && errorRegisters.SectorCount == 0x55) { AtaMcptError = errorRegisters; } break; } case DeviceType.ATAPI: { bool sense = dev.AtapiIdentify(out byte[] ataBuf, out AtaErrorRegistersChs errorRegisters); if (sense) { AaruConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.Status); AaruConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.Error); AaruConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}", errorRegisters.SectorCount); AaruConsole.DebugWriteLine("Device-Info command", "SECTOR = 0x{0:X2}", errorRegisters.Sector); AaruConsole.DebugWriteLine("Device-Info command", "CYLHIGH = 0x{0:X2}", errorRegisters.CylinderHigh); AaruConsole.DebugWriteLine("Device-Info command", "CYLLOW = 0x{0:X2}", errorRegisters.CylinderLow); AaruConsole.DebugWriteLine("Device-Info command", "DEVICE = 0x{0:X2}", errorRegisters.DeviceHead); AaruConsole.DebugWriteLine("Device-Info command", "Error code = {0}", dev.LastError); break; } if (!dev.Error) { AtapiIdentify = ataBuf; } else { AaruConsole.ErrorWriteLine("Error {0} querying ATA PACKET IDENTIFY", dev.LastError); } // ATAPI devices are also SCSI devices goto case DeviceType.SCSI; } case DeviceType.SCSI: { bool sense = dev.ScsiInquiry(out byte[] inqBuf, out byte[] senseBuf); if (sense) { AaruConsole.ErrorWriteLine("SCSI error:\n{0}", Sense.PrettifySense(senseBuf)); break; } ScsiInquiryData = inqBuf; ScsiInquiry = Inquiry.Decode(inqBuf); sense = dev.ScsiInquiry(out inqBuf, out senseBuf, 0x00); if (!sense) { ScsiEvpdPages = new Dictionary <byte, byte[]>(); byte[] pages = EVPD.DecodePage00(inqBuf); if (pages != null) { foreach (byte page in pages) { sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); if (sense) { continue; } ScsiEvpdPages.Add(page, inqBuf); } } } var devType = (PeripheralDeviceTypes)ScsiInquiry.Value.PeripheralDeviceType; sense = dev.ModeSense10(out byte[] modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out _); if (!sense && !dev.Error) { ScsiModeSense10 = modeBuf; } if (sense || dev.Error) { sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out _); if (!sense && !dev.Error) { ScsiModeSense10 = modeBuf; } } if (!sense && !dev.Error) { ScsiMode = Modes.DecodeMode10(modeBuf, devType); } bool useMode10 = !(sense || dev.Error || !ScsiMode.HasValue); sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out _); if (!sense && !dev.Error) { ScsiModeSense6 = modeBuf; } if (sense || dev.Error) { sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out _); if (!sense && !dev.Error) { ScsiModeSense6 = modeBuf; } } if (sense || dev.Error) { sense = dev.ModeSense(out modeBuf, out senseBuf, 5, out _); if (!sense && !dev.Error) { ScsiModeSense6 = modeBuf; } } if (!sense && !dev.Error && !useMode10) { ScsiMode = Modes.DecodeMode6(modeBuf, devType); } switch (devType) { case PeripheralDeviceTypes.MultiMediaDevice: { sense = dev.GetConfiguration(out byte[] confBuf, out senseBuf, dev.Timeout, out _); if (!sense) { MmcConfiguration = confBuf; } var dvdDecrypt = new DVDDecryption(dev); sense = dvdDecrypt.ReadRpc(out byte[] cmdBuf, out _, DvdCssKeyClass.DvdCssCppmOrCprm, dev.Timeout, out _); if (!sense) { CSS_CPRM.RegionalPlaybackControlState?rpc = CSS_CPRM.DecodeRegionalPlaybackControlState(cmdBuf); if (rpc.HasValue) { RPC = rpc; } } // TODO: DVD drives respond correctly to BD status. // While specification says if no medium is present // it should inform all possible capabilities, // testing drives show only supported media capabilities. /* * byte[] strBuf; * sense = dev.ReadDiscStructure(out strBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _); * * if (!sense) * { * Decoders.SCSI.DiscStructureCapabilities.Capability[] caps = Decoders.SCSI.DiscStructureCapabilities.Decode(strBuf); * if (caps != null) * { * foreach (Decoders.SCSI.DiscStructureCapabilities.Capability cap in caps) * { * if (cap.SDS && cap.RDS) * AaruConsole.WriteLine("Drive can READ/SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.SDS) * AaruConsole.WriteLine("Drive can SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.RDS) * AaruConsole.WriteLine("Drive can READ DISC STRUCTURE format {0:X2}h", cap.FormatCode); * } * } * } * * sense = dev.ReadDiscStructure(out strBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _); * * if (!sense) * { * Decoders.SCSI.DiscStructureCapabilities.Capability[] caps = Decoders.SCSI.DiscStructureCapabilities.Decode(strBuf); * if (caps != null) * { * foreach (Decoders.SCSI.DiscStructureCapabilities.Capability cap in caps) * { * if (cap.SDS && cap.RDS) * AaruConsole.WriteLine("Drive can READ/SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.SDS) * AaruConsole.WriteLine("Drive can SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.RDS) * AaruConsole.WriteLine("Drive can READ DISC STRUCTURE format {0:X2}h", cap.FormatCode); * } * } * } */ #region Plextor if (dev.Manufacturer == "PLEXTOR") { bool plxtSense = true; bool plxtDvd = false; byte[] plxtBuf = null; switch (dev.Model) { case "DVDR PX-708A": case "DVDR PX-708A2": case "DVDR PX-712A": plxtDvd = true; plxtSense = dev.PlextorReadEeprom(out plxtBuf, out senseBuf, dev.Timeout, out _); break; case "DVDR PX-714A": case "DVDR PX-716A": case "DVDR PX-716AL": case "DVDR PX-755A": case "DVDR PX-760A": { plxtBuf = new byte[256 * 4]; for (byte i = 0; i < 4; i++) { plxtSense = dev.PlextorReadEepromBlock(out byte[] plxtBufSmall, out senseBuf, i, 256, dev.Timeout, out _); if (plxtSense) { break; } Array.Copy(plxtBufSmall, 0, plxtBuf, i * 256, 256); } plxtDvd = true; break; } default: { if (dev.Model.StartsWith("CD-R ", StringComparison.Ordinal)) { plxtSense = dev.PlextorReadEepromCdr(out plxtBuf, out senseBuf, dev.Timeout, out _); } break; } } PlextorFeatures = new Plextor { IsDvd = plxtDvd }; if (!plxtSense) { PlextorFeatures.Eeprom = plxtBuf; if (plxtDvd) { PlextorFeatures.Discs = BigEndianBitConverter.ToUInt16(plxtBuf, 0x0120); PlextorFeatures.CdReadTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x0122); PlextorFeatures.CdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x0126); PlextorFeatures.DvdReadTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x012A); PlextorFeatures.DvdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x012E); } else { PlextorFeatures.Discs = BigEndianBitConverter.ToUInt16(plxtBuf, 0x0078); PlextorFeatures.CdReadTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x006C); PlextorFeatures.CdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x007A); } } plxtSense = dev.PlextorGetPoweRec(out senseBuf, out bool plxtPwrRecEnabled, out ushort plxtPwrRecSpeed, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.PoweRec = true; if (plxtPwrRecEnabled) { PlextorFeatures.PoweRecEnabled = true; PlextorFeatures.PoweRecRecommendedSpeed = plxtPwrRecSpeed; plxtSense = dev.PlextorGetSpeeds(out senseBuf, out ushort plxtPwrRecSelected, out ushort plxtPwrRecMax, out ushort plxtPwrRecLast, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.PoweRecSelected = plxtPwrRecSelected; PlextorFeatures.PoweRecMax = plxtPwrRecMax; PlextorFeatures.PoweRecLast = plxtPwrRecLast; } } } // TODO: Check it with a drive plxtSense = dev.PlextorGetSilentMode(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { if (plxtBuf[0] == 1) { PlextorFeatures.SilentModeEnabled = true; PlextorFeatures.AccessTimeLimit = plxtBuf[1]; PlextorFeatures.CdReadSpeedLimit = plxtBuf[2]; PlextorFeatures.DvdReadSpeedLimit = plxtBuf[3]; PlextorFeatures.CdWriteSpeedLimit = plxtBuf[4]; // TODO: Check which one is each one /* * if(plxtBuf[6] > 0) * AaruConsole.WriteLine("\tTray eject speed limited to {0}", * -(plxtBuf[6] + 48)); * if(plxtBuf[7] > 0) * AaruConsole.WriteLine("\tTray eject speed limited to {0}", * plxtBuf[7] - 47); */ } } plxtSense = dev.PlextorGetGigaRec(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.GigaRec = true; } plxtSense = dev.PlextorGetSecuRec(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.SecuRec = true; } plxtSense = dev.PlextorGetSpeedRead(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.SpeedRead = true; if ((plxtBuf[2] & 0x01) == 0x01) { PlextorFeatures.SpeedReadEnabled = true; } } plxtSense = dev.PlextorGetHiding(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.Hiding = true; if ((plxtBuf[2] & 0x02) == 0x02) { PlextorFeatures.HidesRecordables = true; } if ((plxtBuf[2] & 0x01) == 0x01) { PlextorFeatures.HidesSessions = true; } } plxtSense = dev.PlextorGetVariRec(out plxtBuf, out senseBuf, false, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.VariRec = true; } if (plxtDvd) { plxtSense = dev.PlextorGetVariRec(out plxtBuf, out senseBuf, true, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.VariRecDvd = true; } plxtSense = dev.PlextorGetBitsetting(out plxtBuf, out senseBuf, false, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.BitSetting = true; } plxtSense = dev.PlextorGetBitsetting(out plxtBuf, out senseBuf, true, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.BitSettingDl = true; } plxtSense = dev.PlextorGetTestWriteDvdPlus(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.DvdPlusWriteTest = true; } } } #endregion Plextor if (ScsiInquiry.Value.KreonPresent) { if (!dev.KreonGetFeatureList(out senseBuf, out KreonFeatures krFeatures, dev.Timeout, out _)) { KreonFeatures = krFeatures; } } break; } case PeripheralDeviceTypes.SequentialAccess: { sense = dev.ReadBlockLimits(out byte[] seqBuf, out senseBuf, dev.Timeout, out _); if (sense) { AaruConsole.ErrorWriteLine("READ BLOCK LIMITS:\n{0}", Sense.PrettifySense(senseBuf)); } else { BlockLimits = seqBuf; } sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, dev.Timeout, out _); if (sense) { AaruConsole.ErrorWriteLine("REPORT DENSITY SUPPORT:\n{0}", Sense.PrettifySense(senseBuf)); } else { DensitySupport = seqBuf; DensitySupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(seqBuf); } sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, true, false, dev.Timeout, out _); if (sense) { AaruConsole.ErrorWriteLine("REPORT DENSITY SUPPORT (MEDIUM):\n{0}", Sense.PrettifySense(senseBuf)); } else { MediumDensitySupport = seqBuf; MediaTypeSupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(seqBuf); } break; } } break; } case DeviceType.MMC: { bool sense = dev.ReadCid(out byte[] mmcBuf, out _, dev.Timeout, out _); if (!sense) { CID = mmcBuf; } sense = dev.ReadCsd(out mmcBuf, out _, dev.Timeout, out _); if (!sense) { CSD = mmcBuf; } sense = dev.ReadOcr(out mmcBuf, out _, dev.Timeout, out _); if (!sense) { OCR = mmcBuf; } sense = dev.ReadExtendedCsd(out mmcBuf, out _, dev.Timeout, out _); if (!sense && !ArrayHelpers.ArrayIsNullOrEmpty(mmcBuf)) { ExtendedCSD = mmcBuf; } } break; case DeviceType.SecureDigital: { bool sense = dev.ReadCid(out byte[] sdBuf, out _, dev.Timeout, out _); if (!sense) { CID = sdBuf; } sense = dev.ReadCsd(out sdBuf, out _, dev.Timeout, out _); if (!sense) { CSD = sdBuf; } sense = dev.ReadSdocr(out sdBuf, out _, dev.Timeout, out _); if (!sense) { OCR = sdBuf; } sense = dev.ReadScr(out sdBuf, out _, dev.Timeout, out _); if (!sense) { SCR = sdBuf; } } break; default: AaruConsole.ErrorWriteLine("Unknown device type {0}, cannot get information.", dev.Type); break; } }