/// <summary> /// This method reads the PAC data for a blu-ray disk /// </summary> /// <param name="pacid">the pac id of the pac to read</param> /// <param name="pacfmt">the format of the pac to read</param> /// <param name="data">return storage for the pac data</param> /// <returns></returns> public CommandStatus ReadDiskStructurePac(uint pacid, byte pacfmt, out byte [] data) { data = null; if (m_logger != null) { string args = "out byte[] data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadDvdStructurePac(" + args + ")")); } ushort len = 4; using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, len, Command.CmdDirection.In, 60)) { cmd.SetCDB24(2, pacid); cmd.SetCDB8(6, pacfmt); cmd.SetCDB8(7, 0x30); // Read PAC data cmd.SetCDB16(8, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = (ushort)(cmd.GetBuffer16(0) + 2); if (len == 2) { data = new byte[0]; return CommandStatus.Success; } Debug.Assert(len < 8192); } using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, len, Command.CmdDirection.In, 60)) { cmd.SetCDB24(2, pacid); cmd.SetCDB8(6, pacfmt); cmd.SetCDB8(7, 0x30); // Read manufacturing information cmd.SetCDB16(8, len); // Up to 2k of data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = (ushort)(cmd.GetBuffer16(0) + 2); data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); } return CommandStatus.Success; }
/// <summary> /// Read the subchannel data from a series of sectors /// </summary> /// <param name="sector"></param> /// <param name="length"></param> /// <param name="data"></param> /// <param name="mode">the subchannel mode</param> /// <param name="timeout">timeout (in seconds)</param> /// <returns></returns> public CommandStatus ReadSubChannel(byte mode, uint sector, uint length, ref byte[] data, int timeout) { byte bytes_per_sector; if (m_logger != null) { string args = sector.ToString() + ", " + length.ToString() + ", data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadSubChannel(" + args + ")")); } if (mode != 1 && mode != 2 && mode != 4) throw new Exception("invalid read mode for ReadSubchannel() call"); bytes_per_sector = 96; if (mode == 2) bytes_per_sector = 16; if (data.GetLength(0) < length * bytes_per_sector) throw new Exception("data buffer is not large enough to hold the data requested"); using (Command cmd = new Command(ScsiCommandCode.ReadCd, 12, (int)(length * bytes_per_sector), Command.CmdDirection.In, timeout)) { byte b = (byte)(1 << 2); cmd.SetCDB8(1, b); cmd.SetCDB32(2, sector); // The sector number to start with cmd.SetCDB24(6, length); // The length in sectors cmd.SetCDB8(10, mode); // Corrected, de-interleaved P - W data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; Marshal.Copy(cmd.GetBuffer(), data, 0, (int)(length * bytes_per_sector)); } return CommandStatus.Success ; }
/// <summary> /// This method reads subheader CD data from a data mode 2 track /// </summary> /// <param name="sector">the sector # of the data to read</param> /// <param name="hdr">return subheader data</param> /// <returns></returns> public CommandStatus ReadCD(uint sector, out SubheaderData hdr) { hdr = null ; if (m_logger != null) { string args = sector.ToString() + ", out SubheaderData hdr"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCD(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadCd, 12, 4, Command.CmdDirection.In, 10)) { cmd.SetCDB32(2, sector); cmd.SetCDB24(6, 1); cmd.SetCDB8(9, 0x40); // Header data only CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; hdr = new SubheaderData(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="submode">subchannel mode</param> /// <param name="start"></param> /// <param name="length"></param> /// <param name="data">the memory area </param> /// <param name="timeout">timeout (in seconds)</param> /// <returns></returns> public CommandStatus ReadCDDA(SubChannelMode submode, uint start, uint length, IntPtr data, int timeout) { if (m_logger != null) { string args = start.ToString() + ", " + length.ToString() + ", data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCDDA(" + args + ")")); } byte mode = (byte)(submode == SubChannelMode.QOnly ? 1 : submode == SubChannelMode.RWMode ? 2 : 0); int size = 4 * 588 + (submode == SubChannelMode.QOnly ? 16 : submode == SubChannelMode.RWMode ? 96 : 0); using (Command cmd = new Command(ScsiCommandCode.ReadCDDA, 12, data, (int)length * size, Command.CmdDirection.In, timeout)) { cmd.SetCDB8(1, 0 << 5); // lun cmd.SetCDB32(2, start); cmd.SetCDB24(7, length); cmd.SetCDB8(10, mode); // Subchannel CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="mainmode">main channel mode</param> /// <param name="submode">subchannel mode</param> /// <param name="c2mode">C2 errors report mode</param> /// <param name="exp">expected sector type</param> /// <param name="dap"></param> /// <param name="start"></param> /// <param name="length"></param> /// <param name="data">the memory area </param> /// <param name="timeout">timeout (in seconds)</param> /// <returns></returns> public CommandStatus ReadCDAndSubChannel(MainChannelSelection mainmode, SubChannelMode submode, C2ErrorMode c2mode, byte exp, bool dap, uint start, uint length, IntPtr data, int timeout) { if (m_logger != null) { string args = exp.ToString() + ", " + dap.ToString() + ", " + start.ToString() + ", " + length.ToString() + ", data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCD(" + args + ")")); } int size = (4 * 588 + (submode == SubChannelMode.QOnly ? 16 : submode == SubChannelMode.RWMode ? 96 : 0) + (c2mode == C2ErrorMode.Mode294 ? 294 : c2mode == C2ErrorMode.Mode296 ? 296 : 0)) * (int) length; byte mode = (byte) (submode == SubChannelMode.QOnly ? 2 : submode == SubChannelMode.RWMode ? 4 : 0); if (exp != 1 && exp != 2 && exp != 3 && exp != 4 && exp != 5) return CommandStatus.NotSupported; using (Command cmd = new Command(ScsiCommandCode.ReadCd, 12, data, size, Command.CmdDirection.In, timeout)) { byte b = (byte)((exp & 0x07) << 2); if (dap) b |= 0x02; byte byte9 = (byte)(mainmode == MainChannelSelection.UserData ? 0x10 : mainmode == MainChannelSelection.F8h ? 0xF8 : 0); if (c2mode == C2ErrorMode.Mode294) byte9 |= 0x02; else if (c2mode == C2ErrorMode.Mode296) byte9 |= 0x04; cmd.SetCDB8(1, b); cmd.SetCDB32(2, start); cmd.SetCDB24(6, length); cmd.SetCDB8(9, byte9); // User data + possibly c2 errors cmd.SetCDB8(10, mode); // Subchannel CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="exp"></param> /// <param name="dap"></param> /// <param name="start"></param> /// <param name="length"></param> /// <param name="data">the memory area </param> /// <param name="size">the size of the memory area given by the data parameter</param> /// <returns></returns> public CommandStatus ReadCD(byte exp, bool dap, uint start, uint length, IntPtr data, int size) { if (m_logger != null) { string args = exp.ToString() + ", " + dap.ToString() + ", " + start.ToString() + ", " + length.ToString() + ", data, " + size.ToString(); m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCD(" + args + ")")); } if (exp != 1 && exp != 2 && exp != 3 && exp != 4 && exp != 5) return CommandStatus.NotSupported; using (Command cmd = new Command(ScsiCommandCode.ReadCd, 12, data, size, Command.CmdDirection.In, 5 * 60)) { byte b = (byte)((exp & 0x07) << 2); if (dap) b |= 0x02; cmd.SetCDB8(1, b); cmd.SetCDB32(2, start); cmd.SetCDB24(6, length); cmd.SetCDB8(9, 0x10); // User data only CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; } return CommandStatus.Success; }