// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : ScsiMmc.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.Metadata; using System.Collections.Generic; namespace DiscImageChef.Server.App_Start { public static class ScsiMmc { public static void Report(mmcType mmc, ref List mmcOneValue, ref testedMediaType[] testedMedia) { testedMedia = mmc.TestedMedia; if(mmc.ModeSense2A != null) { if(mmc.ModeSense2A.PlaysAudio) mmcOneValue.Add("Drive can play audio"); if(mmc.ModeSense2A.ReadsMode2Form1) mmcOneValue.Add("Drive can read sectors in Mode 2 Form 1 format"); if(mmc.ModeSense2A.ReadsMode2Form2) mmcOneValue.Add("Drive can read sectors in Mode 2 Form 2 format"); if(mmc.ModeSense2A.SupportsMultiSession) mmcOneValue.Add("Drive supports multi-session discs and/or Photo-CD"); if(mmc.ModeSense2A.CDDACommand) mmcOneValue.Add("Drive can read digital audio"); if(mmc.ModeSense2A.AccurateCDDA) mmcOneValue.Add("Drive can continue from streaming loss"); if(mmc.ModeSense2A.ReadsSubchannel) mmcOneValue.Add("Drive can read uncorrected and interleaved R-W subchannels"); if(mmc.ModeSense2A.ReadsDeinterlavedSubchannel) mmcOneValue.Add("Drive can read, deinterleave and correct R-W subchannels"); if(mmc.ModeSense2A.ReturnsC2Pointers) mmcOneValue.Add("Drive supports C2 pointers"); if(mmc.ModeSense2A.ReadsUPC) mmcOneValue.Add("Drive can read Media Catalogue Number"); if(mmc.ModeSense2A.ReadsISRC) mmcOneValue.Add("Drive can read ISRC"); switch(mmc.ModeSense2A.LoadingMechanismType) { case 0: mmcOneValue.Add("Drive uses media caddy"); break; case 1: mmcOneValue.Add("Drive uses a tray"); break; case 2: mmcOneValue.Add("Drive is pop-up"); break; case 4: mmcOneValue.Add("Drive is a changer with individually changeable discs"); break; case 5: mmcOneValue.Add("Drive is a changer using cartridges"); break; default: mmcOneValue.Add(string.Format("Drive uses unknown loading mechanism type {0}", mmc.ModeSense2A.LoadingMechanismType)); break; } if(mmc.ModeSense2A.CanLockMedia) mmcOneValue.Add("Drive can lock media"); if(mmc.ModeSense2A.PreventJumperStatus) { mmcOneValue.Add("Drive power ups locked"); if(mmc.ModeSense2A.LockStatus) mmcOneValue.Add("Drive is locked, media cannot be ejected or inserted"); else mmcOneValue.Add("Drive is not locked, media can be ejected and inserted"); } else { if(mmc.ModeSense2A.LockStatus) mmcOneValue.Add("Drive is locked, media cannot be ejected, but if empty, can be inserted"); else mmcOneValue.Add("Drive is not locked, media can be ejected and inserted"); } if(mmc.ModeSense2A.CanEject) mmcOneValue.Add("Drive can eject media"); if(mmc.ModeSense2A.SeparateChannelMute) mmcOneValue.Add("Each channel can be muted independently"); if(mmc.ModeSense2A.SeparateChannelVolume) mmcOneValue.Add("Each channel's volume can be controlled independently"); if(mmc.ModeSense2A.SupportedVolumeLevels > 0) mmcOneValue.Add(string.Format("Drive supports {0} volume levels", mmc.ModeSense2A.SupportedVolumeLevels)); if(mmc.ModeSense2A.BufferSize > 0) mmcOneValue.Add(string.Format("Drive has {0} Kbyte of buffer", mmc.ModeSense2A.BufferSize)); if(mmc.ModeSense2A.MaximumSpeed > 0) mmcOneValue.Add(string.Format("Drive's maximum reading speed is {0} Kbyte/sec.", mmc.ModeSense2A.MaximumSpeed)); if(mmc.ModeSense2A.CurrentSpeed > 0) mmcOneValue.Add(string.Format("Drive's current reading speed is {0} Kbyte/sec.", mmc.ModeSense2A.CurrentSpeed)); if(mmc.ModeSense2A.ReadsCDR) { if(mmc.ModeSense2A.WritesCDR) mmcOneValue.Add("Drive can read and write CD-R"); else mmcOneValue.Add("Drive can read CD-R"); if(mmc.ModeSense2A.ReadsPacketCDR) mmcOneValue.Add("Drive supports reading CD-R packet media"); } if(mmc.ModeSense2A.ReadsCDRW) { if(mmc.ModeSense2A.WritesCDRW) mmcOneValue.Add("Drive can read and write CD-RW"); else mmcOneValue.Add("Drive can read CD-RW"); } if(mmc.ModeSense2A.ReadsDVDROM) mmcOneValue.Add("Drive can read DVD-ROM"); if(mmc.ModeSense2A.ReadsDVDR) { if(mmc.ModeSense2A.WritesDVDR) mmcOneValue.Add("Drive can read and write DVD-R"); else mmcOneValue.Add("Drive can read DVD-R"); } if(mmc.ModeSense2A.ReadsDVDRAM) { if(mmc.ModeSense2A.WritesDVDRAM) mmcOneValue.Add("Drive can read and write DVD-RAM"); else mmcOneValue.Add("Drive can read DVD-RAM"); } if(mmc.ModeSense2A.CompositeAudioVideo) mmcOneValue.Add("Drive can deliver a composite audio and video data stream"); if(mmc.ModeSense2A.DigitalPort1) mmcOneValue.Add("Drive supports IEC-958 digital output on port 1"); if(mmc.ModeSense2A.DigitalPort2) mmcOneValue.Add("Drive supports IEC-958 digital output on port 2"); if(mmc.ModeSense2A.DeterministicSlotChanger) mmcOneValue.Add("Drive contains a changer that can report the exact contents of the slots"); if(mmc.ModeSense2A.CurrentWriteSpeedSelected > 0) { if(mmc.ModeSense2A.RotationControlSelected == 0) mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec. in CLV mode", mmc.ModeSense2A.CurrentWriteSpeedSelected)); else if(mmc.ModeSense2A.RotationControlSelected == 1) mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec. in pure CAV mode", mmc.ModeSense2A.CurrentWriteSpeedSelected)); } else { if(mmc.ModeSense2A.MaximumWriteSpeed > 0) mmcOneValue.Add(string.Format("Drive's maximum writing speed is {0} Kbyte/sec.", mmc.ModeSense2A.MaximumWriteSpeed)); if(mmc.ModeSense2A.CurrentWriteSpeed > 0) mmcOneValue.Add(string.Format("Drive's current writing speed is {0} Kbyte/sec.", mmc.ModeSense2A.CurrentWriteSpeed)); } if(mmc.ModeSense2A.WriteSpeedPerformanceDescriptors != null) { foreach(Decoders.SCSI.Modes.ModePage_2A_WriteDescriptor descriptor in mmc.ModeSense2A.WriteSpeedPerformanceDescriptors) { if(descriptor.WriteSpeed > 0) { if(descriptor.RotationControl == 0) mmcOneValue.Add(string.Format("Drive supports writing at {0} Kbyte/sec. in CLV mode", descriptor.WriteSpeed)); else if(descriptor.RotationControl == 1) mmcOneValue.Add(string.Format("Drive supports writing at is {0} Kbyte/sec. in pure CAV mode", descriptor.WriteSpeed)); } } } if(mmc.ModeSense2A.TestWrite) mmcOneValue.Add("Drive supports test writing"); if(mmc.ModeSense2A.ReadsBarcode) mmcOneValue.Add("Drive can read barcode"); if(mmc.ModeSense2A.ReadsBothSides) mmcOneValue.Add("Drive can read both sides of a disc"); if(mmc.ModeSense2A.LeadInPW) mmcOneValue.Add("Drive an read raw R-W subchannel from the Lead-In"); if(mmc.ModeSense2A.CSSandCPPMSupported) mmcOneValue.Add("Drive supports DVD CSS and/or DVD CPPM"); if(mmc.ModeSense2A.BufferUnderRunProtection) mmcOneValue.Add("Drive supports buffer under-run free recording"); } if(mmc.Features != null) { sb.AppendLine("MMC Core Feature:"); sb.Append("\tDrive uses "); switch(ftr.PhysicalInterfaceStandard) { case PhysicalInterfaces.Unspecified: sb.AppendLine("an unspecified physical interface"); break; case PhysicalInterfaces.SCSI: sb.AppendLine("SCSI interface"); break; case PhysicalInterfaces.ATAPI: sb.AppendLine("ATAPI interface"); break; case PhysicalInterfaces.IEEE1394: sb.AppendLine("IEEE-1394 interface"); break; case PhysicalInterfaces.IEEE1394A: sb.AppendLine("IEEE-1394A interface"); break; case PhysicalInterfaces.FC: sb.AppendLine("Fibre Channel interface"); break; case PhysicalInterfaces.IEEE1394B: sb.AppendLine("IEEE-1394B interface"); break; case PhysicalInterfaces.SerialATAPI: sb.AppendLine("Serial ATAPI interface"); break; case PhysicalInterfaces.USB: sb.AppendLine("USB interface"); break; case PhysicalInterfaces.Vendor: sb.AppendLine("a vendor unique interface"); break; default: sb.AppendFormat("an unknown interface with code {0}", (uint)ftr.PhysicalInterfaceStandard).AppendLine(); break; } if(ftr.DBE) mmcOneValue.Add("Drive supports Device Busy events"); if(ftr.INQ2) mmcOneValue.Add("Drive supports EVPD, Page Code and 16-bit Allocation Length as described in SPC-3"); if(ftr.Async) mmcOneValue.Add("Drive supports polling and asynchronous GET EVENT STATUS NOTIFICATION"); else mmcOneValue.Add("Drive supports only polling GET EVENT STATUS NOTIFICATION"); if(ftr.OCEvent) mmcOneValue.Add("Drive supports operational change request / notification class events"); switch(ftr.LoadingMechanismType) { case 0: mmcOneValue.Add("Drive uses media caddy"); break; case 1: mmcOneValue.Add("Drive uses a tray"); break; case 2: mmcOneValue.Add("Drive is pop-up"); break; case 4: mmcOneValue.Add("Drive is a changer with individually changeable discs"); break; case 5: mmcOneValue.Add("Drive is a changer using cartridges"); break; default: sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", ftr.LoadingMechanismType).AppendLine(); break; } if(ftr.Lock) mmcOneValue.Add("Drive can lock media"); if(ftr.PreventJumper) mmcOneValue.Add("Drive power ups locked"); if(ftr.Eject) mmcOneValue.Add("Drive can eject media"); if(ftr.Load) mmcOneValue.Add("Drive can load media"); if(ftr.DBML) mmcOneValue.Add("Drive reports Device Busy Class events during medium loading/unloading"); if(ftr.DWP) mmcOneValue.Add("Drive supports reading/writing the Disc Write Protect PAC on BD-R/-RE media"); if(ftr.WDCB) mmcOneValue.Add("Drive supports writing the Write Inhibit DCB on DVD+RW media"); if(ftr.SPWP) mmcOneValue.Add("Drive supports set/release of PWP status"); if(ftr.SSWPP) mmcOneValue.Add("Drive supports the SWPP bit of the Timeout and Protect mode page"); if(ftr.PP) mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); if(ftr.LogicalBlockSize > 0) sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); if(ftr.Blocking > 1) sb.AppendFormat("\t{0} logical blocks per media readable unit", ftr.Blocking).AppendLine(); return !feature.HasValue ? null : "Drive claims capability to read all CD formats according to OSTA Multi-Read Specification\n"; if(ftr.DAP) mmcOneValue.Add("Drive supports the DAP bit in the READ CD and READ CD MSF commands"); if(ftr.C2) mmcOneValue.Add("Drive supports C2 Error Pointers"); if(ftr.CDText) mmcOneValue.Add("Drive can return CD-Text from Lead-In"); mmcOneValue.Add("Drive can read DVD media"); if(ftr.DualR) mmcOneValue.Add("Drive can read DVD-R DL from all recording modes"); if(ftr.DualRW) mmcOneValue.Add("Drive can read DVD-RW DL from all recording modes"); if(ftr.MULTI110) mmcOneValue.Add("Drive conforms to DVD Multi Drive Read-only Specifications"); if(ftr.PP) mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); if(ftr.LogicalBlockSize > 0) sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); if(ftr.Blocking > 1) sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); if(ftr.LastLBA > 0) sb.AppendFormat("\tLast adressable logical block is {0}", ftr.LastLBA).AppendLine(); if(ftr.DataTypeSupported > 0) { sb.Append("\tDrive supports data block types:"); if((ftr.DataTypeSupported & 0x0001) == 0x0001) sb.Append(" 0"); if((ftr.DataTypeSupported & 0x0002) == 0x0002) sb.Append(" 1"); if((ftr.DataTypeSupported & 0x0004) == 0x0004) sb.Append(" 2"); if((ftr.DataTypeSupported & 0x0008) == 0x0008) sb.Append(" 3"); if((ftr.DataTypeSupported & 0x0010) == 0x0010) sb.Append(" 4"); if((ftr.DataTypeSupported & 0x0020) == 0x0020) sb.Append(" 5"); if((ftr.DataTypeSupported & 0x0040) == 0x0040) sb.Append(" 6"); if((ftr.DataTypeSupported & 0x0080) == 0x0080) sb.Append(" 7"); if((ftr.DataTypeSupported & 0x0100) == 0x0100) sb.Append(" 8"); if((ftr.DataTypeSupported & 0x0200) == 0x0200) sb.Append(" 9"); if((ftr.DataTypeSupported & 0x0400) == 0x0400) sb.Append(" 10"); if((ftr.DataTypeSupported & 0x0800) == 0x0800) sb.Append(" 11"); if((ftr.DataTypeSupported & 0x1000) == 0x1000) sb.Append(" 12"); if((ftr.DataTypeSupported & 0x2000) == 0x2000) sb.Append(" 13"); if((ftr.DataTypeSupported & 0x4000) == 0x4000) sb.Append(" 14"); if((ftr.DataTypeSupported & 0x8000) == 0x8000) sb.Append(" 15"); sb.AppendLine(); } if(ftr.TRIO) mmcOneValue.Add("Drive claims support to report Track Resources Information"); if(ftr.ARSV) mmcOneValue.Add("Drive supports address mode reservation on the RESERVE TRACK command"); if(ftr.BUF) mmcOneValue.Add("Drive is capable of zero loss linking"); mmcOneValue.Add("Drive can format media into logical blocks"); if(ftr.RENoSA) mmcOneValue.Add("Drive can format BD-RE with no spares allocated"); if(ftr.Expand) mmcOneValue.Add("Drive can expand the spare area on a formatted BD-RE disc"); if(ftr.QCert) mmcOneValue.Add("Drive can format BD-RE discs with quick certification"); if(ftr.Cert) mmcOneValue.Add("Drive can format BD-RE discs with full certification"); if(ftr.FRF) mmcOneValue.Add("Drive can fast re-format BD-RE discs"); if(ftr.RRM) mmcOneValue.Add("Drive can format BD-R discs with RRM format"); sb.AppendLine("MMC Hardware Defect Management:"); mmcOneValue.Add("Drive shall be able to provide a defect-free contiguous address space"); if(ftr.SSA) mmcOneValue.Add("Drive can return Spare Area Information"); if(ftr.PP) mmcOneValue.Add("Drive shall report Read/Write Error Recovery mode page"); if(ftr.LogicalBlockSize > 0) sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); if(ftr.Blocking > 1) sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); return !feature.HasValue ? null : "Drive shall have the ability to overwrite logical blocks only in fixed sets at a time\n"; sb.Append("Drive can write High-Speed CD-RW"); if(ftr.Write && ftr.DVDPRead && ftr.DVDPWrite) sb.Append("Drive can read and write CD-MRW and DVD+MRW"); else if(ftr.DVDPRead && ftr.DVDPWrite) sb.Append("Drive can read and write DVD+MRW"); else if(ftr.Write && ftr.DVDPRead) sb.Append("Drive and read DVD+MRW and read and write CD-MRW"); else if(ftr.Write) sb.Append("Drive can read and write CD-MRW"); else if(ftr.DVDPRead) sb.Append("Drive can read CD-MRW and DVD+MRW"); else sb.Append("Drive can read CD-MRW"); if(ftr.DRTDM) mmcOneValue.Add("Drive supports DRT-DM mode"); else mmcOneValue.Add("Drive supports Persistent-DM mode"); if(ftr.DBICacheZones > 0) sb.AppendFormat("\tDrive has {0} DBI cache zones", ftr.DBICacheZones).AppendLine(); if(ftr.Entries > 0) sb.AppendFormat("\tDrive has {0} DBI entries", ftr.Entries).AppendLine(); if(ftr.Write) { sb.Append("Drive can read and write DVD+RW"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); if(ftr.CloseOnly) mmcOneValue.Add("Drive supports only the read compatibility stop"); else mmcOneValue.Add("Drive supports both forms of background format stopping"); if(ftr.QuickStart) mmcOneValue.Add("Drive can do a quick start formatting"); } else { sb.Append("Drive can read DVD+RW"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); } if(ftr.Write) { sb.Append("Drive can read and write DVD+R"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); } else { sb.Append("Drive can read DVD+R"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); } if(ftr.Blank) mmcOneValue.Add("Drive supports the BLANK command"); if(ftr.Intermediate) mmcOneValue.Add("Drive supports writing on an intermediate state session and quick formatting"); if(ftr.DSDR) mmcOneValue.Add("Drive can read Defect Status data recorded on the medium"); if(ftr.DSDG) mmcOneValue.Add("Drive can generate Defect Status data during formatting"); sb.AppendLine("Drive can write CDs in Track at Once Mode:"); if(ftr.RWSubchannel) { mmcOneValue.Add("Drive can write user provided data in the R-W subchannels"); if(ftr.RWRaw) mmcOneValue.Add("Drive accepts RAW R-W subchannel data"); if(ftr.RWPack) mmcOneValue.Add("Drive accepts Packed R-W subchannel data"); } if(ftr.CDRW) mmcOneValue.Add("Drive can overwrite a TAO track with another in CD-RWs"); if(ftr.TestWrite) mmcOneValue.Add("Drive can do a test writing"); if(ftr.BUF) mmcOneValue.Add("Drive supports zero loss linking"); if(ftr.DataTypeSupported > 0) { sb.Append("\tDrive supports data block types:"); if((ftr.DataTypeSupported & 0x0001) == 0x0001) sb.Append(" 0"); if((ftr.DataTypeSupported & 0x0002) == 0x0002) sb.Append(" 1"); if((ftr.DataTypeSupported & 0x0004) == 0x0004) sb.Append(" 2"); if((ftr.DataTypeSupported & 0x0008) == 0x0008) sb.Append(" 3"); if((ftr.DataTypeSupported & 0x0010) == 0x0010) sb.Append(" 4"); if((ftr.DataTypeSupported & 0x0020) == 0x0020) sb.Append(" 5"); if((ftr.DataTypeSupported & 0x0040) == 0x0040) sb.Append(" 6"); if((ftr.DataTypeSupported & 0x0080) == 0x0080) sb.Append(" 7"); if((ftr.DataTypeSupported & 0x0100) == 0x0100) sb.Append(" 8"); if((ftr.DataTypeSupported & 0x0200) == 0x0200) sb.Append(" 9"); if((ftr.DataTypeSupported & 0x0400) == 0x0400) sb.Append(" 10"); if((ftr.DataTypeSupported & 0x0800) == 0x0800) sb.Append(" 11"); if((ftr.DataTypeSupported & 0x1000) == 0x1000) sb.Append(" 12"); if((ftr.DataTypeSupported & 0x2000) == 0x2000) sb.Append(" 13"); if((ftr.DataTypeSupported & 0x4000) == 0x4000) sb.Append(" 14"); if((ftr.DataTypeSupported & 0x8000) == 0x8000) sb.Append(" 15"); sb.AppendLine(); if(ftr.SAO && !ftr.RAW) sb.AppendLine("Drive can write CDs in Session at Once Mode:"); else if(!ftr.SAO && ftr.RAW) sb.AppendLine("Drive can write CDs in raw Mode:"); else sb.AppendLine("Drive can write CDs in Session at Once and in Raw Modes:"); if(ftr.RAW && ftr.RAWMS) mmcOneValue.Add("Drive can write multi-session CDs in raw mode"); if(ftr.RW) mmcOneValue.Add("Drive can write user provided data in the R-W subchannels"); if(ftr.CDRW) mmcOneValue.Add("Drive can write CD-RWs"); if(ftr.TestWrite) mmcOneValue.Add("Drive can do a test writing"); if(ftr.BUF) mmcOneValue.Add("Drive supports zero loss linking"); if(ftr.MaxCueSheet > 0) sb.AppendFormat("\tDrive supports a maximum of {0} bytes in a single cue sheet", ftr.MaxCueSheet).AppendLine(); if(ftr.DVDRW && ftr.RDL) sb.AppendLine("Drive supports writing DVD-R, DVD-RW and DVD-R DL"); else if(ftr.RDL) sb.AppendLine("Drive supports writing DVD-R and DVD-R DL"); else if(ftr.DVDRW) sb.AppendLine("Drive supports writing DVD-R and DVD-RW"); else sb.AppendLine("Drive supports writing DVD-R"); if(ftr.TestWrite) mmcOneValue.Add("Drive can do a test writing"); if(ftr.BUF) mmcOneValue.Add("Drive supports zero loss linking"); return !feature.HasValue ? null : "Drive can read DDCDs\n"; sb.AppendLine("Drive supports writing DDCD-R"); if(ftr.TestWrite) mmcOneValue.Add("Drive can do a test writing"); sb.AppendLine("Drive supports writing DDCD-RW"); if(ftr.Blank) mmcOneValue.Add("Drive supports the BLANK command"); if(ftr.Intermediate) mmcOneValue.Add("Drive supports quick formatting"); if(ftr.LinkSizes != null) { foreach(byte link in ftr.LinkSizes) sb.AppendFormat("\tCurrent media has a {0} bytes link available", link).AppendLine(); } return !feature.HasValue ? null : "Drive can stop a long immediate operation\n"; sb.AppendLine("Drive can write CD-RW"); if(ftr.SubtypeSupport > 0) { sb.Append("\tDrive supports CD-RW subtypes"); if((ftr.SubtypeSupport & 0x01) == 0x01) sb.Append(" 0"); if((ftr.SubtypeSupport & 0x02) == 0x02) sb.Append(" 1"); if((ftr.SubtypeSupport & 0x04) == 0x04) sb.Append(" 2"); if((ftr.SubtypeSupport & 0x08) == 0x08) sb.Append(" 3"); if((ftr.SubtypeSupport & 0x10) == 0x10) sb.Append(" 4"); if((ftr.SubtypeSupport & 0x20) == 0x20) sb.Append(" 5"); if((ftr.SubtypeSupport & 0x40) == 0x40) sb.Append(" 6"); if((ftr.SubtypeSupport & 0x80) == 0x80) sb.Append(" 7"); sb.AppendLine(); } return !feature.HasValue ? null : "Drive can write BD-R on Pseudo-OVerwrite SRM mode\n"; if(ftr.Write) { sb.Append("Drive can read and write DVD+RW DL"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); if(ftr.CloseOnly) mmcOneValue.Add("Drive supports only the read compatibility stop"); else mmcOneValue.Add("Drive supports both forms of background format stopping"); if(ftr.QuickStart) mmcOneValue.Add("Drive can do a quick start formatting"); } else { sb.Append("Drive can read DVD+RW DL"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); } if(ftr.Write) { sb.Append("Drive can read and write DVD+R DL"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); } else { sb.Append("Drive can read DVD+R DL"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); } if(ftr.OldROM) mmcOneValue.Add("Drive can read BD-ROM pre-1.0"); if(ftr.ROM) mmcOneValue.Add("Drive can read BD-ROM Ver.1"); if(ftr.OldR) mmcOneValue.Add("Drive can read BD-R pre-1.0"); if(ftr.R) mmcOneValue.Add("Drive can read BD-R Ver.1"); if(ftr.OldRE) mmcOneValue.Add("Drive can read BD-RE pre-1.0"); if(ftr.RE1) mmcOneValue.Add("Drive can read BD-RE Ver.1"); if(ftr.RE2) mmcOneValue.Add("Drive can read BD-RE Ver.2"); if(ftr.BCA) mmcOneValue.Add("Drive can read BD's Burst Cutting Area"); if(ftr.OldR) mmcOneValue.Add("Drive can write BD-R pre-1.0"); if(ftr.R) mmcOneValue.Add("Drive can write BD-R Ver.1"); if(ftr.OldRE) mmcOneValue.Add("Drive can write BD-RE pre-1.0"); if(ftr.RE1) mmcOneValue.Add("Drive can write BD-RE Ver.1"); if(ftr.RE2) mmcOneValue.Add("Drive can write BD-RE Ver.2"); if(ftr.SVNR) mmcOneValue.Add("Drive supports write without verify requirement"); return !feature.HasValue ? null : "Drive is able to detect and report defective writable unit and behave accordinly\n"; if(ftr.HDDVDR && ftr.HDDVDRAM) sb.Append("Drive can read HD DVD-ROM, HD DVD-RW, HD DVD-R and HD DVD-RAM"); else if(ftr.HDDVDR) sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-R"); else if(ftr.HDDVDRAM) sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-RAM"); else sb.Append("Drive can read HD DVD-ROM and HD DVD-RW"); if(ftr.HDDVDR && ftr.HDDVDRAM) sb.Append("Drive can write HD DVD-RW, HD DVD-R and HD DVD-RAM"); else if(ftr.HDDVDR) sb.Append("Drive can write HD DVD-RW and HD DVD-R"); else if(ftr.HDDVDRAM) sb.Append("Drive can write HD DVD-RW and HD DVD-RAM"); else sb.Append("Drive can write HD DVD-RW"); sb.Append("Drive is able to access Hybrid discs"); if(ftr.RI) mmcOneValue.Add("Drive is able to maintain the online format layer through reset and power cycling"); return !feature.HasValue ? null : "Drive is able to perform host and drive directed power management\n"; sb.AppendLine("Drive supports S.M.A.R.T."); if(ftr.PP) mmcOneValue.Add("Drive supports the Informational Exceptions Control mode page 1Ch"); sb.AppendLine("MMC Embedded Changer:"); if(ftr.SCC) mmcOneValue.Add("Drive can change disc side"); if(ftr.SDP) mmcOneValue.Add("Drive is able to report slots contents after a reset or change"); sb.AppendFormat("\tDrive has {0} slots", ftr.HighestSlotNumber + 1).AppendLine(); sb.AppendLine("Drive has an analogue audio output"); if(ftr.Scan) mmcOneValue.Add("Drive supports the SCAN command"); if(ftr.SCM) mmcOneValue.Add("Drive is able to mute channels separately"); if(ftr.SV) mmcOneValue.Add("Drive supports separate volume per channel"); sb.AppendFormat("\tDrive has {0} volume levels", ftr.VolumeLevels + 1).AppendLine(); sb.AppendLine("Drive supports Microcode Upgrade"); if(ftr.M5) sb.AppendLine("Drive supports validating the 5-bit Mode of the READ BUFFER and WRITE BUFFER commands"); sb.AppendLine("Drive supports Timeout & Protect mode page 1Dh"); if(ftr.Group3) { mmcOneValue.Add("Drive supports the Group3 in Timeout & Protect mode page 1Dh"); if(ftr.UnitLength > 0) sb.AppendFormat("\tDrive has {0} increase of Group 3 time unit", ftr.UnitLength).AppendLine(); } sb.AppendFormat("Drive supports DVD CSS/CPPM version {0}", ftr.CSSVersion); if(ftr.Current) sb.AppendLine(" and current disc is encrypted"); else sb.AppendLine(); sb.AppendLine("MMC Real Time Streaming:"); if(ftr.SMP) mmcOneValue.Add("Drive supports Set Minimum Performance with the SET STREAMING command"); if(ftr.RBCB) mmcOneValue.Add("Drive supports the block bit in the READ BUFFER CAPACITY command"); if(ftr.SCS) mmcOneValue.Add("Drive supports the SET CD SPEED command"); if(ftr.MP2A) mmcOneValue.Add("Drive supports the Write Speed Performance Descriptor Blocks in the MMC mode page 2Ah"); if(ftr.WSPD) mmcOneValue.Add("Drive supports the Write Speed data of GET PERFORMANCE and the WRC field of SET STREAMING"); if(ftr.SW) mmcOneValue.Add("Drive supports stream recording"); return !feature.HasValue ? null : "Drive is to read media serial number\n"; if(ftr.DCBs != null) { foreach(uint DCB in ftr.DCBs) sb.AppendFormat("Drive supports DCB {0:X8}h", DCB).AppendLine(); } sb.AppendFormat("Drive supports DVD CPRM version {0}", ftr.CPRMVersion); if(ftr.Current) sb.AppendLine(" and current disc is or can be encrypted"); else sb.AppendLine(); string syear, smonth, sday, shour, sminute, ssecond; byte[] temp; temp = new byte[4]; temp[0] = (byte)((ftr.Century & 0xFF00) >> 8); temp[1] = (byte)(ftr.Century & 0xFF); temp[2] = (byte)((ftr.Year & 0xFF00) >> 8); temp[3] = (byte)(ftr.Year & 0xFF); syear = Encoding.ASCII.GetString(temp); temp = new byte[2]; temp[0] = (byte)((ftr.Month & 0xFF00) >> 8); temp[1] = (byte)(ftr.Month & 0xFF); smonth = Encoding.ASCII.GetString(temp); temp = new byte[2]; temp[0] = (byte)((ftr.Day & 0xFF00) >> 8); temp[1] = (byte)(ftr.Day & 0xFF); sday = Encoding.ASCII.GetString(temp); temp = new byte[2]; temp[0] = (byte)((ftr.Hour & 0xFF00) >> 8); temp[1] = (byte)(ftr.Hour & 0xFF); shour = Encoding.ASCII.GetString(temp); temp = new byte[2]; temp[0] = (byte)((ftr.Minute & 0xFF00) >> 8); temp[1] = (byte)(ftr.Minute & 0xFF); sminute = Encoding.ASCII.GetString(temp); temp = new byte[2]; temp[0] = (byte)((ftr.Second & 0xFF00) >> 8); temp[1] = (byte)(ftr.Second & 0xFF); ssecond = Encoding.ASCII.GetString(temp); try { DateTime fwDate = new DateTime(int.Parse(syear), int.Parse(smonth), int.Parse(sday), int.Parse(shour), int.Parse(sminute), int.Parse(ssecond), DateTimeKind.Utc); sb.AppendFormat("Drive firmware is dated {0}", fwDate).AppendLine(); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body { } sb.AppendFormat("Drive supports AACS version {0}", ftr.AACSVersion); if(ftr.Current) sb.AppendLine(" and current disc is encrypted"); else sb.AppendLine(); if(ftr.RDC) mmcOneValue.Add("Drive supports reading the Drive Certificate"); if(ftr.RMC) mmcOneValue.Add("Drive supports reading Media Key Block of CPRM"); if(ftr.WBE) mmcOneValue.Add("Drive supports writing with bus encryption"); if(ftr.BEC) mmcOneValue.Add("Drive supports bus encryption"); if(ftr.BNG) { mmcOneValue.Add("Drive supports generating the binding nonce"); if(ftr.BindNonceBlocks > 0) sb.AppendFormat("\t{0} media blocks are required for the binding nonce", ftr.BindNonceBlocks).AppendLine(); } if(ftr.AGIDs > 0) sb.AppendFormat("\tDrive supports {0} AGIDs concurrently", ftr.AGIDs).AppendLine(); sb.Append("Drive supports DVD-Download"); if(ftr.Current) sb.AppendLine(" (current)"); else sb.AppendLine(); if(ftr.MaxScrambleExtent > 0) sb.AppendFormat("\tMaximum {0} scranble extent information entries", ftr.MaxScrambleExtent).AppendLine(); if(ftr.Current) sb.AppendLine("Drive and currently inserted media support VCPS"); else sb.AppendLine("Drive supports VCPS"); if(ftr.Current) sb.AppendLine("Drive and currently inserted media support SecurDisc"); else sb.AppendLine("Drive supports SecurDisc"); sb.AppendLine("Drive supports the Trusted Computing Group Optical Security Subsystem Class"); if(ftr.Current) mmcOneValue.Add("Current media is initialized with TCG OSSC"); if(ftr.PSAU) mmcOneValue.Add("Drive supports PSA updates on write-once media"); if(ftr.LOSPB) mmcOneValue.Add("Drive supports linked OSPBs"); if(ftr.ME) mmcOneValue.Add("Drive will only record on the OSSC Disc Format"); if(ftr.Profiles != null) { for(int i = 0; i < ftr.Profiles.Length; i++) sb.AppendFormat("\tProfile {0}: {1}", i, ftr.Profiles[i]).AppendLine(); } } } } }