Remove DiscImageChef.CommonTypes dependence on DiscImageChef.Decoders.

This commit is contained in:
2020-01-11 20:55:54 +00:00
parent 53f92aa111
commit 6b1033317a
40 changed files with 1640 additions and 776 deletions

View File

@@ -184,6 +184,18 @@
<e p="Partition.cs" t="Include" />
<e p="PluginBase.cs" t="Include" />
<e p="Structs" t="Include">
<e p="Devices" t="Include">
<e p="ATA" t="Include">
<e p="Identify.cs" t="Include" />
</e>
<e p="SCSI" t="Include">
<e p="Enums.cs" t="Include" />
<e p="Inquiry.cs" t="Include" />
<e p="Modes" t="Include">
<e p="2A.cs" t="Include" />
</e>
</e>
</e>
<e p="Filesystems.cs" t="Include" />
<e p="Images.cs" t="Include" />
<e p="TapeFile.cs" t="Include" />
@@ -515,7 +527,6 @@
<e p="SCSI" t="Include">
<e p="DiscStructureCapabilities.cs" t="Include" />
<e p="EVPD.cs" t="Include" />
<e p="Enums.cs" t="Include" />
<e p="Inquiry.cs" t="Include" />
<e p="MMC" t="Include">
<e p="AACS.cs" t="Include" />

View File

@@ -39,8 +39,8 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Extents;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.PCMCIA;
using Schemas;
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;

View File

@@ -34,6 +34,7 @@ using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Extents;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Devices;

View File

@@ -34,9 +34,9 @@ using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.Bluray;
using DiscImageChef.Decoders.DVD;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Devices;
using Schemas;

View File

@@ -10,6 +10,7 @@ using DiscImageChef.CommonTypes.Extents;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.SCSI;

View File

@@ -41,6 +41,7 @@ using DiscImageChef.CommonTypes.Extents;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.SCSI;

View File

@@ -33,6 +33,7 @@
using System.Threading;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.SCSI;
namespace DiscImageChef.Core.Devices.Dumping

View File

@@ -39,6 +39,7 @@ using DiscImageChef.CommonTypes.Extents;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.DVD;

View File

@@ -33,10 +33,12 @@
using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Devices;
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
namespace DiscImageChef.Core.Devices.Info
{

View File

@@ -32,10 +32,12 @@
using System.Collections.Generic;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Devices;
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
namespace DiscImageChef.Core.Devices.Info
{
@@ -44,7 +46,7 @@ namespace DiscImageChef.Core.Devices.Info
public byte[] AtaIdentify { get; }
public byte[] AtapiIdentify { get; }
public byte[] ScsiInquiryData { get; }
public Inquiry.SCSIInquiry? ScsiInquiry { get; }
public Inquiry? ScsiInquiry { get; }
public AtaErrorRegistersChs? AtaMcptError { get; }
public Dictionary<byte, byte[]> ScsiEvpdPages { get; }
public Modes.DecodedMode? ScsiMode { get; }

View File

@@ -32,7 +32,7 @@
using System;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.Devices;
namespace DiscImageChef.Core.Devices

View File

@@ -34,10 +34,11 @@ using System;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Decoders.ATA;
using Identify = DiscImageChef.CommonTypes.Structs.Devices.ATA.Identify;
namespace DiscImageChef.Core.Devices
{
partial class Reader
internal partial class Reader
{
Identify.IdentifyDevice ataId;
bool ataRead;
@@ -60,9 +61,12 @@ namespace DiscImageChef.Core.Devices
(uint, byte, byte) GetDeviceChs()
{
if(dev.Type != DeviceType.ATA) return (0, 0, 0);
if(dev.Type != DeviceType.ATA)
return(0, 0, 0);
if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0)
if(ataId.CurrentCylinders > 0 &&
ataId.CurrentHeads > 0 &&
ataId.CurrentSectorsPerTrack > 0)
{
Cylinders = ataId.CurrentCylinders;
Heads = (byte)ataId.CurrentHeads;
@@ -70,17 +74,18 @@ namespace DiscImageChef.Core.Devices
Blocks = (ulong)(Cylinders * Heads * Sectors);
}
if(ataId.CurrentCylinders != 0 && ataId.CurrentHeads != 0 && ataId.CurrentSectorsPerTrack != 0 ||
ataId.Cylinders <= 0 ||
ataId.Heads <= 0 ||
ataId.SectorsPerTrack <= 0) return (Cylinders, Heads, Sectors);
if((ataId.CurrentCylinders != 0 && ataId.CurrentHeads != 0 && ataId.CurrentSectorsPerTrack != 0) ||
ataId.Cylinders <= 0 ||
ataId.Heads <= 0 ||
ataId.SectorsPerTrack <= 0)
return(Cylinders, Heads, Sectors);
Cylinders = ataId.Cylinders;
Heads = (byte)ataId.Heads;
Sectors = (byte)ataId.SectorsPerTrack;
Blocks = (ulong)(Cylinders * Heads * Sectors);
return (Cylinders, Heads, Sectors);
return(Cylinders, Heads, Sectors);
}
ulong AtaGetBlocks()
@@ -93,7 +98,8 @@ namespace DiscImageChef.Core.Devices
IsLba = true;
}
if(!ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48)) return Blocks;
if(!ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48))
return Blocks;
Blocks = ataId.LBA48Sectors;
IsLba = true;
@@ -105,6 +111,7 @@ namespace DiscImageChef.Core.Devices
{
bool sense = dev.Read(out byte[] cmdBuf, out AtaErrorRegistersChs errorChs, false, 0, 0, 1, 1, timeout,
out _);
ataRead = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0;
sense = dev.Read(out cmdBuf, out errorChs, true, 0, 0, 1, 1, timeout, out _);
ataReadRetry = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0;
@@ -134,40 +141,62 @@ namespace DiscImageChef.Core.Devices
if(IsLba)
{
if(Blocks > 0xFFFFFFF && !ataReadLba48 && !ataReadDmaLba48)
if(Blocks > 0xFFFFFFF &&
!ataReadLba48 &&
!ataReadDmaLba48)
{
ErrorMessage = "Device needs 48-bit LBA commands but I can't issue them... Aborting.";
return true;
}
if(!ataReadLba && !ataReadRetryLba && !ataReadDmaLba && !ataReadDmaRetryLba)
if(!ataReadLba &&
!ataReadRetryLba &&
!ataReadDmaLba &&
!ataReadDmaRetryLba)
{
ErrorMessage = "Device needs 28-bit LBA commands but I can't issue them... Aborting.";
return true;
}
}
else
{
if(!ataRead && !ataReadRetry && !ataReadDma && !ataReadDmaRetry)
if(!ataRead &&
!ataReadRetry &&
!ataReadDma &&
!ataReadDmaRetry)
{
ErrorMessage = "Device needs CHS commands but I can't issue them... Aborting.";
return true;
}
}
if(ataReadDmaLba48) DicConsole.WriteLine("Using ATA READ DMA EXT command.");
else if(ataReadLba48) DicConsole.WriteLine("Using ATA READ EXT command.");
else if(ataReadDmaRetryLba) DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
else if(ataReadDmaLba) DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
else if(ataReadRetryLba) DicConsole.WriteLine("Using ATA READ command with retries (LBA).");
else if(ataReadLba) DicConsole.WriteLine("Using ATA READ command (LBA).");
else if(ataReadDmaRetry) DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
else if(ataReadDma) DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
else if(ataReadRetry) DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
else if(ataRead) DicConsole.WriteLine("Using ATA READ command (CHS).");
if(ataReadDmaLba48)
DicConsole.WriteLine("Using ATA READ DMA EXT command.");
else if(ataReadLba48)
DicConsole.WriteLine("Using ATA READ EXT command.");
else if(ataReadDmaRetryLba)
DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
else if(ataReadDmaLba)
DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
else if(ataReadRetryLba)
DicConsole.WriteLine("Using ATA READ command with retries (LBA).");
else if(ataReadLba)
DicConsole.WriteLine("Using ATA READ command (LBA).");
else if(ataReadDmaRetry)
DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
else if(ataReadDma)
DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
else if(ataReadRetry)
DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
else if(ataRead)
DicConsole.WriteLine("Using ATA READ command (CHS).");
else
{
ErrorMessage = "Could not get a working read command!";
return true;
}
@@ -176,18 +205,22 @@ namespace DiscImageChef.Core.Devices
bool AtaGetBlockSize()
{
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 &&
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
{
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
if(ataId.LogicalSectorWords <= 255 ||
ataId.LogicalAlignment == 0xFFFF)
LogicalBlockSize = 512;
else
LogicalBlockSize = ataId.LogicalSectorWords * 2;
else LogicalBlockSize = 512;
else
LogicalBlockSize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
PhysicalBlockSize = LogicalBlockSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF);
else PhysicalBlockSize = LogicalBlockSize;
PhysicalBlockSize = LogicalBlockSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF);
else
PhysicalBlockSize = LogicalBlockSize;
}
else
{
@@ -208,6 +241,7 @@ namespace DiscImageChef.Core.Devices
if(!IsLba)
{
BlocksToRead = 1;
return false;
}
@@ -218,6 +252,7 @@ namespace DiscImageChef.Core.Devices
byte[] cmdBuf;
bool sense;
AtaErrorRegistersLba48 errorLba48;
if(ataReadDmaLba48)
{
sense = dev.ReadDma(out cmdBuf, out errorLba48, 0, (byte)BlocksToRead, timeout, out _);
@@ -231,6 +266,7 @@ namespace DiscImageChef.Core.Devices
else
{
AtaErrorRegistersLba28 errorLba;
if(ataReadDmaRetryLba)
{
sense = dev.ReadDma(out cmdBuf, out errorLba, true, 0, (byte)BlocksToRead, timeout, out _);
@@ -253,15 +289,21 @@ namespace DiscImageChef.Core.Devices
}
}
if(error) BlocksToRead /= 2;
if(error)
BlocksToRead /= 2;
if(!error || BlocksToRead == 1) break;
if(!error ||
BlocksToRead == 1)
break;
}
if(!error || !IsLba) return false;
if(!error ||
!IsLba)
return false;
BlocksToRead = 1;
ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length.";
return true;
}
@@ -293,6 +335,7 @@ namespace DiscImageChef.Core.Devices
{
sense = dev.ReadDma(out buffer, out errorLba, true, (uint)block, (byte)count, timeout,
out duration);
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
status = errorLba.Status;
errorByte = errorLba.Error;
@@ -301,6 +344,7 @@ namespace DiscImageChef.Core.Devices
{
sense = dev.ReadDma(out buffer, out errorLba, false, (uint)block, (byte)count, timeout,
out duration);
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
status = errorLba.Status;
errorByte = errorLba.Error;
@@ -320,7 +364,8 @@ namespace DiscImageChef.Core.Devices
errorByte = errorLba.Error;
}
if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
if(error)
DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error;
}
@@ -338,6 +383,7 @@ namespace DiscImageChef.Core.Devices
{
sense = dev.ReadDma(out buffer, out errorChs, true, cylinder, head, sectir, 1, timeout,
out duration);
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
status = errorChs.Status;
errorByte = errorChs.Error;
@@ -346,6 +392,7 @@ namespace DiscImageChef.Core.Devices
{
sense = dev.ReadDma(out buffer, out errorChs, false, cylinder, head, sectir, 1, timeout,
out duration);
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
status = errorChs.Status;
errorByte = errorChs.Error;
@@ -365,7 +412,8 @@ namespace DiscImageChef.Core.Devices
errorByte = errorChs.Error;
}
if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
if(error)
DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error;
}
@@ -373,13 +421,15 @@ namespace DiscImageChef.Core.Devices
bool AtaSeek(ulong block, out double duration)
{
bool sense = dev.Seek(out AtaErrorRegistersLba28 errorLba, (uint)block, timeout, out duration);
return !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0);
return!(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0);
}
bool AtaSeekChs(ushort cylinder, byte head, byte sector, out double duration)
{
bool sense = dev.Seek(out AtaErrorRegistersChs errorChs, cylinder, head, sector, timeout, out duration);
return !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0);
return!(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0);
}
}
}

View File

@@ -31,12 +31,13 @@
// ****************************************************************************/
using System;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.SCSI;
namespace DiscImageChef.Core.Devices
{
partial class Reader
internal partial class Reader
{
// TODO: Raw reading
bool hldtstReadRaw;
@@ -72,23 +73,34 @@ namespace DiscImageChef.Core.Devices
seek10 = !dev.Seek10(out senseBuf, 0, timeout, out _);
if(!read6 && !read10 && !read12 && !read16)
if(!read6 &&
!read10 &&
!read12 &&
!read16)
{
ErrorMessage = "Cannot read medium, aborting scan...";
return true;
}
if(read6 && !read10 && !read12 && !read16 && Blocks > 0x001FFFFF + 1)
if(read6 &&
!read10 &&
!read12 &&
!read16 &&
Blocks > 0x001FFFFF + 1)
{
ErrorMessage =
$"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks} blocks total)";
return true;
}
if(!read16 && Blocks > 0xFFFFFFFF + (long)1)
if(!read16 &&
Blocks > 0xFFFFFFFF + (long)1)
{
ErrorMessage =
$"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({Blocks} blocks total)";
return true;
}
@@ -120,17 +132,23 @@ namespace DiscImageChef.Core.Devices
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 0xFFFF, timeout, out _);
FixedSense? decSense;
if(testSense && !dev.Error)
{
decSense = Sense.DecodeFixed(senseBuf);
if(decSense.HasValue)
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 &&
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 &&
decSense.Value.ASCQ == 0x00)
{
CanReadRaw = true;
if(decSense.Value.InformationValid && decSense.Value.ILI)
if(decSense.Value.InformationValid &&
decSense.Value.ILI)
{
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
readLong10 = !dev.ReadLong10(out _, out senseBuf, false, false, 0,
(ushort)LongBlockSize, timeout, out _);
}
@@ -143,29 +161,37 @@ namespace DiscImageChef.Core.Devices
{
// Long sector sizes for floppies
514,
// Long sector sizes for SuperDisk
536, 558,
// Long sector sizes for 512-byte magneto-opticals
600, 610, 630
})
{
ushort testSize = (ushort)i;
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong16 = true;
LongBlockSize = testSize;
CanReadRaw = true;
break;
}
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout,
out _);
if(testSense || dev.Error) continue;
if(testSense || dev.Error)
continue;
readLong10 = true;
LongBlockSize = testSize;
CanReadRaw = true;
break;
}
else if(LogicalBlockSize == 1024)
@@ -173,33 +199,42 @@ namespace DiscImageChef.Core.Devices
{
// Long sector sizes for floppies
1026,
// Long sector sizes for 1024-byte magneto-opticals
1200
})
{
ushort testSize = (ushort)i;
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong16 = true;
LongBlockSize = testSize;
CanReadRaw = true;
break;
}
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout,
out _);
if(testSense || dev.Error) continue;
if(testSense || dev.Error)
continue;
readLong10 = true;
LongBlockSize = testSize;
CanReadRaw = true;
break;
}
else if(LogicalBlockSize == 2048)
{
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 2380, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong16 = true;
LongBlockSize = 2380;
@@ -208,7 +243,9 @@ namespace DiscImageChef.Core.Devices
else
{
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 2380, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong10 = true;
LongBlockSize = 2380;
@@ -219,7 +256,9 @@ namespace DiscImageChef.Core.Devices
else if(LogicalBlockSize == 4096)
{
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 4760, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong16 = true;
LongBlockSize = 4760;
@@ -228,7 +267,9 @@ namespace DiscImageChef.Core.Devices
else
{
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 4760, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong10 = true;
LongBlockSize = 4760;
@@ -239,7 +280,9 @@ namespace DiscImageChef.Core.Devices
else if(LogicalBlockSize == 8192)
{
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 9424, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong16 = true;
LongBlockSize = 9424;
@@ -248,7 +291,9 @@ namespace DiscImageChef.Core.Devices
else
{
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 9424, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLong10 = true;
LongBlockSize = 9424;
@@ -257,20 +302,27 @@ namespace DiscImageChef.Core.Devices
}
}
if(!CanReadRaw && dev.Manufacturer == "SYQUEST")
if(!CanReadRaw &&
dev.Manufacturer == "SYQUEST")
{
testSense = dev.SyQuestReadLong10(out _, out senseBuf, 0, 0xFFFF, timeout, out _);
if(testSense)
{
decSense = Sense.DecodeFixed(senseBuf);
if(decSense.HasValue)
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 &&
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 &&
decSense.Value.ASCQ == 0x00)
{
CanReadRaw = true;
if(decSense.Value.InformationValid && decSense.Value.ILI)
if(decSense.Value.InformationValid &&
decSense.Value.ILI)
{
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
syqReadLong10 =
!dev.SyQuestReadLong10(out _, out senseBuf, 0, LongBlockSize, timeout,
out _);
@@ -279,18 +331,23 @@ namespace DiscImageChef.Core.Devices
else
{
testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 0xFFFF, timeout, out _);
if(testSense)
{
decSense = Sense.DecodeFixed(senseBuf);
if(decSense.HasValue)
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 &&
decSense.Value.ASCQ == 0x00)
{
CanReadRaw = true;
if(decSense.Value.InformationValid && decSense.Value.ILI)
if(decSense.Value.InformationValid &&
decSense.Value.ILI)
{
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
syqReadLong6 =
!dev.SyQuestReadLong6(out _, out senseBuf, 0, LongBlockSize,
timeout, out _);
@@ -300,10 +357,13 @@ namespace DiscImageChef.Core.Devices
}
}
if(!CanReadRaw && LogicalBlockSize == 256)
if(!CanReadRaw &&
LogicalBlockSize == 256)
{
testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 262, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
syqReadLong6 = true;
LongBlockSize = 262;
@@ -316,11 +376,13 @@ namespace DiscImageChef.Core.Devices
{
switch(dev.Manufacturer)
{
case "HL-DT-ST":
case"HL-DT-ST":
hldtstReadRaw = !dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _);
break;
case "PLEXTOR":
case"PLEXTOR":
plextorReadRaw = !dev.PlextorReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _);
break;
}
@@ -331,10 +393,13 @@ namespace DiscImageChef.Core.Devices
}
// READ LONG (10) for some DVD drives
if(!CanReadRaw && dev.Manufacturer == "MATSHITA")
if(!CanReadRaw &&
dev.Manufacturer == "MATSHITA")
{
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 37856, timeout, out _);
if(!testSense && !dev.Error)
if(!testSense &&
!dev.Error)
{
readLongDvd = true;
LongBlockSize = 37856;
@@ -346,17 +411,27 @@ namespace DiscImageChef.Core.Devices
if(CanReadRaw)
{
if(readLong16) DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
else if(readLong10 || readLongDvd) DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
else if(syqReadLong10) DicConsole.WriteLine("Using SyQuest READ LONG (10) command.");
else if(syqReadLong6) DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
else if(hldtstReadRaw) DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
else if(plextorReadRaw) DicConsole.WriteLine("Using Plextor raw DVD reading.");
if(readLong16)
DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
else if(readLong10 || readLongDvd)
DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
else if(syqReadLong10)
DicConsole.WriteLine("Using SyQuest READ LONG (10) command.");
else if(syqReadLong6)
DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
else if(hldtstReadRaw)
DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
else if(plextorReadRaw)
DicConsole.WriteLine("Using Plextor raw DVD reading.");
}
else if(read16) DicConsole.WriteLine("Using SCSI READ (16) command.");
else if(read12) DicConsole.WriteLine("Using SCSI READ (12) command.");
else if(read10) DicConsole.WriteLine("Using SCSI READ (10) command.");
else if(read6) DicConsole.WriteLine("Using SCSI READ (6) command.");
else if(read16)
DicConsole.WriteLine("Using SCSI READ (16) command.");
else if(read12)
DicConsole.WriteLine("Using SCSI READ (12) command.");
else if(read10)
DicConsole.WriteLine("Using SCSI READ (10) command.");
else if(read6)
DicConsole.WriteLine("Using SCSI READ (6) command.");
return false;
}
@@ -367,6 +442,7 @@ namespace DiscImageChef.Core.Devices
Blocks = 0;
sense = dev.ReadCapacity(out byte[] cmdBuf, out byte[] senseBuf, timeout, out _);
if(!sense)
{
Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]);
@@ -398,6 +474,7 @@ namespace DiscImageChef.Core.Devices
PhysicalBlockSize = LogicalBlockSize;
LongBlockSize = LogicalBlockSize;
return false;
}
@@ -411,33 +488,45 @@ namespace DiscImageChef.Core.Devices
{
dev.Read16(out _, out _, 0, false, true, false, 0, LogicalBlockSize, 0, BlocksToRead, false,
timeout, out _);
if(dev.Error) BlocksToRead /= 2;
if(dev.Error)
BlocksToRead /= 2;
}
else if(read12)
{
dev.Read12(out _, out _, 0, false, false, false, false, 0, LogicalBlockSize, 0, BlocksToRead, false,
timeout, out _);
if(dev.Error) BlocksToRead /= 2;
if(dev.Error)
BlocksToRead /= 2;
}
else if(read10)
{
dev.Read10(out _, out _, 0, false, true, false, false, 0, LogicalBlockSize, 0, (ushort)BlocksToRead,
timeout, out _);
if(dev.Error) BlocksToRead /= 2;
if(dev.Error)
BlocksToRead /= 2;
}
else if(read6)
{
dev.Read6(out _, out _, 0, LogicalBlockSize, (byte)BlocksToRead, timeout, out _);
if(dev.Error) BlocksToRead /= 2;
if(dev.Error)
BlocksToRead /= 2;
}
if(!dev.Error || BlocksToRead == 1) break;
if(!dev.Error ||
BlocksToRead == 1)
break;
}
if(!dev.Error) return false;
if(!dev.Error)
return false;
BlocksToRead = 1;
ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length.";
return true;
}
@@ -467,7 +556,8 @@ namespace DiscImageChef.Core.Devices
else if(plextorReadRaw)
sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, timeout,
out duration);
else return true;
else
return true;
else
{
if(read16)
@@ -482,12 +572,16 @@ namespace DiscImageChef.Core.Devices
else if(read6)
sense = dev.Read6(out buffer, out senseBuf, (uint)block, LogicalBlockSize, (byte)count, timeout,
out duration);
else return true;
else
return true;
}
if(!sense && !dev.Error) return false;
if(!sense &&
!dev.Error)
return false;
DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
return sense;
}
@@ -496,8 +590,10 @@ namespace DiscImageChef.Core.Devices
bool sense = true;
duration = 0;
if(seek6) sense = dev.Seek6(out _, (uint)block, timeout, out duration);
else if(seek10) sense = dev.Seek10(out _, (uint)block, timeout, out duration);
if(seek6)
sense = dev.Seek6(out _, (uint)block, timeout, out duration);
else if(seek10)
sense = dev.Seek10(out _, (uint)block, timeout, out duration);
return sense;
}

View File

@@ -35,6 +35,7 @@ using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Console;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Devices;
using Identify = DiscImageChef.CommonTypes.Structs.Devices.ATA.Identify;
namespace DiscImageChef.Core.Devices.Report
{

View File

@@ -34,9 +34,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Devices;
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
namespace DiscImageChef.Core.Devices.Report
{
@@ -52,12 +54,12 @@ namespace DiscImageChef.Core.Devices.Report
if(sense)
return null;
Inquiry.SCSIInquiry? decodedNullable = Inquiry.Decode(buffer);
Inquiry? decodedNullable = Inquiry.Decode(buffer);
if(!decodedNullable.HasValue)
return null;
Inquiry.SCSIInquiry decoded = decodedNullable.Value;
Inquiry decoded = decodedNullable.Value;
// Clear Seagate serial number
if(decoded.SeagatePresent &&

View File

@@ -32,38 +32,39 @@
using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.ATA;
namespace DiscImageChef.Core.Devices.Scanning
{
/// <summary>
/// Implements scanning the media from an ATA device
/// </summary>
/// <summary>Implements scanning the media from an ATA device</summary>
public partial class MediaScan
{
/// <summary>
/// Scans the media from an ATA device
/// </summary>
/// <summary>Scans the media from an ATA device</summary>
/// <returns>Scanning results</returns>
ScanResults Ata()
{
ScanResults results = new ScanResults();
bool sense;
var results = new ScanResults();
bool sense;
results.Blocks = 0;
const ushort ATA_PROFILE = 0x0001;
const uint TIMEOUT = 5;
sense = dev.AtaIdentify(out byte[] cmdBuf, out _);
if(!sense && Identify.Decode(cmdBuf).HasValue)
if(!sense &&
Identify.Decode(cmdBuf).HasValue)
{
// Initializate reader
Reader ataReader = new Reader(dev, TIMEOUT, cmdBuf);
var ataReader = new Reader(dev, TIMEOUT, cmdBuf);
// Fill reader blocks
results.Blocks = ataReader.GetDeviceBlocks();
if(ataReader.FindReadCommand())
{
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
return results;
}
@@ -71,14 +72,17 @@ namespace DiscImageChef.Core.Devices.Scanning
if(ataReader.GetBlockSize())
{
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
return results;
}
uint blockSize = ataReader.LogicalBlockSize;
// Check how many blocks to read, if error show and return
if(ataReader.GetBlocksToRead())
{
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
return results;
}
@@ -108,11 +112,12 @@ namespace DiscImageChef.Core.Devices.Scanning
double seekCur;
Random rnd = new Random();
var rnd = new Random();
MhddLog mhddLog;
IbgLog ibgLog;
double duration;
if(ataReader.IsLba)
{
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time.");
@@ -125,15 +130,23 @@ namespace DiscImageChef.Core.Devices.Scanning
DateTime timeSpeedStart = DateTime.UtcNow;
ulong sectorSpeedStart = 0;
InitProgress?.Invoke();
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
{
if(aborted) break;
if(aborted)
break;
if(results.Blocks - i < blocksToRead) blocksToRead = (byte)(results.Blocks - i);
if(results.Blocks - i < blocksToRead)
blocksToRead = (byte)(results.Blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed;
if(currentSpeed > results.MaxSpeed &&
currentSpeed != 0)
results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed &&
currentSpeed != 0)
results.MinSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
@@ -143,12 +156,18 @@ namespace DiscImageChef.Core.Devices.Scanning
if(!error)
{
if(duration >= 500) results.F += blocksToRead;
else if(duration >= 150) results.E += blocksToRead;
else if(duration >= 50) results.D += blocksToRead;
else if(duration >= 10) results.C += blocksToRead;
else if(duration >= 3) results.B += blocksToRead;
else results.A += blocksToRead;
if(duration >= 500)
results.F += blocksToRead;
else if(duration >= 150)
results.E += blocksToRead;
else if(duration >= 50)
results.D += blocksToRead;
else if(duration >= 10)
results.C += blocksToRead;
else if(duration >= 3)
results.B += blocksToRead;
else
results.A += blocksToRead;
ScanTime?.Invoke(i, duration);
mhddLog.Write(i, duration);
@@ -158,7 +177,9 @@ namespace DiscImageChef.Core.Devices.Scanning
{
ScanUnreadable?.Invoke(i);
results.Errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
for(ulong b = i; b < i + blocksToRead; b++)
results.UnreadableSectors.Add(b);
mhddLog.Write(i, duration < 500 ? 65535 : duration);
@@ -168,10 +189,12 @@ namespace DiscImageChef.Core.Devices.Scanning
sectorSpeedStart += blocksToRead;
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
if(elapsed < 1) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024);
if(elapsed < 1)
continue;
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0;
timeSpeedStart = DateTime.UtcNow;
}
@@ -179,16 +202,19 @@ namespace DiscImageChef.Core.Devices.Scanning
end = DateTime.UtcNow;
EndProgress?.Invoke();
mhddLog.Close();
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
blockSize * (double)(results.Blocks + 1) / 1024 /
(blockSize * (double)(results.Blocks + 1)) / 1024 /
(results.ProcessingTime / 1000),
devicePath);
InitProgress?.Invoke();
if(ataReader.CanSeekLba)
for(int i = 0; i < SEEK_TIMES; i++)
{
if(aborted) break;
if(aborted)
break;
uint seekPos = (uint)rnd.Next((int)results.Blocks);
@@ -197,8 +223,13 @@ namespace DiscImageChef.Core.Devices.Scanning
ataReader.Seek(seekPos, out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur;
if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur;
if(seekCur > results.SeekMax &&
seekCur != 0)
results.SeekMax = seekCur;
if(seekCur < results.SeekMin &&
seekCur != 0)
results.SeekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.SeekTotal += seekCur;
@@ -219,34 +250,45 @@ namespace DiscImageChef.Core.Devices.Scanning
DateTime timeSpeedStart = DateTime.UtcNow;
ulong sectorSpeedStart = 0;
InitProgress?.Invoke();
for(ushort cy = 0; cy < cylinders; cy++)
{
for(byte hd = 0; hd < heads; hd++)
{
for(byte sc = 1; sc < sectors; sc++)
{
if(aborted) break;
if(aborted)
break;
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.MaxSpeed && currentSpeed != 0)
if(currentSpeed > results.MaxSpeed &&
currentSpeed != 0)
results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed && currentSpeed != 0)
if(currentSpeed < results.MinSpeed &&
currentSpeed != 0)
results.MinSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
PulseProgress
?.Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
PulseProgress?.
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
if(!error)
{
if(duration >= 500) results.F += blocksToRead;
else if(duration >= 150) results.E += blocksToRead;
else if(duration >= 50) results.D += blocksToRead;
else if(duration >= 10) results.C += blocksToRead;
else if(duration >= 3) results.B += blocksToRead;
else results.A += blocksToRead;
if(duration >= 500)
results.F += blocksToRead;
else if(duration >= 150)
results.E += blocksToRead;
else if(duration >= 50)
results.D += blocksToRead;
else if(duration >= 10)
results.C += blocksToRead;
else if(duration >= 3)
results.B += blocksToRead;
else
results.A += blocksToRead;
ScanTime?.Invoke(currentBlock, duration);
mhddLog.Write(currentBlock, duration);
@@ -266,10 +308,12 @@ namespace DiscImageChef.Core.Devices.Scanning
currentBlock++;
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
if(elapsed < 1) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024);
if(elapsed < 1)
continue;
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024);
sectorSpeedStart = 0;
timeSpeedStart = DateTime.UtcNow;
}
@@ -279,29 +323,37 @@ namespace DiscImageChef.Core.Devices.Scanning
end = DateTime.UtcNow;
EndProgress?.Invoke();
mhddLog.Close();
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
blockSize * (double)(results.Blocks + 1) / 1024 /
(blockSize * (double)(results.Blocks + 1)) / 1024 /
(results.ProcessingTime / 1000),
devicePath);
InitProgress?.Invoke();
if(ataReader.CanSeek)
for(int i = 0; i < SEEK_TIMES; i++)
{
if(aborted) break;
if(aborted)
break;
ushort seekCy = (ushort)rnd.Next(cylinders);
byte seekHd = (byte)rnd.Next(heads);
byte seekSc = (byte)rnd.Next(sectors);
PulseProgress
?.Invoke($"\rSeeking to cylinder {seekCy}, head {seekHd}, sector {seekSc}...\t\t");
PulseProgress?.
Invoke($"\rSeeking to cylinder {seekCy}, head {seekHd}, sector {seekSc}...\t\t");
ataReader.SeekChs(seekCy, seekHd, seekSc, out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur;
if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur;
if(seekCur > results.SeekMax &&
seekCur != 0)
results.SeekMax = seekCur;
if(seekCur < results.SeekMin &&
seekCur != 0)
results.SeekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.SeekTotal += seekCur;
@@ -313,13 +365,14 @@ namespace DiscImageChef.Core.Devices.Scanning
results.ProcessingTime /= 1000;
results.TotalTime = (end - start).TotalSeconds;
results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime;
results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime;
results.SeekTimes = SEEK_TIMES;
return results;
}
StoppingErrorMessage?.Invoke("Unable to communicate with ATA device.");
return results;
}
}

View File

@@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.CD;
@@ -42,18 +43,16 @@ using DiscImageChef.Devices;
namespace DiscImageChef.Core.Devices.Scanning
{
/// <summary>
/// Implements scanning the media from an SCSI device
/// </summary>
/// <summary>Implements scanning the media from an SCSI device</summary>
public partial class MediaScan
{
ScanResults Scsi()
{
ScanResults results = new ScanResults();
MhddLog mhddLog;
IbgLog ibgLog;
byte[] senseBuf;
bool sense = false;
var results = new ScanResults();
MhddLog mhddLog;
IbgLog ibgLog;
byte[] senseBuf;
bool sense = false;
results.Blocks = 0;
uint blockSize = 0;
ushort currentProfile = 0x0001;
@@ -61,20 +60,25 @@ namespace DiscImageChef.Core.Devices.Scanning
if(dev.IsRemovable)
{
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
if(sense)
{
InitProgress?.Invoke();
FixedSense? decSense = Sense.DecodeFixed(senseBuf);
if(decSense.HasValue)
if(decSense.Value.ASC == 0x3A)
{
int leftRetries = 5;
while(leftRetries > 0)
{
PulseProgress?.Invoke("Waiting for drive to become ready");
Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
if(!sense) break;
if(!sense)
break;
leftRetries--;
}
@@ -82,59 +86,72 @@ namespace DiscImageChef.Core.Devices.Scanning
if(sense)
{
StoppingErrorMessage?.Invoke("Please insert media in drive");
return results;
}
}
else if(decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01)
else if(decSense.Value.ASC == 0x04 &&
decSense.Value.ASCQ == 0x01)
{
int leftRetries = 10;
while(leftRetries > 0)
{
PulseProgress?.Invoke("Waiting for drive to become ready");
Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
if(!sense) break;
if(!sense)
break;
leftRetries--;
}
if(sense)
{
StoppingErrorMessage
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
StoppingErrorMessage?.
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
return results;
}
}
// These should be trapped by the OS but seems in some cases they're not
else if(decSense.Value.ASC == 0x28)
{
int leftRetries = 10;
while(leftRetries > 0)
{
PulseProgress?.Invoke("Waiting for drive to become ready");
Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
if(!sense) break;
if(!sense)
break;
leftRetries--;
}
if(sense)
{
StoppingErrorMessage
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
StoppingErrorMessage?.
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
return results;
}
}
else
{
StoppingErrorMessage
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
StoppingErrorMessage?.
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
return results;
}
else
{
StoppingErrorMessage?.Invoke("Unknown testing unit was ready.");
return results;
}
@@ -154,19 +171,23 @@ namespace DiscImageChef.Core.Devices.Scanning
case PeripheralDeviceTypes.WriteOnceDevice:
scsiReader = new Reader(dev, dev.Timeout, null);
results.Blocks = scsiReader.GetDeviceBlocks();
if(scsiReader.FindReadCommand())
{
StoppingErrorMessage?.Invoke("Unable to read medium.");
return results;
}
blockSize = scsiReader.LogicalBlockSize;
if(results.Blocks != 0 && blockSize != 0)
if(results.Blocks != 0 &&
blockSize != 0)
{
results.Blocks++;
UpdateStatus
?.Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)");
UpdateStatus?.
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)");
}
break;
@@ -174,12 +195,14 @@ namespace DiscImageChef.Core.Devices.Scanning
StoppingErrorMessage?.Invoke("Scanning will never be supported on SCSI Streaming Devices." +
Environment.NewLine +
"It has no sense to do it, and it will put too much strain on the tape.");
return results;
}
if(results.Blocks == 0)
{
StoppingErrorMessage?.Invoke("Unable to read medium or empty medium present...");
return results;
}
@@ -190,6 +213,7 @@ namespace DiscImageChef.Core.Devices.Scanning
{
sense = dev.GetConfiguration(out byte[] cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current,
dev.Timeout, out _);
if(!sense)
{
Features.SeparatedFeatures ftr = Features.Separate(cmdBuf);
@@ -207,6 +231,7 @@ namespace DiscImageChef.Core.Devices.Scanning
case 0x0022: break;
default:
compactDisc = false;
break;
}
}
@@ -214,13 +239,17 @@ namespace DiscImageChef.Core.Devices.Scanning
if(compactDisc)
{
currentProfile = 0x0008;
// We discarded all discs that falsify a TOC before requesting a real TOC
// No TOC, no CD (or an empty one)
bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _);
if(!tocSense) toc = FullTOC.Decode(cmdBuf);
bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _);
if(!tocSense)
toc = FullTOC.Decode(cmdBuf);
}
}
else compactDisc = false;
else
compactDisc = false;
uint blocksToRead = 64;
@@ -245,6 +274,7 @@ namespace DiscImageChef.Core.Devices.Scanning
if(toc == null)
{
StoppingErrorMessage?.Invoke("Error trying to decode TOC...");
return results;
}
@@ -252,7 +282,8 @@ namespace DiscImageChef.Core.Devices.Scanning
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None,
dev.Timeout, out _);
if(readcd) UpdateStatus?.Invoke("Using MMC READ CD command.");
if(readcd)
UpdateStatus?.Invoke("Using MMC READ CD command.");
start = DateTime.UtcNow;
@@ -263,16 +294,21 @@ namespace DiscImageChef.Core.Devices.Scanning
sense = dev.ReadCd(out _, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false,
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
MmcSubchannel.None, dev.Timeout, out _);
if(dev.Error) blocksToRead /= 2;
if(dev.Error)
blocksToRead /= 2;
}
if(!dev.Error || blocksToRead == 1) break;
if(!dev.Error ||
blocksToRead == 1)
break;
}
if(dev.Error)
{
StoppingErrorMessage
?.Invoke($"Device error {dev.LastError} trying to guess ideal transfer length.");
StoppingErrorMessage?.
Invoke($"Device error {dev.LastError} trying to guess ideal transfer length.");
return results;
}
@@ -285,17 +321,25 @@ namespace DiscImageChef.Core.Devices.Scanning
ulong sectorSpeedStart = 0;
InitProgress?.Invoke();
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
{
if(aborted) break;
if(aborted)
break;
double cmdDuration = 0;
if(results.Blocks - i < blocksToRead) blocksToRead = (uint)(results.Blocks - i);
if(results.Blocks - i < blocksToRead)
blocksToRead = (uint)(results.Blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed;
if(currentSpeed > results.MaxSpeed &&
currentSpeed != 0)
results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed &&
currentSpeed != 0)
results.MinSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
@@ -306,17 +350,24 @@ namespace DiscImageChef.Core.Devices.Scanning
sense = dev.ReadCd(out _, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes,
false, false, true, MmcHeaderCodes.AllHeaders, true, true,
MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration);
results.ProcessingTime += cmdDuration;
}
if(!sense)
{
if(cmdDuration >= 500) results.F += blocksToRead;
else if(cmdDuration >= 150) results.E += blocksToRead;
else if(cmdDuration >= 50) results.D += blocksToRead;
else if(cmdDuration >= 10) results.C += blocksToRead;
else if(cmdDuration >= 3) results.B += blocksToRead;
else results.A += blocksToRead;
if(cmdDuration >= 500)
results.F += blocksToRead;
else if(cmdDuration >= 150)
results.E += blocksToRead;
else if(cmdDuration >= 50)
results.D += blocksToRead;
else if(cmdDuration >= 10)
results.C += blocksToRead;
else if(cmdDuration >= 3)
results.B += blocksToRead;
else
results.A += blocksToRead;
ScanTime?.Invoke(i, cmdDuration);
mhddLog.Write(i, cmdDuration);
@@ -327,17 +378,21 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Sense.PrettifySense(senseBuf));
FixedSense? senseDecoded = Sense.DecodeFixed(senseBuf);
if(senseDecoded.HasValue)
{
// TODO: This error happens when changing from track type afaik. Need to solve that more cleanly
// LOGICAL BLOCK ADDRESS OUT OF RANGE
if((senseDecoded.Value.ASC != 0x21 || senseDecoded.Value.ASCQ != 0x00) &&
// ILLEGAL MODE FOR THIS TRACK (requesting sectors as-is, this is a firmware misconception when audio sectors
// are in a track where subchannel indicates data)
(senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00))
{
results.Errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
for(ulong b = i; b < i + blocksToRead; b++)
results.UnreadableSectors.Add(b);
ScanUnreadable?.Invoke(i);
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
@@ -349,7 +404,9 @@ namespace DiscImageChef.Core.Devices.Scanning
{
ScanUnreadable?.Invoke(i);
results.Errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
for(ulong b = i; b < i + blocksToRead; b++)
results.UnreadableSectors.Add(b);
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
@@ -360,10 +417,12 @@ namespace DiscImageChef.Core.Devices.Scanning
sectorSpeedStart += blocksToRead;
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
if(elapsed < 1) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024);
if(elapsed < 1)
continue;
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0;
timeSpeedStart = DateTime.UtcNow;
}
@@ -371,8 +430,9 @@ namespace DiscImageChef.Core.Devices.Scanning
end = DateTime.UtcNow;
EndProgress?.Invoke();
mhddLog.Close();
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
blockSize * (double)(results.Blocks + 1) / 1024 /
(blockSize * (double)(results.Blocks + 1)) / 1024 /
(results.ProcessingTime / 1000),
devicePath);
}
@@ -389,15 +449,23 @@ namespace DiscImageChef.Core.Devices.Scanning
ulong sectorSpeedStart = 0;
InitProgress?.Invoke();
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
{
if(aborted) break;
if(aborted)
break;
if(results.Blocks - i < blocksToRead) blocksToRead = (uint)(results.Blocks - i);
if(results.Blocks - i < blocksToRead)
blocksToRead = (uint)(results.Blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed;
if(currentSpeed > results.MaxSpeed &&
currentSpeed != 0)
results.MaxSpeed = currentSpeed;
if(currentSpeed < results.MinSpeed &&
currentSpeed != 0)
results.MinSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
@@ -406,25 +474,35 @@ namespace DiscImageChef.Core.Devices.Scanning
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration);
results.ProcessingTime += cmdDuration;
if(!sense && !dev.Error)
if(!sense &&
!dev.Error)
{
if(cmdDuration >= 500) results.F += blocksToRead;
else if(cmdDuration >= 150) results.E += blocksToRead;
else if(cmdDuration >= 50) results.D += blocksToRead;
else if(cmdDuration >= 10) results.C += blocksToRead;
else if(cmdDuration >= 3) results.B += blocksToRead;
else results.A += blocksToRead;
if(cmdDuration >= 500)
results.F += blocksToRead;
else if(cmdDuration >= 150)
results.E += blocksToRead;
else if(cmdDuration >= 50)
results.D += blocksToRead;
else if(cmdDuration >= 10)
results.C += blocksToRead;
else if(cmdDuration >= 3)
results.B += blocksToRead;
else
results.A += blocksToRead;
ScanTime?.Invoke(i, cmdDuration);
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, currentSpeed * 1024);
}
// TODO: Separate errors on kind of errors.
else
{
ScanUnreadable?.Invoke(i);
results.Errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
for(ulong b = i; b < i + blocksToRead; b++)
results.UnreadableSectors.Add(b);
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
ibgLog.Write(i, 0);
@@ -433,10 +511,12 @@ namespace DiscImageChef.Core.Devices.Scanning
sectorSpeedStart += blocksToRead;
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
if(elapsed < 1) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024);
if(elapsed < 1)
continue;
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0;
timeSpeedStart = DateTime.UtcNow;
}
@@ -444,8 +524,9 @@ namespace DiscImageChef.Core.Devices.Scanning
end = DateTime.UtcNow;
EndProgress?.Invoke();
mhddLog.Close();
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
blockSize * (double)(results.Blocks + 1) / 1024 /
(blockSize * (double)(results.Blocks + 1)) / 1024 /
(results.ProcessingTime / 1000),
devicePath);
}
@@ -455,24 +536,34 @@ namespace DiscImageChef.Core.Devices.Scanning
results.SeekTotal = 0;
const int SEEK_TIMES = 1000;
Random rnd = new Random();
var rnd = new Random();
InitProgress?.Invoke();
for(int i = 0; i < SEEK_TIMES; i++)
{
if(aborted) break;
if(aborted)
break;
uint seekPos = (uint)rnd.Next((int)results.Blocks);
PulseProgress?.Invoke($"Seeking to sector {seekPos}...\t\t");
double seekCur;
if(scsiReader.CanSeek) scsiReader.Seek(seekPos, out seekCur);
else scsiReader.ReadBlock(out _, seekPos, out seekCur);
if(scsiReader.CanSeek)
scsiReader.Seek(seekPos, out seekCur);
else
scsiReader.ReadBlock(out _, seekPos, out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur;
if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur;
if(seekCur > results.SeekMax &&
seekCur != 0)
results.SeekMax = seekCur;
if(seekCur < results.SeekMin &&
seekCur != 0)
results.SeekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.SeekTotal += seekCur;
@@ -483,7 +574,7 @@ namespace DiscImageChef.Core.Devices.Scanning
results.ProcessingTime /= 1000;
results.TotalTime = (end - start).TotalSeconds;
results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime;
results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime;
results.SeekTimes = SEEK_TIMES;
return results;

View File

@@ -36,6 +36,7 @@ using System.Text;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.Bluray;
@@ -47,6 +48,7 @@ using DiscImageChef.Decoders.Xbox;
using Schemas;
using DDS = DiscImageChef.Decoders.DVD.DDS;
using DMI = DiscImageChef.Decoders.Xbox.DMI;
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
using Session = DiscImageChef.CommonTypes.Structs.Session;
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
@@ -57,55 +59,80 @@ namespace DiscImageChef.Core
public static void PrintImageInfo(IMediaImage imageFormat)
{
DicConsole.WriteLine("Image information:");
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Version))
DicConsole.WriteLine("Format: {0} version {1}", imageFormat.Format, imageFormat.Info.Version);
else DicConsole.WriteLine("Format: {0}", imageFormat.Format);
else
DicConsole.WriteLine("Format: {0}", imageFormat.Format);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application) &&
!string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion))
DicConsole.WriteLine("Was created with {0} version {1}", imageFormat.Info.Application,
imageFormat.Info.ApplicationVersion);
else if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
DicConsole.WriteLine("Was created with {0}", imageFormat.Info.Application);
DicConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize);
DicConsole.WriteLine("Contains a media of {0} sectors with a maximum sector size of {1} bytes (if all sectors are of the same size this would be {2} bytes)",
imageFormat.Info.Sectors, imageFormat.Info.SectorSize,
imageFormat.Info.Sectors * imageFormat.Info.SectorSize);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
DicConsole.WriteLine("Created by: {0}", imageFormat.Info.Creator);
if(imageFormat.Info.CreationTime != DateTime.MinValue)
DicConsole.WriteLine("Created on {0}", imageFormat.Info.CreationTime);
if(imageFormat.Info.LastModificationTime != DateTime.MinValue)
DicConsole.WriteLine("Last modified on {0}", imageFormat.Info.LastModificationTime);
DicConsole.WriteLine("Contains a media of type {0} and XML type {1}", imageFormat.Info.MediaType,
imageFormat.Info.XmlMediaType);
DicConsole.WriteLine("{0} partitions", imageFormat.Info.HasPartitions ? "Has" : "Doesn't have");
DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have");
DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have");
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Comments))
DicConsole.WriteLine("Comments: {0}", imageFormat.Info.Comments);
if(imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0)
if(imageFormat.Info.MediaSequence != 0 &&
imageFormat.Info.LastMediaSequence != 0)
DicConsole.WriteLine("Media is number {0} on a set of {1} medias", imageFormat.Info.MediaSequence,
imageFormat.Info.LastMediaSequence);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
DicConsole.WriteLine("Media title: {0}", imageFormat.Info.MediaTitle);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
DicConsole.WriteLine("Media manufacturer: {0}", imageFormat.Info.MediaManufacturer);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
DicConsole.WriteLine("Media model: {0}", imageFormat.Info.MediaModel);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
DicConsole.WriteLine("Media serial number: {0}", imageFormat.Info.MediaSerialNumber);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
DicConsole.WriteLine("Media barcode: {0}", imageFormat.Info.MediaBarcode);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
DicConsole.WriteLine("Media part number: {0}", imageFormat.Info.MediaPartNumber);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
DicConsole.WriteLine("Drive manufacturer: {0}", imageFormat.Info.DriveManufacturer);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
DicConsole.WriteLine("Drive model: {0}", imageFormat.Info.DriveModel);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
DicConsole.WriteLine("Drive serial number: {0}", imageFormat.Info.DriveSerialNumber);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
DicConsole.WriteLine("Drive firmware info: {0}", imageFormat.Info.DriveFirmwareRevision);
if(imageFormat.Info.Cylinders > 0 && imageFormat.Info.Heads > 0 &&
if(imageFormat.Info.Cylinders > 0 &&
imageFormat.Info.Heads > 0 &&
imageFormat.Info.SectorsPerTrack > 0 &&
imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc &&
(!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape))
@@ -113,19 +140,25 @@ namespace DiscImageChef.Core
imageFormat.Info.Cylinders, imageFormat.Info.Heads,
imageFormat.Info.SectorsPerTrack);
if(imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Count > 0)
if(imageFormat.Info.ReadableMediaTags != null &&
imageFormat.Info.ReadableMediaTags.Count > 0)
{
DicConsole.WriteLine("Contains {0} readable media tags:", imageFormat.Info.ReadableMediaTags.Count);
foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t))
DicConsole.Write("{0} ", tag);
DicConsole.WriteLine();
}
if(imageFormat.Info.ReadableSectorTags != null && imageFormat.Info.ReadableSectorTags.Count > 0)
if(imageFormat.Info.ReadableSectorTags != null &&
imageFormat.Info.ReadableSectorTags.Count > 0)
{
DicConsole.WriteLine("Contains {0} readable sector tags:", imageFormat.Info.ReadableSectorTags.Count);
foreach(SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t))
DicConsole.Write("{0} ", tag);
DicConsole.WriteLine();
}
@@ -139,6 +172,7 @@ namespace DiscImageChef.Core
byte[] inquiry = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);
scsiDeviceType = (PeripheralDeviceTypes)(inquiry[0] & 0x1F);
if(inquiry.Length >= 16)
{
scsiVendorId = new byte[8];
@@ -213,6 +247,7 @@ namespace DiscImageChef.Core
if(toc.Length > 0)
{
ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0));
if(dataLen + 2 != toc.Length)
{
byte[] tmp = new byte[toc.Length + 2];
@@ -236,6 +271,7 @@ namespace DiscImageChef.Core
if(pma.Length > 0)
{
ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0));
if(dataLen + 2 != pma.Length)
{
byte[] tmp = new byte[pma.Length + 2];
@@ -257,6 +293,7 @@ namespace DiscImageChef.Core
byte[] atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP);
uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0));
if(dataLen + 4 != atip.Length)
{
byte[] tmp = new byte[atip.Length + 4];
@@ -279,6 +316,7 @@ namespace DiscImageChef.Core
byte[] cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT);
uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0));
if(dataLen + 4 != cdtext.Length)
{
byte[] tmp = new byte[cdtext.Length + 4];
@@ -302,6 +340,7 @@ namespace DiscImageChef.Core
DicConsole.WriteLine("CompactDisc Media Catalogue Number contained in image: {0}",
Encoding.UTF8.GetString(mcn));
DicConsole.WriteLine();
}
@@ -362,6 +401,7 @@ namespace DiscImageChef.Core
DicConsole.WriteLine("PCMCIA CIS:");
Tuple[] tuples = CIS.GetTuples(cis);
if(tuples != null)
foreach(Tuple tuple in tuples)
switch(tuple.Code)
@@ -371,12 +411,15 @@ namespace DiscImageChef.Core
case TupleCodes.CISTPL_DEVICEGEO:
case TupleCodes.CISTPL_DEVICEGEO_A:
DicConsole.WriteLine("{0}", CIS.PrettifyDeviceGeometryTuple(tuple));
break;
case TupleCodes.CISTPL_MANFID:
DicConsole.WriteLine("{0}", CIS.PrettifyManufacturerIdentificationTuple(tuple));
break;
case TupleCodes.CISTPL_VERS_1:
DicConsole.WriteLine("{0}", CIS.PrettifyLevel1VersionTuple(tuple));
break;
case TupleCodes.CISTPL_ALTSTR:
case TupleCodes.CISTPL_BAR:
@@ -414,13 +457,16 @@ namespace DiscImageChef.Core
case TupleCodes.CISTPL_VERS_2:
DicConsole.DebugWriteLine("Device-Info command", "Found undecoded tuple ID {0}",
tuple.Code);
break;
default:
DicConsole.DebugWriteLine("Device-Info command", "Found unknown tuple ID 0x{0:X2}",
(byte)tuple.Code);
break;
}
else DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples");
else
DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples");
}
if(imageFormat.Info.ReadableMediaTags != null &&
@@ -521,6 +567,7 @@ namespace DiscImageChef.Core
if(DMI.IsXbox(xdmi))
{
DMI.XboxDMI? xmi = DMI.DecodeXbox(xdmi);
if(xmi.HasValue)
{
DicConsole.WriteLine("Xbox DMI contained in image:");
@@ -532,6 +579,7 @@ namespace DiscImageChef.Core
if(DMI.IsXbox360(xdmi))
{
DMI.Xbox360DMI? xmi = DMI.DecodeXbox360(xdmi);
if(xmi.HasValue)
{
DicConsole.WriteLine("Xbox 360 DMI contained in image:");
@@ -555,16 +603,21 @@ namespace DiscImageChef.Core
{
try
{
if(opticalImage.Sessions != null && opticalImage.Sessions.Count > 0)
if(opticalImage.Sessions != null &&
opticalImage.Sessions.Count > 0)
{
DicConsole.WriteLine("Image sessions:");
DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", "Session", "First track",
"Last track", "Start", "End");
DicConsole.WriteLine("=========================================================");
foreach(Session session in opticalImage.Sessions)
DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", session.SessionSequence,
session.StartTrack, session.EndTrack, session.StartSector,
session.EndSector);
DicConsole.WriteLine();
}
}
@@ -575,18 +628,23 @@ namespace DiscImageChef.Core
try
{
if(opticalImage.Tracks != null && opticalImage.Tracks.Count > 0)
if(opticalImage.Tracks != null &&
opticalImage.Tracks.Count > 0)
{
DicConsole.WriteLine("Image tracks:");
DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", "Track", "Type",
"Bps", "Raw bps", "Subchannel", "Pregap", "Start", "End");
DicConsole
.WriteLine("=================================================================================");
DicConsole.
WriteLine("=================================================================================");
foreach(Track track in opticalImage.Tracks)
DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}",
track.TrackSequence, track.TrackType, track.TrackBytesPerSector,
track.TrackRawBytesPerSector, track.TrackSubchannelType,
track.TrackPregap, track.TrackStartSector, track.TrackEndSector);
DicConsole.WriteLine();
}
}
@@ -596,7 +654,8 @@ namespace DiscImageChef.Core
}
}
if(imageFormat.DumpHardware == null) return;
if(imageFormat.DumpHardware == null)
return;
const string MANUFACTURER_STRING = "Manufacturer";
const string MODEL_STRING = "Model";
@@ -616,19 +675,31 @@ namespace DiscImageChef.Core
foreach(DumpHardwareType dump in imageFormat.DumpHardware)
{
if(dump.Manufacturer?.Length > manufacturerLen) manufacturerLen = dump.Manufacturer.Length;
if(dump.Model?.Length > modelLen) modelLen = dump.Model.Length;
if(dump.Serial?.Length > serialLen) serialLen = dump.Serial.Length;
if(dump.Manufacturer?.Length > manufacturerLen)
manufacturerLen = dump.Manufacturer.Length;
if(dump.Model?.Length > modelLen)
modelLen = dump.Model.Length;
if(dump.Serial?.Length > serialLen)
serialLen = dump.Serial.Length;
if(dump.Software?.Name?.Length > softwareLen)
softwareLen = dump.Software.Name.Length;
if(dump.Software?.Version?.Length > versionLen)
versionLen = dump.Software.Version.Length;
if(dump.Software?.OperatingSystem?.Length > osLen)
osLen = dump.Software.OperatingSystem.Length;
foreach(ExtentType extent in dump.Extents)
{
if($"{extent.Start}".Length > sectorLen) sectorLen = $"{extent.Start}".Length;
if($"{extent.End}".Length > sectorLen) sectorLen = $"{extent.End}".Length;
if($"{extent.Start}".Length > sectorLen)
sectorLen = $"{extent.Start}".Length;
if($"{extent.End}".Length > sectorLen)
sectorLen = $"{extent.End}".Length;
}
}
@@ -643,14 +714,20 @@ namespace DiscImageChef.Core
char[] separator = new char[manufacturerLen + modelLen + serialLen + softwareLen + versionLen + osLen +
sectorLen + sectorLen];
for(int i = 0; i < separator.Length; i++) separator[i] = '=';
for(int i = 0; i < separator.Length; i++)
separator[i] = '=';
string format =
$"{{0,-{manufacturerLen}}}{{1,-{modelLen}}}{{2,-{serialLen}}}{{3,-{softwareLen}}}{{4,-{versionLen}}}{{5,-{osLen}}}{{6,-{sectorLen}}}{{7,-{sectorLen}}}";
DicConsole.WriteLine("Dump hardware information:");
DicConsole.WriteLine(format, MANUFACTURER_STRING, MODEL_STRING, SERIAL_STRING, SOFTWARE_STRING,
VERSION_STRING, OS_STRING, START_STRING, END_STRING);
DicConsole.WriteLine(new string(separator));
foreach(DumpHardwareType dump in imageFormat.DumpHardware)
{
foreach(ExtentType extent in dump.Extents)

View File

@@ -36,6 +36,7 @@ using System.Linq;
using System.Threading;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core.Media.Detection;
using DiscImageChef.Decoders.CD;
@@ -47,6 +48,7 @@ using DiscImageChef.Decoders.Xbox;
using DiscImageChef.Devices;
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
using DMI = DiscImageChef.Decoders.Xbox.DMI;
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
namespace DiscImageChef.Core.Media.Info
{
@@ -1289,7 +1291,7 @@ namespace DiscImageChef.Core.Media.Info
if(!sense)
{
Inquiry.SCSIInquiry? inq = Inquiry.Decode(inqBuffer);
var inq = CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(inqBuffer);
if(inq.HasValue &&
inq.Value.KreonPresent)

View File

@@ -30,6 +30,7 @@
// Copyright © 2011-2020 Natalia Portillo
// ****************************************************************************/
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.SCSI;
@@ -41,22 +42,26 @@ namespace DiscImageChef.Core
{
DicConsole.WriteLine(Modes.PrettifyModeHeader(decMode.Header, devType));
if(decMode.Pages == null) return;
if(decMode.Pages == null)
return;
foreach(Modes.ModePage page in decMode.Pages)
//DicConsole.WriteLine("Page {0:X2}h subpage {1:X2}h is {2} bytes long", page.Page, page.Subpage, page.PageResponse.Length);
switch(page.Page)
{
case 0x00:
{
if(devType == PeripheralDeviceTypes.MultiMediaDevice && page.Subpage == 0)
if(devType == PeripheralDeviceTypes.MultiMediaDevice &&
page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_00_SFF(page.PageResponse));
else
{
if(page.Subpage != 0)
DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h subpage {1:X2}h",
page.Page, page.Subpage);
else DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h", page.Page);
else
DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h", page.Page);
}
break;
@@ -67,42 +72,53 @@ namespace DiscImageChef.Core
DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice
? Modes.PrettifyModePage_01_MMC(page.PageResponse)
: Modes.PrettifyModePage_01(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x02:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_02(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_02(page.PageResponse));
else
goto default;
break;
}
case 0x03:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_03(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_03(page.PageResponse));
else
goto default;
break;
}
case 0x04:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_04(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_04(page.PageResponse));
else
goto default;
break;
}
case 0x05:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_05(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_05(page.PageResponse));
else
goto default;
break;
}
case 0x06:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_06(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_06(page.PageResponse));
else
goto default;
break;
}
@@ -112,51 +128,64 @@ namespace DiscImageChef.Core
DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice
? Modes.PrettifyModePage_07_MMC(page.PageResponse)
: Modes.PrettifyModePage_07(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x08:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_08(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_08(page.PageResponse));
else
goto default;
break;
}
case 0x0A:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0A(page.PageResponse));
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_0A(page.PageResponse));
else if(page.Subpage == 1)
DicConsole.WriteLine(Modes.PrettifyModePage_0A_S01(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x0B:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0B(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_0B(page.PageResponse));
else
goto default;
break;
}
case 0x0D:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0D(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_0D(page.PageResponse));
else
goto default;
break;
}
case 0x0E:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0E(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_0E(page.PageResponse));
else
goto default;
break;
}
case 0x0F:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0F(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_0F(page.PageResponse));
else
goto default;
break;
}
@@ -166,14 +195,17 @@ namespace DiscImageChef.Core
DicConsole.WriteLine(devType == PeripheralDeviceTypes.SequentialAccess
? Modes.PrettifyModePage_10_SSC(page.PageResponse)
: Modes.PrettifyModePage_10(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x11:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_11(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_11(page.PageResponse));
else
goto default;
break;
}
@@ -181,24 +213,30 @@ namespace DiscImageChef.Core
case 0x13:
case 0x14:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_12_13_14(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_12_13_14(page.PageResponse));
else
goto default;
break;
}
case 0x1A:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1A(page.PageResponse));
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_1A(page.PageResponse));
else if(page.Subpage == 1)
DicConsole.WriteLine(Modes.PrettifyModePage_1A_S01(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x1B:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1B(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_1B(page.PageResponse));
else
goto default;
break;
}
@@ -210,14 +248,17 @@ namespace DiscImageChef.Core
: Modes.PrettifyModePage_1C(page.PageResponse));
else if(page.Subpage == 1)
DicConsole.WriteLine(Modes.PrettifyModePage_1C_S01(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x1D:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1D(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_1D(page.PageResponse));
else
goto default;
break;
}
@@ -225,7 +266,8 @@ namespace DiscImageChef.Core
{
if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE")
DicConsole.WriteLine(Modes.PrettifyCertanceModePage_21(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -233,7 +275,8 @@ namespace DiscImageChef.Core
{
if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE")
DicConsole.WriteLine(Modes.PrettifyCertanceModePage_22(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -241,14 +284,17 @@ namespace DiscImageChef.Core
{
if(StringHandlers.CToString(vendorId).Trim() == "IBM")
DicConsole.WriteLine(Modes.PrettifyIBMModePage_24(page.PageResponse));
else goto default;
else
goto default;
break;
}
case 0x2A:
{
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_2A(page.PageResponse));
else goto default;
if(page.Subpage == 0)
DicConsole.WriteLine(Modes.PrettifyModePage_2A(page.PageResponse));
else
goto default;
break;
}
@@ -256,7 +302,8 @@ namespace DiscImageChef.Core
{
if(StringHandlers.CToString(vendorId).Trim() == "IBM")
DicConsole.WriteLine(Modes.PrettifyIBMModePage_2F(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -264,7 +311,8 @@ namespace DiscImageChef.Core
{
if(Modes.IsAppleModePage_30(page.PageResponse))
DicConsole.WriteLine("Drive identifies as Apple OEM drive");
else goto default;
else
goto default;
break;
}
@@ -272,7 +320,8 @@ namespace DiscImageChef.Core
{
if(StringHandlers.CToString(vendorId).Trim() == "HP")
DicConsole.WriteLine(Modes.PrettifyHPModePage_3B(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -280,7 +329,8 @@ namespace DiscImageChef.Core
{
if(StringHandlers.CToString(vendorId).Trim() == "HP")
DicConsole.WriteLine(Modes.PrettifyHPModePage_3C(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -290,7 +340,8 @@ namespace DiscImageChef.Core
DicConsole.WriteLine(Modes.PrettifyIBMModePage_3D(page.PageResponse));
else if(StringHandlers.CToString(vendorId).Trim() == "HP")
DicConsole.WriteLine(Modes.PrettifyHPModePage_3D(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -300,7 +351,8 @@ namespace DiscImageChef.Core
DicConsole.WriteLine(Modes.PrettifyFujitsuModePage_3E(page.PageResponse));
else if(StringHandlers.CToString(vendorId).Trim() == "HP")
DicConsole.WriteLine(Modes.PrettifyHPModePage_3E(page.PageResponse));
else goto default;
else
goto default;
break;
}
@@ -309,7 +361,9 @@ namespace DiscImageChef.Core
if(page.Subpage != 0)
DicConsole.WriteLine("Found unknown mode page {0:X2}h subpage {1:X2}h", page.Page,
page.Subpage);
else DicConsole.WriteLine("Found unknown mode page {0:X2}h", page.Page);
else
DicConsole.WriteLine("Found unknown mode page {0:X2}h", page.Page);
break;
}
}

View File

@@ -681,7 +681,7 @@ namespace DiscImageChef.Core
if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
{
Identify.IdentifyDevice? ataId = Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
CommonTypes.Structs.Devices.ATA.Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
if(ataId.HasValue)
if(ataId.Value.CurrentCylinders > 0 &&

View File

@@ -37,7 +37,8 @@ using System.Linq;
using System.Runtime.InteropServices;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SecureDigital;
@@ -50,6 +51,7 @@ using FileAttributes = DiscImageChef.Devices.Windows.FileAttributes;
using FileFlags = DiscImageChef.Devices.Linux.FileFlags;
using FileMode = DiscImageChef.Devices.Windows.FileMode;
using FileShare = DiscImageChef.Devices.Windows.FileShare;
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString;
@@ -761,7 +763,7 @@ namespace DiscImageChef.Devices
if(!scsiSense)
{
Inquiry.SCSIInquiry? inquiry = Inquiry.Decode(inqBuf);
Inquiry? inquiry = Inquiry.Decode(inqBuf);
Type = DeviceType.SCSI;
bool serialSense = ScsiInquiry(out inqBuf, out _, 0x80);

View File

@@ -32,211 +32,156 @@
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
namespace DiscImageChef.Devices
{
public partial class Device
{
private readonly ushort usbVendor;
private readonly ushort usbProduct;
private readonly ulong firewireGuid;
private readonly uint firewireModel;
private readonly uint firewireVendor;
readonly ushort usbVendor;
readonly ushort usbProduct;
readonly ulong firewireGuid;
readonly uint firewireModel;
readonly uint firewireVendor;
// MMC and SecureDigital, values that need to be get with card idle, something that may
// not be possible to do but usually is already done by the SDHCI driver.
private readonly byte[] cachedCsd;
private readonly byte[] cachedCid;
private readonly byte[] cachedScr;
private readonly byte[] cachedOcr;
readonly byte[] cachedCsd;
readonly byte[] cachedCid;
readonly byte[] cachedScr;
readonly byte[] cachedOcr;
/// <summary>
/// Gets the Platform ID for this device
/// </summary>
/// <summary>Gets the Platform ID for this device</summary>
/// <value>The Platform ID</value>
public PlatformID PlatformId { get; }
/// <summary>
/// Gets the file handle representing this device
/// </summary>
/// <summary>Gets the file handle representing this device</summary>
/// <value>The file handle</value>
public object FileHandle { get; private set; }
/// <summary>
/// Gets or sets the standard timeout for commands sent to this device
/// </summary>
/// <summary>Gets or sets the standard timeout for commands sent to this device</summary>
/// <value>The timeout in seconds</value>
public uint Timeout { get; }
/// <summary>
/// Gets a value indicating whether this <see cref="Device" /> is in error.
/// </summary>
/// <summary>Gets a value indicating whether this <see cref="Device" /> is in error.</summary>
/// <value><c>true</c> if error; otherwise, <c>false</c>.</value>
public bool Error { get; private set; }
/// <summary>
/// Gets the last error number.
/// </summary>
/// <summary>Gets the last error number.</summary>
/// <value>The last error.</value>
public int LastError { get; private set; }
/// <summary>
/// Gets the device type.
/// </summary>
/// <summary>Gets the device type.</summary>
/// <value>The device type.</value>
public DeviceType Type { get; }
/// <summary>
/// Gets the device's manufacturer
/// </summary>
/// <summary>Gets the device's manufacturer</summary>
/// <value>The manufacturer.</value>
public string Manufacturer { get; }
/// <summary>
/// Gets the device model
/// </summary>
/// <summary>Gets the device model</summary>
/// <value>The model.</value>
public string Model { get; }
/// <summary>
/// Gets the device's firmware version.
/// </summary>
/// <summary>Gets the device's firmware version.</summary>
/// <value>The firmware version.</value>
public string FirmwareRevision { get; }
/// <summary>
/// Gets the device's serial number.
/// </summary>
/// <summary>Gets the device's serial number.</summary>
/// <value>The serial number.</value>
public string Serial { get; }
/// <summary>
/// Gets the device's SCSI peripheral device type
/// </summary>
/// <summary>Gets the device's SCSI peripheral device type</summary>
/// <value>The SCSI peripheral device type.</value>
public PeripheralDeviceTypes ScsiType { get; }
/// <summary>
/// Gets a value indicating whether this device's media is removable.
/// </summary>
/// <summary>Gets a value indicating whether this device's media is removable.</summary>
/// <value><c>true</c> if this device's media is removable; otherwise, <c>false</c>.</value>
public bool IsRemovable { get; }
/// <summary>
/// Gets a value indicating whether this device is attached via USB.
/// </summary>
/// <summary>Gets a value indicating whether this device is attached via USB.</summary>
/// <value><c>true</c> if this device is attached via USB; otherwise, <c>false</c>.</value>
public bool IsUsb { get; }
/// <summary>
/// Gets the USB vendor ID.
/// </summary>
/// <summary>Gets the USB vendor ID.</summary>
/// <value>The USB vendor ID.</value>
public ushort UsbVendorId => usbVendor;
/// <summary>
/// Gets the USB product ID.
/// </summary>
/// <summary>Gets the USB product ID.</summary>
/// <value>The USB product ID.</value>
public ushort UsbProductId => usbProduct;
/// <summary>
/// Gets the USB descriptors.
/// </summary>
/// <summary>Gets the USB descriptors.</summary>
/// <value>The USB descriptors.</value>
public byte[] UsbDescriptors { get; }
/// <summary>
/// Gets the USB manufacturer string.
/// </summary>
/// <summary>Gets the USB manufacturer string.</summary>
/// <value>The USB manufacturer string.</value>
public string UsbManufacturerString { get; }
/// <summary>
/// Gets the USB product string.
/// </summary>
/// <summary>Gets the USB product string.</summary>
/// <value>The USB product string.</value>
public string UsbProductString { get; }
/// <summary>
/// Gets the USB serial string.
/// </summary>
/// <summary>Gets the USB serial string.</summary>
/// <value>The USB serial string.</value>
public string UsbSerialString { get; }
/// <summary>
/// Gets a value indicating whether this device is attached via FireWire.
/// </summary>
/// <summary>Gets a value indicating whether this device is attached via FireWire.</summary>
/// <value><c>true</c> if this device is attached via FireWire; otherwise, <c>false</c>.</value>
public bool IsFireWire { get; }
/// <summary>
/// Gets the FireWire GUID
/// </summary>
/// <summary>Gets the FireWire GUID</summary>
/// <value>The FireWire GUID.</value>
public ulong FireWireGuid => firewireGuid;
/// <summary>
/// Gets the FireWire model number
/// </summary>
/// <summary>Gets the FireWire model number</summary>
/// <value>The FireWire model.</value>
public uint FireWireModel => firewireModel;
/// <summary>
/// Gets the FireWire model name.
/// </summary>
/// <summary>Gets the FireWire model name.</summary>
/// <value>The FireWire model name.</value>
public string FireWireModelName { get; }
/// <summary>
/// Gets the FireWire vendor number.
/// </summary>
/// <summary>Gets the FireWire vendor number.</summary>
/// <value>The FireWire vendor number.</value>
public uint FireWireVendor => firewireVendor;
/// <summary>
/// Gets the FireWire vendor name.
/// </summary>
/// <summary>Gets the FireWire vendor name.</summary>
/// <value>The FireWire vendor name.</value>
public string FireWireVendorName { get; }
/// <summary>
/// Gets a value indicating whether this device is a CompactFlash device.
/// </summary>
/// <summary>Gets a value indicating whether this device is a CompactFlash device.</summary>
/// <value><c>true</c> if this device is a CompactFlash device; otherwise, <c>false</c>.</value>
public bool IsCompactFlash { get; }
/// <summary>
/// Gets a value indicating whether this device is a PCMCIA device.
/// </summary>
/// <summary>Gets a value indicating whether this device is a PCMCIA device.</summary>
/// <value><c>true</c> if this device is a PCMCIA device; otherwise, <c>false</c>.</value>
public bool IsPcmcia { get; }
/// <summary>
/// Contains the PCMCIA CIS if applicable
/// </summary>
/// <summary>Contains the PCMCIA CIS if applicable</summary>
public byte[] Cis { get; }
private readonly Remote.Remote _remote;
private bool? _isRemoteAdmin;
readonly Remote.Remote _remote;
bool? _isRemoteAdmin;
public bool IsRemoteAdmin
{
get
{
if (_isRemoteAdmin is null) _isRemoteAdmin = _remote.IsRoot;
if(_isRemoteAdmin is null)
_isRemoteAdmin = _remote.IsRoot;
return _isRemoteAdmin == true;
}
}
public bool IsRemote => _remote != null;
public string RemoteApplication => _remote?.ServerApplication;
public string RemoteVersion => _remote?.ServerVersion;
public string RemoteOperatingSystem => _remote?.ServerOperatingSystem;
public bool IsRemote => _remote != null;
public string RemoteApplication => _remote?.ServerApplication;
public string RemoteVersion => _remote?.ServerVersion;
public string RemoteOperatingSystem => _remote?.ServerOperatingSystem;
public string RemoteOperatingSystemVersion => _remote?.ServerOperatingSystemVersion;
public string RemoteArchitecture => _remote?.ServerArchitecture;
public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0;
public string RemoteArchitecture => _remote?.ServerArchitecture;
public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0;
}
}

View File

@@ -35,17 +35,15 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using static DiscImageChef.Devices.FreeBSD.Extern;
namespace DiscImageChef.Devices.FreeBSD
{
static class ListDevices
internal static class ListDevices
{
/// <summary>
/// Gets a list of all known storage devices on FreeBSD
/// </summary>
/// <summary>Gets a list of all known storage devices on FreeBSD</summary>
/// <returns>List of devices</returns>
internal static DeviceInfo[] GetList()
{
@@ -54,15 +52,16 @@ namespace DiscImageChef.Devices.FreeBSD
foreach(string passDevice in passDevices)
{
DeviceInfo deviceInfo = new DeviceInfo();
IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite);
CamDevice camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice));
var deviceInfo = new DeviceInfo();
IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite);
var camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice));
IntPtr ccbPtr = cam_getccb(dev);
if(ccbPtr.ToInt64() == 0) continue;
if(ccbPtr.ToInt64() == 0)
continue;
CcbGetdev cgd = (CcbGetdev)Marshal.PtrToStructure(ccbPtr, typeof(CcbGetdev));
var cgd = (CcbGetdev)Marshal.PtrToStructure(ccbPtr, typeof(CcbGetdev));
cgd.ccb_h.func_code = XptOpcode.XptGdevType;
@@ -73,6 +72,7 @@ namespace DiscImageChef.Devices.FreeBSD
if(error < 0)
{
cam_freeccb(ccbPtr);
continue;
}
@@ -96,6 +96,7 @@ namespace DiscImageChef.Devices.FreeBSD
// Little-endian FreeBSD gives it resorted
// Big-endian FreeBSD, no idea
byte[] atadTneid = new byte[512];
for(int aIndex = 0; aIndex < 512; aIndex += 2)
{
atadTneid[aIndex] = cgd.ident_data[aIndex + 1];
@@ -103,6 +104,7 @@ namespace DiscImageChef.Devices.FreeBSD
}
Identify.IdentifyDevice? idt = Identify.Decode(atadTneid);
if(idt.HasValue)
{
string[] separated = idt.Value.Model.Split(' ');
@@ -123,12 +125,15 @@ namespace DiscImageChef.Devices.FreeBSD
deviceInfo.Supported = simName != "ata";
}
if(cgd.protocol == CamProto.ProtoAtapi) goto case CamProto.ProtoScsi;
if(cgd.protocol == CamProto.ProtoAtapi)
goto case CamProto.ProtoScsi;
break;
}
case CamProto.ProtoScsi:
{
Inquiry.SCSIInquiry? inq = Inquiry.Decode(cgd.inq_data);
Inquiry? inq = Inquiry.Decode(cgd.inq_data);
if(inq.HasValue)
{
deviceInfo.Vendor = StringHandlers.CToString(inq.Value.VendorIdentification).Trim();
@@ -142,11 +147,13 @@ namespace DiscImageChef.Devices.FreeBSD
case CamProto.ProtoNvme:
deviceInfo.Bus = "NVMe";
deviceInfo.Supported = false;
break;
case CamProto.ProtoMmcsd:
deviceInfo.Model = "Unknown card";
deviceInfo.Bus = "MMC/SD";
deviceInfo.Supported = false;
break;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -33,31 +33,33 @@
using System;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.SecureDigital;
using DiscImageChef.Helpers;
using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString;
namespace DiscImageChef.DiscImages
{
public partial class DiscImageChef
{
/// <summary>
/// Checks for media tags that may contain metadata and sets it up if not already set
/// </summary>
/// <summary>Checks for media tags that may contain metadata and sets it up if not already set</summary>
void SetMetadataFromTags()
{
// Search for SecureDigital CID
if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid))
{
CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid);
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
imageInfo.DriveManufacturer = VendorString.Prettify(decoded.Manufacturer);
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName;
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
imageInfo.DriveModel = decoded.ProductName;
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
imageInfo.DriveFirmwareRevision =
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
}
@@ -66,12 +68,17 @@ namespace DiscImageChef.DiscImages
if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid))
{
Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid);
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
imageInfo.DriveManufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer);
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName;
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
imageInfo.DriveModel = decoded.ProductName;
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
imageInfo.DriveFirmwareRevision =
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
}
@@ -79,15 +86,18 @@ namespace DiscImageChef.DiscImages
// Search for SCSI INQUIRY
if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry))
{
Inquiry.SCSIInquiry? nullableInquiry = Inquiry.Decode(scsiInquiry);
Inquiry? nullableInquiry = Inquiry.Decode(scsiInquiry);
if(nullableInquiry.HasValue)
{
Inquiry.SCSIInquiry inquiry = nullableInquiry.Value;
Inquiry inquiry = nullableInquiry.Value;
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
imageInfo.DriveManufacturer = StringHandlers.CToString(inquiry.VendorIdentification)?.Trim();
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
imageInfo.DriveModel = StringHandlers.CToString(inquiry.ProductIdentification)?.Trim();
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
imageInfo.DriveFirmwareRevision =
StringHandlers.CToString(inquiry.ProductRevisionLevel)?.Trim();
@@ -95,29 +105,34 @@ namespace DiscImageChef.DiscImages
}
// Search for ATA or ATAPI IDENTIFY
if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
!mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) return;
if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
!mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify))
return;
Identify.IdentifyDevice? nullableIdentify = Decoders.ATA.Identify.Decode(ataIdentify);
Identify.IdentifyDevice? nullableIdentify = CommonTypes.Structs.Devices.ATA.Identify.Decode(ataIdentify);
if(!nullableIdentify.HasValue) return;
if(!nullableIdentify.HasValue)
return;
Identify.IdentifyDevice identify = nullableIdentify.Value;
string[] separated = identify.Model.Split(' ');
if(separated.Length == 1)
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = separated[0];
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
imageInfo.DriveModel = separated[0];
else
{
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
imageInfo.DriveManufacturer = separated[0];
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
imageInfo.DriveModel = separated[separated.Length - 1];
}
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
imageInfo.DriveFirmwareRevision = identify.FirmwareRevision;
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
imageInfo.DriveSerialNumber = identify.SerialNumber;
}
@@ -225,9 +240,11 @@ namespace DiscImageChef.DiscImages
// Gets a DDT entry
ulong GetDdtEntry(ulong sectorAddress)
{
if(inMemoryDdt) return userDataDdt[sectorAddress];
if(inMemoryDdt)
return userDataDdt[sectorAddress];
if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry)) return entry;
if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry))
return entry;
long oldPosition = imageStream.Position;
imageStream.Position = outMemoryDdtPosition + Marshal.SizeOf<DdtHeader>();
@@ -237,9 +254,11 @@ namespace DiscImageChef.DiscImages
imageStream.Position = oldPosition;
entry = BitConverter.ToUInt64(temp, 0);
if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE) ddtEntryCache.Clear();
if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE)
ddtEntryCache.Clear();
ddtEntryCache.Add(sectorAddress, entry);
return entry;
}
@@ -248,8 +267,11 @@ namespace DiscImageChef.DiscImages
{
if(inMemoryDdt)
{
if(IsTape) tapeDdt[sectorAddress] = pointer;
else userDataDdt[sectorAddress] = pointer;
if(IsTape)
tapeDdt[sectorAddress] = pointer;
else
userDataDdt[sectorAddress] = pointer;
return;
}

View File

@@ -37,7 +37,7 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Exceptions;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.Helpers;
namespace DiscImageChef.DiscImages
@@ -54,7 +54,8 @@ namespace DiscImageChef.DiscImages
RsIdeHeader hdr = Marshal.ByteArrayToStructureLittleEndian<RsIdeHeader>(hdrB);
if(!hdr.magic.SequenceEqual(signature)) return false;
if(!hdr.magic.SequenceEqual(signature))
return false;
dataOff = hdr.dataOff;
@@ -72,7 +73,7 @@ namespace DiscImageChef.DiscImages
{
identify = new byte[512];
Array.Copy(hdr.identify, 0, identify, 0, hdr.identify.Length);
Identify.IdentifyDevice? ataId = Decoders.ATA.Identify.Decode(identify);
Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identify);
if(ataId.HasValue)
{
@@ -88,7 +89,9 @@ namespace DiscImageChef.DiscImages
}
}
if(imageInfo.Cylinders == 0 || imageInfo.Heads == 0 || imageInfo.SectorsPerTrack == 0)
if(imageInfo.Cylinders == 0 ||
imageInfo.Heads == 0 ||
imageInfo.SectorsPerTrack == 0)
{
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
@@ -114,7 +117,7 @@ namespace DiscImageChef.DiscImages
Stream stream = rsIdeImageFilter.GetDataForkStream();
stream.Seek((long)(dataOff + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
stream.Seek((long)(dataOff + (sectorAddress * imageInfo.SectorSize)), SeekOrigin.Begin);
stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
@@ -123,11 +126,13 @@ namespace DiscImageChef.DiscImages
public byte[] ReadDiskTag(MediaTagType tag)
{
if(!imageInfo.ReadableMediaTags.Contains(tag) || tag != MediaTagType.ATA_IDENTIFY)
if(!imageInfo.ReadableMediaTags.Contains(tag) ||
tag != MediaTagType.ATA_IDENTIFY)
throw new FeatureUnsupportedImageException("Feature not supported by image format");
byte[] buffer = new byte[512];
Array.Copy(identify, 0, buffer, 0, 512);
return buffer;
}
}

View File

@@ -37,7 +37,7 @@ using System.Linq;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.Helpers;
using Schemas;
using Version = DiscImageChef.CommonTypes.Interop.Version;
@@ -47,37 +47,49 @@ namespace DiscImageChef.DiscImages
public partial class RsIde
{
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(sectorSize != 256 && sectorSize != 512)
if(sectorSize != 256 &&
sectorSize != 512)
{
ErrorMessage = "Unsupported sector size";
return false;
}
if(sectors > 63 * 16 * 1024)
{
ErrorMessage = "Too many sectors";
return false;
}
if(!SupportedMediaTypes.Contains(mediaType))
{
ErrorMessage = $"Unsupport media format {mediaType}";
return false;
}
imageInfo = new ImageInfo {MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors};
imageInfo = new ImageInfo
{
MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors
};
try { writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); }
try
{
writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
}
catch(IOException e)
{
ErrorMessage = $"Could not create new image file, exception {e.Message}";
return false;
}
IsWriting = true;
ErrorMessage = null;
return true;
}
@@ -86,17 +98,20 @@ namespace DiscImageChef.DiscImages
if(tag != MediaTagType.ATA_IDENTIFY)
{
ErrorMessage = $"Unsupported media tag {tag}.";
return false;
}
if(!IsWriting)
{
ErrorMessage = "Tried to write on a non-writable image";
return false;
}
identify = new byte[106];
Array.Copy(data, 0, identify, 0, 106);
return true;
}
@@ -105,26 +120,31 @@ namespace DiscImageChef.DiscImages
if(!IsWriting)
{
ErrorMessage = "Tried to write on a non-writable image";
return false;
}
if(data.Length != imageInfo.SectorSize)
{
ErrorMessage = "Incorrect data size";
return false;
}
if(sectorAddress >= imageInfo.Sectors)
{
ErrorMessage = "Tried to write past image size";
return false;
}
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + sectorAddress * imageInfo.SectorSize),
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + (sectorAddress * imageInfo.SectorSize)),
SeekOrigin.Begin);
writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
return true;
}
@@ -133,38 +153,45 @@ namespace DiscImageChef.DiscImages
if(!IsWriting)
{
ErrorMessage = "Tried to write on a non-writable image";
return false;
}
if(data.Length % imageInfo.SectorSize != 0)
{
ErrorMessage = "Incorrect data size";
return false;
}
if(sectorAddress + length > imageInfo.Sectors)
{
ErrorMessage = "Tried to write past image size";
return false;
}
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + sectorAddress * imageInfo.SectorSize),
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + (sectorAddress * imageInfo.SectorSize)),
SeekOrigin.Begin);
writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
return true;
}
public bool WriteSectorLong(byte[] data, ulong sectorAddress)
{
ErrorMessage = "Writing sectors with tags is not supported.";
return false;
}
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
{
ErrorMessage = "Writing sectors with tags is not supported.";
return false;
}
@@ -173,6 +200,7 @@ namespace DiscImageChef.DiscImages
if(!IsWriting)
{
ErrorMessage = "Image is not opened for writing";
return false;
}
@@ -194,52 +222,53 @@ namespace DiscImageChef.DiscImages
imageInfo.Cylinders = (uint)(imageInfo.Sectors / imageInfo.Heads / imageInfo.SectorsPerTrack);
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
if(imageInfo.Cylinders == 0 &&
imageInfo.Heads == 0 &&
imageInfo.SectorsPerTrack == 0)
break;
}
}
RsIdeHeader header = new RsIdeHeader
var header = new RsIdeHeader
{
magic = signature,
identify = new byte[106],
dataOff = (ushort)Marshal.SizeOf<RsIdeHeader>(),
revision = 1,
reserved = new byte[11]
magic = signature, identify = new byte[106], dataOff = (ushort)Marshal.SizeOf<RsIdeHeader>(),
revision = 1, reserved = new byte[11]
};
if(imageInfo.SectorSize == 256) header.flags = RsIdeFlags.HalfSectors;
if(imageInfo.SectorSize == 256)
header.flags = RsIdeFlags.HalfSectors;
if(identify == null)
{
Identify.IdentifyDevice ataId = new Identify.IdentifyDevice
var ataId = new Identify.IdentifyDevice
{
GeneralConfiguration =
Decoders.ATA.Identify.GeneralConfigurationBit.UltraFastIDE |
Decoders.ATA.Identify.GeneralConfigurationBit.Fixed |
Decoders.ATA.Identify.GeneralConfigurationBit.NotMFM |
Decoders.ATA.Identify.GeneralConfigurationBit.SoftSector,
Cylinders = (ushort)imageInfo.Cylinders,
Heads = (ushort)imageInfo.Heads,
SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack,
VendorWord47 = 0x80,
Capabilities =
Decoders.ATA.Identify.CapabilitiesBit.DMASupport |
Decoders.ATA.Identify.CapabilitiesBit.IORDY |
Decoders.ATA.Identify.CapabilitiesBit.LBASupport,
ExtendedIdentify = Decoders.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid,
CurrentCylinders = (ushort)imageInfo.Cylinders,
CurrentHeads = (ushort)imageInfo.Heads,
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.UltraFastIDE |
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.Fixed |
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.NotMFM |
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.SoftSector,
Cylinders = (ushort)imageInfo.Cylinders, Heads = (ushort)imageInfo.Heads,
SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, VendorWord47 = 0x80,
Capabilities = CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.DMASupport |
CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.IORDY |
CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.LBASupport,
ExtendedIdentify =
CommonTypes.Structs.Devices.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid,
CurrentCylinders = (ushort)imageInfo.Cylinders, CurrentHeads = (ushort)imageInfo.Heads,
CurrentSectorsPerTrack = (ushort)imageInfo.SectorsPerTrack,
CurrentSectors = (uint)imageInfo.Sectors,
LBASectors = (uint)imageInfo.Sectors,
DMASupported = Decoders.ATA.Identify.TransferMode.Mode0,
DMAActive = Decoders.ATA.Identify.TransferMode.Mode0
CurrentSectors = (uint)imageInfo.Sectors, LBASectors = (uint)imageInfo.Sectors,
DMASupported = CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0,
DMAActive = CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0
};
if(string.IsNullOrEmpty(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = "DiscImageChef";
if(string.IsNullOrEmpty(imageInfo.DriveManufacturer))
imageInfo.DriveManufacturer = "DiscImageChef";
if(string.IsNullOrEmpty(imageInfo.DriveModel)) imageInfo.DriveModel = "";
if(string.IsNullOrEmpty(imageInfo.DriveModel))
imageInfo.DriveModel = "";
if(string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision)) Version.GetVersion();
if(string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision))
Version.GetVersion();
if(string.IsNullOrEmpty(imageInfo.DriveSerialNumber))
imageInfo.DriveSerialNumber = $"{new Random().NextDouble():16X}";
@@ -247,17 +276,21 @@ namespace DiscImageChef.DiscImages
byte[] ataIdBytes = new byte[Marshal.SizeOf<Identify.IdentifyDevice>()];
IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512);
System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, true);
System.Runtime.InteropServices.Marshal.Copy(ptr, ataIdBytes, 0,
Marshal.SizeOf<Identify.IdentifyDevice>());
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
Array.Copy(ScrambleAtaString(imageInfo.DriveManufacturer + " " + imageInfo.DriveModel, 40), 0,
ataIdBytes, 27 * 2, 40);
Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8);
Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20);
Array.Copy(ataIdBytes, 0, header.identify, 0, 106);
Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8);
Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20);
Array.Copy(ataIdBytes, 0, header.identify, 0, 106);
}
else Array.Copy(identify, 0, header.identify, 0, 106);
else
Array.Copy(identify, 0, header.identify, 0, 106);
byte[] hdr = new byte[Marshal.SizeOf<RsIdeHeader>()];
IntPtr hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<RsIdeHeader>());
@@ -273,6 +306,7 @@ namespace DiscImageChef.DiscImages
IsWriting = false;
ErrorMessage = "";
return true;
}
@@ -291,18 +325,21 @@ namespace DiscImageChef.DiscImages
if(cylinders > ushort.MaxValue)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > ushort.MaxValue)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > ushort.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
@@ -316,12 +353,14 @@ namespace DiscImageChef.DiscImages
public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag)
{
ErrorMessage = "Unsupported feature";
return false;
}
public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag)
{
ErrorMessage = "Unsupported feature";
return false;
}

View File

@@ -40,12 +40,14 @@ using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Exceptions;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.CD;
using DiscImageChef.Decoders.DVD;
using DiscImageChef.Decoders.SCSI;
using Schemas;
using DMI = DiscImageChef.Decoders.Xbox.DMI;
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
using Session = DiscImageChef.CommonTypes.Structs.Session;
using TrackType = DiscImageChef.CommonTypes.Enums.TrackType;
@@ -781,7 +783,7 @@ namespace DiscImageChef.DiscImages
if (mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY))
{
var devType = PeripheralDeviceTypes.DirectAccess;
Inquiry.SCSIInquiry? scsiInq = null;
Inquiry? scsiInq = null;
if (mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out var inq))
{
scsiInq = Inquiry.Decode(inq);
@@ -858,7 +860,7 @@ namespace DiscImageChef.DiscImages
// It's ATA, check tags
if (mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out var identifyBuf))
{
var ataId = Decoders.ATA.Identify.Decode(identifyBuf);
var ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identifyBuf);
if (ataId.HasValue)
{
imageInfo.MediaType = (ushort) ataId.Value.GeneralConfiguration == 0x848A

View File

@@ -35,6 +35,7 @@ using System.Collections.ObjectModel;
using System.Text;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.Bluray;
using DiscImageChef.Decoders.CD;
@@ -48,6 +49,7 @@ using BCA = DiscImageChef.Decoders.Bluray.BCA;
using Cartridge = DiscImageChef.Decoders.Bluray.Cartridge;
using DDS = DiscImageChef.Decoders.DVD.DDS;
using DMI = DiscImageChef.Decoders.Xbox.DMI;
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
using Spare = DiscImageChef.Decoders.DVD.Spare;
namespace DiscImageChef.Gui.Forms

View File

@@ -39,6 +39,7 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Core.Media.Info;

View File

@@ -37,6 +37,7 @@ using System.Text;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Decoders.CD;
using DiscImageChef.Decoders.DVD;
using DiscImageChef.Decoders.SCSI;
@@ -48,6 +49,7 @@ using Eto.Drawing;
using Eto.Forms;
using Eto.Serialization.Xaml;
using Schemas;
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
using Session = DiscImageChef.CommonTypes.Structs.Session;
namespace DiscImageChef.Gui.Panels
@@ -258,7 +260,7 @@ namespace DiscImageChef.Gui.Panels
PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess;
byte[] scsiInquiryData = null;
Inquiry.SCSIInquiry? scsiInquiry = null;
CommonTypes.Structs.Devices.SCSI.Inquiry? scsiInquiry = null;
Modes.DecodedMode? scsiMode = null;
byte[] scsiModeSense6 = null;
byte[] scsiModeSense10 = null;
@@ -270,7 +272,7 @@ namespace DiscImageChef.Gui.Panels
scsiDeviceType = (PeripheralDeviceTypes)(scsiInquiryData[0] & 0x1F);
scsiInquiry = Inquiry.Decode(scsiInquiryData);
scsiInquiry = CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(scsiInquiryData);
}
if(imageFormat.Info.ReadableMediaTags != null &&

View File

@@ -34,11 +34,13 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC;
using Eto.Forms;
using Eto.Serialization.Xaml;
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
namespace DiscImageChef.Gui.Tabs
{
@@ -46,7 +48,7 @@ namespace DiscImageChef.Gui.Tabs
{
private byte[] configuration;
private Dictionary<byte, byte[]> evpdPages;
private Inquiry.SCSIInquiry? inquiry;
private CommonTypes.Structs.Devices.SCSI.Inquiry? inquiry;
private byte[] inquiryData;
private Modes.DecodedMode? mode;
private byte[] modeSense10;
@@ -58,7 +60,7 @@ namespace DiscImageChef.Gui.Tabs
XamlReader.Load(this);
}
internal void LoadData(byte[] scsiInquiryData, Inquiry.SCSIInquiry? scsiInquiry,
internal void LoadData(byte[] scsiInquiryData, CommonTypes.Structs.Devices.SCSI.Inquiry? scsiInquiry,
Dictionary<byte, byte[]> scsiEvpdPages, Modes.DecodedMode? scsiMode,
PeripheralDeviceTypes scsiType, byte[] scsiModeSense6,
byte[] scsiModeSense10,

View File

@@ -251,6 +251,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=leadout/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=manuallj/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mapfile/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=MDMA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaserialnumber/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mhdd/@EntryIndexedValue">True</s:Boolean>
@@ -287,6 +288,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reiser/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=remapanchor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=reportdensitysupport/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SATA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SCMS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SDHCI/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Secu/@EntryIndexedValue">True</s:Boolean>

View File

@@ -39,11 +39,12 @@ using System.Threading;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Database;
using DiscImageChef.Database.Models;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Devices;
using Newtonsoft.Json;

View File

@@ -35,6 +35,7 @@ using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Database;
@@ -47,6 +48,7 @@ using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Devices;
using Command = System.CommandLine.Command;
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
namespace DiscImageChef.Commands.Device
{

View File

@@ -37,6 +37,7 @@ using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Core.Devices.Dumping;
@@ -46,7 +47,6 @@ using DiscImageChef.Database.Models;
using DiscImageChef.Decoders.Bluray;
using DiscImageChef.Decoders.CD;
using DiscImageChef.Decoders.DVD;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Decoders.Xbox;