// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : DI.cs // Author(s) : Natalia Portillo // // Component : Device structures decoders. // // --[ Description ] ---------------------------------------------------------- // // Decodes Blu-ray Disc Information. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2016 Natalia Portillo // ****************************************************************************/ using System; using DiscImageChef.Console; using System.Collections.Generic; using System.Text; namespace DiscImageChef.Decoders.Bluray { /// /// Information from the following standards: /// ANSI X3.304-1997 /// T10/1048-D revision 9.0 /// T10/1048-D revision 10a /// T10/1228-D revision 7.0c /// T10/1228-D revision 11a /// T10/1363-D revision 10g /// T10/1545-D revision 1d /// T10/1545-D revision 5 /// T10/1545-D revision 5a /// T10/1675-D revision 2c /// T10/1675-D revision 4 /// T10/1836-D revision 2g /// public static class DI { #region Private constants const string DiscTypeBDROM = "BDO"; const string DiscTypeBDRE = "BDW"; const string DiscTypeBDR = "BDR"; /// /// Disc Information Unit Identifier "DI" /// const UInt16 DIUIdentifier = 0x4449; #endregion Private constants #region Public methods public static DiscInformation? Decode(byte[] DIResponse) { if(DIResponse == null) return null; if(DIResponse.Length != 4100) { DicConsole.DebugWriteLine("BD Disc Information decoder", "Found incorrect Blu-ray Disc Information size ({0} bytes)", DIResponse.Length); return null; } DiscInformation decoded = new DiscInformation(); BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; decoded.DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0); decoded.Reserved1 = DIResponse[2]; decoded.Reserved2 = DIResponse[3]; int offset = 4; List units = new List(); while(true) { if(offset >= 100) break; DiscInformationUnits unit = new DiscInformationUnits(); unit.Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset); if(unit.Signature != DIUIdentifier) break; unit.Format = DIResponse[2 + offset]; unit.UnitsPerBlock = DIResponse[3 + offset]; unit.Legacy = DIResponse[4 + offset]; unit.Sequence = DIResponse[5 + offset]; unit.Length = DIResponse[6 + offset]; unit.Reserved = DIResponse[7 + offset]; unit.DiscTypeIdentifier = new byte[3]; Array.Copy(DIResponse, 8 + offset, unit.DiscTypeIdentifier, 0, 3); unit.DiscSizeClassVersion = DIResponse[11 + offset]; switch(Encoding.ASCII.GetString(unit.DiscTypeIdentifier)) { case DiscTypeBDROM: { unit.FormatDependentContents = new byte[52]; Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 52); break; } case DiscTypeBDRE: case DiscTypeBDR: { unit.FormatDependentContents = new byte[88]; Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 88); unit.ManufacturerID = new byte[6]; Array.Copy(DIResponse, 100 + offset, unit.ManufacturerID, 0, 6); unit.MediaTypeID = new byte[3]; Array.Copy(DIResponse, 106 + offset, unit.MediaTypeID, 0, 3); unit.TimeStamp = BigEndianBitConverter.ToUInt16(DIResponse, 109 + offset); unit.ProductRevisionNumber = DIResponse[111 + offset]; break; } default: { DicConsole.DebugWriteLine("BD Disc Information decoder", "Found unknown disc type identifier \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)); break; } } units.Add(unit); offset += unit.Length; } if(units.Count > 0) { decoded.Units = new DiscInformationUnits[units.Count]; for(int i = 0; i < units.Count; i++) decoded.Units[i] = units[i]; } return decoded; } public static string Prettify(DiscInformation? DIResponse) { if(DIResponse == null) return null; DiscInformation response = DIResponse.Value; StringBuilder sb = new StringBuilder(); foreach(DiscInformationUnits unit in response.Units) { sb.AppendFormat("DI Unit Sequence: {0}", unit.Sequence).AppendLine(); sb.AppendFormat("DI Unit Format: 0x{0:X2}", unit.Format).AppendLine(); sb.AppendFormat("There are {0} per block", unit.UnitsPerBlock).AppendLine(); if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) != DiscTypeBDROM) sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine(); sb.AppendFormat("DI Unit is {0} bytes", unit.Length).AppendLine(); sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)).AppendLine(); sb.AppendFormat("Disc size/class/version: {0}", unit.DiscSizeClassVersion).AppendLine(); if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR || Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) { sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)).AppendLine(); sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)).AppendLine(); sb.AppendFormat("Disc timestamp: 0x{0:X2}", unit.TimeStamp).AppendLine(); sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine(); } sb.AppendFormat("Blu-ray DI Unit format dependent contents as hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(unit.FormatDependentContents, 80)); } return sb.ToString(); } public static string Prettify(byte[] DIResponse) { return Prettify(Decode(DIResponse)); } #endregion Public methods #region Public structures public struct DiscInformation { /// /// Bytes 0 to 1 /// Always 4098 /// public UInt16 DataLength; /// /// Byte 2 /// Reserved /// public byte Reserved1; /// /// Byte 3 /// Reserved /// public byte Reserved2; /// /// Byte 4 to 4099 /// Disc information units /// public DiscInformationUnits[] Units; } public struct DiscInformationUnits { /// /// Byte 0 /// "DI" /// public UInt16 Signature; /// /// Byte 2 /// Disc information format /// public byte Format; /// /// Byte 3 /// Number of DI units per block /// public byte UnitsPerBlock; /// /// Byte 4 /// Reserved for BD-ROM, legacy information for BD-R/-RE /// public byte Legacy; /// /// Byte 5 /// Sequence number for this DI unit /// public byte Sequence; /// /// Byte 6 /// Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE /// public byte Length; /// /// Byte 7 /// Reserved /// public byte Reserved; /// /// Bytes 8 to 10 /// Disc type identifier /// public byte[] DiscTypeIdentifier; /// /// Byte 11 /// Disc size/class/version /// public byte DiscSizeClassVersion; /// /// Bytes 12 to 63 for BD-ROM, bytes 12 to 99 for BD-R/-RE /// Format dependent contents, disclosed in private blu-ray specifications /// public byte[] FormatDependentContents; /// /// Bytes 100 to 105, BD-R/-RE only /// Manufacturer ID /// public byte[] ManufacturerID; /// /// Bytes 106 to 108, BD-R/-RE only /// Media type ID /// public byte[] MediaTypeID; /// /// Bytes 109 to 110, BD-R/-RE only /// Timestamp /// public UInt16 TimeStamp; /// /// Byte 111 /// Product revision number /// public byte ProductRevisionNumber; } #endregion Public structures } }