/// <summary>Sends the MMC READ CD command</summary> /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns> /// <param name="buffer">Buffer where the MMC READ CD response will be stored</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="timeout">Timeout in seconds.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="lba">Start block address.</param> /// <param name="transferLength">How many blocks to read.</param> /// <param name="blockSize">Block size.</param> /// <param name="expectedSectorType">Expected sector type.</param> /// <param name="dap">If set to <c>true</c> CD-DA should be modified by mute and interpolation</param> /// <param name="relAddr">If set to <c>true</c> address is relative to current position.</param> /// <param name="sync">If set to <c>true</c> we request the sync bytes for data sectors.</param> /// <param name="headerCodes">Header codes.</param> /// <param name="userData">If set to <c>true</c> we request the user data.</param> /// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param> /// <param name="c2Error">C2 error options.</param> /// <param name="subchannel">Subchannel selection.</param> public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint transferLength, MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync, MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error, MmcSubchannel subchannel, uint timeout, out double duration) { senseBuffer = new byte[32]; byte[] cdb = new byte[12]; cdb[0] = (byte)ScsiCommands.ReadCd; cdb[1] = (byte)((byte)expectedSectorType << 2); if (dap) { cdb[1] += 0x02; } if (relAddr) { cdb[1] += 0x01; } cdb[2] = (byte)((lba & 0xFF000000) >> 24); cdb[3] = (byte)((lba & 0xFF0000) >> 16); cdb[4] = (byte)((lba & 0xFF00) >> 8); cdb[5] = (byte)(lba & 0xFF); cdb[6] = (byte)((transferLength & 0xFF0000) >> 16); cdb[7] = (byte)((transferLength & 0xFF00) >> 8); cdb[8] = (byte)(transferLength & 0xFF); cdb[9] = (byte)((byte)c2Error << 1); cdb[9] += (byte)((byte)headerCodes << 5); if (sync) { cdb[9] += 0x80; } if (userData) { cdb[9] += 0x10; } if (edcEcc) { cdb[9] += 0x08; } cdb[10] = (byte)subchannel; buffer = new byte[blockSize * transferLength]; LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); Error = LastError != 0; DicConsole.DebugWriteLine("SCSI Device", "READ CD took {0} ms.", duration); return(sense); }
/// <summary>Sends the MMC READ CD MSF command</summary> /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns> /// <param name="buffer">Buffer where the MMC READ CD MSF response will be stored</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="timeout">Timeout in seconds.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="startMsf">Start MM:SS:FF of read encoded as 0x00MMSSFF.</param> /// <param name="endMsf">End MM:SS:FF of read encoded as 0x00MMSSFF.</param> /// <param name="blockSize">Block size.</param> /// <param name="expectedSectorType">Expected sector type.</param> /// <param name="dap">If set to <c>true</c> CD-DA should be modified by mute and interpolation</param> /// <param name="sync">If set to <c>true</c> we request the sync bytes for data sectors.</param> /// <param name="headerCodes">Header codes.</param> /// <param name="userData">If set to <c>true</c> we request the user data.</param> /// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param> /// <param name="c2Error">C2 error options.</param> /// <param name="subchannel">Subchannel selection.</param> public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf, uint endMsf, uint blockSize, MmcSectorTypes expectedSectorType, bool dap, bool sync, MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error, MmcSubchannel subchannel, uint timeout, out double duration) { senseBuffer = new byte[32]; byte[] cdb = new byte[12]; cdb[0] = (byte)ScsiCommands.ReadCdMsf; cdb[1] = (byte)((byte)expectedSectorType << 2); if (dap) { cdb[1] += 0x02; } cdb[3] = (byte)((startMsf & 0xFF0000) >> 16); cdb[4] = (byte)((startMsf & 0xFF00) >> 8); cdb[5] = (byte)(startMsf & 0xFF); cdb[6] = (byte)((endMsf & 0xFF0000) >> 16); cdb[7] = (byte)((endMsf & 0xFF00) >> 8); cdb[8] = (byte)(endMsf & 0xFF); cdb[9] = (byte)((byte)c2Error << 1); cdb[9] += (byte)((byte)headerCodes << 5); if (sync) { cdb[9] += 0x80; } if (userData) { cdb[9] += 0x10; } if (edcEcc) { cdb[9] += 0x08; } cdb[10] = (byte)subchannel; uint transferLength = (uint)(((cdb[6] - cdb[3]) * 60 * 75) + ((cdb[7] - cdb[4]) * 75) + (cdb[8] - cdb[5])); buffer = new byte[blockSize * transferLength]; LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); Error = LastError != 0; AaruConsole.DebugWriteLine("SCSI Device", "READ CD MSF (Start MSF: {1}, End MSF: {2}, Block Size: {3}, Expected Sector Type: {4}, DAP: {5}, Sync: {6}, Headers: {7}, User Data: {8}, ECC/EDC: {9}, C2: {10}, Subchannel: {11}, Sense: {12}, LastError: {13}) took {0} ms.", duration, startMsf, endMsf, blockSize, expectedSectorType, dap, sync, headerCodes, userData, edcEcc, c2Error, subchannel, sense, LastError); return(sense); }
/// <summary>Sends the MMC READ CD command</summary> /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns> /// <param name="buffer">Buffer where the MMC READ CD response will be stored</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="timeout">Timeout in seconds.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="lba">Start block address.</param> /// <param name="transferLength">How many blocks to read.</param> /// <param name="blockSize">Block size.</param> /// <param name="expectedSectorType">Expected sector type.</param> /// <param name="dap">If set to <c>true</c> CD-DA should be modified by mute and interpolation</param> /// <param name="relAddr">If set to <c>true</c> address is relative to current position.</param> /// <param name="sync">If set to <c>true</c> we request the sync bytes for data sectors.</param> /// <param name="headerCodes">Header codes.</param> /// <param name="userData">If set to <c>true</c> we request the user data.</param> /// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param> /// <param name="c2Error">C2 error options.</param> /// <param name="subchannel">Subchannel selection.</param> public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint transferLength, MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync, MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error, MmcSubchannel subchannel, uint timeout, out double duration) { senseBuffer = new byte[32]; byte[] cdb = new byte[12]; cdb[0] = (byte)ScsiCommands.ReadCd; cdb[1] = (byte)((byte)expectedSectorType << 2); if (dap) { cdb[1] += 0x02; } if (relAddr) { cdb[1] += 0x01; } cdb[2] = (byte)((lba & 0xFF000000) >> 24); cdb[3] = (byte)((lba & 0xFF0000) >> 16); cdb[4] = (byte)((lba & 0xFF00) >> 8); cdb[5] = (byte)(lba & 0xFF); cdb[6] = (byte)((transferLength & 0xFF0000) >> 16); cdb[7] = (byte)((transferLength & 0xFF00) >> 8); cdb[8] = (byte)(transferLength & 0xFF); cdb[9] = (byte)((byte)c2Error << 1); cdb[9] += (byte)((byte)headerCodes << 5); if (sync) { cdb[9] += 0x80; } if (userData) { cdb[9] += 0x10; } if (edcEcc) { cdb[9] += 0x08; } cdb[10] = (byte)subchannel; buffer = new byte[blockSize * transferLength]; LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); Error = LastError != 0; AaruConsole.DebugWriteLine("SCSI Device", "READ CD (LBA: {1}, Block Size: {2}, Transfer Length: {3}, Expected Sector Type: {4}, DAP: {5}, Relative Address: {6}, Sync: {7}, Headers: {8}, User Data: {9}, ECC/EDC: {10}, C2: {11}, Subchannel: {12}, Sense: {13}, Last Error: {14}) took {0} ms.", duration, lba, blockSize, transferLength, expectedSectorType, dap, relAddr, sync, headerCodes, userData, edcEcc, c2Error, subchannel, sense, LastError); return(sense); }